mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-07 21:42:16 -07:00
UI Action Handler Changes, Misc Fixes
This commit is contained in:
parent
7825319d89
commit
cd5b658196
193 changed files with 6992 additions and 6341 deletions
|
@ -8,7 +8,7 @@ import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus';
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
(state) => state.app,
|
(state) => state.app,
|
||||||
(state) => state.queue.queueStatus,
|
(state) => state.queue.status,
|
||||||
(app, status) => {
|
(app, status) => {
|
||||||
return {
|
return {
|
||||||
isConnected: app.isConnected,
|
isConnected: app.isConnected,
|
||||||
|
|
|
@ -80,7 +80,7 @@ class ImportArtistTable extends Component {
|
||||||
|
|
||||||
// Props doesn't have a selected artist or
|
// Props doesn't have a selected artist or
|
||||||
// the selected artist is an existing artist.
|
// the selected artist is an existing artist.
|
||||||
if ((selectedArtist && !prevItem.selectedArtist) || (isExistingArtist && !prevItem.selectedArtist)) {
|
if ((!selectedArtist && prevItem.selectedArtist) || (isExistingArtist && !prevItem.selectedArtist)) {
|
||||||
onSelectedChange({ id, value: false });
|
onSelectedChange({ id, value: false });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export const CALENDAR = 'calendar';
|
export const CALENDAR = 'calendar';
|
||||||
export const EPISODES = 'episodes';
|
export const EPISODES = 'episodes';
|
||||||
export const INTERACTIVE_IMPORT = 'interactiveImport.interactiveImportAlbums';
|
export const INTERACTIVE_IMPORT = 'interactiveImport.episodes';
|
||||||
export const WANTED_CUTOFF_UNMET = 'wanted.cutoffUnmet';
|
export const WANTED_CUTOFF_UNMET = 'wanted.cutoffUnmet';
|
||||||
export const WANTED_MISSING = 'wanted.missing';
|
export const WANTED_MISSING = 'wanted.missing';
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||||
import { toggleArtistMonitored, toggleSeasonMonitored } from 'Store/Actions/artistActions';
|
import { toggleArtistMonitored } from 'Store/Actions/artistActions';
|
||||||
import { toggleEpisodeMonitored } from 'Store/Actions/episodeActions';
|
import { toggleEpisodeMonitored } from 'Store/Actions/episodeActions';
|
||||||
import AlbumStudioRow from './AlbumStudioRow';
|
import AlbumStudioRow from './AlbumStudioRow';
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ function createMapStateToProps() {
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
toggleArtistMonitored,
|
toggleArtistMonitored,
|
||||||
toggleSeasonMonitored,
|
|
||||||
toggleEpisodeMonitored
|
toggleEpisodeMonitored
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,7 +77,6 @@ AlbumStudioRowConnector.propTypes = {
|
||||||
artistId: PropTypes.number.isRequired,
|
artistId: PropTypes.number.isRequired,
|
||||||
monitored: PropTypes.bool.isRequired,
|
monitored: PropTypes.bool.isRequired,
|
||||||
toggleArtistMonitored: PropTypes.func.isRequired,
|
toggleArtistMonitored: PropTypes.func.isRequired,
|
||||||
toggleSeasonMonitored: PropTypes.func.isRequired,
|
|
||||||
toggleEpisodeMonitored: PropTypes.func.isRequired
|
toggleEpisodeMonitored: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,6 @@ class ArtistDetailsSeason extends Component {
|
||||||
artistMonitored,
|
artistMonitored,
|
||||||
isSmallScreen,
|
isSmallScreen,
|
||||||
onTableOptionChange,
|
onTableOptionChange,
|
||||||
onMonitorSeasonPress,
|
|
||||||
onSearchPress
|
onSearchPress
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -309,7 +308,6 @@ ArtistDetailsSeason.propTypes = {
|
||||||
artistMonitored: PropTypes.bool.isRequired,
|
artistMonitored: PropTypes.bool.isRequired,
|
||||||
isSmallScreen: PropTypes.bool.isRequired,
|
isSmallScreen: PropTypes.bool.isRequired,
|
||||||
onTableOptionChange: PropTypes.func.isRequired,
|
onTableOptionChange: PropTypes.func.isRequired,
|
||||||
onMonitorSeasonPress: PropTypes.func.isRequired,
|
|
||||||
onExpandPress: PropTypes.func.isRequired,
|
onExpandPress: PropTypes.func.isRequired,
|
||||||
onMonitorAlbumPress: PropTypes.func.isRequired,
|
onMonitorAlbumPress: PropTypes.func.isRequired,
|
||||||
onSearchPress: PropTypes.func.isRequired
|
onSearchPress: PropTypes.func.isRequired
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { findCommand } from 'Utilities/Command';
|
||||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||||
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
import createArtistSelector from 'Store/Selectors/createArtistSelector';
|
||||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||||
import { toggleSeasonMonitored } from 'Store/Actions/artistActions';
|
|
||||||
import { toggleEpisodesMonitored, setEpisodesTableOption } from 'Store/Actions/episodeActions';
|
import { toggleEpisodesMonitored, setEpisodesTableOption } from 'Store/Actions/episodeActions';
|
||||||
import { executeCommand } from 'Store/Actions/commandActions';
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import * as commandNames from 'Commands/commandNames';
|
import * as commandNames from 'Commands/commandNames';
|
||||||
|
@ -42,7 +41,6 @@ function createMapStateToProps() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
toggleSeasonMonitored,
|
|
||||||
toggleEpisodesMonitored,
|
toggleEpisodesMonitored,
|
||||||
setEpisodesTableOption,
|
setEpisodesTableOption,
|
||||||
executeCommand
|
executeCommand
|
||||||
|
@ -57,17 +55,6 @@ class ArtistDetailsSeasonConnector extends Component {
|
||||||
this.props.setEpisodesTableOption(payload);
|
this.props.setEpisodesTableOption(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMonitorSeasonPress = (monitored) => {
|
|
||||||
const {
|
|
||||||
artistId
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
this.props.toggleSeasonMonitored({
|
|
||||||
artistId,
|
|
||||||
monitored
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearchPress = () => {
|
onSearchPress = () => {
|
||||||
const {
|
const {
|
||||||
artistId
|
artistId
|
||||||
|
@ -104,7 +91,6 @@ class ArtistDetailsSeasonConnector extends Component {
|
||||||
|
|
||||||
ArtistDetailsSeasonConnector.propTypes = {
|
ArtistDetailsSeasonConnector.propTypes = {
|
||||||
artistId: PropTypes.number.isRequired,
|
artistId: PropTypes.number.isRequired,
|
||||||
toggleSeasonMonitored: PropTypes.func.isRequired,
|
|
||||||
toggleEpisodesMonitored: PropTypes.func.isRequired,
|
toggleEpisodesMonitored: PropTypes.func.isRequired,
|
||||||
setEpisodesTableOption: PropTypes.func.isRequired,
|
setEpisodesTableOption: PropTypes.func.isRequired,
|
||||||
executeCommand: PropTypes.func.isRequired
|
executeCommand: PropTypes.func.isRequired
|
||||||
|
|
|
@ -214,6 +214,7 @@ class ArtistIndex extends Component {
|
||||||
|
|
||||||
const ViewComponent = getViewComponent(view);
|
const ViewComponent = getViewComponent(view);
|
||||||
const isLoaded = !error && isPopulated && !!items.length && contentBody;
|
const isLoaded = !error && isPopulated && !!items.length && contentBody;
|
||||||
|
const hasNoArtist = !items.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent>
|
<PageContent>
|
||||||
|
@ -224,6 +225,7 @@ class ArtistIndex extends Component {
|
||||||
iconName={icons.REFRESH}
|
iconName={icons.REFRESH}
|
||||||
spinningName={icons.REFRESH}
|
spinningName={icons.REFRESH}
|
||||||
isSpinning={isRefreshingArtist}
|
isSpinning={isRefreshingArtist}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onPress={onRefreshArtistPress}
|
onPress={onRefreshArtistPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -231,6 +233,7 @@ class ArtistIndex extends Component {
|
||||||
label="RSS Sync"
|
label="RSS Sync"
|
||||||
iconName={icons.RSS}
|
iconName={icons.RSS}
|
||||||
isSpinning={isRssSyncExecuting}
|
isSpinning={isRssSyncExecuting}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onPress={onRssSyncPress}
|
onPress={onRssSyncPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -246,6 +249,7 @@ class ArtistIndex extends Component {
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Options"
|
label="Options"
|
||||||
iconName={icons.POSTER}
|
iconName={icons.POSTER}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onPress={this.onPosterOptionsPress}
|
onPress={this.onPosterOptionsPress}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -255,6 +259,7 @@ class ArtistIndex extends Component {
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Options"
|
label="Options"
|
||||||
iconName={icons.POSTER}
|
iconName={icons.POSTER}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onPress={this.onBannerOptionsPress}
|
onPress={this.onBannerOptionsPress}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -264,6 +269,7 @@ class ArtistIndex extends Component {
|
||||||
<PageToolbarButton
|
<PageToolbarButton
|
||||||
label="Options"
|
label="Options"
|
||||||
iconName={icons.OVERVIEW}
|
iconName={icons.OVERVIEW}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onPress={this.onOverviewOptionsPress}
|
onPress={this.onOverviewOptionsPress}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -276,18 +282,21 @@ class ArtistIndex extends Component {
|
||||||
|
|
||||||
<ArtistIndexViewMenu
|
<ArtistIndexViewMenu
|
||||||
view={view}
|
view={view}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onViewSelect={onViewSelect}
|
onViewSelect={onViewSelect}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ArtistIndexSortMenu
|
<ArtistIndexSortMenu
|
||||||
sortKey={sortKey}
|
sortKey={sortKey}
|
||||||
sortDirection={sortDirection}
|
sortDirection={sortDirection}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onSortSelect={onSortSelect}
|
onSortSelect={onSortSelect}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ArtistIndexFilterMenu
|
<ArtistIndexFilterMenu
|
||||||
filterKey={filterKey}
|
filterKey={filterKey}
|
||||||
filterValue={filterValue}
|
filterValue={filterValue}
|
||||||
|
isDisabled={hasNoArtist}
|
||||||
onFilterSelect={onFilterSelect}
|
onFilterSelect={onFilterSelect}
|
||||||
/>
|
/>
|
||||||
</PageToolbarSection>
|
</PageToolbarSection>
|
||||||
|
|
|
@ -9,11 +9,15 @@ function ArtistIndexFilterMenu(props) {
|
||||||
const {
|
const {
|
||||||
filterKey,
|
filterKey,
|
||||||
filterValue,
|
filterValue,
|
||||||
|
isDisabled,
|
||||||
onFilterSelect
|
onFilterSelect
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilterMenu alignMenu={align.RIGHT}>
|
<FilterMenu
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
alignMenu={align.RIGHT}
|
||||||
|
>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
<FilterMenuItem
|
<FilterMenuItem
|
||||||
filterKey={filterKey}
|
filterKey={filterKey}
|
||||||
|
@ -70,6 +74,7 @@ function ArtistIndexFilterMenu(props) {
|
||||||
ArtistIndexFilterMenu.propTypes = {
|
ArtistIndexFilterMenu.propTypes = {
|
||||||
filterKey: PropTypes.string,
|
filterKey: PropTypes.string,
|
||||||
filterValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.number, PropTypes.string]),
|
filterValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.number, PropTypes.string]),
|
||||||
|
isDisabled: PropTypes.bool.isRequired,
|
||||||
onFilterSelect: PropTypes.func.isRequired
|
onFilterSelect: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,15 @@ function ArtistIndexSortMenu(props) {
|
||||||
const {
|
const {
|
||||||
sortKey,
|
sortKey,
|
||||||
sortDirection,
|
sortDirection,
|
||||||
|
isDisabled,
|
||||||
onSortSelect
|
onSortSelect
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SortMenu alignMenu={align.RIGHT}>
|
<SortMenu
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
alignMenu={align.RIGHT}
|
||||||
|
>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
<SortMenuItem
|
<SortMenuItem
|
||||||
name="sortName"
|
name="sortName"
|
||||||
|
@ -148,6 +152,7 @@ function ArtistIndexSortMenu(props) {
|
||||||
ArtistIndexSortMenu.propTypes = {
|
ArtistIndexSortMenu.propTypes = {
|
||||||
sortKey: PropTypes.string,
|
sortKey: PropTypes.string,
|
||||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
sortDirection: PropTypes.oneOf(sortDirections.all),
|
||||||
|
isDisabled: PropTypes.bool.isRequired,
|
||||||
onSortSelect: PropTypes.func.isRequired
|
onSortSelect: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,15 @@ import ViewMenuItem from 'Components/Menu/ViewMenuItem';
|
||||||
function ArtistIndexViewMenu(props) {
|
function ArtistIndexViewMenu(props) {
|
||||||
const {
|
const {
|
||||||
view,
|
view,
|
||||||
|
isDisabled,
|
||||||
onViewSelect
|
onViewSelect
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewMenu alignMenu={align.RIGHT}>
|
<ViewMenu
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
alignMenu={align.RIGHT}
|
||||||
|
>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
<ViewMenuItem
|
<ViewMenuItem
|
||||||
name="table"
|
name="table"
|
||||||
|
@ -52,6 +56,7 @@ function ArtistIndexViewMenu(props) {
|
||||||
|
|
||||||
ArtistIndexViewMenu.propTypes = {
|
ArtistIndexViewMenu.propTypes = {
|
||||||
view: PropTypes.string.isRequired,
|
view: PropTypes.string.isRequired,
|
||||||
|
isDisabled: PropTypes.bool.isRequired,
|
||||||
onViewSelect: PropTypes.func.isRequired
|
onViewSelect: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ $hoverScale: 1.05;
|
||||||
.titleRow {
|
.titleRow {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
flex: 0 0 auto;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,14 @@ const columnPaddingSmallScreen = parseInt(dimensions.artistIndexColumnPaddingSma
|
||||||
const defaultFontSize = parseInt(fonts.defaultFontSize);
|
const defaultFontSize = parseInt(fonts.defaultFontSize);
|
||||||
const lineHeight = parseFloat(fonts.lineHeight);
|
const lineHeight = parseFloat(fonts.lineHeight);
|
||||||
|
|
||||||
function calculateHeight(rowHeight, isSmallScreen) {
|
// Hardcoded height beased on line-height of 32 + bottom margin of 10.
|
||||||
let height = rowHeight - 45;
|
// Less side-effecty than using react-measure.
|
||||||
|
const titleRowHeight = 42;
|
||||||
|
|
||||||
if (isSmallScreen) {
|
function getContentHeight(rowHeight, isSmallScreen) {
|
||||||
height -= columnPaddingSmallScreen;
|
const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding;
|
||||||
} else {
|
|
||||||
height -= columnPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
return height;
|
return rowHeight - padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArtistIndexOverview extends Component {
|
class ArtistIndexOverview extends Component {
|
||||||
|
@ -109,7 +107,8 @@ class ArtistIndexOverview extends Component {
|
||||||
height: `${posterHeight}px`
|
height: `${posterHeight}px`
|
||||||
};
|
};
|
||||||
|
|
||||||
const height = calculateHeight(rowHeight, isSmallScreen);
|
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
|
||||||
|
const overviewHeight = contentHeight - titleRowHeight;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container} style={style}>
|
<div className={styles.container} style={style}>
|
||||||
|
@ -150,7 +149,7 @@ class ArtistIndexOverview extends Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.info}>
|
<div className={styles.info} style={{ maxHeight: contentHeight }}>
|
||||||
<div className={styles.titleRow}>
|
<div className={styles.titleRow}>
|
||||||
<Link
|
<Link
|
||||||
className={styles.title}
|
className={styles.title}
|
||||||
|
@ -182,13 +181,13 @@ class ArtistIndexOverview extends Component {
|
||||||
to={link}
|
to={link}
|
||||||
>
|
>
|
||||||
<TextTruncate
|
<TextTruncate
|
||||||
line={Math.floor(height / (defaultFontSize * lineHeight))}
|
line={Math.floor(overviewHeight / (defaultFontSize * lineHeight))}
|
||||||
text={overview}
|
text={overview}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<ArtistIndexOverviewInfo
|
<ArtistIndexOverviewInfo
|
||||||
height={height}
|
height={overviewHeight}
|
||||||
nextAiring={nextAiring}
|
nextAiring={nextAiring}
|
||||||
qualityProfile={qualityProfile}
|
qualityProfile={qualityProfile}
|
||||||
showRelativeDates={showRelativeDates}
|
showRelativeDates={showRelativeDates}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||||
import MenuContent from 'Components/Menu/MenuContent';
|
import MenuContent from 'Components/Menu/MenuContent';
|
||||||
import FilterMenuItem from 'Components/Menu/FilterMenuItem';
|
import FilterMenuItem from 'Components/Menu/FilterMenuItem';
|
||||||
|
import NoArtist from 'Artist/NoArtist';
|
||||||
import CalendarLinkModal from './iCal/CalendarLinkModal';
|
import CalendarLinkModal from './iCal/CalendarLinkModal';
|
||||||
import Legend from './Legend/Legend';
|
import Legend from './Legend/Legend';
|
||||||
import CalendarConnector from './CalendarConnector';
|
import CalendarConnector from './CalendarConnector';
|
||||||
|
@ -59,9 +60,17 @@ class CalendarPage extends Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
unmonitored,
|
unmonitored,
|
||||||
|
hasArtist,
|
||||||
colorImpairedMode
|
colorImpairedMode
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
const isMeasured = this.state.width > 0;
|
||||||
|
let PageComponent = 'div';
|
||||||
|
|
||||||
|
if (isMeasured) {
|
||||||
|
PageComponent = hasArtist ? CalendarConnector : NoArtist;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent title="Calendar">
|
<PageContent title="Calendar">
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
|
@ -74,7 +83,10 @@ class CalendarPage extends Component {
|
||||||
</PageToolbarSection>
|
</PageToolbarSection>
|
||||||
|
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
<PageToolbarSection alignContent={align.RIGHT}>
|
||||||
<FilterMenu alignMenu={align.RIGHT}>
|
<FilterMenu
|
||||||
|
alignMenu={align.RIGHT}
|
||||||
|
isDisabled={!hasArtist}
|
||||||
|
>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
<FilterMenuItem
|
<FilterMenuItem
|
||||||
name="unmonitored"
|
name="unmonitored"
|
||||||
|
@ -108,14 +120,13 @@ class CalendarPage extends Component {
|
||||||
whitelist={['width']}
|
whitelist={['width']}
|
||||||
onMeasure={this.onMeasure}
|
onMeasure={this.onMeasure}
|
||||||
>
|
>
|
||||||
{
|
<PageComponent />
|
||||||
this.state.width > 0 ?
|
|
||||||
<CalendarConnector /> :
|
|
||||||
<div />
|
|
||||||
}
|
|
||||||
</Measure>
|
</Measure>
|
||||||
|
|
||||||
<Legend colorImpairedMode={colorImpairedMode} />
|
{
|
||||||
|
hasArtist &&
|
||||||
|
<Legend colorImpairedMode={colorImpairedMode} />
|
||||||
|
}
|
||||||
</PageContentBodyConnector>
|
</PageContentBodyConnector>
|
||||||
|
|
||||||
<CalendarLinkModal
|
<CalendarLinkModal
|
||||||
|
@ -129,6 +140,7 @@ class CalendarPage extends Component {
|
||||||
|
|
||||||
CalendarPage.propTypes = {
|
CalendarPage.propTypes = {
|
||||||
unmonitored: PropTypes.bool.isRequired,
|
unmonitored: PropTypes.bool.isRequired,
|
||||||
|
hasArtist: PropTypes.bool.isRequired,
|
||||||
colorImpairedMode: PropTypes.bool.isRequired,
|
colorImpairedMode: PropTypes.bool.isRequired,
|
||||||
onDaysCountChange: PropTypes.func.isRequired,
|
onDaysCountChange: PropTypes.func.isRequired,
|
||||||
onUnmonitoredChange: PropTypes.func.isRequired
|
onUnmonitoredChange: PropTypes.func.isRequired
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { setCalendarDaysCount, setCalendarIncludeUnmonitored } from 'Store/Actions/calendarActions';
|
import { setCalendarDaysCount, setCalendarIncludeUnmonitored } from 'Store/Actions/calendarActions';
|
||||||
|
import createArtistCountSelector from 'Store/Selectors/createArtistCountSelector';
|
||||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||||
import CalendarPage from './CalendarPage';
|
import CalendarPage from './CalendarPage';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
(state) => state.calendar,
|
(state) => state.calendar,
|
||||||
|
createArtistCountSelector(),
|
||||||
createUISettingsSelector(),
|
createUISettingsSelector(),
|
||||||
(calendar, uiSettings) => {
|
(calendar, artistCount, uiSettings) => {
|
||||||
return {
|
return {
|
||||||
unmonitored: calendar.unmonitored,
|
unmonitored: calendar.unmonitored,
|
||||||
showUpcoming: calendar.showUpcoming,
|
showUpcoming: calendar.showUpcoming,
|
||||||
colorImpairedMode: uiSettings.enableColorImpairedMode
|
colorImpairedMode: uiSettings.enableColorImpairedMode,
|
||||||
|
hasArtist: !!artistCount
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,11 +55,17 @@
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsInnerModalBody {
|
.optionsModalBody {
|
||||||
composes: innerModalBody from 'Components/Modal/ModalBody.css';
|
composes: modalBody from 'Components/Modal/ModalBody.css';
|
||||||
|
|
||||||
padding: 0;
|
display: flex;
|
||||||
width: 100%;
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsModalScroller {
|
||||||
|
composes: scroller from 'Components/Scroller/Scroller.css';
|
||||||
border: 1px solid $inputBorderColor;
|
border: 1px solid $inputBorderColor;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
|
|
|
@ -7,11 +7,12 @@ import TetherComponent from 'react-tether';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import isMobileUtil from 'Utilities/isMobile';
|
import isMobileUtil from 'Utilities/isMobile';
|
||||||
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons, scrollDirections } from 'Helpers/Props';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import Modal from 'Components/Modal/Modal';
|
import Modal from 'Components/Modal/Modal';
|
||||||
import ModalBody from 'Components/Modal/ModalBody';
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
|
import Scroller from 'Components/Scroller/Scroller';
|
||||||
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue';
|
import EnhancedSelectInputSelectedValue from './EnhancedSelectInputSelectedValue';
|
||||||
import EnhancedSelectInputOption from './EnhancedSelectInputOption';
|
import EnhancedSelectInputOption from './EnhancedSelectInputOption';
|
||||||
import styles from './EnhancedSelectInput.css';
|
import styles from './EnhancedSelectInput.css';
|
||||||
|
@ -346,24 +347,28 @@ class EnhancedSelectInput extends Component {
|
||||||
onModalClose={this.onOptionsModalClose}
|
onModalClose={this.onOptionsModalClose}
|
||||||
>
|
>
|
||||||
<ModalBody
|
<ModalBody
|
||||||
|
className={styles.optionsModalBody}
|
||||||
innerClassName={styles.optionsInnerModalBody}
|
innerClassName={styles.optionsInnerModalBody}
|
||||||
|
scrollDirection={scrollDirections.NONE}
|
||||||
>
|
>
|
||||||
{
|
<Scroller className={styles.optionsModalScroller}>
|
||||||
values.map((v, index) => {
|
{
|
||||||
return (
|
values.map((v, index) => {
|
||||||
<OptionComponent
|
return (
|
||||||
key={v.key}
|
<OptionComponent
|
||||||
id={v.key}
|
key={v.key}
|
||||||
isSelected={index === selectedIndex}
|
id={v.key}
|
||||||
{...v}
|
isSelected={index === selectedIndex}
|
||||||
isMobile={true}
|
{...v}
|
||||||
onSelect={this.onSelect}
|
isMobile={true}
|
||||||
>
|
onSelect={this.onSelect}
|
||||||
{v.value}
|
>
|
||||||
</OptionComponent>
|
{v.value}
|
||||||
);
|
</OptionComponent>
|
||||||
})
|
);
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
</Scroller>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ function FilterMenu(props) {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
|
isDisabled,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ function FilterMenu(props) {
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
iconName={icons.FILTER}
|
iconName={icons.FILTER}
|
||||||
text="Filter"
|
text="Filter"
|
||||||
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
@ -28,11 +30,13 @@ function FilterMenu(props) {
|
||||||
|
|
||||||
FilterMenu.propTypes = {
|
FilterMenu.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
children: PropTypes.node.isRequired
|
children: PropTypes.node.isRequired,
|
||||||
|
isDisabled: PropTypes.bool.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterMenu.defaultProps = {
|
FilterMenu.defaultProps = {
|
||||||
className: styles.filterMenu
|
className: styles.filterMenu,
|
||||||
|
isDisabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FilterMenu;
|
export default FilterMenu;
|
||||||
|
|
|
@ -13,3 +13,7 @@
|
||||||
color: $toobarButtonHoverColor;
|
color: $toobarButtonHoverColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.isDisabled {
|
||||||
|
color: $disabledColor;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import styles from './MenuButton.css';
|
import styles from './MenuButton.css';
|
||||||
|
|
||||||
|
@ -12,13 +13,18 @@ class MenuButton extends Component {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
|
isDisabled,
|
||||||
onPress,
|
onPress,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className={className}
|
className={classNames(
|
||||||
|
className,
|
||||||
|
isDisabled && styles.isDisabled
|
||||||
|
)}
|
||||||
|
isDisabled={isDisabled}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
>
|
>
|
||||||
|
@ -31,11 +37,13 @@ class MenuButton extends Component {
|
||||||
MenuButton.propTypes = {
|
MenuButton.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
|
isDisabled: PropTypes.bool.isRequired,
|
||||||
onPress: PropTypes.func
|
onPress: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
MenuButton.defaultProps = {
|
MenuButton.defaultProps = {
|
||||||
className: styles.menuButton
|
className: styles.menuButton,
|
||||||
|
isDisabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MenuButton;
|
export default MenuButton;
|
||||||
|
|
|
@ -8,6 +8,7 @@ function SortMenu(props) {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
|
isDisabled,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ function SortMenu(props) {
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
iconName={icons.SORT}
|
iconName={icons.SORT}
|
||||||
text="Sort"
|
text="Sort"
|
||||||
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
@ -27,7 +29,12 @@ function SortMenu(props) {
|
||||||
|
|
||||||
SortMenu.propTypes = {
|
SortMenu.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
children: PropTypes.node.isRequired
|
children: PropTypes.node.isRequired,
|
||||||
|
isDisabled: PropTypes.bool.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
SortMenu.defaultProps = {
|
||||||
|
isDisabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SortMenu;
|
export default SortMenu;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ToolbarMenuButton from 'Components/Menu/ToolbarMenuButton';
|
||||||
function ViewMenu(props) {
|
function ViewMenu(props) {
|
||||||
const {
|
const {
|
||||||
children,
|
children,
|
||||||
|
isDisabled,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ function ViewMenu(props) {
|
||||||
<ToolbarMenuButton
|
<ToolbarMenuButton
|
||||||
iconName={icons.VIEW}
|
iconName={icons.VIEW}
|
||||||
text="View"
|
text="View"
|
||||||
|
isDisabled={isDisabled}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
@ -24,7 +26,12 @@ function ViewMenu(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewMenu.propTypes = {
|
ViewMenu.propTypes = {
|
||||||
children: PropTypes.node.isRequired
|
children: PropTypes.node.isRequired,
|
||||||
|
isDisabled: PropTypes.bool.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
ViewMenu.defaultProps = {
|
||||||
|
isDisabled: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ViewMenu;
|
export default ViewMenu;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
.poster {
|
.poster {
|
||||||
width: 35px;
|
width: 35px;
|
||||||
height: 50px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titles {
|
.titles {
|
||||||
|
|
|
@ -72,7 +72,7 @@ class SignalRConnector extends Component {
|
||||||
|
|
||||||
this.signalRconnectionOptions = { transport: ['webSockets', 'longPolling'] };
|
this.signalRconnectionOptions = { transport: ['webSockets', 'longPolling'] };
|
||||||
this.signalRconnection = null;
|
this.signalRconnection = null;
|
||||||
this.retryInterval = 5;
|
this.retryInterval = 1;
|
||||||
this.retryTimeoutId = null;
|
this.retryTimeoutId = null;
|
||||||
this.disconnectedTime = null;
|
this.disconnectedTime = null;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ class SignalRConnector extends Component {
|
||||||
|
|
||||||
this.retryTimeoutId = setTimeout(() => {
|
this.retryTimeoutId = setTimeout(() => {
|
||||||
this.signalRconnection.start(this.signalRconnectionOptions);
|
this.signalRconnection.start(this.signalRconnectionOptions);
|
||||||
this.retryInterval = Math.min(this.retryInterval + 5, 30);
|
this.retryInterval = Math.min(this.retryInterval + 1, 10);
|
||||||
}, this.retryInterval * 1000);
|
}, this.retryInterval * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ class SignalRConnector extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleQueueStatus = (body) => {
|
handleQueueStatus = (body) => {
|
||||||
this.props.update({ section: 'queueStatus', data: body.resource });
|
this.props.update({ section: 'queue.status', data: body.resource });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVersion = (body) => {
|
handleVersion = (body) => {
|
||||||
|
|
|
@ -97,5 +97,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
{ section: 'interactiveImport.interactiveImportAlbums' }
|
{ section: 'interactiveImport.albums' }
|
||||||
)(SelectAlbumModalContentConnector);
|
)(SelectAlbumModalContentConnector);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { cancelTestDownloadClient, cancelSaveDownloadClient } from 'Store/Action
|
||||||
import EditDownloadClientModal from './EditDownloadClientModal';
|
import EditDownloadClientModal from './EditDownloadClientModal';
|
||||||
|
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
const section = 'downloadClients';
|
const section = 'settings.downloadClients';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dispatchClearPendingChanges() {
|
dispatchClearPendingChanges() {
|
||||||
|
|
|
@ -88,5 +88,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
{ withRef: true },
|
{ withRef: true },
|
||||||
{ section: 'downloadClientOptions' }
|
{ section: 'settings.downloadClientOptions' }
|
||||||
)(DownloadClientOptionsConnector);
|
)(DownloadClientOptionsConnector);
|
||||||
|
|
|
@ -18,7 +18,7 @@ class EditRemotePathMappingModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'remotePathMappings' });
|
this.props.clearPendingChanges({ section: 'settings.remotePathMappings' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,5 +113,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
{ section: 'general' }
|
{ section: 'settings.general' }
|
||||||
)(GeneralSettingsConnector);
|
)(GeneralSettingsConnector);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { cancelTestIndexer, cancelSaveIndexer } from 'Store/Actions/settingsActi
|
||||||
import EditIndexerModal from './EditIndexerModal';
|
import EditIndexerModal from './EditIndexerModal';
|
||||||
|
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
const section = 'indexers';
|
const section = 'settings.indexers';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dispatchClearPendingChanges() {
|
dispatchClearPendingChanges() {
|
||||||
|
|
|
@ -88,5 +88,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
{ withRef: true },
|
{ withRef: true },
|
||||||
{ section: 'indexerOptions' }
|
{ section: 'settings.indexerOptions' }
|
||||||
)(IndexerOptionsConnector);
|
)(IndexerOptionsConnector);
|
||||||
|
|
|
@ -14,7 +14,7 @@ class EditRestrictionModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'restrictions' });
|
this.props.clearPendingChanges({ section: 'settings.restrictions' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,5 +87,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
{ section: 'mediaManagement' }
|
{ section: 'settings.mediaManagement' }
|
||||||
)(MediaManagementConnector);
|
)(MediaManagementConnector);
|
||||||
|
|
|
@ -98,5 +98,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
{ section: 'naming' }
|
{ section: 'settings.naming' }
|
||||||
)(NamingConnector);
|
)(NamingConnector);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||||
import EditMetadataModal from './EditMetadataModal';
|
import EditMetadataModal from './EditMetadataModal';
|
||||||
|
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
const section = 'metadata';
|
const section = 'settings.metadata';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dispatchClearPendingChanges() {
|
dispatchClearPendingChanges() {
|
||||||
|
|
|
@ -84,9 +84,9 @@ MetadataProviderConnector.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connectSection(
|
export default connectSection(
|
||||||
createMapStateToProps,
|
createMapStateToProps,
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
{ withRef: true },
|
{ withRef: true },
|
||||||
{ section: 'metadataProvider' }
|
{ section: 'settings.metadataProvider' }
|
||||||
)(MetadataProviderConnector);
|
)(MetadataProviderConnector);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { cancelTestNotification, cancelSaveNotification } from 'Store/Actions/se
|
||||||
import EditNotificationModal from './EditNotificationModal';
|
import EditNotificationModal from './EditNotificationModal';
|
||||||
|
|
||||||
function createMapDispatchToProps(dispatch, props) {
|
function createMapDispatchToProps(dispatch, props) {
|
||||||
const section = 'notifications';
|
const section = 'settings.notifications';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dispatchClearPendingChanges() {
|
dispatchClearPendingChanges() {
|
||||||
|
|
|
@ -18,7 +18,7 @@ class EditDelayProfileModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'delayProfiles' });
|
this.props.clearPendingChanges({ section: 'settings.delayProfiles' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class EditLanguageProfileModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'languageProfiles' });
|
this.props.clearPendingChanges({ section: 'settings.languageProfiles' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class EditMetadataProfileModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'metadataProfiles' });
|
this.props.clearPendingChanges({ section: 'settings.metadataProfiles' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class EditQualityProfileModalConnector extends Component {
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onModalClose = () => {
|
onModalClose = () => {
|
||||||
this.props.clearPendingChanges({ section: 'qualityProfiles' });
|
this.props.clearPendingChanges({ section: 'settings.qualityProfiles' });
|
||||||
this.props.onModalClose();
|
this.props.onModalClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ const mapDispatchToProps = {
|
||||||
class QualityDefinitionConnector extends Component {
|
class QualityDefinitionConnector extends Component {
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.props.clearPendingChanges({ section: 'qualityDefinitions' });
|
this.props.clearPendingChanges({ section: 'settings.qualityDefinitions' });
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -78,5 +78,5 @@ export default connectSection(
|
||||||
mapDispatchToProps,
|
mapDispatchToProps,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
{ section: 'ui' }
|
{ section: 'settings.ui' }
|
||||||
)(UISettingsConnector);
|
)(UISettingsConnector);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import updateAlbums from 'Utilities/Album/updateAlbums';
|
import updateAlbums from 'Utilities/Album/updateAlbums';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
|
||||||
function createBatchToggleAlbumMonitoredHandler(section, getFromState) {
|
function createBatchToggleAlbumMonitoredHandler(section) {
|
||||||
return function(payload) {
|
return function(payload) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const {
|
const {
|
||||||
|
@ -9,7 +10,7 @@ function createBatchToggleAlbumMonitoredHandler(section, getFromState) {
|
||||||
monitored
|
monitored
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
const state = getFromState(getState());
|
const state = getSectionState(getState(), section, true);
|
||||||
|
|
||||||
updateAlbums(dispatch, section, state.items, albumIds, {
|
updateAlbums(dispatch, section, state.items, albumIds, {
|
||||||
isSaving: true
|
isSaving: true
|
||||||
|
|
|
@ -2,47 +2,43 @@ import { batchActions } from 'redux-batched-actions';
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
import { set, update, updateItem } from '../baseActions';
|
import { set, update, updateItem } from '../baseActions';
|
||||||
|
|
||||||
function createFetchHandler(section, url) {
|
export default function createFetchHandler(section, url) {
|
||||||
return function(payload = {}) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isFetching: true }));
|
||||||
dispatch(set({ section, isFetching: true }));
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
id,
|
id,
|
||||||
...otherPayload
|
...otherPayload
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
const { request, abortRequest } = createAjaxRequest({
|
const { request, abortRequest } = createAjaxRequest({
|
||||||
url: id == null ? url : `${url}/${id}`,
|
url: id == null ? url : `${url}/${id}`,
|
||||||
data: otherPayload,
|
data: otherPayload,
|
||||||
traditional: true
|
traditional: true
|
||||||
});
|
});
|
||||||
|
|
||||||
request.done((data) => {
|
request.done((data) => {
|
||||||
dispatch(batchActions([
|
dispatch(batchActions([
|
||||||
id == null ? update({ section, data }) : updateItem({ section, ...data }),
|
id == null ? update({ section, data }) : updateItem({ section, ...data }),
|
||||||
|
|
||||||
set({
|
set({
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: true,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
request.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
section,
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
isPopulated: false,
|
isPopulated: true,
|
||||||
error: xhr.aborted ? null : xhr
|
error: null
|
||||||
}));
|
})
|
||||||
});
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
return abortRequest;
|
request.fail((xhr) => {
|
||||||
};
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr.aborted ? null : xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return abortRequest;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createFetchHandler;
|
|
||||||
|
|
|
@ -2,33 +2,31 @@ import $ from 'jquery';
|
||||||
import { set } from '../baseActions';
|
import { set } from '../baseActions';
|
||||||
|
|
||||||
function createFetchSchemaHandler(section, url) {
|
function createFetchSchemaHandler(section, url) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isFetchingSchema: true }));
|
||||||
dispatch(set({ section, isFetchingSchema: true }));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
const promise = $.ajax({
|
||||||
url
|
url
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.done((data) => {
|
promise.done((data) => {
|
||||||
dispatch(set({
|
dispatch(set({
|
||||||
section,
|
section,
|
||||||
isFetchingSchema: false,
|
isFetchingSchema: false,
|
||||||
schemaPopulated: true,
|
schemaPopulated: true,
|
||||||
schemaError: null,
|
schemaError: null,
|
||||||
schema: data
|
schema: data
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
promise.fail((xhr) => {
|
||||||
dispatch(set({
|
dispatch(set({
|
||||||
section,
|
section,
|
||||||
isFetchingSchema: false,
|
isFetchingSchema: false,
|
||||||
schemaPopulated: true,
|
schemaPopulated: true,
|
||||||
schemaError: xhr
|
schemaError: xhr
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,53 +1,51 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { batchActions } from 'redux-batched-actions';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
import { set, updateServerSideCollection } from '../baseActions';
|
import { set, updateServerSideCollection } from '../baseActions';
|
||||||
|
|
||||||
function createFetchServerSideCollectionHandler(section, url, getFromState) {
|
function createFetchServerSideCollectionHandler(section, url) {
|
||||||
return function(payload = {}) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isFetching: true }));
|
||||||
dispatch(set({ section, isFetching: true }));
|
|
||||||
|
|
||||||
const state = getFromState(getState());
|
const sectionState = getSectionState(getState(), section, true);
|
||||||
const sectionState = state.hasOwnProperty(section) ? state[section] : state;
|
const page = payload.page || sectionState.page || 1;
|
||||||
const page = payload.page || sectionState.page || 1;
|
|
||||||
|
|
||||||
const data = Object.assign({ page },
|
const data = Object.assign({ page },
|
||||||
_.pick(sectionState, [
|
_.pick(sectionState, [
|
||||||
'pageSize',
|
'pageSize',
|
||||||
'sortDirection',
|
'sortDirection',
|
||||||
'sortKey',
|
'sortKey',
|
||||||
'filterKey',
|
'filterKey',
|
||||||
'filterValue'
|
'filterValue'
|
||||||
]));
|
]));
|
||||||
|
|
||||||
const promise = $.ajax({
|
const promise = $.ajax({
|
||||||
url,
|
url,
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.done((response) => {
|
promise.done((response) => {
|
||||||
dispatch(batchActions([
|
dispatch(batchActions([
|
||||||
updateServerSideCollection({ section, data: response }),
|
updateServerSideCollection({ section, data: response }),
|
||||||
|
|
||||||
set({
|
set({
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: true,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
section,
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
isPopulated: false,
|
isPopulated: true,
|
||||||
error: xhr
|
error: null
|
||||||
}));
|
})
|
||||||
});
|
]));
|
||||||
};
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
143
frontend/src/Store/Actions/Creators/createHandleActions.js
Normal file
143
frontend/src/Store/Actions/Creators/createHandleActions.js
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { handleActions } from 'redux-actions';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
import {
|
||||||
|
SET,
|
||||||
|
UPDATE,
|
||||||
|
UPDATE_ITEM,
|
||||||
|
UPDATE_SERVER_SIDE_COLLECTION,
|
||||||
|
CLEAR_PENDING_CHANGES,
|
||||||
|
REMOVE_ITEM
|
||||||
|
} from 'Store/Actions/baseActions';
|
||||||
|
|
||||||
|
const blacklistedProperties = [
|
||||||
|
'section',
|
||||||
|
'id'
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function createHandleActions(handlers, defaultState, section) {
|
||||||
|
return handleActions({
|
||||||
|
|
||||||
|
[SET]: function(state, { payload }) {
|
||||||
|
const payloadSection = payload.section;
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const newState = Object.assign(getSectionState(state, payloadSection),
|
||||||
|
_.omit(payload, blacklistedProperties));
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
[UPDATE]: function(state, { payload }) {
|
||||||
|
const payloadSection = payload.section;
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const newState = getSectionState(state, payloadSection);
|
||||||
|
|
||||||
|
if (_.isArray(payload.data)) {
|
||||||
|
newState.items = payload.data;
|
||||||
|
} else {
|
||||||
|
newState.item = payload.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
[UPDATE_ITEM]: function(state, { payload }) {
|
||||||
|
const {
|
||||||
|
section: payloadSection,
|
||||||
|
updateOnly = false,
|
||||||
|
...otherProps
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const newState = getSectionState(state, payloadSection);
|
||||||
|
const items = newState.items;
|
||||||
|
const index = _.findIndex(items, { id: payload.id });
|
||||||
|
|
||||||
|
newState.items = [...items];
|
||||||
|
|
||||||
|
// TODO: Move adding to it's own reducer
|
||||||
|
if (index >= 0) {
|
||||||
|
const item = items[index];
|
||||||
|
|
||||||
|
newState.items.splice(index, 1, { ...item, ...otherProps });
|
||||||
|
} else if (!updateOnly) {
|
||||||
|
newState.items.push({ ...otherProps });
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
[CLEAR_PENDING_CHANGES]: function(state, { payload }) {
|
||||||
|
const payloadSection = payload.section;
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const newState = getSectionState(state, payloadSection);
|
||||||
|
newState.pendingChanges = {};
|
||||||
|
|
||||||
|
if (newState.hasOwnProperty('saveError')) {
|
||||||
|
newState.saveError = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
[REMOVE_ITEM]: function(state, { payload }) {
|
||||||
|
const payloadSection = payload.section;
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const newState = getSectionState(state, payloadSection);
|
||||||
|
|
||||||
|
newState.items = [...newState.items];
|
||||||
|
_.remove(newState.items, { id: payload.id });
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
[UPDATE_SERVER_SIDE_COLLECTION]: function(state, { payload }) {
|
||||||
|
const payloadSection = payload.section;
|
||||||
|
const [baseSection] = payloadSection.split('.');
|
||||||
|
|
||||||
|
if (section === baseSection) {
|
||||||
|
const data = payload.data;
|
||||||
|
const newState = getSectionState(state, payloadSection);
|
||||||
|
|
||||||
|
const serverState = _.omit(data, ['records']);
|
||||||
|
const calculatedState = {
|
||||||
|
totalPages: Math.max(Math.ceil(data.totalRecords / data.pageSize), 1),
|
||||||
|
items: data.records
|
||||||
|
};
|
||||||
|
|
||||||
|
return updateSectionState(state, payloadSection, Object.assign(newState, serverState, calculatedState));
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
...handlers
|
||||||
|
|
||||||
|
}, defaultState);
|
||||||
|
}
|
|
@ -3,44 +3,42 @@ import { batchActions } from 'redux-batched-actions';
|
||||||
import { set, removeItem } from '../baseActions';
|
import { set, removeItem } from '../baseActions';
|
||||||
|
|
||||||
function createRemoveItemHandler(section, url) {
|
function createRemoveItemHandler(section, url) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
const {
|
||||||
const {
|
id,
|
||||||
id,
|
...queryParms
|
||||||
...queryParms
|
} = payload;
|
||||||
} = payload;
|
|
||||||
|
|
||||||
dispatch(set({ section, isDeleting: true }));
|
dispatch(set({ section, isDeleting: true }));
|
||||||
|
|
||||||
const ajaxOptions = {
|
const ajaxOptions = {
|
||||||
url: `${url}/${id}?${$.param(queryParms, true)}`,
|
url: `${url}/${id}?${$.param(queryParms, true)}`,
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
};
|
};
|
||||||
|
|
||||||
const promise = $.ajax(ajaxOptions);
|
const promise = $.ajax(ajaxOptions);
|
||||||
|
|
||||||
promise.done((data) => {
|
promise.done((data) => {
|
||||||
dispatch(batchActions([
|
dispatch(batchActions([
|
||||||
removeItem({ section, id }),
|
removeItem({ section, id }),
|
||||||
|
|
||||||
set({
|
set({
|
||||||
section,
|
|
||||||
isDeleting: false,
|
|
||||||
deleteError: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
section,
|
||||||
isDeleting: false,
|
isDeleting: false,
|
||||||
deleteError: xhr
|
deleteError: null
|
||||||
}));
|
})
|
||||||
});
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
return promise;
|
promise.fail((xhr) => {
|
||||||
};
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,42 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { batchActions } from 'redux-batched-actions';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
import { set, update } from '../baseActions';
|
import { set, update } from '../baseActions';
|
||||||
|
|
||||||
function createSaveHandler(section, url, getFromState) {
|
function createSaveHandler(section, url) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isSaving: true }));
|
||||||
dispatch(set({ section, isSaving: true }));
|
|
||||||
|
|
||||||
const state = getFromState(getState());
|
const state = getSectionState(getState(), section, true);
|
||||||
const saveData = Object.assign({}, state.item, state.pendingChanges);
|
const saveData = Object.assign({}, state.item, state.pendingChanges);
|
||||||
|
|
||||||
const promise = $.ajax({
|
const promise = $.ajax({
|
||||||
url,
|
url,
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: JSON.stringify(saveData)
|
data: JSON.stringify(saveData)
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.done((data) => {
|
promise.done((data) => {
|
||||||
dispatch(batchActions([
|
dispatch(batchActions([
|
||||||
update({ section, data }),
|
update({ section, data }),
|
||||||
|
|
||||||
set({
|
set({
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: null,
|
|
||||||
pendingChanges: {}
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
section,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
saveError: xhr
|
saveError: null,
|
||||||
}));
|
pendingChanges: {}
|
||||||
});
|
})
|
||||||
};
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,62 +6,58 @@ import { set, updateItem } from '../baseActions';
|
||||||
const abortCurrentRequests = {};
|
const abortCurrentRequests = {};
|
||||||
|
|
||||||
export function createCancelSaveProviderHandler(section) {
|
export function createCancelSaveProviderHandler(section) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
if (abortCurrentRequests[section]) {
|
||||||
if (abortCurrentRequests[section]) {
|
abortCurrentRequests[section]();
|
||||||
abortCurrentRequests[section]();
|
abortCurrentRequests[section] = null;
|
||||||
abortCurrentRequests[section] = null;
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSaveProviderHandler(section, url, getFromState) {
|
function createSaveProviderHandler(section, url) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isSaving: true }));
|
||||||
dispatch(set({ section, isSaving: true }));
|
|
||||||
|
|
||||||
const id = payload.id;
|
const id = payload.id;
|
||||||
const saveData = getProviderState(payload, getState, getFromState);
|
const saveData = getProviderState(payload, getState, section);
|
||||||
|
|
||||||
const ajaxOptions = {
|
const ajaxOptions = {
|
||||||
url,
|
url,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: JSON.stringify(saveData)
|
data: JSON.stringify(saveData)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
ajaxOptions.url = `${url}/${id}`;
|
ajaxOptions.url = `${url}/${id}`;
|
||||||
ajaxOptions.method = 'PUT';
|
ajaxOptions.method = 'PUT';
|
||||||
}
|
}
|
||||||
|
|
||||||
const { request, abortRequest } = createAjaxRequest(ajaxOptions);
|
const { request, abortRequest } = createAjaxRequest(ajaxOptions);
|
||||||
|
|
||||||
abortCurrentRequests[section] = abortRequest;
|
|
||||||
|
|
||||||
request.done((data) => {
|
abortCurrentRequests[section] = abortRequest;
|
||||||
dispatch(batchActions([
|
|
||||||
updateItem({ section, ...data }),
|
|
||||||
|
|
||||||
set({
|
request.done((data) => {
|
||||||
section,
|
dispatch(batchActions([
|
||||||
isSaving: false,
|
updateItem({ section, ...data }),
|
||||||
saveError: null,
|
|
||||||
pendingChanges: {}
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
request.fail((xhr) => {
|
set({
|
||||||
dispatch(set({
|
|
||||||
section,
|
section,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
saveError: xhr.aborted ? null : xhr
|
saveError: null,
|
||||||
}));
|
pendingChanges: {}
|
||||||
});
|
})
|
||||||
};
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
request.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: xhr.aborted ? null : xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,45 +5,45 @@ import createSetServerSideCollectionPageHandler from './createSetServerSideColle
|
||||||
import createSetServerSideCollectionSortHandler from './createSetServerSideCollectionSortHandler';
|
import createSetServerSideCollectionSortHandler from './createSetServerSideCollectionSortHandler';
|
||||||
import createSetServerSideCollectionFilterHandler from './createSetServerSideCollectionFilterHandler';
|
import createSetServerSideCollectionFilterHandler from './createSetServerSideCollectionFilterHandler';
|
||||||
|
|
||||||
function createServerSideCollectionHandlers(section, url, getFromState, handlers) {
|
function createServerSideCollectionHandlers(section, url, fetchThunk, handlers) {
|
||||||
const actionHandlers = {};
|
const actionHandlers = {};
|
||||||
const fetchHandlerType = handlers[serverSideCollectionHandlers.FETCH];
|
const fetchHandlerType = handlers[serverSideCollectionHandlers.FETCH];
|
||||||
const fetchHandler = createFetchServerSideCollectionHandler(section, url, getFromState);
|
const fetchHandler = createFetchServerSideCollectionHandler(section, url);
|
||||||
actionHandlers[fetchHandlerType] = fetchHandler;
|
actionHandlers[fetchHandlerType] = fetchHandler;
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.FIRST_PAGE)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.FIRST_PAGE)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.FIRST_PAGE];
|
const handlerType = handlers[serverSideCollectionHandlers.FIRST_PAGE];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.FIRST, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.FIRST, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.PREVIOUS_PAGE)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.PREVIOUS_PAGE)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.PREVIOUS_PAGE];
|
const handlerType = handlers[serverSideCollectionHandlers.PREVIOUS_PAGE];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.PREVIOUS, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.PREVIOUS, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.NEXT_PAGE)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.NEXT_PAGE)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.NEXT_PAGE];
|
const handlerType = handlers[serverSideCollectionHandlers.NEXT_PAGE];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.NEXT, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.NEXT, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.LAST_PAGE)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.LAST_PAGE)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.LAST_PAGE];
|
const handlerType = handlers[serverSideCollectionHandlers.LAST_PAGE];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.LAST, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.LAST, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.EXACT_PAGE)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.EXACT_PAGE)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.EXACT_PAGE];
|
const handlerType = handlers[serverSideCollectionHandlers.EXACT_PAGE];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.EXACT, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.EXACT, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.SORT)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.SORT)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.SORT];
|
const handlerType = handlers[serverSideCollectionHandlers.SORT];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionSortHandler(section, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionSortHandler(section, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers.hasOwnProperty(serverSideCollectionHandlers.FILTER)) {
|
if (handlers.hasOwnProperty(serverSideCollectionHandlers.FILTER)) {
|
||||||
const handlerType = handlers[serverSideCollectionHandlers.FILTER];
|
const handlerType = handlers[serverSideCollectionHandlers.FILTER];
|
||||||
actionHandlers[handlerType] = createSetServerSideCollectionFilterHandler(section, getFromState, fetchHandler);
|
actionHandlers[handlerType] = createSetServerSideCollectionFilterHandler(section, fetchThunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionHandlers;
|
return actionHandlers;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import { set } from '../baseActions';
|
import { set } from '../baseActions';
|
||||||
|
|
||||||
function createSetServerSideCollectionFilterHandler(section, getFromState, fetchHandler) {
|
function createSetServerSideCollectionFilterHandler(section, fetchHandler) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, ...payload }));
|
||||||
dispatch(set({ section, ...payload }));
|
dispatch(fetchHandler({ page: 1 }));
|
||||||
dispatch(fetchHandler({ page: 1 }));
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,34 @@
|
||||||
import pages from 'Utilities/pages';
|
import pages from 'Utilities/pages';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
|
||||||
function createSetServerSideCollectionPageHandler(section, page, getFromState, fetchHandler) {
|
function createSetServerSideCollectionPageHandler(section, page, fetchHandler) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
const sectionState = getSectionState(getState(), section, true);
|
||||||
const state = getFromState(getState());
|
const currentPage = sectionState.page || 1;
|
||||||
const sectionState = state.hasOwnProperty(section) ? state[section] : state;
|
let nextPage = 0;
|
||||||
const currentPage = sectionState.page || 1;
|
|
||||||
let nextPage = 0;
|
|
||||||
|
|
||||||
switch (page) {
|
switch (page) {
|
||||||
case pages.FIRST:
|
case pages.FIRST:
|
||||||
nextPage = 1;
|
nextPage = 1;
|
||||||
break;
|
break;
|
||||||
case pages.PREVIOUS:
|
case pages.PREVIOUS:
|
||||||
nextPage = currentPage - 1;
|
nextPage = currentPage - 1;
|
||||||
break;
|
break;
|
||||||
case pages.NEXT:
|
case pages.NEXT:
|
||||||
nextPage = currentPage + 1;
|
nextPage = currentPage + 1;
|
||||||
break;
|
break;
|
||||||
case pages.LAST:
|
case pages.LAST:
|
||||||
nextPage = sectionState.totalPages;
|
nextPage = sectionState.totalPages;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nextPage = payload.page;
|
nextPage = payload.page;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we prefer to update the page immediately we should
|
// If we prefer to update the page immediately we should
|
||||||
// set the page and not pass a page to the fetch handler.
|
// set the page and not pass a page to the fetch handler.
|
||||||
|
|
||||||
// dispatch(set({ section, page: nextPage }));
|
// dispatch(set({ section, page: nextPage }));
|
||||||
dispatch(fetchHandler({ page: nextPage }));
|
dispatch(fetchHandler({ page: nextPage }));
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,25 @@
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
import { sortDirections } from 'Helpers/Props';
|
import { sortDirections } from 'Helpers/Props';
|
||||||
import { set } from '../baseActions';
|
import { set } from '../baseActions';
|
||||||
|
|
||||||
function createSetServerSideCollectionSortHandler(section, getFromState, fetchHandler) {
|
function createSetServerSideCollectionSortHandler(section, fetchHandler) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
const sectionState = getSectionState(getState(), section, true);
|
||||||
const state = getFromState(getState());
|
const sortKey = payload.sortKey || sectionState.sortKey;
|
||||||
const sectionState = state.hasOwnProperty(section) ? state[section] : state;
|
let sortDirection = payload.sortDirection;
|
||||||
const sortKey = payload.sortKey || sectionState.sortKey;
|
|
||||||
let sortDirection = payload.sortDirection;
|
|
||||||
|
|
||||||
if (!sortDirection) {
|
if (!sortDirection) {
|
||||||
if (payload.sortKey === sectionState.sortKey) {
|
if (payload.sortKey === sectionState.sortKey) {
|
||||||
sortDirection = sectionState.sortDirection === sortDirections.ASCENDING ?
|
sortDirection = sectionState.sortDirection === sortDirections.ASCENDING ?
|
||||||
sortDirections.DESCENDING :
|
sortDirections.DESCENDING :
|
||||||
sortDirections.ASCENDING;
|
sortDirections.ASCENDING;
|
||||||
} else {
|
} else {
|
||||||
sortDirection = sectionState.sortDirection;
|
sortDirection = sectionState.sortDirection;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(set({ section, sortKey, sortDirection }));
|
dispatch(set({ section, sortKey, sortDirection }));
|
||||||
dispatch(fetchHandler());
|
dispatch(fetchHandler());
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,51 +5,47 @@ import { set } from '../baseActions';
|
||||||
const abortCurrentRequests = {};
|
const abortCurrentRequests = {};
|
||||||
|
|
||||||
export function createCancelTestProviderHandler(section) {
|
export function createCancelTestProviderHandler(section) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
if (abortCurrentRequests[section]) {
|
||||||
if (abortCurrentRequests[section]) {
|
abortCurrentRequests[section]();
|
||||||
abortCurrentRequests[section]();
|
abortCurrentRequests[section] = null;
|
||||||
abortCurrentRequests[section] = null;
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTestProviderHandler(section, url, getFromState) {
|
function createTestProviderHandler(section, url) {
|
||||||
return function(payload) {
|
return function(getState, payload, dispatch) {
|
||||||
return function(dispatch, getState) {
|
dispatch(set({ section, isTesting: true }));
|
||||||
dispatch(set({ section, isTesting: true }));
|
|
||||||
|
|
||||||
const testData = getProviderState(payload, getState, getFromState);
|
const testData = getProviderState(payload, getState, section);
|
||||||
|
|
||||||
const ajaxOptions = {
|
const ajaxOptions = {
|
||||||
url: `${url}/test`,
|
url: `${url}/test`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
data: JSON.stringify(testData)
|
data: JSON.stringify(testData)
|
||||||
};
|
|
||||||
|
|
||||||
const { request, abortRequest } = createAjaxRequest(ajaxOptions);
|
|
||||||
|
|
||||||
abortCurrentRequests[section] = abortRequest;
|
|
||||||
|
|
||||||
request.done((data) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isTesting: false,
|
|
||||||
saveError: null
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
request.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isTesting: false,
|
|
||||||
saveError: xhr.aborted ? null : xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { request, abortRequest } = createAjaxRequest(ajaxOptions);
|
||||||
|
|
||||||
|
abortCurrentRequests[section] = abortRequest;
|
||||||
|
|
||||||
|
request.done((data) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isTesting: false,
|
||||||
|
saveError: null
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
request.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isTesting: false,
|
||||||
|
saveError: xhr.aborted ? null : xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import updateAlbums from 'Utilities/Album/updateAlbums';
|
import updateAlbums from 'Utilities/Album/updateAlbums';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
|
||||||
function createToggleAlbumMonitoredHandler(section, getFromState) {
|
function createToggleAlbumMonitoredHandler(section) {
|
||||||
return function(payload) {
|
return function(payload) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
const {
|
const {
|
||||||
|
@ -9,8 +10,8 @@ function createToggleAlbumMonitoredHandler(section, getFromState) {
|
||||||
monitored
|
monitored
|
||||||
} = payload;
|
} = payload;
|
||||||
|
|
||||||
const state = getFromState(getState());
|
const state = getSectionState(getState(), section, true);
|
||||||
|
|
||||||
updateAlbums(dispatch, section, state.items, [albumId], {
|
updateAlbums(dispatch, section, state.items, [albumId], {
|
||||||
isSaving: true
|
isSaving: true
|
||||||
});
|
});
|
||||||
|
|
103
frontend/src/Store/Actions/Settings/delayProfiles.js
Normal file
103
frontend/src/Store/Actions/Settings/delayProfiles.js
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
import { update } from 'Store/Actions/baseActions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.delayProfiles';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_DELAY_PROFILES = 'settings/delayProfiles/fetchDelayProfiles';
|
||||||
|
export const FETCH_DELAY_PROFILE_SCHEMA = 'settings/delayProfiles/fetchDelayProfileSchema';
|
||||||
|
export const SAVE_DELAY_PROFILE = 'settings/delayProfiles/saveDelayProfile';
|
||||||
|
export const DELETE_DELAY_PROFILE = 'settings/delayProfiles/deleteDelayProfile';
|
||||||
|
export const REORDER_DELAY_PROFILE = 'settings/delayProfiles/reorderDelayProfile';
|
||||||
|
export const SET_DELAY_PROFILE_VALUE = 'settings/delayProfiles/setDelayProfileValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchDelayProfiles = createThunk(FETCH_DELAY_PROFILES);
|
||||||
|
export const fetchDelayProfileSchema = createThunk(FETCH_DELAY_PROFILE_SCHEMA);
|
||||||
|
export const saveDelayProfile = createThunk(SAVE_DELAY_PROFILE);
|
||||||
|
export const deleteDelayProfile = createThunk(DELETE_DELAY_PROFILE);
|
||||||
|
export const reorderDelayProfile = createThunk(REORDER_DELAY_PROFILE);
|
||||||
|
|
||||||
|
export const setDelayProfileValue = createAction(SET_DELAY_PROFILE_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
items: [],
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_DELAY_PROFILES]: createFetchHandler(section, '/delayprofile'),
|
||||||
|
[FETCH_DELAY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/delayprofile/schema'),
|
||||||
|
|
||||||
|
[SAVE_DELAY_PROFILE]: createSaveProviderHandler(section, '/delayprofile'),
|
||||||
|
[DELETE_DELAY_PROFILE]: createRemoveItemHandler(section, '/delayprofile'),
|
||||||
|
|
||||||
|
[REORDER_DELAY_PROFILE]: (getState, payload, dispatch) => {
|
||||||
|
const { id, moveIndex } = payload;
|
||||||
|
const moveOrder = moveIndex + 1;
|
||||||
|
const delayProfiles = getState().settings.delayProfiles.items;
|
||||||
|
const moving = _.find(delayProfiles, { id });
|
||||||
|
|
||||||
|
// Don't move if the order hasn't changed
|
||||||
|
if (moving.order === moveOrder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const after = moveIndex > 0 ? _.find(delayProfiles, { order: moveIndex }) : null;
|
||||||
|
const afterQueryParam = after ? `after=${after.id}` : '';
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
method: 'PUT',
|
||||||
|
url: `/delayprofile/reorder/${id}?${afterQueryParam}`
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(update({ section, data }));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_DELAY_PROFILE_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/downloadClientOptions.js
Normal file
64
frontend/src/Store/Actions/Settings/downloadClientOptions.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.downloadClientOptions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_DOWNLOAD_CLIENT_OPTIONS = 'FETCH_DOWNLOAD_CLIENT_OPTIONS';
|
||||||
|
export const SET_DOWNLOAD_CLIENT_OPTIONS_VALUE = 'SET_DOWNLOAD_CLIENT_OPTIONS_VALUE';
|
||||||
|
export const SAVE_DOWNLOAD_CLIENT_OPTIONS = 'SAVE_DOWNLOAD_CLIENT_OPTIONS';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchDownloadClientOptions = createThunk(FETCH_DOWNLOAD_CLIENT_OPTIONS);
|
||||||
|
export const saveDownloadClientOptions = createThunk(SAVE_DOWNLOAD_CLIENT_OPTIONS);
|
||||||
|
export const setDownloadClientOptionsValue = createAction(SET_DOWNLOAD_CLIENT_OPTIONS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_DOWNLOAD_CLIENT_OPTIONS]: createFetchHandler(section, '/config/downloadclient'),
|
||||||
|
[SAVE_DOWNLOAD_CLIENT_OPTIONS]: createSaveHandler(section, '/config/downloadclient')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_DOWNLOAD_CLIENT_OPTIONS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
112
frontend/src/Store/Actions/Settings/downloadClients.js
Normal file
112
frontend/src/Store/Actions/Settings/downloadClients.js
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.downloadClients';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_DOWNLOAD_CLIENTS = 'settings/downloadClients/fetchDownloadClients';
|
||||||
|
export const FETCH_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/fetchDownloadClientSchema';
|
||||||
|
export const SELECT_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/selectDownloadClientSchema';
|
||||||
|
export const SET_DOWNLOAD_CLIENT_VALUE = 'settings/downloadClients/setDownloadClientValue';
|
||||||
|
export const SET_DOWNLOAD_CLIENT_FIELD_VALUE = 'settings/downloadClients/setDownloadClientFieldValue';
|
||||||
|
export const SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/saveDownloadClient';
|
||||||
|
export const CANCEL_SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelSaveDownloadClient';
|
||||||
|
export const DELETE_DOWNLOAD_CLIENT = 'settings/downloadClients/deleteDownloadClient';
|
||||||
|
export const TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/testDownloadClient';
|
||||||
|
export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestDownloadClient';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchDownloadClients = createThunk(FETCH_DOWNLOAD_CLIENTS);
|
||||||
|
export const fetchDownloadClientSchema = createThunk(FETCH_DOWNLOAD_CLIENT_SCHEMA);
|
||||||
|
export const selectDownloadClientSchema = createAction(SELECT_DOWNLOAD_CLIENT_SCHEMA);
|
||||||
|
|
||||||
|
export const saveDownloadClient = createThunk(SAVE_DOWNLOAD_CLIENT);
|
||||||
|
export const cancelSaveDownloadClient = createThunk(CANCEL_SAVE_DOWNLOAD_CLIENT);
|
||||||
|
export const deleteDownloadClient = createThunk(DELETE_DOWNLOAD_CLIENT);
|
||||||
|
export const testDownloadClient = createThunk(TEST_DOWNLOAD_CLIENT);
|
||||||
|
export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT);
|
||||||
|
|
||||||
|
export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setDownloadClientFieldValue = createAction(SET_DOWNLOAD_CLIENT_FIELD_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: [],
|
||||||
|
selectedSchema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
isTesting: false,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_DOWNLOAD_CLIENTS]: createFetchHandler(section, '/downloadclient'),
|
||||||
|
[FETCH_DOWNLOAD_CLIENT_SCHEMA]: createFetchSchemaHandler(section, '/downloadclient/schema'),
|
||||||
|
|
||||||
|
[SAVE_DOWNLOAD_CLIENT]: createSaveProviderHandler(section, '/downloadclient'),
|
||||||
|
[CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section),
|
||||||
|
[DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'),
|
||||||
|
[TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'),
|
||||||
|
[CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section)
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_DOWNLOAD_CLIENT_VALUE]: createSetSettingValueReducer(section),
|
||||||
|
[SET_DOWNLOAD_CLIENT_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
|
||||||
|
|
||||||
|
[SELECT_DOWNLOAD_CLIENT_SCHEMA]: (state, { payload }) => {
|
||||||
|
return selectProviderSchema(state, section, payload, (selectedSchema) => {
|
||||||
|
selectedSchema.enable = true;
|
||||||
|
|
||||||
|
return selectedSchema;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/general.js
Normal file
64
frontend/src/Store/Actions/Settings/general.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.general';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_GENERAL_SETTINGS = 'settings/general/fetchGeneralSettings';
|
||||||
|
export const SET_GENERAL_SETTINGS_VALUE = 'settings/general/setGeneralSettingsValue';
|
||||||
|
export const SAVE_GENERAL_SETTINGS = 'settings/general/saveGeneralSettings';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchGeneralSettings = createThunk(FETCH_GENERAL_SETTINGS);
|
||||||
|
export const saveGeneralSettings = createThunk(SAVE_GENERAL_SETTINGS);
|
||||||
|
export const setGeneralSettingsValue = createAction(SET_GENERAL_SETTINGS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_GENERAL_SETTINGS]: createFetchHandler(section, '/config/host'),
|
||||||
|
[SAVE_GENERAL_SETTINGS]: createSaveHandler(section, '/config/host')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_GENERAL_SETTINGS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/indexerOptions.js
Normal file
64
frontend/src/Store/Actions/Settings/indexerOptions.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.indexerOptions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_INDEXER_OPTIONS = 'settings/indexerOptions/fetchIndexerOptions';
|
||||||
|
export const SAVE_INDEXER_OPTIONS = 'settings/indexerOptions/saveIndexerOptions';
|
||||||
|
export const SET_INDEXER_OPTIONS_VALUE = 'settings/indexerOptions/setIndexerOptionsValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchIndexerOptions = createThunk(FETCH_INDEXER_OPTIONS);
|
||||||
|
export const saveIndexerOptions = createThunk(SAVE_INDEXER_OPTIONS);
|
||||||
|
export const setIndexerOptionsValue = createAction(SET_INDEXER_OPTIONS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_INDEXER_OPTIONS]: createFetchHandler(section, '/config/indexer'),
|
||||||
|
[SAVE_INDEXER_OPTIONS]: createSaveHandler(section, '/config/indexer')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_INDEXER_OPTIONS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
113
frontend/src/Store/Actions/Settings/indexers.js
Normal file
113
frontend/src/Store/Actions/Settings/indexers.js
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.indexers';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_INDEXERS = 'settings/indexers/fetchIndexers';
|
||||||
|
export const FETCH_INDEXER_SCHEMA = 'settings/indexers/fetchIndexerSchema';
|
||||||
|
export const SELECT_INDEXER_SCHEMA = 'settings/indexers/selectIndexerSchema';
|
||||||
|
export const SET_INDEXER_VALUE = 'settings/indexers/setIndexerValue';
|
||||||
|
export const SET_INDEXER_FIELD_VALUE = 'settings/indexers/setIndexerFieldValue';
|
||||||
|
export const SAVE_INDEXER = 'settings/indexers/saveIndexer';
|
||||||
|
export const CANCEL_SAVE_INDEXER = 'settings/indexers/cancelSaveIndexer';
|
||||||
|
export const DELETE_INDEXER = 'settings/indexers/deleteIndexer';
|
||||||
|
export const TEST_INDEXER = 'settings/indexers/testIndexer';
|
||||||
|
export const CANCEL_TEST_INDEXER = 'settings/indexers/cancelTestIndexer';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchIndexers = createThunk(FETCH_INDEXERS);
|
||||||
|
export const fetchIndexerSchema = createThunk(FETCH_INDEXER_SCHEMA);
|
||||||
|
export const selectIndexerSchema = createAction(SELECT_INDEXER_SCHEMA);
|
||||||
|
|
||||||
|
export const saveIndexer = createThunk(SAVE_INDEXER);
|
||||||
|
export const cancelSaveIndexer = createThunk(CANCEL_SAVE_INDEXER);
|
||||||
|
export const deleteIndexer = createThunk(DELETE_INDEXER);
|
||||||
|
export const testIndexer = createThunk(TEST_INDEXER);
|
||||||
|
export const cancelTestIndexer = createThunk(CANCEL_TEST_INDEXER);
|
||||||
|
|
||||||
|
export const setIndexerValue = createAction(SET_INDEXER_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setIndexerFieldValue = createAction(SET_INDEXER_FIELD_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: [],
|
||||||
|
selectedSchema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
isTesting: false,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_INDEXERS]: createFetchHandler(section, '/indexer'),
|
||||||
|
[FETCH_INDEXER_SCHEMA]: createFetchSchemaHandler(section, '/indexer/schema'),
|
||||||
|
|
||||||
|
[SAVE_INDEXER]: createSaveProviderHandler(section, '/indexer'),
|
||||||
|
[CANCEL_SAVE_INDEXER]: createCancelSaveProviderHandler(section),
|
||||||
|
[DELETE_INDEXER]: createRemoveItemHandler(section, '/indexer'),
|
||||||
|
[TEST_INDEXER]: createTestProviderHandler(section, '/indexer'),
|
||||||
|
[CANCEL_TEST_INDEXER]: createCancelTestProviderHandler(section)
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_INDEXER_VALUE]: createSetSettingValueReducer(section),
|
||||||
|
[SET_INDEXER_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
|
||||||
|
|
||||||
|
[SELECT_INDEXER_SCHEMA]: (state, { payload }) => {
|
||||||
|
return selectProviderSchema(state, section, payload, (selectedSchema) => {
|
||||||
|
selectedSchema.enableRss = selectedSchema.supportsRss;
|
||||||
|
selectedSchema.enableSearch = selectedSchema.supportsSearch;
|
||||||
|
|
||||||
|
return selectedSchema;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
79
frontend/src/Store/Actions/Settings/languageProfiles.js
Normal file
79
frontend/src/Store/Actions/Settings/languageProfiles.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.languageProfiles';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_LANGUAGE_PROFILES = 'settings/languageProfiles/fetchLanguageProfiles';
|
||||||
|
export const FETCH_LANGUAGE_PROFILE_SCHEMA = 'settings/languageProfiles/fetchLanguageProfileSchema';
|
||||||
|
export const SAVE_LANGUAGE_PROFILE = 'settings/languageProfiles/saveLanguageProfile';
|
||||||
|
export const DELETE_LANGUAGE_PROFILE = 'settings/languageProfiles/deleteLanguageProfile';
|
||||||
|
export const SET_LANGUAGE_PROFILE_VALUE = 'settings/languageProfiles/setLanguageProfileValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchLanguageProfiles = createThunk(FETCH_LANGUAGE_PROFILES);
|
||||||
|
export const fetchLanguageProfileSchema = createThunk(FETCH_LANGUAGE_PROFILE_SCHEMA);
|
||||||
|
export const saveLanguageProfile = createThunk(SAVE_LANGUAGE_PROFILE);
|
||||||
|
export const deleteLanguageProfile = createThunk(DELETE_LANGUAGE_PROFILE);
|
||||||
|
|
||||||
|
export const setLanguageProfileValue = createAction(SET_LANGUAGE_PROFILE_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_LANGUAGE_PROFILES]: createFetchHandler(section, '/languageprofile'),
|
||||||
|
[FETCH_LANGUAGE_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/languageprofile/schema'),
|
||||||
|
[SAVE_LANGUAGE_PROFILE]: createSaveProviderHandler(section, '/languageprofile'),
|
||||||
|
[DELETE_LANGUAGE_PROFILE]: createRemoveItemHandler(section, '/languageprofile')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_LANGUAGE_PROFILE_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/mediaManagement.js
Normal file
64
frontend/src/Store/Actions/Settings/mediaManagement.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.mediaManagement';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/fetchMediaManagementSettings';
|
||||||
|
export const SAVE_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/saveMediaManagementSettings';
|
||||||
|
export const SET_MEDIA_MANAGEMENT_SETTINGS_VALUE = 'settings/mediaManagement/setMediaManagementSettingsValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchMediaManagementSettings = createThunk(FETCH_MEDIA_MANAGEMENT_SETTINGS);
|
||||||
|
export const saveMediaManagementSettings = createThunk(SAVE_MEDIA_MANAGEMENT_SETTINGS);
|
||||||
|
export const setMediaManagementSettingsValue = createAction(SET_MEDIA_MANAGEMENT_SETTINGS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_MEDIA_MANAGEMENT_SETTINGS]: createFetchHandler(section, '/config/mediamanagement'),
|
||||||
|
[SAVE_MEDIA_MANAGEMENT_SETTINGS]: createSaveHandler(section, '/config/mediamanagement')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_MEDIA_MANAGEMENT_SETTINGS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
75
frontend/src/Store/Actions/Settings/metadata.js
Normal file
75
frontend/src/Store/Actions/Settings/metadata.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.metadata';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_METADATA = 'settings/metadata/fetchMetadata';
|
||||||
|
export const SET_METADATA_VALUE = 'settings/metadata/setMetadataValue';
|
||||||
|
export const SET_METADATA_FIELD_VALUE = 'settings/metadata/setMetadataFieldValue';
|
||||||
|
export const SAVE_METADATA = 'settings/metadata/saveMetadata';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchMetadata = createThunk(FETCH_METADATA);
|
||||||
|
export const saveMetadata = createThunk(SAVE_METADATA);
|
||||||
|
|
||||||
|
export const setMetadataValue = createAction(SET_METADATA_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setMetadataFieldValue = createAction(SET_METADATA_FIELD_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_METADATA]: createFetchHandler(section, '/metadata'),
|
||||||
|
[SAVE_METADATA]: createSaveProviderHandler(section, '/metadata')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_METADATA_VALUE]: createSetSettingValueReducer(section),
|
||||||
|
[SET_METADATA_FIELD_VALUE]: createSetProviderFieldValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
79
frontend/src/Store/Actions/Settings/metadataProfiles.js
Normal file
79
frontend/src/Store/Actions/Settings/metadataProfiles.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.metadataProfiles';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_METADATA_PROFILES = 'settings/metadataProfiles/fetchMetadataProfiles';
|
||||||
|
export const FETCH_METADATA_PROFILE_SCHEMA = 'settings/metadataProfiles/fetchMetadataProfileSchema';
|
||||||
|
export const SAVE_METADATA_PROFILE = 'settings/metadataProfiles/saveMetadataProfile';
|
||||||
|
export const DELETE_METADATA_PROFILE = 'settings/metadataProfiles/deleteMetadataProfile';
|
||||||
|
export const SET_METADATA_PROFILE_VALUE = 'settings/metadataProfiles/setMetadataProfileValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchMetadataProfiles = createThunk(FETCH_METADATA_PROFILES);
|
||||||
|
export const fetchMetadataProfileSchema = createThunk(FETCH_METADATA_PROFILE_SCHEMA);
|
||||||
|
export const saveMetadataProfile = createThunk(SAVE_METADATA_PROFILE);
|
||||||
|
export const deleteMetadataProfile = createThunk(DELETE_METADATA_PROFILE);
|
||||||
|
|
||||||
|
export const setMetadataProfileValue = createAction(SET_METADATA_PROFILE_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_METADATA_PROFILES]: createFetchHandler(section, '/metadataprofile'),
|
||||||
|
[FETCH_METADATA_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/metadataprofile/schema'),
|
||||||
|
[SAVE_METADATA_PROFILE]: createSaveProviderHandler(section, '/metadataprofile'),
|
||||||
|
[DELETE_METADATA_PROFILE]: createRemoveItemHandler(section, '/metadataprofile')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_METADATA_PROFILE_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/metadataProvider.js
Normal file
64
frontend/src/Store/Actions/Settings/metadataProvider.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.metadataProvider';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_METADATA_PROVIDER = 'settings/metadataProvider/fetchMetadataProvider';
|
||||||
|
export const SET_METADATA_PROVIDER_VALUE = 'settings/metadataProvider/setMetadataProviderValue';
|
||||||
|
export const SAVE_METADATA_PROVIDER = 'settings/metadataProvider/saveMetadataProvider';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchMetadataProvider = createThunk(FETCH_METADATA_PROVIDER);
|
||||||
|
export const saveMetadataProvider = createThunk(SAVE_METADATA_PROVIDER);
|
||||||
|
export const setMetadataProviderValue = createAction(SET_METADATA_PROVIDER_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_METADATA_PROVIDER]: createFetchHandler(section, '/config/metadataProvider'),
|
||||||
|
[SAVE_METADATA_PROVIDER]: createSaveHandler(section, '/config/metadataProvider')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_METADATA_PROVIDER_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/naming.js
Normal file
64
frontend/src/Store/Actions/Settings/naming.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.naming';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_NAMING_SETTINGS = 'settings/naming/fetchNamingSettings';
|
||||||
|
export const SAVE_NAMING_SETTINGS = 'settings/naming/saveNamingSettings';
|
||||||
|
export const SET_NAMING_SETTINGS_VALUE = 'settings/naming/setNamingSettingsValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchNamingSettings = createThunk(FETCH_NAMING_SETTINGS);
|
||||||
|
export const saveNamingSettings = createThunk(SAVE_NAMING_SETTINGS);
|
||||||
|
export const setNamingSettingsValue = createAction(SET_NAMING_SETTINGS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_NAMING_SETTINGS]: createFetchHandler(section, '/config/naming'),
|
||||||
|
[SAVE_NAMING_SETTINGS]: createSaveHandler(section, '/config/naming')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_NAMING_SETTINGS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
79
frontend/src/Store/Actions/Settings/namingExamples.js
Normal file
79
frontend/src/Store/Actions/Settings/namingExamples.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import $ from 'jquery';
|
||||||
|
import { batchActions } from 'redux-batched-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import { set, update } from 'Store/Actions/baseActions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.namingExamples';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_NAMING_EXAMPLES = 'settings/namingExamples/fetchNamingExamples';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchNamingExamples = createThunk(FETCH_NAMING_EXAMPLES);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_NAMING_EXAMPLES]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({ section, isFetching: true }));
|
||||||
|
|
||||||
|
const naming = getState().settings.naming;
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/config/naming/examples',
|
||||||
|
data: Object.assign({}, naming.item, naming.pendingChanges)
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
update({ section, data }),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: true,
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {}
|
||||||
|
|
||||||
|
};
|
115
frontend/src/Store/Actions/Settings/notifications.js
Normal file
115
frontend/src/Store/Actions/Settings/notifications.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.notifications';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_NOTIFICATIONS = 'settings/notifications/fetchNotifications';
|
||||||
|
export const FETCH_NOTIFICATION_SCHEMA = 'settings/notifications/fetchNotificationSchema';
|
||||||
|
export const SELECT_NOTIFICATION_SCHEMA = 'settings/notifications/selectNotificationSchema';
|
||||||
|
export const SET_NOTIFICATION_VALUE = 'settings/notifications/setNotificationValue';
|
||||||
|
export const SET_NOTIFICATION_FIELD_VALUE = 'settings/notifications/setNotificationFieldValue';
|
||||||
|
export const SAVE_NOTIFICATION = 'settings/notifications/saveNotification';
|
||||||
|
export const CANCEL_SAVE_NOTIFICATION = 'settings/notifications/cancelSaveNotification';
|
||||||
|
export const DELETE_NOTIFICATION = 'settings/notifications/deleteNotification';
|
||||||
|
export const TEST_NOTIFICATION = 'settings/notifications/testNotification';
|
||||||
|
export const CANCEL_TEST_NOTIFICATION = 'settings/notifications/cancelTestNotification';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchNotifications = createThunk(FETCH_NOTIFICATIONS);
|
||||||
|
export const fetchNotificationSchema = createThunk(FETCH_NOTIFICATION_SCHEMA);
|
||||||
|
export const selectNotificationSchema = createAction(SELECT_NOTIFICATION_SCHEMA);
|
||||||
|
|
||||||
|
export const saveNotification = createThunk(SAVE_NOTIFICATION);
|
||||||
|
export const cancelSaveNotification = createThunk(CANCEL_SAVE_NOTIFICATION);
|
||||||
|
export const deleteNotification = createThunk(DELETE_NOTIFICATION);
|
||||||
|
export const testNotification = createThunk(TEST_NOTIFICATION);
|
||||||
|
export const cancelTestNotification = createThunk(CANCEL_TEST_NOTIFICATION);
|
||||||
|
|
||||||
|
export const setNotificationValue = createAction(SET_NOTIFICATION_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const setNotificationFieldValue = createAction(SET_NOTIFICATION_FIELD_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: [],
|
||||||
|
selectedSchema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
isTesting: false,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_NOTIFICATIONS]: createFetchHandler(section, '/notification'),
|
||||||
|
[FETCH_NOTIFICATION_SCHEMA]: createFetchSchemaHandler(section, '/notification/schema'),
|
||||||
|
|
||||||
|
[SAVE_NOTIFICATION]: createSaveProviderHandler(section, '/notification'),
|
||||||
|
[CANCEL_SAVE_NOTIFICATION]: createCancelSaveProviderHandler(section),
|
||||||
|
[DELETE_NOTIFICATION]: createRemoveItemHandler(section, '/notification'),
|
||||||
|
[TEST_NOTIFICATION]: createTestProviderHandler(section, '/notification'),
|
||||||
|
[CANCEL_TEST_NOTIFICATION]: createCancelTestProviderHandler(section)
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_NOTIFICATION_VALUE]: createSetSettingValueReducer(section),
|
||||||
|
[SET_NOTIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
|
||||||
|
|
||||||
|
[SELECT_NOTIFICATION_SCHEMA]: (state, { payload }) => {
|
||||||
|
return selectProviderSchema(state, section, payload, (selectedSchema) => {
|
||||||
|
selectedSchema.onGrab = selectedSchema.supportsOnGrab;
|
||||||
|
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
|
||||||
|
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
|
||||||
|
selectedSchema.onRename = selectedSchema.supportsOnRename;
|
||||||
|
|
||||||
|
return selectedSchema;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
116
frontend/src/Store/Actions/Settings/qualityDefinitions.js
Normal file
116
frontend/src/Store/Actions/Settings/qualityDefinitions.js
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { batchActions } from 'redux-batched-actions';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
import { clearPendingChanges, update } from 'Store/Actions/baseActions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.qualityDefinitions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/fetchQualityDefinitions';
|
||||||
|
export const SAVE_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/saveQualityDefinitions';
|
||||||
|
export const SET_QUALITY_DEFINITION_VALUE = 'settings/qualityDefinitions/setQualityDefinitionValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchQualityDefinitions = createThunk(FETCH_QUALITY_DEFINITIONS);
|
||||||
|
export const saveQualityDefinitions = createThunk(SAVE_QUALITY_DEFINITIONS);
|
||||||
|
|
||||||
|
export const setQualityDefinitionValue = createAction(SET_QUALITY_DEFINITION_VALUE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
items: [],
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_QUALITY_DEFINITIONS]: createFetchHandler(section, '/qualitydefinition'),
|
||||||
|
[SAVE_QUALITY_DEFINITIONS]: createSaveHandler(section, '/qualitydefinition'),
|
||||||
|
|
||||||
|
[SAVE_QUALITY_DEFINITIONS]: function(getState, payload, dispatch) {
|
||||||
|
const qualityDefinitions = getState().settings.qualityDefinitions;
|
||||||
|
|
||||||
|
const upatedDefinitions = Object.keys(qualityDefinitions.pendingChanges).map((key) => {
|
||||||
|
const id = parseInt(key);
|
||||||
|
const pendingChanges = qualityDefinitions.pendingChanges[id] || {};
|
||||||
|
const item = _.find(qualityDefinitions.items, { id });
|
||||||
|
|
||||||
|
return Object.assign({}, item, pendingChanges);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If there is nothing to save don't bother isSaving
|
||||||
|
if (!upatedDefinitions || !upatedDefinitions.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
method: 'PUT',
|
||||||
|
url: '/qualityDefinition/update',
|
||||||
|
data: JSON.stringify(upatedDefinitions)
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
update({ section, data }),
|
||||||
|
clearPendingChanges({ section })
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_QUALITY_DEFINITION_VALUE]: function(state, { payload }) {
|
||||||
|
const { id, name, value } = payload;
|
||||||
|
const newState = getSectionState(state, section);
|
||||||
|
newState.pendingChanges = _.cloneDeep(newState.pendingChanges);
|
||||||
|
|
||||||
|
const pendingState = newState.pendingChanges[id] || {};
|
||||||
|
const currentValue = _.find(newState.items, { id })[name];
|
||||||
|
|
||||||
|
if (currentValue === value) {
|
||||||
|
delete pendingState[name];
|
||||||
|
} else {
|
||||||
|
pendingState[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isEmpty(pendingState)) {
|
||||||
|
delete newState.pendingChanges[id];
|
||||||
|
} else {
|
||||||
|
newState.pendingChanges[id] = pendingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateSectionState(state, section, newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
79
frontend/src/Store/Actions/Settings/qualityProfiles.js
Normal file
79
frontend/src/Store/Actions/Settings/qualityProfiles.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.qualityProfiles';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_QUALITY_PROFILES = 'settings/qualityProfiles/fetchQualityProfiles';
|
||||||
|
export const FETCH_QUALITY_PROFILE_SCHEMA = 'settings/qualityProfiles/fetchQualityProfileSchema';
|
||||||
|
export const SAVE_QUALITY_PROFILE = 'settings/qualityProfiles/saveQualityProfile';
|
||||||
|
export const DELETE_QUALITY_PROFILE = 'settings/qualityProfiles/deleteQualityProfile';
|
||||||
|
export const SET_QUALITY_PROFILE_VALUE = 'settings/qualityProfiles/setQualityProfileValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchQualityProfiles = createThunk(FETCH_QUALITY_PROFILES);
|
||||||
|
export const fetchQualityProfileSchema = createThunk(FETCH_QUALITY_PROFILE_SCHEMA);
|
||||||
|
export const saveQualityProfile = createThunk(SAVE_QUALITY_PROFILE);
|
||||||
|
export const deleteQualityProfile = createThunk(DELETE_QUALITY_PROFILE);
|
||||||
|
|
||||||
|
export const setQualityProfileValue = createAction(SET_QUALITY_PROFILE_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: null,
|
||||||
|
isFetchingSchema: false,
|
||||||
|
schemaPopulated: false,
|
||||||
|
schemaError: null,
|
||||||
|
schema: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_QUALITY_PROFILES]: createFetchHandler(section, '/qualityprofile'),
|
||||||
|
[FETCH_QUALITY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/qualityprofile/schema'),
|
||||||
|
[SAVE_QUALITY_PROFILE]: createSaveProviderHandler(section, '/qualityprofile'),
|
||||||
|
[DELETE_QUALITY_PROFILE]: createRemoveItemHandler(section, '/qualityprofile')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_QUALITY_PROFILE_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
69
frontend/src/Store/Actions/Settings/remotePathMappings.js
Normal file
69
frontend/src/Store/Actions/Settings/remotePathMappings.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.remotePathMappings';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_REMOTE_PATH_MAPPINGS = 'settings/remotePathMappings/fetchRemotePathMappings';
|
||||||
|
export const SAVE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/saveRemotePathMapping';
|
||||||
|
export const DELETE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/deleteRemotePathMapping';
|
||||||
|
export const SET_REMOTE_PATH_MAPPING_VALUE = 'settings/remotePathMappings/setRemotePathMappingValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchRemotePathMappings = createThunk(FETCH_REMOTE_PATH_MAPPINGS);
|
||||||
|
export const saveRemotePathMapping = createThunk(SAVE_REMOTE_PATH_MAPPING);
|
||||||
|
export const deleteRemotePathMapping = createThunk(DELETE_REMOTE_PATH_MAPPING);
|
||||||
|
|
||||||
|
export const setRemotePathMappingValue = createAction(SET_REMOTE_PATH_MAPPING_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
items: [],
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_REMOTE_PATH_MAPPINGS]: createFetchHandler(section, '/remotepathmapping'),
|
||||||
|
[SAVE_REMOTE_PATH_MAPPING]: createSaveProviderHandler(section, '/remotepathmapping'),
|
||||||
|
[DELETE_REMOTE_PATH_MAPPING]: createRemoveItemHandler(section, '/remotepathmapping')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_REMOTE_PATH_MAPPING_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
71
frontend/src/Store/Actions/Settings/restrictions.js
Normal file
71
frontend/src/Store/Actions/Settings/restrictions.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.restrictions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_RESTRICTIONS = 'settings/restrictions/fetchRestrictions';
|
||||||
|
export const SAVE_RESTRICTION = 'settings/restrictions/saveRestriction';
|
||||||
|
export const DELETE_RESTRICTION = 'settings/restrictions/deleteRestriction';
|
||||||
|
export const SET_RESTRICTION_VALUE = 'settings/restrictions/setRestrictionValue';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchRestrictions = createThunk(FETCH_RESTRICTIONS);
|
||||||
|
export const saveRestriction = createThunk(SAVE_RESTRICTION);
|
||||||
|
export const deleteRestriction = createThunk(DELETE_RESTRICTION);
|
||||||
|
|
||||||
|
export const setRestrictionValue = createAction(SET_RESTRICTION_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
pendingChanges: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_RESTRICTIONS]: createFetchHandler(section, '/restriction'),
|
||||||
|
|
||||||
|
[SAVE_RESTRICTION]: createSaveProviderHandler(section, '/restriction'),
|
||||||
|
|
||||||
|
[DELETE_RESTRICTION]: createRemoveItemHandler(section, '/restriction')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_RESTRICTION_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
64
frontend/src/Store/Actions/Settings/ui.js
Normal file
64
frontend/src/Store/Actions/Settings/ui.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
import { createThunk } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
|
import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
const section = 'settings.ui';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_UI_SETTINGS = 'settings/ui/fetchUiSettings';
|
||||||
|
export const SET_UI_SETTINGS_VALUE = 'SET_UI_SETTINGS_VALUE';
|
||||||
|
export const SAVE_UI_SETTINGS = 'SAVE_UI_SETTINGS';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchUISettings = createThunk(FETCH_UI_SETTINGS);
|
||||||
|
export const saveUISettings = createThunk(SAVE_UI_SETTINGS);
|
||||||
|
export const setUISettingsValue = createAction(SET_UI_SETTINGS_VALUE, (payload) => {
|
||||||
|
return {
|
||||||
|
section,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Details
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
defaultState: {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
pendingChanges: {},
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
item: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
actionHandlers: {
|
||||||
|
[FETCH_UI_SETTINGS]: createFetchHandler(section, '/config/ui'),
|
||||||
|
[SAVE_UI_SETTINGS]: createSaveHandler(section, '/config/ui')
|
||||||
|
},
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
reducers: {
|
||||||
|
[SET_UI_SETTINGS_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -1,18 +1,3 @@
|
||||||
//
|
|
||||||
// BASE
|
|
||||||
|
|
||||||
export const SET = 'SET';
|
|
||||||
|
|
||||||
export const UPDATE = 'UPDATE';
|
|
||||||
export const UPDATE_ITEM = 'UPDATE_ITEM';
|
|
||||||
export const UPDATE_SERVER_SIDE_COLLECTION = 'UPDATE_SERVER_SIDE_COLLECTION';
|
|
||||||
|
|
||||||
export const SET_SETTING_VALUE = 'SET_SETTING_VALUE';
|
|
||||||
export const CLEAR_PENDING_CHANGES = 'CLEAR_PENDING_CHANGES';
|
|
||||||
export const SAVE_SETTINGS = 'SAVE_SETTINGS';
|
|
||||||
|
|
||||||
export const REMOVE_ITEM = 'REMOVE_ITEM';
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// App
|
// App
|
||||||
|
|
||||||
|
@ -23,401 +8,14 @@ export const SET_VERSION = 'SET_VERSION';
|
||||||
export const SET_APP_VALUE = 'SET_APP_VALUE';
|
export const SET_APP_VALUE = 'SET_APP_VALUE';
|
||||||
export const SET_IS_SIDEBAR_VISIBLE = 'SET_IS_SIDEBAR_VISIBLE';
|
export const SET_IS_SIDEBAR_VISIBLE = 'SET_IS_SIDEBAR_VISIBLE';
|
||||||
|
|
||||||
//
|
|
||||||
// Add Artist
|
|
||||||
|
|
||||||
export const LOOKUP_ARTIST = 'LOOKUP_ARTIST';
|
|
||||||
export const ADD_ARTIST = 'ADD_ARTIST';
|
|
||||||
export const SET_ADD_ARTIST_VALUE = 'SET_ADD_ARTIST_VALUE';
|
|
||||||
export const CLEAR_ADD_ARTIST = 'CLEAR_ADD_ARTIST';
|
|
||||||
export const SET_ADD_ARTIST_DEFAULT = 'SET_ADD_ARTIST_DEFAULT';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Import Artist
|
|
||||||
|
|
||||||
export const QUEUE_LOOKUP_ARTIST = 'QUEUE_LOOKUP_ARTIST';
|
|
||||||
export const START_LOOKUP_ARTIST = 'START_LOOKUP_ARTIST';
|
|
||||||
export const CLEAR_IMPORT_ARTIST = 'CLEAR_IMPORT_ARTIST';
|
|
||||||
export const SET_IMPORT_ARTIST_VALUE = 'SET_IMPORT_ARTIST_VALUE';
|
|
||||||
export const IMPORT_ARTIST = 'IMPORT_ARTIST';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Artist
|
|
||||||
|
|
||||||
export const FETCH_ARTIST = 'FETCH_ARTIST';
|
|
||||||
export const SET_ARTIST_VALUE = 'SET_ARTIST_VALUE';
|
|
||||||
export const SAVE_ARTIST = 'SAVE_ARTIST';
|
|
||||||
export const DELETE_ARTIST = 'DELETE_ARTIST';
|
|
||||||
|
|
||||||
export const SET_ARTIST_SORT = 'SET_ARTIST_SORT';
|
|
||||||
export const SET_ARTIST_FILTER = 'SET_ARTIST_FILTER';
|
|
||||||
export const SET_ARTIST_VIEW = 'SET_ARTIST_VIEW';
|
|
||||||
export const SET_ARTIST_TABLE_OPTION = 'SET_ARTIST_TABLE_OPTION';
|
|
||||||
export const SET_ARTIST_POSTER_OPTION = 'SET_ARTIST_POSTER_OPTION';
|
|
||||||
export const SET_ARTIST_BANNER_OPTION = 'SET_ARTIST_BANNER_OPTION';
|
|
||||||
export const SET_ARTIST_OVERVIEW_OPTION = 'SET_ARTIST_OVERVIEW_OPTION';
|
|
||||||
|
|
||||||
export const TOGGLE_ARTIST_MONITORED = 'TOGGLE_ARTIST_MONITORED';
|
|
||||||
export const TOGGLE_ALBUM_MONITORED = 'TOGGLE_ALBUM_MONITORED';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Artist Editor
|
|
||||||
|
|
||||||
export const SET_ARTIST_EDITOR_SORT = 'SET_ARTIST_EDITOR_SORT';
|
|
||||||
export const SET_ARTIST_EDITOR_FILTER = 'SET_ARTIST_EDITOR_FILTER';
|
|
||||||
export const SAVE_ARTIST_EDITOR = 'SAVE_ARTIST_EDITOR';
|
|
||||||
export const BULK_DELETE_ARTIST = 'BULK_DELETE_ARTIST';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Season Pass
|
|
||||||
|
|
||||||
export const SET_ALBUM_STUDIO_SORT = 'SET_ALBUM_STUDIO_SORT';
|
|
||||||
export const SET_ALBUM_STUDIO_FILTER = 'SET_ALBUM_STUDIO_FILTER';
|
|
||||||
export const SAVE_ALBUM_STUDIO = 'SAVE_ALBUM_STUDIO';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Episodes
|
|
||||||
|
|
||||||
export const FETCH_EPISODES = 'FETCH_EPISODES';
|
|
||||||
export const SET_EPISODES_SORT = 'SET_EPISODES_SORT';
|
|
||||||
export const SET_EPISODES_TABLE_OPTION = 'SET_EPISODES_TABLE_OPTION';
|
|
||||||
export const CLEAR_EPISODES = 'CLEAR_EPISODES';
|
|
||||||
export const TOGGLE_EPISODE_MONITORED = 'TOGGLE_EPISODE_MONITORED';
|
|
||||||
export const TOGGLE_EPISODES_MONITORED = 'TOGGLE_EPISODES_MONITORED';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Tracks
|
|
||||||
|
|
||||||
export const FETCH_TRACKS = 'FETCH_TRACKS';
|
|
||||||
export const SET_TRACKS_SORT = 'SET_TRACKS_SORT';
|
|
||||||
export const SET_TRACKS_TABLE_OPTION = 'SET_TRACKS_TABLE_OPTION';
|
|
||||||
export const CLEAR_TRACKS = 'CLEAR_TRACKS';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Episode Files
|
|
||||||
|
|
||||||
export const FETCH_TRACK_FILES = 'FETCH_TRACK_FILES';
|
|
||||||
export const CLEAR_TRACK_FILES = 'CLEAR_TRACK_FILES';
|
|
||||||
export const DELETE_TRACK_FILE = 'DELETE_TRACK_FILE';
|
|
||||||
export const DELETE_TRACK_FILES = 'DELETE_TRACK_FILES';
|
|
||||||
export const UPDATE_TRACK_FILES = 'UPDATE_TRACK_FILES';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Album History
|
|
||||||
|
|
||||||
export const FETCH_ALBUM_HISTORY = 'FETCH_ALBUM_HISTORY';
|
|
||||||
export const CLEAR_ALBUM_HISTORY = 'CLEAR_ALBUM_HISTORY';
|
|
||||||
export const ALBUM_HISTORY_MARK_AS_FAILED = 'ALBUM_HISTORY_MARK_AS_FAILED';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Releases
|
|
||||||
|
|
||||||
export const FETCH_RELEASES = 'FETCH_RELEASES';
|
|
||||||
export const CANCEL_FETCH_RELEASES = 'CANCEL_FETCH_RELEASES';
|
|
||||||
export const SET_RELEASES_SORT = 'SET_RELEASES_SORT';
|
|
||||||
export const CLEAR_RELEASES = 'CLEAR_RELEASES';
|
|
||||||
export const GRAB_RELEASE = 'GRAB_RELEASE';
|
|
||||||
export const UPDATE_RELEASE = 'UPDATE_RELEASE';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Calendar
|
|
||||||
|
|
||||||
export const FETCH_CALENDAR = 'FETCH_CALENDAR';
|
|
||||||
export const SET_CALENDAR_DAYS_COUNT = 'SET_CALENDAR_DAYS_COUNT';
|
|
||||||
export const SET_CALENDAR_INCLUDE_UNMONITORED = 'SET_CALENDAR_INCLUDE_UNMONITORED';
|
|
||||||
export const SET_CALENDAR_VIEW = 'SET_CALENDAR_VIEW';
|
|
||||||
export const GOTO_CALENDAR_TODAY = 'GOTO_CALENDAR_TODAY';
|
|
||||||
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'GOTO_CALENDAR_PREVIOUS_RANGE';
|
|
||||||
export const GOTO_CALENDAR_NEXT_RANGE = 'GOTO_CALENDAR_NEXT_RANGE';
|
|
||||||
export const CLEAR_CALENDAR = 'CLEAR_CALENDAR';
|
|
||||||
|
|
||||||
//
|
|
||||||
// History
|
|
||||||
|
|
||||||
export const FETCH_HISTORY = 'FETCH_HISTORY';
|
|
||||||
export const GOTO_FIRST_HISTORY_PAGE = 'GOTO_FIRST_HISTORY_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_HISTORY_PAGE = 'GOTO_PREVIOUS_HISTORY_PAGE';
|
|
||||||
export const GOTO_NEXT_HISTORY_PAGE = 'GOTO_NEXT_HISTORY_PAGE';
|
|
||||||
export const GOTO_LAST_HISTORY_PAGE = 'GOTO_LAST_HISTORY_PAGE';
|
|
||||||
export const GOTO_HISTORY_PAGE = 'GOTO_HISTORY_PAGE';
|
|
||||||
export const SET_HISTORY_SORT = 'SET_HISTORY_SORT';
|
|
||||||
export const SET_HISTORY_FILTER = 'SET_HISTORY_FILTER';
|
|
||||||
export const SET_HISTORY_TABLE_OPTION = 'SET_HISTORY_TABLE_OPTION';
|
|
||||||
export const CLEAR_HISTORY = 'CLEAR_HISTORY';
|
|
||||||
|
|
||||||
export const MARK_AS_FAILED = 'MARK_AS_FAILED';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Queue
|
|
||||||
|
|
||||||
export const FETCH_QUEUE_STATUS = 'FETCH_QUEUE_STATUS';
|
|
||||||
|
|
||||||
export const FETCH_QUEUE_DETAILS = 'FETCH_QUEUE_DETAILS';
|
|
||||||
export const CLEAR_QUEUE_DETAILS = 'CLEAR_QUEUE_DETAILS';
|
|
||||||
|
|
||||||
export const FETCH_QUEUE = 'FETCH_QUEUE';
|
|
||||||
export const GOTO_FIRST_QUEUE_PAGE = 'GOTO_FIRST_QUEUE_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_QUEUE_PAGE = 'GOTO_PREVIOUS_QUEUE_PAGE';
|
|
||||||
export const GOTO_NEXT_QUEUE_PAGE = 'GOTO_NEXT_QUEUE_PAGE';
|
|
||||||
export const GOTO_LAST_QUEUE_PAGE = 'GOTO_LAST_QUEUE_PAGE';
|
|
||||||
export const GOTO_QUEUE_PAGE = 'GOTO_QUEUE_PAGE';
|
|
||||||
export const SET_QUEUE_SORT = 'SET_QUEUE_SORT';
|
|
||||||
export const SET_QUEUE_TABLE_OPTION = 'SET_QUEUE_TABLE_OPTION';
|
|
||||||
export const CLEAR_QUEUE = 'CLEAR_QUEUE';
|
|
||||||
|
|
||||||
export const GRAB_QUEUE_ITEM = 'GRAB_QUEUE_ITEM';
|
|
||||||
export const GRAB_QUEUE_ITEMS = 'GRAB_QUEUE_ITEMS';
|
|
||||||
export const REMOVE_QUEUE_ITEM = 'REMOVE_QUEUE_ITEM';
|
|
||||||
export const REMOVE_QUEUE_ITEMS = 'REMOVE_QUEUE_ITEMS';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Blacklist
|
|
||||||
|
|
||||||
export const FETCH_BLACKLIST = 'FETCH_BLACKLIST';
|
|
||||||
export const GOTO_FIRST_BLACKLIST_PAGE = 'GOTO_FIRST_BLACKLIST_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_BLACKLIST_PAGE = 'GOTO_PREVIOUS_BLACKLIST_PAGE';
|
|
||||||
export const GOTO_NEXT_BLACKLIST_PAGE = 'GOTO_NEXT_BLACKLIST_PAGE';
|
|
||||||
export const GOTO_LAST_BLACKLIST_PAGE = 'GOTO_LAST_BLACKLIST_PAGE';
|
|
||||||
export const GOTO_BLACKLIST_PAGE = 'GOTO_BLACKLIST_PAGE';
|
|
||||||
export const SET_BLACKLIST_SORT = 'SET_BLACKLIST_SORT';
|
|
||||||
export const SET_BLACKLIST_TABLE_OPTION = 'SET_BLACKLIST_TABLE_OPTION';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Wanted
|
|
||||||
|
|
||||||
export const FETCH_MISSING = 'FETCH_MISSING';
|
|
||||||
export const GOTO_FIRST_MISSING_PAGE = 'GOTO_FIRST_MISSING_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_MISSING_PAGE = 'GOTO_PREVIOUS_MISSING_PAGE';
|
|
||||||
export const GOTO_NEXT_MISSING_PAGE = 'GOTO_NEXT_MISSING_PAGE';
|
|
||||||
export const GOTO_LAST_MISSING_PAGE = 'GOTO_LAST_MISSING_PAGE';
|
|
||||||
export const GOTO_MISSING_PAGE = 'GOTO_MISSING_PAGE';
|
|
||||||
export const SET_MISSING_SORT = 'SET_MISSING_SORT';
|
|
||||||
export const SET_MISSING_FILTER = 'SET_MISSING_FILTER';
|
|
||||||
export const SET_MISSING_TABLE_OPTION = 'SET_MISSING_TABLE_OPTION';
|
|
||||||
export const CLEAR_MISSING = 'CLEAR_MISSING';
|
|
||||||
|
|
||||||
export const BATCH_TOGGLE_MISSING_ALBUMS = 'BATCH_TOGGLE_MISSING_ALBUMS';
|
|
||||||
|
|
||||||
export const FETCH_CUTOFF_UNMET = 'FETCH_CUTOFF_UNMET';
|
|
||||||
export const GOTO_FIRST_CUTOFF_UNMET_PAGE = 'GOTO_FIRST_CUTOFF_UNMET_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_CUTOFF_UNMET_PAGE = 'GOTO_PREVIOUS_CUTOFF_UNMET_PAGE';
|
|
||||||
export const GOTO_NEXT_CUTOFF_UNMET_PAGE = 'GOTO_NEXT_CUTOFF_UNMET_PAGE';
|
|
||||||
export const GOTO_LAST_CUTOFF_UNMET_PAGE = 'GOTO_LAST_CUTOFF_UNMET_PAGE';
|
|
||||||
export const GOTO_CUTOFF_UNMET_PAGE = 'GOTO_CUTOFF_UNMET_PAGE';
|
|
||||||
export const SET_CUTOFF_UNMET_SORT = 'SET_CUTOFF_UNMET_SORT';
|
|
||||||
export const SET_CUTOFF_UNMET_FILTER = 'SET_CUTOFF_UNMET_FILTER';
|
|
||||||
export const SET_CUTOFF_UNMET_TABLE_OPTION = 'SET_CUTOFF_UNMET_TABLE_OPTION';
|
|
||||||
export const CLEAR_CUTOFF_UNMET = 'CLEAR_CUTOFF_UNMET';
|
|
||||||
|
|
||||||
export const BATCH_TOGGLE_CUTOFF_UNMET_ALBUMS = 'BATCH_TOGGLE_CUTOFF_UNMET_ALBUMS';
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Settings
|
// Settings
|
||||||
|
|
||||||
export const TOGGLE_ADVANCED_SETTINGS = 'TOGGLE_ADVANCED_SETTINGS';
|
export const FETCH_GENERAL_SETTINGS = 'settings/general/fetchGeneralSettings';
|
||||||
|
export const SET_GENERAL_SETTINGS_VALUE = 'settings/general/setGeneralSettingsValue';
|
||||||
export const FETCH_UI_SETTINGS = 'FETCH_UI_SETTINGS';
|
export const SAVE_GENERAL_SETTINGS = 'settings/general/saveGeneralSettings';
|
||||||
export const SET_UI_SETTINGS_VALUE = 'SET_UI_SETTINGS_VALUE';
|
|
||||||
export const SAVE_UI_SETTINGS = 'SAVE_UI_SETTINGS';
|
|
||||||
|
|
||||||
export const FETCH_MEDIA_MANAGEMENT_SETTINGS = 'FETCH_MEDIA_MANAGEMENT_SETTINGS';
|
|
||||||
export const SET_MEDIA_MANAGEMENT_SETTINGS_VALUE = 'SET_MEDIA_MANAGEMENT_SETTINGS_VALUE';
|
|
||||||
export const SAVE_MEDIA_MANAGEMENT_SETTINGS = 'SAVE_MEDIA_MANAGEMENT_SETTINGS';
|
|
||||||
|
|
||||||
export const FETCH_NAMING_SETTINGS = 'FETCH_NAMING_SETTINGS';
|
|
||||||
export const SET_NAMING_SETTINGS_VALUE = 'SET_NAMING_SETTINGS_VALUE';
|
|
||||||
export const SAVE_NAMING_SETTINGS = 'SAVE_NAMING_SETTINGS';
|
|
||||||
export const FETCH_NAMING_EXAMPLES = 'FETCH_NAMING_EXAMPLES';
|
|
||||||
|
|
||||||
export const FETCH_QUALITY_PROFILES = 'FETCH_QUALITY_PROFILES';
|
|
||||||
export const FETCH_QUALITY_PROFILE_SCHEMA = 'FETCH_QUALITY_PROFILE_SCHEMA';
|
|
||||||
export const SET_QUALITY_PROFILE_VALUE = 'SET_QUALITY_PROFILE_VALUE';
|
|
||||||
export const SAVE_QUALITY_PROFILE = 'SAVE_QUALITY_PROFILE';
|
|
||||||
export const DELETE_QUALITY_PROFILE = 'DELETE_QUALITY_PROFILE';
|
|
||||||
|
|
||||||
export const FETCH_LANGUAGE_PROFILES = 'FETCH_LANGUAGE_PROFILES';
|
|
||||||
export const FETCH_LANGUAGE_PROFILE_SCHEMA = 'FETCH_LANGUAGE_PROFILE_SCHEMA';
|
|
||||||
export const SET_LANGUAGE_PROFILE_VALUE = 'SET_LANGUAGE_PROFILE_VALUE';
|
|
||||||
export const SAVE_LANGUAGE_PROFILE = 'SAVE_LANGUAGE_PROFILE';
|
|
||||||
export const DELETE_LANGUAGE_PROFILE = 'DELETE_LANGUAGE_PROFILE';
|
|
||||||
|
|
||||||
export const FETCH_METADATA_PROFILES = 'FETCH_METADATA_PROFILES';
|
|
||||||
export const FETCH_METADATA_PROFILE_SCHEMA = 'FETCH_METADATA_PROFILE_SCHEMA';
|
|
||||||
export const SET_METADATA_PROFILE_VALUE = 'SET_METADATA_PROFILE_VALUE';
|
|
||||||
export const SAVE_METADATA_PROFILE = 'SAVE_METADATA_PROFILE';
|
|
||||||
export const DELETE_METADATA_PROFILE = 'DELETE_METADATA_PROFILE';
|
|
||||||
|
|
||||||
export const FETCH_DELAY_PROFILES = 'FETCH_DELAY_PROFILES';
|
|
||||||
export const SET_DELAY_PROFILE_VALUE = 'SET_DELAY_PROFILE_VALUE';
|
|
||||||
export const SAVE_DELAY_PROFILE = 'SAVE_DELAY_PROFILE';
|
|
||||||
export const DELETE_DELAY_PROFILE = 'DELETE_DELAY_PROFILE';
|
|
||||||
export const REORDER_DELAY_PROFILE = 'REORDER_DELAY_PROFILE';
|
|
||||||
|
|
||||||
export const FETCH_QUALITY_DEFINITIONS = 'FETCH_QUALITY_DEFINITIONS';
|
|
||||||
export const SET_QUALITY_DEFINITION_VALUE = 'SET_QUALITY_DEFINITION_VALUE';
|
|
||||||
export const SAVE_QUALITY_DEFINITIONS = 'SAVE_QUALITY_DEFINITIONS';
|
|
||||||
|
|
||||||
export const FETCH_INDEXERS = 'FETCH_INDEXERS';
|
|
||||||
export const FETCH_INDEXER_SCHEMA = 'FETCH_INDEXER_SCHEMA';
|
|
||||||
export const SELECT_INDEXER_SCHEMA = 'SELECT_INDEXER_SCHEMA';
|
|
||||||
export const SET_INDEXER_VALUE = 'SET_INDEXER_VALUE';
|
|
||||||
export const SET_INDEXER_FIELD_VALUE = 'SET_INDEXER_FIELD_VALUE';
|
|
||||||
export const SAVE_INDEXER = 'SAVE_INDEXER';
|
|
||||||
export const CANCEL_SAVE_INDEXER = 'CANCEL_SAVE_INDEXER';
|
|
||||||
export const DELETE_INDEXER = 'DELETE_INDEXER';
|
|
||||||
export const TEST_INDEXER = 'TEST_INDEXER';
|
|
||||||
export const CANCEL_TEST_INDEXER = 'CANCEL_TEST_INDEXER';
|
|
||||||
|
|
||||||
export const FETCH_INDEXER_OPTIONS = 'FETCH_INDEXER_OPTIONS';
|
|
||||||
export const SET_INDEXER_OPTIONS_VALUE = 'SET_INDEXER_OPTIONS_VALUE';
|
|
||||||
export const SAVE_INDEXER_OPTIONS = 'SAVE_INDEXER_OPTIONS';
|
|
||||||
|
|
||||||
export const FETCH_RESTRICTIONS = 'FETCH_RESTRICTIONS';
|
|
||||||
export const SET_RESTRICTION_VALUE = 'SET_RESTRICTION_VALUE';
|
|
||||||
export const SAVE_RESTRICTION = 'SAVE_RESTRICTION';
|
|
||||||
export const DELETE_RESTRICTION = 'DELETE_RESTRICTION';
|
|
||||||
|
|
||||||
export const FETCH_DOWNLOAD_CLIENTS = 'FETCH_DOWNLOAD_CLIENTS';
|
|
||||||
export const FETCH_DOWNLOAD_CLIENT_SCHEMA = 'FETCH_DOWNLOAD_CLIENT_SCHEMA';
|
|
||||||
export const SELECT_DOWNLOAD_CLIENT_SCHEMA = 'SELECT_DOWNLOAD_CLIENT_SCHEMA';
|
|
||||||
export const SET_DOWNLOAD_CLIENT_VALUE = 'SET_DOWNLOAD_CLIENT_VALUE';
|
|
||||||
export const SET_DOWNLOAD_CLIENT_FIELD_VALUE = 'SET_DOWNLOAD_CLIENT_FIELD_VALUE';
|
|
||||||
export const SAVE_DOWNLOAD_CLIENT = 'SAVE_DOWNLOAD_CLIENT';
|
|
||||||
export const CANCEL_SAVE_DOWNLOAD_CLIENT = 'CANCEL_SAVE_DOWNLOAD_CLIENT';
|
|
||||||
export const DELETE_DOWNLOAD_CLIENT = 'DELETE_DOWNLOAD_CLIENT';
|
|
||||||
export const TEST_DOWNLOAD_CLIENT = 'TEST_DOWNLOAD_CLIENT';
|
|
||||||
export const CANCEL_TEST_DOWNLOAD_CLIENT = 'CANCEL_TEST_DOWNLOAD_CLIENT';
|
|
||||||
|
|
||||||
export const FETCH_DOWNLOAD_CLIENT_OPTIONS = 'FETCH_DOWNLOAD_CLIENT_OPTIONS';
|
|
||||||
export const SET_DOWNLOAD_CLIENT_OPTIONS_VALUE = 'SET_DOWNLOAD_CLIENT_OPTIONS_VALUE';
|
|
||||||
export const SAVE_DOWNLOAD_CLIENT_OPTIONS = 'SAVE_DOWNLOAD_CLIENT_OPTIONS';
|
|
||||||
|
|
||||||
export const FETCH_REMOTE_PATH_MAPPINGS = 'FETCH_REMOTE_PATH_MAPPINGS';
|
|
||||||
export const SET_REMOTE_PATH_MAPPING_VALUE = 'SET_REMOTE_PATH_MAPPING_VALUE';
|
|
||||||
export const SAVE_REMOTE_PATH_MAPPING = 'SAVE_REMOTE_PATH_MAPPING';
|
|
||||||
export const DELETE_REMOTE_PATH_MAPPING = 'DELETE_REMOTE_PATH_MAPPING';
|
|
||||||
|
|
||||||
export const FETCH_NOTIFICATIONS = 'FETCH_NOTIFICATIONS';
|
|
||||||
export const FETCH_NOTIFICATION_SCHEMA = 'FETCH_NOTIFICATION_SCHEMA';
|
|
||||||
export const SELECT_NOTIFICATION_SCHEMA = 'SELECT_NOTIFICATION_SCHEMA';
|
|
||||||
export const SET_NOTIFICATION_VALUE = 'SET_NOTIFICATION_VALUE';
|
|
||||||
export const SET_NOTIFICATION_FIELD_VALUE = 'SET_NOTIFICATION_FIELD_VALUE';
|
|
||||||
export const SAVE_NOTIFICATION = 'SAVE_NOTIFICATION';
|
|
||||||
export const CANCEL_SAVE_NOTIFICATION = 'CANCEL_SAVE_NOTIFICATION';
|
|
||||||
export const DELETE_NOTIFICATION = 'DELETE_NOTIFICATION';
|
|
||||||
export const CANCEL_TEST_NOTIFICATION = 'CANCEL_TEST_NOTIFICATION';
|
|
||||||
|
|
||||||
export const FETCH_METADATA = 'FETCH_METADATA';
|
|
||||||
export const SET_METADATA_VALUE = 'SET_METADATA_VALUE';
|
|
||||||
export const SET_METADATA_FIELD_VALUE = 'SET_METADATA_FIELD_VALUE';
|
|
||||||
export const SAVE_METADATA = 'SAVE_METADATA';
|
|
||||||
|
|
||||||
export const FETCH_METADATA_PROVIDER = 'FETCH_METADATA_PROVIDER';
|
|
||||||
export const SET_METADATA_PROVIDER_VALUE = 'SET_METADATA_PROVIDER_VALUE';
|
|
||||||
export const SAVE_METADATA_PROVIDER = 'SAVE_METADATA_PROVIDER';
|
|
||||||
|
|
||||||
//
|
|
||||||
// System
|
|
||||||
|
|
||||||
export const FETCH_STATUS = 'FETCH_STATUS';
|
|
||||||
export const FETCH_HEALTH = 'FETCH_HEALTH';
|
|
||||||
export const FETCH_DISK_SPACE = 'FETCH_DISK_SPACE';
|
|
||||||
|
|
||||||
export const FETCH_TASK = 'FETCH_TASK';
|
|
||||||
export const FETCH_TASKS = 'FETCH_TASKS';
|
|
||||||
export const FETCH_BACKUPS = 'FETCH_BACKUPS';
|
|
||||||
export const FETCH_UPDATES = 'FETCH_UPDATES';
|
|
||||||
|
|
||||||
export const FETCH_LOGS = 'FETCH_LOGS';
|
|
||||||
export const GOTO_FIRST_LOGS_PAGE = 'GOTO_FIRST_LOGS_PAGE';
|
|
||||||
export const GOTO_PREVIOUS_LOGS_PAGE = 'GOTO_PREVIOUS_LOGS_PAGE';
|
|
||||||
export const GOTO_NEXT_LOGS_PAGE = 'GOTO_NEXT_LOGS_PAGE';
|
|
||||||
export const GOTO_LAST_LOGS_PAGE = 'GOTO_LAST_LOGS_PAGE';
|
|
||||||
export const GOTO_LOGS_PAGE = 'GOTO_LOGS_PAGE';
|
|
||||||
export const SET_LOGS_SORT = 'SET_LOGS_SORT';
|
|
||||||
export const SET_LOGS_FILTER = 'SET_LOGS_FILTER';
|
|
||||||
export const SET_LOGS_TABLE_OPTION = 'SET_LOGS_TABLE_OPTION';
|
|
||||||
|
|
||||||
export const FETCH_LOG_FILES = 'FETCH_LOG_FILES';
|
|
||||||
export const FETCH_UPDATE_LOG_FILES = 'FETCH_UPDATE_LOG_FILES';
|
|
||||||
|
|
||||||
export const FETCH_GENERAL_SETTINGS = 'FETCH_GENERAL_SETTINGS';
|
|
||||||
export const SET_GENERAL_SETTINGS_VALUE = 'SET_GENERAL_SETTINGS_VALUE';
|
|
||||||
export const SAVE_GENERAL_SETTINGS = 'SAVE_GENERAL_SETTINGS';
|
|
||||||
|
|
||||||
export const RESTART = 'RESTART';
|
|
||||||
export const SHUTDOWN = 'SHUTDOWN';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Commands
|
|
||||||
|
|
||||||
export const FETCH_COMMANDS = 'FETCH_COMMANDS';
|
|
||||||
export const EXECUTE_COMMAND = 'EXECUTE_COMMAND';
|
|
||||||
export const ADD_COMMAND = 'ADD_COMMAND';
|
|
||||||
export const UPDATE_COMMAND = 'UPDATE_COMMAND';
|
|
||||||
export const FINISH_COMMAND = 'FINISH_COMMAND';
|
|
||||||
export const REMOVE_COMMAND = 'REMOVE_COMMAND';
|
|
||||||
export const REGISTER_FINISH_COMMAND_HANDLER = 'REGISTER_FINISH_COMMAND_HANDLER';
|
|
||||||
export const UNREGISTER_FINISH_COMMAND_HANDLER = 'UNREGISTER_FINISH_COMMAND_HANDLER';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Paths
|
|
||||||
|
|
||||||
export const FETCH_PATHS = 'FETCH_PATHS';
|
|
||||||
export const UPDATE_PATHS = 'UPDATE_PATHS';
|
|
||||||
export const CLEAR_PATHS = 'CLEAR_PATHS';
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Languages
|
// Languages
|
||||||
|
|
||||||
export const FETCH_LANGUAGES = 'FETCH_LANGUAGES';
|
export const FETCH_LANGUAGES = 'FETCH_LANGUAGES';
|
||||||
|
|
||||||
//
|
|
||||||
// Tags
|
|
||||||
|
|
||||||
export const FETCH_TAGS = 'FETCH_TAGS';
|
|
||||||
export const ADD_TAG = 'ADD_TAG';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Captcha
|
|
||||||
|
|
||||||
export const REFRESH_CAPTCHA = 'REFRESH_CAPTCHA';
|
|
||||||
export const GET_CAPTCHA_COOKIE = 'GET_CAPTCHA_COOKIE';
|
|
||||||
export const SET_CAPTCHA_VALUE = 'SET_CAPTCHA_VALUE';
|
|
||||||
export const RESET_CAPTCHA = 'RESET_CAPTCHA';
|
|
||||||
|
|
||||||
//
|
|
||||||
// OAuth
|
|
||||||
|
|
||||||
export const START_OAUTH = 'START_OAUTH';
|
|
||||||
export const GET_OAUTH_TOKEN = 'GET_OAUTH_TOKEN';
|
|
||||||
export const SET_OAUTH_VALUE = 'SET_OAUTH_VALUE';
|
|
||||||
export const RESET_OAUTH = 'RESET_OAUTH';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Interactive Import
|
|
||||||
|
|
||||||
export const FETCH_INTERACTIVE_IMPORT_ITEMS = 'FETCH_INTERACTIVE_IMPORT_ITEMS';
|
|
||||||
export const UPDATE_INTERACTIVE_IMPORT_ITEM = 'UPDATE_INTERACTIVE_IMPORT_ITEM';
|
|
||||||
export const SET_INTERACTIVE_IMPORT_SORT = 'SET_INTERACTIVE_IMPORT_SORT';
|
|
||||||
export const CLEAR_INTERACTIVE_IMPORT = 'CLEAR_INTERACTIVE_IMPORT';
|
|
||||||
export const ADD_RECENT_FOLDER = 'ADD_RECENT_FOLDER';
|
|
||||||
export const REMOVE_RECENT_FOLDER = 'REMOVE_RECENT_FOLDER';
|
|
||||||
export const SET_INTERACTIVE_IMPORT_MODE = 'SET_INTERACTIVE_IMPORT_MODE';
|
|
||||||
|
|
||||||
export const FETCH_INTERACTIVE_IMPORT_ALBUMS = 'FETCH_INTERACTIVE_IMPORT_ALBUMS';
|
|
||||||
export const SET_INTERACTIVE_IMPORT_ALBUMS_SORT = 'SET_INTERACTIVE_IMPORT_ALBUMS_SORT';
|
|
||||||
export const CLEAR_INTERACTIVE_IMPORT_ALBUMS = 'CLEAR_INTERACTIVE_IMPORT_ALBUMS';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Root Folders
|
|
||||||
|
|
||||||
export const FETCH_ROOT_FOLDERS = 'FETCH_ROOT_FOLDERS';
|
|
||||||
export const ADD_ROOT_FOLDER = 'ADD_ROOT_FOLDER';
|
|
||||||
export const DELETE_ROOT_FOLDER = 'DELETE_ROOT_FOLDER';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Organize Preview
|
|
||||||
|
|
||||||
export const FETCH_ORGANIZE_PREVIEW = 'FETCH_ORGANIZE_PREVIEW';
|
|
||||||
export const CLEAR_ORGANIZE_PREVIEW = 'CLEAR_ORGANIZE_PREVIEW';
|
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import { batchActions } from 'redux-batched-actions';
|
|
||||||
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
|
||||||
import getNewArtist from 'Utilities/Artist/getNewArtist';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { set, update, updateItem } from './baseActions';
|
|
||||||
|
|
||||||
let abortCurrentRequest = null;
|
|
||||||
const section = 'addArtist';
|
|
||||||
|
|
||||||
const addArtistActionHandlers = {
|
|
||||||
[types.LOOKUP_ARTIST]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({ section, isFetching: true }));
|
|
||||||
|
|
||||||
if (abortCurrentRequest) {
|
|
||||||
abortCurrentRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { request, abortRequest } = createAjaxRequest({
|
|
||||||
url: '/artist/lookup',
|
|
||||||
data: {
|
|
||||||
term: payload.term
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
abortCurrentRequest = abortRequest;
|
|
||||||
|
|
||||||
request.done((data) => {
|
|
||||||
dispatch(batchActions([
|
|
||||||
update({ section, data }),
|
|
||||||
|
|
||||||
set({
|
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: true,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
request.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: false,
|
|
||||||
error: xhr.aborted ? null : xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.ADD_ARTIST]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({ section, isAdding: true }));
|
|
||||||
|
|
||||||
const foreignArtistId = payload.foreignArtistId;
|
|
||||||
const items = getState().addArtist.items;
|
|
||||||
const newSeries = getNewArtist(_.cloneDeep(_.find(items, { foreignArtistId })), payload);
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/artist',
|
|
||||||
method: 'POST',
|
|
||||||
contentType: 'application/json',
|
|
||||||
data: JSON.stringify(newSeries)
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(batchActions([
|
|
||||||
updateItem({ section: 'artist', ...data }),
|
|
||||||
|
|
||||||
set({
|
|
||||||
section,
|
|
||||||
isAdding: false,
|
|
||||||
isAdded: true,
|
|
||||||
addError: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isAdding: false,
|
|
||||||
isAdded: false,
|
|
||||||
addError: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default addArtistActionHandlers;
|
|
|
@ -1,15 +1,180 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import addArtistActionHandlers from './addArtistActionHandlers';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
import createAjaxRequest from 'Utilities/createAjaxRequest';
|
||||||
|
import getNewArtist from 'Utilities/Artist/getNewArtist';
|
||||||
|
import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { set, update, updateItem } from './baseActions';
|
||||||
|
|
||||||
export const lookupArtist = addArtistActionHandlers[types.LOOKUP_ARTIST];
|
//
|
||||||
export const addArtist = addArtistActionHandlers[types.ADD_ARTIST];
|
// Variables
|
||||||
export const clearAddArtist = createAction(types.CLEAR_ADD_ARTIST);
|
|
||||||
export const setAddArtistDefault = createAction(types.SET_ADD_ARTIST_DEFAULT);
|
|
||||||
|
|
||||||
export const setAddArtistValue = createAction(types.SET_ADD_ARTIST_VALUE, (payload) => {
|
export const section = 'addArtist';
|
||||||
|
let abortCurrentRequest = null;
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isAdding: false,
|
||||||
|
isAdded: false,
|
||||||
|
addError: null,
|
||||||
|
items: [],
|
||||||
|
|
||||||
|
defaults: {
|
||||||
|
rootFolderPath: '',
|
||||||
|
monitor: 'allAlbums',
|
||||||
|
qualityProfileId: 0,
|
||||||
|
languageProfileId: 0,
|
||||||
|
metadataProfileId: 0,
|
||||||
|
albumFolder: true,
|
||||||
|
tags: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'addArtist.defaults'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const LOOKUP_ARTIST = 'addArtist/lookupArtist';
|
||||||
|
export const ADD_ARTIST = 'addArtist/addArtist';
|
||||||
|
export const SET_ADD_ARTIST_VALUE = 'addArtist/setAddArtistValue';
|
||||||
|
export const CLEAR_ADD_ARTIST = 'addArtist/clearAddArtist';
|
||||||
|
export const SET_ADD_ARTIST_DEFAULT = 'addArtist/setAddArtistDefault';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const lookupArtist = createThunk(LOOKUP_ARTIST);
|
||||||
|
export const addArtist = createThunk(ADD_ARTIST);
|
||||||
|
export const clearAddArtist = createAction(CLEAR_ADD_ARTIST);
|
||||||
|
export const setAddArtistDefault = createAction(SET_ADD_ARTIST_DEFAULT);
|
||||||
|
|
||||||
|
export const setAddArtistValue = createAction(SET_ADD_ARTIST_VALUE, (payload) => {
|
||||||
return {
|
return {
|
||||||
section: 'addArtist',
|
section,
|
||||||
...payload
|
...payload
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
|
[LOOKUP_ARTIST]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({ section, isFetching: true }));
|
||||||
|
|
||||||
|
if (abortCurrentRequest) {
|
||||||
|
abortCurrentRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { request, abortRequest } = createAjaxRequest({
|
||||||
|
url: '/artist/lookup',
|
||||||
|
data: {
|
||||||
|
term: payload.term
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
abortCurrentRequest = abortRequest;
|
||||||
|
|
||||||
|
request.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
update({ section, data }),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: true,
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
request.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr.aborted ? null : xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[ADD_ARTIST]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({ section, isAdding: true }));
|
||||||
|
|
||||||
|
const foreignArtistId = payload.foreignArtistId;
|
||||||
|
const items = getState().addArtist.items;
|
||||||
|
const newArtist = getNewArtist(_.cloneDeep(_.find(items, { foreignArtistId })), payload);
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/artist',
|
||||||
|
method: 'POST',
|
||||||
|
contentType: 'application/json',
|
||||||
|
data: JSON.stringify(newArtist)
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
updateItem({ section: 'artist', ...data }),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
isAdding: false,
|
||||||
|
isAdded: true,
|
||||||
|
addError: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isAdding: false,
|
||||||
|
isAdded: false,
|
||||||
|
addError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ADD_ARTIST_VALUE]: createSetSettingValueReducer(section),
|
||||||
|
|
||||||
|
[SET_ADD_ARTIST_DEFAULT]: function(state, { payload }) {
|
||||||
|
const newState = getSectionState(state, section);
|
||||||
|
|
||||||
|
newState.defaults = {
|
||||||
|
...newState.defaults,
|
||||||
|
...payload
|
||||||
|
};
|
||||||
|
|
||||||
|
return updateSectionState(state, section, newState);
|
||||||
|
},
|
||||||
|
|
||||||
|
[CLEAR_ADD_ARTIST]: function(state) {
|
||||||
|
const {
|
||||||
|
defaults,
|
||||||
|
...otherDefaultState
|
||||||
|
} = defaultState;
|
||||||
|
|
||||||
|
return Object.assign({}, state, otherDefaultState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import { batchActions } from 'redux-batched-actions';
|
|
||||||
import { sortDirections } from 'Helpers/Props';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { set, update } from './baseActions';
|
|
||||||
import { fetchAlbumHistory } from './albumHistoryActions';
|
|
||||||
|
|
||||||
const albumHistoryActionHandlers = {
|
|
||||||
[types.FETCH_ALBUM_HISTORY]: function(payload) {
|
|
||||||
const section = 'albumHistory';
|
|
||||||
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({ section, isFetching: true }));
|
|
||||||
|
|
||||||
const queryParams = {
|
|
||||||
pageSize: 1000,
|
|
||||||
page: 1,
|
|
||||||
filterKey: 'albumId',
|
|
||||||
filterValue: payload.albumId,
|
|
||||||
sortKey: 'date',
|
|
||||||
sortDirection: sortDirections.DESCENDING
|
|
||||||
};
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/history',
|
|
||||||
data: queryParams
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(batchActions([
|
|
||||||
update({ section, data: data.records }),
|
|
||||||
|
|
||||||
set({
|
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: true,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: false,
|
|
||||||
error: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.ALBUM_HISTORY_MARK_AS_FAILED]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const {
|
|
||||||
historyId,
|
|
||||||
albumId
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/history/failed',
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
id: historyId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done(() => {
|
|
||||||
dispatch(fetchAlbumHistory({ albumId }));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default albumHistoryActionHandlers;
|
|
|
@ -1,7 +1,113 @@
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import albumHistoryActionHandlers from './albumHistoryActionHandlers';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import { sortDirections } from 'Helpers/Props';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { set, update } from './baseActions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
export const section = 'albumHistory';
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_ALBUM_HISTORY = 'albumHistory/fetchAlbumHistory';
|
||||||
|
export const CLEAR_ALBUM_HISTORY = 'albumHistory/clearAlbumHistory';
|
||||||
|
export const ALBUM_HISTORY_MARK_AS_FAILED = 'albumHistory/albumHistoryMarkAsFailed';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchAlbumHistory = createThunk(FETCH_ALBUM_HISTORY);
|
||||||
|
export const clearAlbumHistory = createAction(CLEAR_ALBUM_HISTORY);
|
||||||
|
export const albumHistoryMarkAsFailed = createThunk(ALBUM_HISTORY_MARK_AS_FAILED);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
|
[FETCH_ALBUM_HISTORY]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({ section, isFetching: true }));
|
||||||
|
|
||||||
|
const queryParams = {
|
||||||
|
pageSize: 1000,
|
||||||
|
page: 1,
|
||||||
|
filterKey: 'albumId',
|
||||||
|
filterValue: payload.albumId,
|
||||||
|
sortKey: 'date',
|
||||||
|
sortDirection: sortDirections.DESCENDING
|
||||||
|
};
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/history',
|
||||||
|
data: queryParams
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
update({ section, data: data.records }),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: true,
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[ALBUM_HISTORY_MARK_AS_FAILED]: function(getState, payload, dispatch) {
|
||||||
|
const {
|
||||||
|
historyId,
|
||||||
|
albumId
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/history/failed',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
id: historyId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done(() => {
|
||||||
|
dispatch(fetchAlbumHistory({ albumId }));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[CLEAR_ALBUM_HISTORY]: (state) => {
|
||||||
|
return Object.assign({}, state, defaultState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
||||||
export const fetchAlbumHistory = albumHistoryActionHandlers[types.FETCH_ALBUM_HISTORY];
|
|
||||||
export const clearAlbumHistory = createAction(types.CLEAR_ALBUM_HISTORY);
|
|
||||||
export const albumHistoryMarkAsFailed = albumHistoryActionHandlers[types.ALBUM_HISTORY_MARK_AS_FAILED];
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import getMonitoringOptions from 'Utilities/Artist/getMonitoringOptions';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { set } from './baseActions';
|
|
||||||
import { fetchArtist } from './artistActions';
|
|
||||||
|
|
||||||
const section = 'albumStudio';
|
|
||||||
|
|
||||||
const albumStudioActionHandlers = {
|
|
||||||
[types.SAVE_ALBUM_STUDIO]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const {
|
|
||||||
artistIds,
|
|
||||||
monitored,
|
|
||||||
monitor
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
let monitoringOptions = null;
|
|
||||||
const artist = [];
|
|
||||||
const allArtists = getState().artist.items;
|
|
||||||
|
|
||||||
artistIds.forEach((id) => {
|
|
||||||
const s = _.find(allArtists, { id });
|
|
||||||
const artistToUpdate = { id };
|
|
||||||
|
|
||||||
if (payload.hasOwnProperty('monitored')) {
|
|
||||||
artistToUpdate.monitored = monitored;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor) {
|
|
||||||
const {
|
|
||||||
albums,
|
|
||||||
options: artistMonitoringOptions
|
|
||||||
} = getMonitoringOptions(_.cloneDeep(s.albums), monitor);
|
|
||||||
|
|
||||||
if (!monitoringOptions) {
|
|
||||||
monitoringOptions = artistMonitoringOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
artistToUpdate.albums = albums;
|
|
||||||
}
|
|
||||||
|
|
||||||
artist.push(artistToUpdate);
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/albumStudio',
|
|
||||||
method: 'POST',
|
|
||||||
data: JSON.stringify({
|
|
||||||
artist,
|
|
||||||
monitoringOptions
|
|
||||||
}),
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(fetchArtist());
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: null
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default albumStudioActionHandlers;
|
|
|
@ -1,7 +1,139 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import getMonitoringOptions from 'Utilities/Artist/getMonitoringOptions';
|
||||||
import albumStudioActionHandlers from './albumStudioActionHandlers';
|
import { filterTypes, sortDirections } from 'Helpers/Props';
|
||||||
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||||
|
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { set } from './baseActions';
|
||||||
|
import { fetchArtist } from './artistActions';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
|
||||||
|
export const section = 'albumStudio';
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
sortKey: 'sortName',
|
||||||
|
sortDirection: sortDirections.ASCENDING,
|
||||||
|
secondarySortKey: 'sortName',
|
||||||
|
secondarySortDirection: sortDirections.ASCENDING,
|
||||||
|
filterKey: null,
|
||||||
|
filterValue: null,
|
||||||
|
filterType: filterTypes.EQUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'albumStudio.sortKey',
|
||||||
|
'albumStudio.sortDirection',
|
||||||
|
'albumStudio.filterKey',
|
||||||
|
'albumStudio.filterValue',
|
||||||
|
'albumStudio.filterType'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const SET_ALBUM_STUDIO_SORT = 'albumStudio/setAlbumStudioSort';
|
||||||
|
export const SET_ALBUM_STUDIO_FILTER = 'albumStudio/setAlbumStudioFilter';
|
||||||
|
export const SAVE_ALBUM_STUDIO = 'albumStudio/saveAlbumStudio';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const setAlbumStudioSort = createAction(SET_ALBUM_STUDIO_SORT);
|
||||||
|
export const setAlbumStudioFilter = createAction(SET_ALBUM_STUDIO_FILTER);
|
||||||
|
export const saveAlbumStudio = createThunk(SAVE_ALBUM_STUDIO);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
|
[SAVE_ALBUM_STUDIO]: function(getState, payload, dispatch) {
|
||||||
|
const {
|
||||||
|
artistIds,
|
||||||
|
monitored,
|
||||||
|
monitor
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
let monitoringOptions = null;
|
||||||
|
const artist = [];
|
||||||
|
const allArtists = getState().artist.items;
|
||||||
|
|
||||||
|
artistIds.forEach((id) => {
|
||||||
|
const s = _.find(allArtists, { id });
|
||||||
|
const artistToUpdate = { id };
|
||||||
|
|
||||||
|
if (payload.hasOwnProperty('monitored')) {
|
||||||
|
artistToUpdate.monitored = monitored;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor) {
|
||||||
|
const {
|
||||||
|
albums,
|
||||||
|
options: artistMonitoringOptions
|
||||||
|
} = getMonitoringOptions(_.cloneDeep(s.albums), monitor);
|
||||||
|
|
||||||
|
if (!monitoringOptions) {
|
||||||
|
monitoringOptions = artistMonitoringOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
artistToUpdate.albums = albums;
|
||||||
|
}
|
||||||
|
|
||||||
|
artist.push(artistToUpdate);
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/albumStudio',
|
||||||
|
method: 'POST',
|
||||||
|
data: JSON.stringify({
|
||||||
|
artist,
|
||||||
|
monitoringOptions
|
||||||
|
}),
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(fetchArtist());
|
||||||
|
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ALBUM_STUDIO_SORT]: createSetClientSideCollectionSortReducer(section),
|
||||||
|
[SET_ALBUM_STUDIO_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
||||||
export const setAlbumStudioSort = createAction(types.SET_ALBUM_STUDIO_SORT);
|
|
||||||
export const setAlbumStudioFilter = createAction(types.SET_ALBUM_STUDIO_FILTER);
|
|
||||||
export const saveAlbumStudio = albumStudioActionHandlers[types.SAVE_ALBUM_STUDIO];
|
|
||||||
|
|
|
@ -1,27 +1,134 @@
|
||||||
|
import _ from 'lodash';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import getSectionState from 'Utilities/State/getSectionState';
|
||||||
|
import updateSectionState from 'Utilities/State/updateSectionState';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
|
||||||
export const saveDimensions = createAction(types.SAVE_DIMENSIONS);
|
function getDimensions(width, height) {
|
||||||
export const setVersion = createAction(types.SET_VERSION);
|
const dimensions = {
|
||||||
export const setIsSidebarVisible = createAction(types.SET_IS_SIDEBAR_VISIBLE);
|
width,
|
||||||
|
height,
|
||||||
export const setAppValue = createAction(types.SET_APP_VALUE, (payload) => {
|
isExtraSmallScreen: width <= 480,
|
||||||
return {
|
isSmallScreen: width <= 768,
|
||||||
section: 'app',
|
isMediumScreen: width <= 992,
|
||||||
...payload
|
isLargeScreen: width <= 1200
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
||||||
export const showMessage = createAction(types.SHOW_MESSAGE, (payload) => {
|
return dimensions;
|
||||||
return {
|
}
|
||||||
section: 'messages',
|
|
||||||
...payload
|
//
|
||||||
};
|
// Variables
|
||||||
});
|
|
||||||
|
export const section = 'app';
|
||||||
|
const messagesSection = 'app.messages';
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
dimensions: getDimensions(window.innerWidth, window.innerHeight),
|
||||||
|
messages: {
|
||||||
|
items: []
|
||||||
|
},
|
||||||
|
version: window.Sonarr.version,
|
||||||
|
isUpdated: false,
|
||||||
|
isConnected: true,
|
||||||
|
isReconnecting: false,
|
||||||
|
isDisconnected: false,
|
||||||
|
isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Types
|
||||||
|
|
||||||
|
export const SHOW_MESSAGE = 'app/showMessage';
|
||||||
|
export const HIDE_MESSAGE = 'app/hideMessage';
|
||||||
|
export const SAVE_DIMENSIONS = 'app/saveDimensions';
|
||||||
|
export const SET_VERSION = 'app/setVersion';
|
||||||
|
export const SET_APP_VALUE = 'app/setAppValue';
|
||||||
|
export const SET_IS_SIDEBAR_VISIBLE = 'app/setIsSidebarVisible';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const saveDimensions = createAction(SAVE_DIMENSIONS);
|
||||||
|
export const setVersion = createAction(SET_VERSION);
|
||||||
|
export const setIsSidebarVisible = createAction(SET_IS_SIDEBAR_VISIBLE);
|
||||||
|
export const setAppValue = createAction(SET_APP_VALUE);
|
||||||
|
export const showMessage = createAction(SHOW_MESSAGE);
|
||||||
|
export const hideMessage = createAction(HIDE_MESSAGE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SAVE_DIMENSIONS]: function(state, { payload }) {
|
||||||
|
const {
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const dimensions = getDimensions(width, height);
|
||||||
|
|
||||||
|
return Object.assign({}, state, { dimensions });
|
||||||
|
},
|
||||||
|
|
||||||
|
[SHOW_MESSAGE]: function(state, { payload }) {
|
||||||
|
const newState = getSectionState(state, messagesSection);
|
||||||
|
const items = newState.items;
|
||||||
|
const index = _.findIndex(items, { id: payload.id });
|
||||||
|
|
||||||
|
newState.items = [...items];
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
const item = items[index];
|
||||||
|
|
||||||
|
newState.items.splice(index, 1, { ...item, ...payload });
|
||||||
|
} else {
|
||||||
|
newState.items.push({ ...payload });
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateSectionState(state, messagesSection, newState);
|
||||||
|
},
|
||||||
|
|
||||||
|
[HIDE_MESSAGE]: function(state, { payload }) {
|
||||||
|
const newState = getSectionState(state, messagesSection);
|
||||||
|
|
||||||
|
newState.items = [...newState.items];
|
||||||
|
_.remove(newState.items, { id: payload.id });
|
||||||
|
|
||||||
|
return updateSectionState(state, messagesSection, newState);
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_APP_VALUE]: function(state, { payload }) {
|
||||||
|
const newState = Object.assign(getSectionState(state, section), payload);
|
||||||
|
|
||||||
|
return updateSectionState(state, section, newState);
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_VERSION]: function(state, { payload }) {
|
||||||
|
const version = payload.version;
|
||||||
|
|
||||||
|
const newState = {
|
||||||
|
version
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state.version !== version) {
|
||||||
|
newState.isUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign({}, state, newState);
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_IS_SIDEBAR_VISIBLE]: function(state, { payload }) {
|
||||||
|
const newState = {
|
||||||
|
isSidebarVisible: payload.isSidebarVisible
|
||||||
|
};
|
||||||
|
|
||||||
|
return Object.assign({}, state, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
||||||
export const hideMessage = createAction(types.HIDE_MESSAGE, (payload) => {
|
|
||||||
return {
|
|
||||||
section: 'messages',
|
|
||||||
...payload
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import { batchActions } from 'redux-batched-actions';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import createFetchHandler from './Creators/createFetchHandler';
|
|
||||||
import createSaveProviderHandler from './Creators/createSaveProviderHandler';
|
|
||||||
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
|
||||||
import { updateItem } from './baseActions';
|
|
||||||
|
|
||||||
const section = 'artist';
|
|
||||||
|
|
||||||
const artistActionHandlers = {
|
|
||||||
[types.FETCH_ARTIST]: createFetchHandler(section, '/artist'),
|
|
||||||
|
|
||||||
[types.SAVE_ARTIST]: createSaveProviderHandler(
|
|
||||||
section,
|
|
||||||
'/artist',
|
|
||||||
(state) => state.artist),
|
|
||||||
|
|
||||||
[types.DELETE_ARTIST]: createRemoveItemHandler(
|
|
||||||
section,
|
|
||||||
'/artist',
|
|
||||||
(state) => state.artist),
|
|
||||||
|
|
||||||
[types.TOGGLE_ARTIST_MONITORED]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const {
|
|
||||||
artistId: id,
|
|
||||||
monitored
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
const artist = _.find(getState().artist.items, { id });
|
|
||||||
|
|
||||||
dispatch(updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
isSaving: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: `/artist/${id}`,
|
|
||||||
method: 'PUT',
|
|
||||||
data: JSON.stringify({
|
|
||||||
...artist,
|
|
||||||
monitored
|
|
||||||
}),
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
monitored
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
isSaving: false
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.TOGGLE_ALBUM_MONITORED]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const {
|
|
||||||
artistId: id,
|
|
||||||
seasonNumber,
|
|
||||||
monitored
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
const artist = _.find(getState().artist.items, { id });
|
|
||||||
const seasons = _.cloneDeep(artist.seasons);
|
|
||||||
const season = _.find(seasons, { seasonNumber });
|
|
||||||
|
|
||||||
season.isSaving = true;
|
|
||||||
|
|
||||||
dispatch(updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
seasons
|
|
||||||
}));
|
|
||||||
|
|
||||||
season.monitored = monitored;
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: `/artist/${id}`,
|
|
||||||
method: 'PUT',
|
|
||||||
data: JSON.stringify({
|
|
||||||
...artist,
|
|
||||||
seasons
|
|
||||||
}),
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
const episodes = _.filter(getState().episodes.items, { artistId: id, seasonNumber });
|
|
||||||
|
|
||||||
dispatch(batchActions([
|
|
||||||
updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
...data
|
|
||||||
}),
|
|
||||||
|
|
||||||
...episodes.map((episode) => {
|
|
||||||
return updateItem({
|
|
||||||
id: episode.id,
|
|
||||||
section: 'episodes',
|
|
||||||
monitored
|
|
||||||
});
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(updateItem({
|
|
||||||
id,
|
|
||||||
section,
|
|
||||||
seasons: artist.seasons
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default artistActionHandlers;
|
|
|
@ -1,16 +1,187 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import artistActionHandlers from './artistActionHandlers';
|
import { sortDirections } from 'Helpers/Props';
|
||||||
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer';
|
||||||
|
import createFetchHandler from './Creators/createFetchHandler';
|
||||||
|
import createSaveProviderHandler from './Creators/createSaveProviderHandler';
|
||||||
|
import createRemoveItemHandler from './Creators/createRemoveItemHandler';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { updateItem } from './baseActions';
|
||||||
|
|
||||||
export const fetchArtist = artistActionHandlers[types.FETCH_ARTIST];
|
//
|
||||||
export const saveArtist = artistActionHandlers[types.SAVE_ARTIST];
|
// Variables
|
||||||
export const deleteArtist = artistActionHandlers[types.DELETE_ARTIST];
|
|
||||||
export const toggleArtistMonitored = artistActionHandlers[types.TOGGLE_ARTIST_MONITORED];
|
|
||||||
export const toggleSeasonMonitored = artistActionHandlers[types.TOGGLE_ALBUM_MONITORED];
|
|
||||||
|
|
||||||
export const setArtistValue = createAction(types.SET_ARTIST_VALUE, (payload) => {
|
export const section = 'artist';
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: null,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
items: [],
|
||||||
|
sortKey: 'sortName',
|
||||||
|
sortDirection: sortDirections.ASCENDING,
|
||||||
|
pendingChanges: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_ARTIST = 'artist/fetchArtist';
|
||||||
|
export const SET_ARTIST_VALUE = 'artist/setArtistValue';
|
||||||
|
export const SAVE_ARTIST = 'artist/saveArtist';
|
||||||
|
export const DELETE_ARTIST = 'artist/deleteArtist';
|
||||||
|
|
||||||
|
export const TOGGLE_ARTIST_MONITORED = 'artist/toggleArtistMonitored';
|
||||||
|
export const TOGGLE_ALBUM_MONITORED = 'artist/toggleAlbumMonitored';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchArtist = createThunk(FETCH_ARTIST);
|
||||||
|
export const saveArtist = createThunk(SAVE_ARTIST);
|
||||||
|
export const deleteArtist = createThunk(DELETE_ARTIST);
|
||||||
|
export const toggleArtistMonitored = createThunk(TOGGLE_ARTIST_MONITORED);
|
||||||
|
export const toggleAlbumMonitored = createThunk(TOGGLE_ALBUM_MONITORED);
|
||||||
|
|
||||||
|
export const setArtistValue = createAction(SET_ARTIST_VALUE, (payload) => {
|
||||||
return {
|
return {
|
||||||
section: 'artist',
|
section: 'artist',
|
||||||
...payload
|
...payload
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
|
[FETCH_ARTIST]: createFetchHandler(section, '/artist'),
|
||||||
|
|
||||||
|
[SAVE_ARTIST]: createSaveProviderHandler(
|
||||||
|
section, '/artist'),
|
||||||
|
|
||||||
|
[DELETE_ARTIST]: createRemoveItemHandler(
|
||||||
|
section,
|
||||||
|
'/artist'
|
||||||
|
),
|
||||||
|
|
||||||
|
[TOGGLE_ARTIST_MONITORED]: (getState, payload, dispatch) => {
|
||||||
|
const {
|
||||||
|
artistId: id,
|
||||||
|
monitored
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const artist = _.find(getState().artist.items, { id });
|
||||||
|
|
||||||
|
dispatch(updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
isSaving: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: `/artist/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: JSON.stringify({
|
||||||
|
...artist,
|
||||||
|
monitored
|
||||||
|
}),
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
monitored
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
isSaving: false
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[TOGGLE_ALBUM_MONITORED]: (getState, payload, dispatch) => {
|
||||||
|
const {
|
||||||
|
artistId: id,
|
||||||
|
seasonNumber,
|
||||||
|
monitored
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const artist = _.find(getState().artist.items, { id });
|
||||||
|
const seasons = _.cloneDeep(artist.seasons);
|
||||||
|
const season = _.find(seasons, { seasonNumber });
|
||||||
|
|
||||||
|
season.isSaving = true;
|
||||||
|
|
||||||
|
dispatch(updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
seasons
|
||||||
|
}));
|
||||||
|
|
||||||
|
season.monitored = monitored;
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: `/artist/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: JSON.stringify({
|
||||||
|
...artist,
|
||||||
|
seasons
|
||||||
|
}),
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
const episodes = _.filter(getState().episodes.items, { artistId: id, seasonNumber });
|
||||||
|
|
||||||
|
dispatch(batchActions([
|
||||||
|
updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
...data
|
||||||
|
}),
|
||||||
|
|
||||||
|
...episodes.map((episode) => {
|
||||||
|
return updateItem({
|
||||||
|
id: episode.id,
|
||||||
|
section: 'episodes',
|
||||||
|
monitored
|
||||||
|
});
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(updateItem({
|
||||||
|
id,
|
||||||
|
section,
|
||||||
|
seasons: artist.seasons
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ARTIST_VALUE]: createSetSettingValueReducer(section)
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
import $ from 'jquery';
|
|
||||||
import { batchActions } from 'redux-batched-actions';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { set, updateItem } from './baseActions';
|
|
||||||
|
|
||||||
const section = 'artistEditor';
|
|
||||||
|
|
||||||
const artistEditorActionHandlers = {
|
|
||||||
[types.SAVE_ARTIST_EDITOR]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/artist/editor',
|
|
||||||
method: 'PUT',
|
|
||||||
data: JSON.stringify(payload),
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(batchActions([
|
|
||||||
...data.map((artist) => {
|
|
||||||
return updateItem({
|
|
||||||
id: artist.id,
|
|
||||||
section: 'artist',
|
|
||||||
...artist
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
|
|
||||||
set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isSaving: false,
|
|
||||||
saveError: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.BULK_DELETE_ARTIST]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isDeleting: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/artist/editor',
|
|
||||||
method: 'DELETE',
|
|
||||||
data: JSON.stringify(payload),
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done(() => {
|
|
||||||
// SignaR will take care of removing the serires from the collection
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isDeleting: false,
|
|
||||||
deleteError: null
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isDeleting: false,
|
|
||||||
deleteError: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default artistEditorActionHandlers;
|
|
|
@ -1,8 +1,142 @@
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import artistEditorActionHandlers from './artistEditorActionHandlers';
|
import { filterTypes, sortDirections } from 'Helpers/Props';
|
||||||
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||||
|
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { set, updateItem } from './baseActions';
|
||||||
|
|
||||||
export const setArtistEditorSort = createAction(types.SET_ARTIST_EDITOR_SORT);
|
//
|
||||||
export const setArtistEditorFilter = createAction(types.SET_ARTIST_EDITOR_FILTER);
|
// Variables
|
||||||
export const saveArtistEditor = artistEditorActionHandlers[types.SAVE_ARTIST_EDITOR];
|
|
||||||
export const bulkDeleteArtist = artistEditorActionHandlers[types.BULK_DELETE_ARTIST];
|
export const section = 'artistEditor';
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: null,
|
||||||
|
sortKey: 'sortName',
|
||||||
|
sortDirection: sortDirections.ASCENDING,
|
||||||
|
secondarySortKey: 'sortName',
|
||||||
|
secondarySortDirection: sortDirections.ASCENDING,
|
||||||
|
filterKey: null,
|
||||||
|
filterValue: null,
|
||||||
|
filterType: filterTypes.EQUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'artistEditor.sortKey',
|
||||||
|
'artistEditor.sortDirection',
|
||||||
|
'artistEditor.filterKey',
|
||||||
|
'artistEditor.filterValue',
|
||||||
|
'artistEditor.filterType'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const SET_ARTIST_EDITOR_SORT = 'artistEditor/setArtistEditorSort';
|
||||||
|
export const SET_ARTIST_EDITOR_FILTER = 'artistEditor/setArtistEditorFilter';
|
||||||
|
export const SAVE_ARTIST_EDITOR = 'artistEditor/saveArtistEditor';
|
||||||
|
export const BULK_DELETE_ARTIST = 'artistEditor/bulkDeleteArtist';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const setArtistEditorSort = createAction(SET_ARTIST_EDITOR_SORT);
|
||||||
|
export const setArtistEditorFilter = createAction(SET_ARTIST_EDITOR_FILTER);
|
||||||
|
export const saveArtistEditor = createThunk(SAVE_ARTIST_EDITOR);
|
||||||
|
export const bulkDeleteArtist = createThunk(BULK_DELETE_ARTIST);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
[SAVE_ARTIST_EDITOR]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/artist/editor',
|
||||||
|
method: 'PUT',
|
||||||
|
data: JSON.stringify(payload),
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
...data.map((artist) => {
|
||||||
|
return updateItem({
|
||||||
|
id: artist.id,
|
||||||
|
section: 'artist',
|
||||||
|
...artist
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isSaving: false,
|
||||||
|
saveError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[BULK_DELETE_ARTIST]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isDeleting: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/artist/editor',
|
||||||
|
method: 'DELETE',
|
||||||
|
data: JSON.stringify(payload),
|
||||||
|
dataType: 'json'
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done(() => {
|
||||||
|
// SignaR will take care of removing the serires from the collection
|
||||||
|
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: null
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isDeleting: false,
|
||||||
|
deleteError: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ARTIST_EDITOR_SORT]: createSetClientSideCollectionSortReducer(section),
|
||||||
|
[SET_ARTIST_EDITOR_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,10 +1,279 @@
|
||||||
|
import moment from 'moment';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { filterTypes, sortDirections } from 'Helpers/Props';
|
||||||
|
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
|
||||||
|
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||||
|
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
|
||||||
export const setArtistSort = createAction(types.SET_ARTIST_SORT);
|
//
|
||||||
export const setArtistFilter = createAction(types.SET_ARTIST_FILTER);
|
// Variables
|
||||||
export const setArtistView = createAction(types.SET_ARTIST_VIEW);
|
|
||||||
export const setArtistTableOption = createAction(types.SET_ARTIST_TABLE_OPTION);
|
export const section = 'artistIndex';
|
||||||
export const setArtistPosterOption = createAction(types.SET_ARTIST_POSTER_OPTION);
|
|
||||||
export const setArtistBannerOption = createAction(types.SET_ARTIST_BANNER_OPTION);
|
//
|
||||||
export const setArtistOverviewOption = createAction(types.SET_ARTIST_OVERVIEW_OPTION);
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
sortKey: 'sortName',
|
||||||
|
sortDirection: sortDirections.ASCENDING,
|
||||||
|
secondarySortKey: 'sortName',
|
||||||
|
secondarySortDirection: sortDirections.ASCENDING,
|
||||||
|
filterKey: null,
|
||||||
|
filterValue: null,
|
||||||
|
filterType: filterTypes.EQUAL,
|
||||||
|
view: 'posters',
|
||||||
|
|
||||||
|
posterOptions: {
|
||||||
|
detailedProgressBar: false,
|
||||||
|
size: 'large',
|
||||||
|
showTitle: false,
|
||||||
|
showQualityProfile: true
|
||||||
|
},
|
||||||
|
|
||||||
|
bannerOptions: {
|
||||||
|
detailedProgressBar: false,
|
||||||
|
size: 'large',
|
||||||
|
showTitle: false,
|
||||||
|
showQualityProfile: true
|
||||||
|
},
|
||||||
|
|
||||||
|
overviewOptions: {
|
||||||
|
detailedProgressBar: false,
|
||||||
|
size: 'medium',
|
||||||
|
showNetwork: true,
|
||||||
|
showQualityProfile: true,
|
||||||
|
showPreviousAiring: false,
|
||||||
|
showAdded: false,
|
||||||
|
showAlbumCount: true,
|
||||||
|
showPath: false,
|
||||||
|
showSizeOnDisk: false
|
||||||
|
},
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
columnLabel: 'Status',
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sortName',
|
||||||
|
label: 'Artist Name',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'artistType',
|
||||||
|
label: 'Type',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'qualityProfileId',
|
||||||
|
label: 'Quality Profile',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'languageProfileId',
|
||||||
|
label: 'Language Profile',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'metadataProfileId',
|
||||||
|
label: 'Metadata Profile',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'nextAiring',
|
||||||
|
label: 'Next Airing',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'previousAiring',
|
||||||
|
label: 'Previous Airing',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'added',
|
||||||
|
label: 'Added',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'albumCount',
|
||||||
|
label: 'Albums',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trackProgress',
|
||||||
|
label: 'Tracks',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trackCount',
|
||||||
|
label: 'Track Count',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'latestAlbum',
|
||||||
|
label: 'Latest Album',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'path',
|
||||||
|
label: 'Path',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sizeOnDisk',
|
||||||
|
label: 'Size on Disk',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'tags',
|
||||||
|
label: 'Tags',
|
||||||
|
isSortable: false,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'actions',
|
||||||
|
columnLabel: 'Actions',
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
sortPredicates: {
|
||||||
|
nextAiring: function(item, direction) {
|
||||||
|
const nextAiring = item.nextAiring;
|
||||||
|
|
||||||
|
if (nextAiring) {
|
||||||
|
return moment(nextAiring).unix();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction === sortDirections.DESCENDING) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number.MAX_VALUE;
|
||||||
|
},
|
||||||
|
|
||||||
|
trackProgress: function(item) {
|
||||||
|
const {
|
||||||
|
trackCount = 0,
|
||||||
|
trackFileCount
|
||||||
|
} = item;
|
||||||
|
|
||||||
|
const progress = trackCount ? trackFileCount / trackCount * 100 : 100;
|
||||||
|
|
||||||
|
return progress + trackCount / 1000000;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
filterPredicates: {
|
||||||
|
missing: function(item) {
|
||||||
|
return item.trackCount - item.trackFileCount > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'artistIndex.sortKey',
|
||||||
|
'artistIndex.sortDirection',
|
||||||
|
'artistIndex.filterKey',
|
||||||
|
'artistIndex.filterValue',
|
||||||
|
'artistIndex.filterType',
|
||||||
|
'artistIndex.view',
|
||||||
|
'artistIndex.columns',
|
||||||
|
'artistIndex.posterOptions',
|
||||||
|
'artistIndex.bannerOptions',
|
||||||
|
'artistIndex.overviewOptions'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const SET_ARTIST_SORT = 'artistIndex/setArtistSort';
|
||||||
|
export const SET_ARTIST_FILTER = 'artistIndex/setArtistFilter';
|
||||||
|
export const SET_ARTIST_VIEW = 'artistIndex/setArtistView';
|
||||||
|
export const SET_ARTIST_TABLE_OPTION = 'artistIndex/setArtistTableOption';
|
||||||
|
export const SET_ARTIST_POSTER_OPTION = 'artistIndex/setArtistPosterOption';
|
||||||
|
export const SET_ARTIST_BANNER_OPTION = 'artistIndex/setArtistBannerOption';
|
||||||
|
export const SET_ARTIST_OVERVIEW_OPTION = 'artistIndex/setArtistOverviewOption';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const setArtistSort = createAction(SET_ARTIST_SORT);
|
||||||
|
export const setArtistFilter = createAction(SET_ARTIST_FILTER);
|
||||||
|
export const setArtistView = createAction(SET_ARTIST_VIEW);
|
||||||
|
export const setArtistTableOption = createAction(SET_ARTIST_TABLE_OPTION);
|
||||||
|
export const setArtistPosterOption = createAction(SET_ARTIST_POSTER_OPTION);
|
||||||
|
export const setArtistBannerOption = createAction(SET_ARTIST_BANNER_OPTION);
|
||||||
|
export const setArtistOverviewOption = createAction(SET_ARTIST_OVERVIEW_OPTION);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ARTIST_SORT]: createSetClientSideCollectionSortReducer(section),
|
||||||
|
[SET_ARTIST_FILTER]: createSetClientSideCollectionFilterReducer(section),
|
||||||
|
|
||||||
|
[SET_ARTIST_VIEW]: function(state, { payload }) {
|
||||||
|
return Object.assign({}, state, { view: payload.view });
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_ARTIST_TABLE_OPTION]: createSetTableOptionReducer(section),
|
||||||
|
|
||||||
|
[SET_ARTIST_POSTER_OPTION]: function(state, { payload }) {
|
||||||
|
const posterOptions = state.posterOptions;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
posterOptions: {
|
||||||
|
...posterOptions,
|
||||||
|
...payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_ARTIST_BANNER_OPTION]: function(state, { payload }) {
|
||||||
|
const bannerOptions = state.bannerOptions;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
bannerOptions: {
|
||||||
|
...bannerOptions,
|
||||||
|
...payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_ARTIST_OVERVIEW_OPTION]: function(state, { payload }) {
|
||||||
|
const overviewOptions = state.overviewOptions;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
overviewOptions: {
|
||||||
|
...overviewOptions,
|
||||||
|
...payload
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,13 +1,29 @@
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
|
||||||
|
|
||||||
export const set = createAction(types.SET);
|
//
|
||||||
|
// Action Types
|
||||||
|
|
||||||
export const update = createAction(types.UPDATE);
|
export const SET = 'base/set';
|
||||||
export const updateItem = createAction(types.UPDATE_ITEM);
|
|
||||||
export const updateServerSideCollection = createAction(types.UPDATE_SERVER_SIDE_COLLECTION);
|
|
||||||
|
|
||||||
export const setSettingValue = createAction(types.SET_SETTING_VALUE);
|
export const UPDATE = 'base/update';
|
||||||
export const clearPendingChanges = createAction(types.CLEAR_PENDING_CHANGES);
|
export const UPDATE_ITEM = 'base/updateItem';
|
||||||
|
export const UPDATE_SERVER_SIDE_COLLECTION = 'base/updateServerSideCollection';
|
||||||
|
|
||||||
export const removeItem = createAction(types.REMOVE_ITEM);
|
export const SET_SETTING_VALUE = 'base/setSettingValue';
|
||||||
|
export const CLEAR_PENDING_CHANGES = 'base/clearPendingChanges';
|
||||||
|
|
||||||
|
export const REMOVE_ITEM = 'base/removeItem';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const set = createAction(SET);
|
||||||
|
|
||||||
|
export const update = createAction(UPDATE);
|
||||||
|
export const updateItem = createAction(UPDATE_ITEM);
|
||||||
|
export const updateServerSideCollection = createAction(UPDATE_SERVER_SIDE_COLLECTION);
|
||||||
|
|
||||||
|
export const setSettingValue = createAction(SET_SETTING_VALUE);
|
||||||
|
export const clearPendingChanges = createAction(CLEAR_PENDING_CHANGES);
|
||||||
|
|
||||||
|
export const removeItem = createAction(REMOVE_ITEM);
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
|
|
||||||
|
|
||||||
const blacklistActionHandlers = {
|
|
||||||
...createServerSideCollectionHandlers('blacklist', '/blacklist', (state) => state, {
|
|
||||||
[serverSideCollectionHandlers.FETCH]: types.FETCH_BLACKLIST,
|
|
||||||
[serverSideCollectionHandlers.FIRST_PAGE]: types.GOTO_FIRST_BLACKLIST_PAGE,
|
|
||||||
[serverSideCollectionHandlers.PREVIOUS_PAGE]: types.GOTO_PREVIOUS_BLACKLIST_PAGE,
|
|
||||||
[serverSideCollectionHandlers.NEXT_PAGE]: types.GOTO_NEXT_BLACKLIST_PAGE,
|
|
||||||
[serverSideCollectionHandlers.LAST_PAGE]: types.GOTO_LAST_BLACKLIST_PAGE,
|
|
||||||
[serverSideCollectionHandlers.EXACT_PAGE]: types.GOTO_BLACKLIST_PAGE,
|
|
||||||
[serverSideCollectionHandlers.SORT]: types.SET_BLACKLIST_SORT
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
export default blacklistActionHandlers;
|
|
|
@ -1,12 +1,127 @@
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
|
||||||
import blacklistActionHandlers from './blacklistActionHandlers';
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import { sortDirections } from 'Helpers/Props';
|
||||||
|
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
|
||||||
|
|
||||||
export const fetchBlacklist = blacklistActionHandlers[types.FETCH_BLACKLIST];
|
//
|
||||||
export const gotoBlacklistFirstPage = blacklistActionHandlers[types.GOTO_FIRST_BLACKLIST_PAGE];
|
// Variables
|
||||||
export const gotoBlacklistPreviousPage = blacklistActionHandlers[types.GOTO_PREVIOUS_BLACKLIST_PAGE];
|
|
||||||
export const gotoBlacklistNextPage = blacklistActionHandlers[types.GOTO_NEXT_BLACKLIST_PAGE];
|
export const section = 'blacklist';
|
||||||
export const gotoBlacklistLastPage = blacklistActionHandlers[types.GOTO_LAST_BLACKLIST_PAGE];
|
|
||||||
export const gotoBlacklistPage = blacklistActionHandlers[types.GOTO_BLACKLIST_PAGE];
|
//
|
||||||
export const setBlacklistSort = blacklistActionHandlers[types.SET_BLACKLIST_SORT];
|
// State
|
||||||
export const setBlacklistTableOption = createAction(types.SET_BLACKLIST_TABLE_OPTION);
|
|
||||||
|
export const defaultState = {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
pageSize: 20,
|
||||||
|
sortKey: 'date',
|
||||||
|
sortDirection: sortDirections.DESCENDING,
|
||||||
|
error: null,
|
||||||
|
items: [],
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'artist.sortName',
|
||||||
|
label: 'Artist Name',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sourceTitle',
|
||||||
|
label: 'Source Title',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'language',
|
||||||
|
label: 'Language',
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'quality',
|
||||||
|
label: 'Quality',
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'date',
|
||||||
|
label: 'Date',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'indexer',
|
||||||
|
label: 'Indexer',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'details',
|
||||||
|
columnLabel: 'Details',
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'blacklist.pageSize',
|
||||||
|
'blacklist.sortKey',
|
||||||
|
'blacklist.sortDirection',
|
||||||
|
'blacklist.columns'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Types
|
||||||
|
|
||||||
|
export const FETCH_BLACKLIST = 'blacklist/fetchBlacklist';
|
||||||
|
export const GOTO_FIRST_BLACKLIST_PAGE = 'blacklist/gotoBlacklistFirstPage';
|
||||||
|
export const GOTO_PREVIOUS_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPreviousPage';
|
||||||
|
export const GOTO_NEXT_BLACKLIST_PAGE = 'blacklist/gotoBlacklistNextPage';
|
||||||
|
export const GOTO_LAST_BLACKLIST_PAGE = 'blacklist/gotoBlacklistLastPage';
|
||||||
|
export const GOTO_BLACKLIST_PAGE = 'blacklist/gotoBlacklistPage';
|
||||||
|
export const SET_BLACKLIST_SORT = 'blacklist/setBlacklistSort';
|
||||||
|
export const SET_BLACKLIST_TABLE_OPTION = 'blacklist/setBlacklistTableOption';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchBlacklist = createThunk(FETCH_BLACKLIST);
|
||||||
|
export const gotoBlacklistFirstPage = createThunk(GOTO_FIRST_BLACKLIST_PAGE);
|
||||||
|
export const gotoBlacklistPreviousPage = createThunk(GOTO_PREVIOUS_BLACKLIST_PAGE);
|
||||||
|
export const gotoBlacklistNextPage = createThunk(GOTO_NEXT_BLACKLIST_PAGE);
|
||||||
|
export const gotoBlacklistLastPage = createThunk(GOTO_LAST_BLACKLIST_PAGE);
|
||||||
|
export const gotoBlacklistPage = createThunk(GOTO_BLACKLIST_PAGE);
|
||||||
|
export const setBlacklistSort = createThunk(SET_BLACKLIST_SORT);
|
||||||
|
export const setBlacklistTableOption = createAction(SET_BLACKLIST_TABLE_OPTION);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
...createServerSideCollectionHandlers(
|
||||||
|
section,
|
||||||
|
'/blacklist',
|
||||||
|
fetchBlacklist,
|
||||||
|
{
|
||||||
|
[serverSideCollectionHandlers.FETCH]: FETCH_BLACKLIST,
|
||||||
|
[serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_BLACKLIST_PAGE,
|
||||||
|
[serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_BLACKLIST_PAGE,
|
||||||
|
[serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_BLACKLIST_PAGE,
|
||||||
|
[serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_BLACKLIST_PAGE,
|
||||||
|
[serverSideCollectionHandlers.EXACT_PAGE]: GOTO_BLACKLIST_PAGE,
|
||||||
|
[serverSideCollectionHandlers.SORT]: SET_BLACKLIST_SORT
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_BLACKLIST_TABLE_OPTION]: createSetTableOptionReducer(section)
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,264 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import moment from 'moment';
|
|
||||||
import { batchActions } from 'redux-batched-actions';
|
|
||||||
import * as calendarViews from 'Calendar/calendarViews';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { set, update } from './baseActions';
|
|
||||||
import { fetchCalendar } from './calendarActions';
|
|
||||||
|
|
||||||
const viewRanges = {
|
|
||||||
[calendarViews.DAY]: 'day',
|
|
||||||
[calendarViews.WEEK]: 'week',
|
|
||||||
[calendarViews.MONTH]: 'month',
|
|
||||||
[calendarViews.FORECAST]: 'day'
|
|
||||||
};
|
|
||||||
|
|
||||||
function getDays(start, end) {
|
|
||||||
const startTime = moment(start);
|
|
||||||
const endTime = moment(end);
|
|
||||||
const difference = endTime.diff(startTime, 'days');
|
|
||||||
|
|
||||||
// Difference is one less than the number of days we need to account for.
|
|
||||||
return _.times(difference + 1, (i) => {
|
|
||||||
return startTime.clone().add(i, 'days').toISOString();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDates(time, view, firstDayOfWeek, dayCount) {
|
|
||||||
const weekName = firstDayOfWeek === 0 ? 'week' : 'isoWeek';
|
|
||||||
|
|
||||||
let start = time.clone().startOf('day');
|
|
||||||
let end = time.clone().endOf('day');
|
|
||||||
|
|
||||||
if (view === calendarViews.WEEK) {
|
|
||||||
start = time.clone().startOf(weekName);
|
|
||||||
end = time.clone().endOf(weekName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view === calendarViews.FORECAST) {
|
|
||||||
start = time.clone().subtract(1, 'day').startOf('day');
|
|
||||||
end = time.clone().add(dayCount - 2, 'days').endOf('day');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view === calendarViews.MONTH) {
|
|
||||||
start = time.clone().startOf('month').startOf(weekName);
|
|
||||||
end = time.clone().endOf('month').endOf(weekName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view === calendarViews.AGENDA) {
|
|
||||||
start = time.clone().subtract(1, 'day').startOf('day');
|
|
||||||
end = time.clone().add(1, 'month').endOf('day');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
start: start.toISOString(),
|
|
||||||
end: end.toISOString(),
|
|
||||||
time: time.toISOString(),
|
|
||||||
dates: getDays(start, end)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPopulatableRange(startDate, endDate, view) {
|
|
||||||
switch (view) {
|
|
||||||
case calendarViews.DAY:
|
|
||||||
return {
|
|
||||||
start: moment(startDate).subtract(1, 'day').toISOString(),
|
|
||||||
end: moment(endDate).add(1, 'day').toISOString()
|
|
||||||
};
|
|
||||||
case calendarViews.WEEK:
|
|
||||||
case calendarViews.FORECAST:
|
|
||||||
return {
|
|
||||||
start: moment(startDate).subtract(1, 'week').toISOString(),
|
|
||||||
end: moment(endDate).add(1, 'week').toISOString()
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return {
|
|
||||||
start: startDate,
|
|
||||||
end: endDate
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isRangePopulated(start, end, state) {
|
|
||||||
const {
|
|
||||||
start: currentStart,
|
|
||||||
end: currentEnd,
|
|
||||||
view: currentView
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
if (!currentStart || !currentEnd) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
start: currentPopulatedStart,
|
|
||||||
end: currentPopulatedEnd
|
|
||||||
} = getPopulatableRange(currentStart, currentEnd, currentView);
|
|
||||||
|
|
||||||
if (
|
|
||||||
moment(start).isAfter(currentPopulatedStart) &&
|
|
||||||
moment(start).isBefore(currentPopulatedEnd)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const section = 'calendar';
|
|
||||||
|
|
||||||
const calendarActionHandlers = {
|
|
||||||
[types.FETCH_CALENDAR]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const state = getState();
|
|
||||||
const unmonitored = state.calendar.unmonitored;
|
|
||||||
|
|
||||||
const {
|
|
||||||
time,
|
|
||||||
view
|
|
||||||
} = payload;
|
|
||||||
|
|
||||||
const dayCount = state.calendar.dayCount;
|
|
||||||
const dates = getDates(moment(time), view, state.settings.ui.item.firstDayOfWeek, dayCount);
|
|
||||||
const { start, end } = getPopulatableRange(dates.start, dates.end, view);
|
|
||||||
const isPrePopulated = isRangePopulated(start, end, state.calendar);
|
|
||||||
|
|
||||||
const basesAttrs = {
|
|
||||||
section,
|
|
||||||
isFetching: true
|
|
||||||
};
|
|
||||||
|
|
||||||
const attrs = isPrePopulated ?
|
|
||||||
{
|
|
||||||
view,
|
|
||||||
...basesAttrs,
|
|
||||||
...dates
|
|
||||||
} :
|
|
||||||
basesAttrs;
|
|
||||||
|
|
||||||
dispatch(set(attrs));
|
|
||||||
|
|
||||||
const promise = $.ajax({
|
|
||||||
url: '/calendar',
|
|
||||||
data: {
|
|
||||||
unmonitored,
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(batchActions([
|
|
||||||
update({ section, data }),
|
|
||||||
|
|
||||||
set({
|
|
||||||
section,
|
|
||||||
view,
|
|
||||||
...dates,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: true,
|
|
||||||
error: null
|
|
||||||
})
|
|
||||||
]));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail((xhr) => {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: false,
|
|
||||||
error: xhr
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.SET_CALENDAR_DAYS_COUNT]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
if (payload.dayCount === getState().calendar.dayCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
dayCount: payload.dayCount
|
|
||||||
}));
|
|
||||||
|
|
||||||
const state = getState();
|
|
||||||
const { time, view } = state.calendar;
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.SET_CALENDAR_INCLUDE_UNMONITORED]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
dispatch(set({
|
|
||||||
section,
|
|
||||||
unmonitored: payload.unmonitored
|
|
||||||
}));
|
|
||||||
|
|
||||||
const state = getState();
|
|
||||||
const { time, view } = state.calendar;
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.SET_CALENDAR_VIEW]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const state = getState();
|
|
||||||
const view = payload.view;
|
|
||||||
const time = view === calendarViews.FORECAST ?
|
|
||||||
moment() :
|
|
||||||
state.calendar.time;
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.GOTO_CALENDAR_TODAY]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const state = getState();
|
|
||||||
const view = state.calendar.view;
|
|
||||||
const time = moment();
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.GOTO_CALENDAR_PREVIOUS_RANGE]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
const {
|
|
||||||
view,
|
|
||||||
dayCount
|
|
||||||
} = state.calendar;
|
|
||||||
|
|
||||||
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
|
||||||
const time = moment(state.calendar.time).subtract(amount, viewRanges[view]);
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.GOTO_CALENDAR_NEXT_RANGE]: function(payload) {
|
|
||||||
return function(dispatch, getState) {
|
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
const {
|
|
||||||
view,
|
|
||||||
dayCount
|
|
||||||
} = state.calendar;
|
|
||||||
|
|
||||||
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
|
||||||
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
|
|
||||||
|
|
||||||
dispatch(fetchCalendar({ time, view }));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default calendarActionHandlers;
|
|
|
@ -1,12 +1,323 @@
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import * as types from './actionTypes';
|
import { batchActions } from 'redux-batched-actions';
|
||||||
import calendarActionHandlers from './calendarActionHandlers';
|
import moment from 'moment';
|
||||||
|
import { createThunk, handleThunks } from 'Store/thunks';
|
||||||
|
import * as calendarViews from 'Calendar/calendarViews';
|
||||||
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
|
import { set, update } from './baseActions';
|
||||||
|
|
||||||
export const fetchCalendar = calendarActionHandlers[types.FETCH_CALENDAR];
|
//
|
||||||
export const setCalendarDaysCount = calendarActionHandlers[types.SET_CALENDAR_DAYS_COUNT];
|
// Variables
|
||||||
export const setCalendarIncludeUnmonitored = calendarActionHandlers[types.SET_CALENDAR_INCLUDE_UNMONITORED];
|
|
||||||
export const setCalendarView = calendarActionHandlers[types.SET_CALENDAR_VIEW];
|
export const section = 'calendar';
|
||||||
export const gotoCalendarToday = calendarActionHandlers[types.GOTO_CALENDAR_TODAY];
|
|
||||||
export const gotoCalendarPreviousRange = calendarActionHandlers[types.GOTO_CALENDAR_PREVIOUS_RANGE];
|
const viewRanges = {
|
||||||
export const gotoCalendarNextRange = calendarActionHandlers[types.GOTO_CALENDAR_NEXT_RANGE];
|
[calendarViews.DAY]: 'day',
|
||||||
export const clearCalendar = createAction(types.CLEAR_CALENDAR);
|
[calendarViews.WEEK]: 'week',
|
||||||
|
[calendarViews.MONTH]: 'month',
|
||||||
|
[calendarViews.FORECAST]: 'day'
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// State
|
||||||
|
|
||||||
|
export const defaultState = {
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
start: null,
|
||||||
|
end: null,
|
||||||
|
dates: [],
|
||||||
|
dayCount: 7,
|
||||||
|
view: window.innerWidth > 768 ? 'week' : 'day',
|
||||||
|
unmonitored: false,
|
||||||
|
showUpcoming: true,
|
||||||
|
error: null,
|
||||||
|
items: []
|
||||||
|
};
|
||||||
|
|
||||||
|
export const persistState = [
|
||||||
|
'calendar.view',
|
||||||
|
'calendar.unmonitored',
|
||||||
|
'calendar.showUpcoming'
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Actions Types
|
||||||
|
|
||||||
|
export const FETCH_CALENDAR = 'calendar/fetchCalendar';
|
||||||
|
export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
|
||||||
|
export const SET_CALENDAR_INCLUDE_UNMONITORED = 'calendar/setCalendarIncludeUnmonitored';
|
||||||
|
export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
|
||||||
|
export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
|
||||||
|
export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
|
||||||
|
export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
|
||||||
|
export const CLEAR_CALENDAR = 'calendar/clearCalendar';
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
function getDays(start, end) {
|
||||||
|
const startTime = moment(start);
|
||||||
|
const endTime = moment(end);
|
||||||
|
const difference = endTime.diff(startTime, 'days');
|
||||||
|
|
||||||
|
// Difference is one less than the number of days we need to account for.
|
||||||
|
return _.times(difference + 1, (i) => {
|
||||||
|
return startTime.clone().add(i, 'days').toISOString();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDates(time, view, firstDayOfWeek, dayCount) {
|
||||||
|
const weekName = firstDayOfWeek === 0 ? 'week' : 'isoWeek';
|
||||||
|
|
||||||
|
let start = time.clone().startOf('day');
|
||||||
|
let end = time.clone().endOf('day');
|
||||||
|
|
||||||
|
if (view === calendarViews.WEEK) {
|
||||||
|
start = time.clone().startOf(weekName);
|
||||||
|
end = time.clone().endOf(weekName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view === calendarViews.FORECAST) {
|
||||||
|
start = time.clone().subtract(1, 'day').startOf('day');
|
||||||
|
end = time.clone().add(dayCount - 2, 'days').endOf('day');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view === calendarViews.MONTH) {
|
||||||
|
start = time.clone().startOf('month').startOf(weekName);
|
||||||
|
end = time.clone().endOf('month').endOf(weekName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view === calendarViews.AGENDA) {
|
||||||
|
start = time.clone().subtract(1, 'day').startOf('day');
|
||||||
|
end = time.clone().add(1, 'month').endOf('day');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start.toISOString(),
|
||||||
|
end: end.toISOString(),
|
||||||
|
time: time.toISOString(),
|
||||||
|
dates: getDays(start, end)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPopulatableRange(startDate, endDate, view) {
|
||||||
|
switch (view) {
|
||||||
|
case calendarViews.DAY:
|
||||||
|
return {
|
||||||
|
start: moment(startDate).subtract(1, 'day').toISOString(),
|
||||||
|
end: moment(endDate).add(1, 'day').toISOString()
|
||||||
|
};
|
||||||
|
case calendarViews.WEEK:
|
||||||
|
case calendarViews.FORECAST:
|
||||||
|
return {
|
||||||
|
start: moment(startDate).subtract(1, 'week').toISOString(),
|
||||||
|
end: moment(endDate).add(1, 'week').toISOString()
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
start: startDate,
|
||||||
|
end: endDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRangePopulated(start, end, state) {
|
||||||
|
const {
|
||||||
|
start: currentStart,
|
||||||
|
end: currentEnd,
|
||||||
|
view: currentView
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
if (!currentStart || !currentEnd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
start: currentPopulatedStart,
|
||||||
|
end: currentPopulatedEnd
|
||||||
|
} = getPopulatableRange(currentStart, currentEnd, currentView);
|
||||||
|
|
||||||
|
if (
|
||||||
|
moment(start).isAfter(currentPopulatedStart) &&
|
||||||
|
moment(start).isBefore(currentPopulatedEnd)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
export const fetchCalendar = createThunk(FETCH_CALENDAR);
|
||||||
|
export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT);
|
||||||
|
export const setCalendarIncludeUnmonitored = createThunk(SET_CALENDAR_INCLUDE_UNMONITORED);
|
||||||
|
export const setCalendarView = createThunk(SET_CALENDAR_VIEW);
|
||||||
|
export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
|
||||||
|
export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
|
||||||
|
export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
|
||||||
|
export const clearCalendar = createAction(CLEAR_CALENDAR);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Action Handlers
|
||||||
|
|
||||||
|
export const actionHandlers = handleThunks({
|
||||||
|
[FETCH_CALENDAR]: function(getState, payload, dispatch) {
|
||||||
|
const state = getState();
|
||||||
|
const unmonitored = state.calendar.unmonitored;
|
||||||
|
|
||||||
|
const {
|
||||||
|
time,
|
||||||
|
view
|
||||||
|
} = payload;
|
||||||
|
|
||||||
|
const dayCount = state.calendar.dayCount;
|
||||||
|
const dates = getDates(moment(time), view, state.settings.ui.item.firstDayOfWeek, dayCount);
|
||||||
|
const { start, end } = getPopulatableRange(dates.start, dates.end, view);
|
||||||
|
const isPrePopulated = isRangePopulated(start, end, state.calendar);
|
||||||
|
|
||||||
|
const basesAttrs = {
|
||||||
|
section,
|
||||||
|
isFetching: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const attrs = isPrePopulated ?
|
||||||
|
{
|
||||||
|
view,
|
||||||
|
...basesAttrs,
|
||||||
|
...dates
|
||||||
|
} :
|
||||||
|
basesAttrs;
|
||||||
|
|
||||||
|
dispatch(set(attrs));
|
||||||
|
|
||||||
|
const promise = $.ajax({
|
||||||
|
url: '/calendar',
|
||||||
|
data: {
|
||||||
|
unmonitored,
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.done((data) => {
|
||||||
|
dispatch(batchActions([
|
||||||
|
update({ section, data }),
|
||||||
|
|
||||||
|
set({
|
||||||
|
section,
|
||||||
|
view,
|
||||||
|
...dates,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: true,
|
||||||
|
error: null
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.fail((xhr) => {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
isFetching: false,
|
||||||
|
isPopulated: false,
|
||||||
|
error: xhr
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_CALENDAR_DAYS_COUNT]: function(getState, payload, dispatch) {
|
||||||
|
if (payload.dayCount === getState().calendar.dayCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
dayCount: payload.dayCount
|
||||||
|
}));
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const { time, view } = state.calendar;
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_CALENDAR_INCLUDE_UNMONITORED]: function(getState, payload, dispatch) {
|
||||||
|
dispatch(set({
|
||||||
|
section,
|
||||||
|
unmonitored: payload.unmonitored
|
||||||
|
}));
|
||||||
|
|
||||||
|
const state = getState();
|
||||||
|
const { time, view } = state.calendar;
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
|
[SET_CALENDAR_VIEW]: function(getState, payload, dispatch) {
|
||||||
|
const state = getState();
|
||||||
|
const view = payload.view;
|
||||||
|
const time = view === calendarViews.FORECAST ?
|
||||||
|
moment() :
|
||||||
|
state.calendar.time;
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
|
[GOTO_CALENDAR_TODAY]: function(getState, payload, dispatch) {
|
||||||
|
const state = getState();
|
||||||
|
const view = state.calendar.view;
|
||||||
|
const time = moment();
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
|
[GOTO_CALENDAR_PREVIOUS_RANGE]: function(getState, payload, dispatch) {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
|
const {
|
||||||
|
view,
|
||||||
|
dayCount
|
||||||
|
} = state.calendar;
|
||||||
|
|
||||||
|
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
||||||
|
const time = moment(state.calendar.time).subtract(amount, viewRanges[view]);
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
},
|
||||||
|
|
||||||
|
[GOTO_CALENDAR_NEXT_RANGE]: function(getState, payload, dispatch) {
|
||||||
|
const state = getState();
|
||||||
|
|
||||||
|
const {
|
||||||
|
view,
|
||||||
|
dayCount
|
||||||
|
} = state.calendar;
|
||||||
|
|
||||||
|
const amount = view === calendarViews.FORECAST ? dayCount : 1;
|
||||||
|
const time = moment(state.calendar.time).add(amount, viewRanges[view]);
|
||||||
|
|
||||||
|
dispatch(fetchCalendar({ time, view }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reducers
|
||||||
|
|
||||||
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[CLEAR_CALENDAR]: (state) => {
|
||||||
|
const {
|
||||||
|
view,
|
||||||
|
unmonitored,
|
||||||
|
showUpcoming,
|
||||||
|
...otherDefaultState
|
||||||
|
} = defaultState;
|
||||||
|
|
||||||
|
return Object.assign({}, state, otherDefaultState);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, defaultState, section);
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
import requestAction from 'Utilities/requestAction';
|
|
||||||
import * as types from './actionTypes';
|
|
||||||
import { setCaptchaValue } from './captchaActions';
|
|
||||||
|
|
||||||
const captchaActionHandlers = {
|
|
||||||
[types.REFRESH_CAPTCHA]: function(payload) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const actionPayload = {
|
|
||||||
action: 'checkCaptcha',
|
|
||||||
...payload
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatch(setCaptchaValue({
|
|
||||||
refreshing: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
const promise = requestAction(actionPayload);
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
if (!data.captchaRequest) {
|
|
||||||
dispatch(setCaptchaValue({
|
|
||||||
refreshing: false
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(setCaptchaValue({
|
|
||||||
refreshing: false,
|
|
||||||
...data.captchaRequest
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
promise.fail(() => {
|
|
||||||
dispatch(setCaptchaValue({
|
|
||||||
refreshing: false
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
[types.GET_CAPTCHA_COOKIE]: function(payload) {
|
|
||||||
return (dispatch, getState) => {
|
|
||||||
const state = getState().captcha;
|
|
||||||
|
|
||||||
const queryParams = {
|
|
||||||
responseUrl: state.responseUrl,
|
|
||||||
ray: state.ray,
|
|
||||||
captchaResponse: payload.captchaResponse
|
|
||||||
};
|
|
||||||
|
|
||||||
const actionPayload = {
|
|
||||||
action: 'getCaptchaCookie',
|
|
||||||
queryParams,
|
|
||||||
...payload
|
|
||||||
};
|
|
||||||
|
|
||||||
const promise = requestAction(actionPayload);
|
|
||||||
|
|
||||||
promise.done((data) => {
|
|
||||||
dispatch(setCaptchaValue({
|
|
||||||
token: data.captchaToken
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default captchaActionHandlers;
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue