Fixed: Backend/Frontend Cleanup

This commit is contained in:
Qstick
2019-06-30 00:58:54 -04:00
parent 286f73f38d
commit d178dce0d3
56 changed files with 519 additions and 925 deletions

View File

@@ -163,7 +163,7 @@ function HistoryDetails(props) {
);
}
if (eventType === 'episodeFileDeleted') {
if (eventType === 'movieFileDeleted') {
const {
reason
} = data;
@@ -199,7 +199,7 @@ function HistoryDetails(props) {
);
}
if (eventType === 'episodeFileRenamed') {
if (eventType === 'movieFileRenamed') {
const {
sourcePath,
sourceRelativePath,

View File

@@ -18,11 +18,11 @@ function getHeaderTitle(eventType) {
case 'downloadFailed':
return 'Download Failed';
case 'downloadFolderImported':
return 'Episode Imported';
case 'episodeFileDeleted':
return 'Episode File Deleted';
case 'episodeFileRenamed':
return 'Episode File Renamed';
return 'Movie Imported';
case 'movieFileDeleted':
return 'Movie File Deleted';
case 'movieFileRenamed':
return 'Movie File Renamed';
default:
return 'Unknown';
}

View File

@@ -71,6 +71,7 @@ class QueueRow extends Component {
quality,
protocol,
indexer,
outputPath,
downloadClient,
estimatedCompletionTime,
timeleft,
@@ -195,6 +196,14 @@ class QueueRow extends Component {
);
}
if (name === 'outputPath') {
return (
<TableRowCell key={name}>
{outputPath}
</TableRowCell>
);
}
if (name === 'estimatedCompletionTime') {
return (
<TimeleftCell
@@ -297,6 +306,7 @@ QueueRow.propTypes = {
quality: PropTypes.object.isRequired,
protocol: PropTypes.string.isRequired,
indexer: PropTypes.string,
outputPath: PropTypes.string,
downloadClient: PropTypes.string,
estimatedCompletionTime: PropTypes.string,
timeleft: PropTypes.string,

View File

@@ -12,8 +12,12 @@ function createMapStateToProps() {
(state) => state.queue.options.includeUnknownMovieItems,
(app, status, includeUnknownMovieItems) => {
const {
errors,
warnings,
unknownErrors,
unknownWarnings,
count,
unknownCount
totalCount
} = status.item;
return {
@@ -21,7 +25,9 @@ function createMapStateToProps() {
isReconnecting: app.isReconnecting,
isPopulated: status.isPopulated,
...status.item,
count: includeUnknownMovieItems ? count : count - unknownCount
count: includeUnknownMovieItems ? totalCount : count,
errors: includeUnknownMovieItems ? errors || unknownErrors : errors,
warnings: includeUnknownMovieItems ? warnings || unknownWarnings : warnings
};
}
);

View File

@@ -13,10 +13,10 @@ function createMapStateToProps() {
createMovieFileSelector(),
createQueueItemSelector(),
createUISettingsSelector(),
(calendarOptions, series, episodeFile, queueItem, uiSettings) => {
(calendarOptions, movie, movieFile, queueItem, uiSettings) => {
return {
series,
episodeFile,
movie,
movieFile,
queueItem,
...calendarOptions,
timeFormat: uiSettings.timeFormat,

View File

@@ -6,11 +6,11 @@ import CalendarEventGroup from './CalendarEventGroup';
function createIsDownloadingSelector() {
return createSelector(
(state, { episodeIds }) => episodeIds,
(state, { movieIds }) => movieIds,
(state) => state.queue.details,
(episodeIds, details) => {
(movieIds, details) => {
return details.items.some((item) => {
return episodeIds.includes(item.episode.id);
return item.movie && movieIds.includes(item.movie.id);
});
}
);
@@ -22,9 +22,9 @@ function createMapStateToProps() {
createMovieSelector(),
createIsDownloadingSelector(),
createUISettingsSelector(),
(calendarOptions, series, isDownloading, uiSettings) => {
(calendarOptions, movie, isDownloading, uiSettings) => {
return {
series,
movie,
isDownloading,
...calendarOptions,
timeFormat: uiSettings.timeFormat,

View File

@@ -83,6 +83,7 @@ class CalendarHeader extends Component {
end,
longDateFormat,
isSmallScreen,
collapseViewButtons,
onTodayPress,
onPreviousPress,
onNextPress
@@ -145,7 +146,7 @@ class CalendarHeader extends Component {
}
{
isSmallScreen ?
collapseViewButtons ?
<Menu
className={styles.viewMenu}
alignMenu={align.RIGHT}
@@ -158,6 +159,18 @@ class CalendarHeader extends Component {
</MenuButton>
<MenuContent>
{
isSmallScreen ?
null :
<ViewMenuItem
name={calendarViews.MONTH}
selectedView={view}
onPress={this.onViewChange}
>
Month
</ViewMenuItem>
}
<ViewMenuItem
name={calendarViews.WEEK}
selectedView={view}
@@ -243,6 +256,7 @@ CalendarHeader.propTypes = {
end: PropTypes.string.isRequired,
view: PropTypes.oneOf(calendarViews.all).isRequired,
isSmallScreen: PropTypes.bool.isRequired,
collapseViewButtons: PropTypes.bool.isRequired,
longDateFormat: PropTypes.string.isRequired,
onViewChange: PropTypes.func.isRequired,
onTodayPress: PropTypes.func.isRequired,

View File

@@ -23,6 +23,7 @@ function createMapStateToProps() {
]);
result.isSmallScreen = dimensions.isSmallScreen;
result.collapseViewButtons = dimensions.isLargeScreen;
result.longDateFormat = uiSettings.longDateFormat;
return result;

View File

@@ -78,8 +78,8 @@
color: $disabledColor;
}
.addNewSeriesSuggestion {
padding: 0 3px;
.addNewMovieSuggestion {
padding: 5px 3px;
cursor: pointer;
}

View File

@@ -76,7 +76,7 @@ class MovieSearchInput extends Component {
renderSuggestion(item, { query }) {
if (item.type === ADD_NEW_TYPE) {
return (
<div className={styles.addNewSeriesSuggestion}>
<div className={styles.addNewMovieSuggestion}>
Search for {query}
</div>
);

View File

@@ -1,10 +1,40 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createDeepEqualSelector from 'Store/Selectors/createDeepEqualSelector';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import MovieIndexFooter from './MovieIndexFooter';
function createUnoptimizedSelector() {
return createSelector(
createClientSideCollectionSelector('movies', 'movieIndex'),
(movies) => {
return movies.items.map((s) => {
const {
monitored,
status,
statistics
} = s;
return {
monitored,
status,
statistics
};
});
}
);
}
function createMoviesSelector() {
return createDeepEqualSelector(
createUnoptimizedSelector(),
(movies) => movies
);
}
function createMapStateToProps() {
return createSelector(
(state) => state.movies.items,
createMoviesSelector(),
(movies) => {
return {
movies

View File

@@ -32,7 +32,7 @@ function BackupSettings(props) {
<FormLabel>Folder</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
type={inputTypes.PATH}
name="backupFolder"
helpText="Relative paths will be under Radarr's AppData directory"
onChange={onInputChange}

View File

@@ -83,10 +83,6 @@ class NamingModal extends Component {
value,
isOpen,
advancedSettings,
season,
episode,
daily,
anime,
additional,
onInputChange,
onModalClose
@@ -112,58 +108,21 @@ class NamingModal extends Component {
const fileNameTokens = [
{
token: '{Series Title} - S{season:00}E{episode:00} - {Episode Title} {Quality Full}',
example: 'Series Title (2010) - S01E01 - Episode Title HDTV-720p Proper'
},
{
token: '{Series Title} - {season:0}x{episode:00} - {Episode Title} {Quality Full}',
example: 'Series Title (2010) - 1x01 - Episode Title HDTV-720p Proper'
},
{
token: '{Series.Title}.S{season:00}E{episode:00}.{EpisodeClean.Title}.{Quality.Full}',
example: 'Series.Title.(2010).S01E01.Episode.Title.HDTV-720p'
token: '{Movie Title} - {Quality Full}',
example: 'Movie Title (2010) - HDTV-720p Proper'
}
];
const seriesTokens = [
{ token: '{Series Title}', example: 'Series Title!' },
{ token: '{Series CleanTitle}', example: 'Series Title' },
{ token: '{Series CleanTitleYear}', example: 'Series Title 2010' },
{ token: '{Series TitleThe}', example: 'Series Title, The' },
{ token: '{Series TitleTheYear}', example: 'Series Title, The (2010)' },
{ token: '{Series TitleYear}', example: 'Series Title (2010)' }
const movieTokens = [
{ token: '{Movie Title}', example: 'Movie Title!' },
{ token: '{Movie CleanTitle}', example: 'Movie Title' },
{ token: '{Movie TitleThe}', example: 'Movie Title, The' }
];
const seriesIdTokens = [
const movieIdTokens = [
{ token: '{ImdbId}', example: 'tt12345' },
{ token: '{TvdbId}', example: '12345' },
{ token: '{TvMazeId}', example: '54321' }
];
const seasonTokens = [
{ token: '{season:0}', example: '1' },
{ token: '{season:00}', example: '01' }
];
const episodeTokens = [
{ token: '{episode:0}', example: '1' },
{ token: '{episode:00}', example: '01' }
];
const airDateTokens = [
{ token: '{Air-Date}', example: '2016-03-20' },
{ token: '{Air Date}', example: '2016 03 20' }
];
const absoluteTokens = [
{ token: '{absolute:0}', example: '1' },
{ token: '{absolute:00}', example: '01' },
{ token: '{absolute:000}', example: '001' }
];
const episodeTitleTokens = [
{ token: '{Episode Title}', example: 'Episode Title' },
{ token: '{Episode CleanTitle}', example: 'Episode Title' }
{ token: '{TmdbId}', example: '123456' }
];
const qualityTokens = [
@@ -175,8 +134,14 @@ class NamingModal extends Component {
{ token: '{MediaInfo Simple}', example: 'x264 DTS' },
{ token: '{MediaInfo Full}', example: 'x264 DTS [EN+DE]' },
{ token: '{MediaInfo VideoCodec}', example: 'x264' },
{ token: '{MediaInfo AudioFormat}', example: 'DTS' },
{ token: '{MediaInfo AudioChannels}', example: '5.1' }
{ token: '{MediaInfo AudioCodec}', example: 'DTS' },
{ token: '{MediaInfo AudioChannels}', example: '5.1' },
{ token: '{MediaInfo AudioLanguages}', example: '[EN+DE]' },
{ token: '{MediaInfo SubtitleLanguages}', example: '[DE]' },
{ token: '{MediaInfo VideoCodec}', example: 'x264' },
{ token: '{MediaInfo VideoBitDepth}', example: '10' },
{ token: '{MediaInfo VideoDynamicRange}', example: 'HDR' }
];
const releaseGroupTokens = [
@@ -184,8 +149,8 @@ class NamingModal extends Component {
];
const originalTokens = [
{ token: '{Original Title}', example: 'Series.Title.S01E01.HDTV.x264-EVOLVE' },
{ token: '{Original Filename}', example: 'series.title.s01e01.hdtv.x264-EVOLVE' }
{ token: '{Original Title}', example: 'Movie.Title.HDTV.x264-EVOLVE' },
{ token: '{Original Filename}', example: 'Movie.title.hdtv.x264-EVOLVE' }
];
return (
@@ -244,10 +209,10 @@ class NamingModal extends Component {
</FieldSet>
}
<FieldSet legend="Series">
<FieldSet legend="Movie">
<div className={styles.groups}>
{
seriesTokens.map(({ token, example }) => {
movieTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
@@ -266,10 +231,10 @@ class NamingModal extends Component {
</div>
</FieldSet>
<FieldSet legend="Series ID">
<FieldSet legend="Movie ID">
<div className={styles.groups}>
{
seriesIdTokens.map(({ token, example }) => {
movieIdTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
@@ -288,133 +253,9 @@ class NamingModal extends Component {
</div>
</FieldSet>
{
season &&
<FieldSet legend="Season">
<div className={styles.groups}>
{
seasonTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
}
{
episode &&
<div>
<FieldSet legend="Episode">
<div className={styles.groups}>
{
episodeTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
{
daily &&
<FieldSet legend="Air-Date">
<div className={styles.groups}>
{
airDateTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
}
{
anime &&
<FieldSet legend="Absolute Episode Number">
<div className={styles.groups}>
{
absoluteTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
}
</div>
}
{
additional &&
<div>
<FieldSet legend="Episode Title">
<div className={styles.groups}>
{
episodeTitleTokens.map(({ token, example }) => {
return (
<NamingOption
key={token}
name={name}
value={value}
token={token}
example={example}
tokenSeparator={tokenSeparator}
tokenCase={tokenCase}
onPress={this.onOptionPress}
/>
);
}
)
}
</div>
</FieldSet>
<FieldSet legend="Quality">
<div className={styles.groups}>
{
@@ -529,20 +370,12 @@ NamingModal.propTypes = {
value: PropTypes.string.isRequired,
isOpen: PropTypes.bool.isRequired,
advancedSettings: PropTypes.bool.isRequired,
season: PropTypes.bool.isRequired,
episode: PropTypes.bool.isRequired,
daily: PropTypes.bool.isRequired,
anime: PropTypes.bool.isRequired,
additional: PropTypes.bool.isRequired,
onInputChange: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
NamingModal.defaultProps = {
season: false,
episode: false,
daily: false,
anime: false,
additional: false
};

View File

@@ -1,6 +1,6 @@
.option {
display: flex;
align-items: center;
align-items: stretch;
flex-wrap: wrap;
margin: 3px;
border: 1px solid $borderColor;
@@ -17,7 +17,7 @@
}
.small {
width: 420px;
width: 480px;
}
.large {
@@ -32,6 +32,9 @@
}
.example {
display: flex;
align-items: center;
align-self: stretch;
flex: 0 0 50%;
padding: 6px 16px;
background-color: #ddd;

View File

@@ -84,7 +84,7 @@ class Notification extends Component {
{
supportsOnDownload && onDownload &&
<Label kind={kinds.SUCCESS}>
On Download
On Import
</Label>
}

View File

@@ -19,6 +19,11 @@ class MoreInfo extends Component {
<Link to="https://radarr.video/">radarr.video</Link>
</DescriptionListItemDescription>
<DescriptionListItemTitle>Discord</DescriptionListItemTitle>
<DescriptionListItemDescription>
<Link to="https://discord.gg/AD3UP37">discord.gg/AD3UP37</Link>
</DescriptionListItemDescription>
<DescriptionListItemTitle>Wiki</DescriptionListItemTitle>
<DescriptionListItemDescription>
<Link to="https://github.com/Radarr/Radarr/wiki">github.com/Radarr/Radarr/wiki</Link>