Compare commits
120 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47360d4d38 | |||
| 788782d009 | |||
| 847d6244aa | |||
| 8fd8128641 | |||
| 136075d233 | |||
| 02cec5312c | |||
| e5f728352c | |||
| 2cc1333e5c | |||
| a79980aae5 | |||
| f2bbef75dd | |||
| d5c1f58839 | |||
| 430ea81937 | |||
| 80099dcacb | |||
| 938b69b240 | |||
| 9839b482b2 | |||
| 4dbd962fca | |||
| 856c4fa4bb | |||
| 45f5ce5f29 | |||
| 9d3e7f62ca | |||
| 594ed666e1 | |||
| 36338310df | |||
| ffde07e4d6 | |||
| 90a1e1dbb3 | |||
| 8b5f305462 | |||
| 2fe6847eb3 | |||
| bf0f681d46 | |||
| f9cb4c1abd | |||
| 1190bf791c | |||
| 53eb88d9a9 | |||
| ed5c063127 | |||
| e691253419 | |||
| 2959f72a10 | |||
| 78ae059f3d | |||
| 7226cab3d8 | |||
| 622162c5f6 | |||
| e612d8c485 | |||
| b20e15855c | |||
| 41e95ef98c | |||
| d8ba7f4d67 | |||
| 97a28fee3b | |||
| e6b782aa20 | |||
| 7aa72b30cb | |||
| 490a0cb2fb | |||
| fa50f60e6b | |||
| b5c9c996a5 | |||
| 9b69d3b051 | |||
| c8a1e49b7b | |||
| 0b300eee1c | |||
| ed107cadac | |||
| a2216f23ec | |||
| faaef80a80 | |||
| 5f70581a59 | |||
| 8369a77365 | |||
| 00f4176dad | |||
| 056c224431 | |||
| d84230d4cc | |||
| a6197ba70d | |||
| 31a16ab571 | |||
| 79c9225b00 | |||
| dd6be39063 | |||
| 668797b406 | |||
| 7bb9250877 | |||
| 6ad9ebb19e | |||
| f8cbca7958 | |||
| f65835b874 | |||
| 59ea905e06 | |||
| d8eda4d089 | |||
| e4eb8f63bb | |||
| d936591b66 | |||
| c61cca7952 | |||
| f38077aac7 | |||
| 3055ed5336 | |||
| 164625a0b2 | |||
| 09ca0a1c0a | |||
| bef881a9e2 | |||
| f7e36581e1 | |||
| 20a8f1cbe7 | |||
| 3da8396b7e | |||
| d61f914bd7 | |||
| 25837adfc7 | |||
| 5516d7e3cd | |||
| e2647deea3 | |||
| 8c34946134 | |||
| 4a66a832b3 | |||
| 2d18e4f89e | |||
| d6c1721f51 | |||
| 99709d6445 | |||
| 916d43d70d | |||
| bc004b3b5b | |||
| 7a222dcd9f | |||
| 48b9c1e8b9 | |||
| 7dde88387a | |||
| 0eddf76622 | |||
| f69a847d9a | |||
| 97ed820575 | |||
| 0ee94a4624 | |||
| 3b7914f63b | |||
| 0005fa57ac | |||
| bbde1dc7a6 | |||
| 1c99ce8876 | |||
| 7a5ae56a96 | |||
| ae8820178d | |||
| c214a6b67b | |||
| b3f6774820 | |||
| 8fd4e41c85 | |||
| 8984fd735b | |||
| 3321123043 | |||
| 23a13b5c23 | |||
| 304a07e23f | |||
| 1e0ec4aefb | |||
| 5c46c75ce7 | |||
| 1c26dd4aca | |||
| 6fae00f51c | |||
| 653ef0a501 | |||
| e606ff05a4 | |||
| dd3ac26604 | |||
| 122d0056ea | |||
| fe41aada06 | |||
| bd1844030d | |||
| 148ee5983d |
@@ -270,7 +270,7 @@ dotnet_diagnostic.CA5397.severity = suggestion
|
|||||||
|
|
||||||
dotnet_diagnostic.SYSLIB0006.severity = none
|
dotnet_diagnostic.SYSLIB0006.severity = none
|
||||||
|
|
||||||
[*.{js,html,js,hbs,less,css}]
|
[*.{js,html,hbs,less,css,ts,tsx}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 577 B After Width: | Height: | Size: 331 B |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 987 B |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 21 KiB |
@@ -9,7 +9,7 @@ variables:
|
|||||||
testsFolder: './_tests'
|
testsFolder: './_tests'
|
||||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||||
majorVersion: '4.6.4'
|
majorVersion: '4.7.3'
|
||||||
minorVersion: $[counter('minorVersion', 2000)]
|
minorVersion: $[counter('minorVersion', 2000)]
|
||||||
radarrVersion: '$(majorVersion).$(minorVersion)'
|
radarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
||||||
@@ -363,7 +363,7 @@ stages:
|
|||||||
- bash: |
|
- bash: |
|
||||||
echo "Uploading source maps to sentry"
|
echo "Uploading source maps to sentry"
|
||||||
curl -sL https://sentry.io/get-cli/ | bash
|
curl -sL https://sentry.io/get-cli/ | bash
|
||||||
RELEASENAME="${RADARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
|
RELEASENAME="Radarr@${RADARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
|
||||||
sentry-cli releases new --finalize -p radarr -p radarr-ui -p radarr-update "${RELEASENAME}"
|
sentry-cli releases new --finalize -p radarr -p radarr-ui -p radarr-update "${RELEASENAME}"
|
||||||
sentry-cli releases -p radarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite
|
sentry-cli releases -p radarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite
|
||||||
sentry-cli releases set-commits --auto "${RELEASENAME}"
|
sentry-cli releases set-commits --auto "${RELEASENAME}"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ module.exports = (env) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
entry: {
|
entry: {
|
||||||
index: 'index.js'
|
index: 'index.ts'
|
||||||
},
|
},
|
||||||
|
|
||||||
resolve: {
|
resolve: {
|
||||||
@@ -66,23 +66,23 @@ module.exports = (env) => {
|
|||||||
output: {
|
output: {
|
||||||
path: distFolder,
|
path: distFolder,
|
||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
filename: '[name].js',
|
filename: '[name]-[contenthash].js',
|
||||||
sourceMapFilename: '[file].map'
|
sourceMapFilename: '[file].map'
|
||||||
},
|
},
|
||||||
|
|
||||||
optimization: {
|
optimization: {
|
||||||
moduleIds: 'deterministic',
|
moduleIds: 'deterministic',
|
||||||
chunkIds: 'named',
|
chunkIds: isProduction ? 'deterministic' : 'named'
|
||||||
splitChunks: {
|
|
||||||
chunks: 'initial',
|
|
||||||
name: 'vendors'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
performance: {
|
performance: {
|
||||||
hints: false
|
hints: false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
experiments: {
|
||||||
|
topLevelAwait: true
|
||||||
|
},
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
__DEV__: !isProduction,
|
__DEV__: !isProduction,
|
||||||
@@ -90,13 +90,15 @@ module.exports = (env) => {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: 'Content/styles.css'
|
filename: 'Content/styles.css',
|
||||||
|
chunkFilename: 'Content/[id]-[chunkhash].css'
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: 'frontend/src/index.ejs',
|
template: 'frontend/src/index.ejs',
|
||||||
filename: 'index.html',
|
filename: 'index.html',
|
||||||
publicPath: '/'
|
publicPath: '/',
|
||||||
|
inject: false
|
||||||
}),
|
}),
|
||||||
|
|
||||||
new FileManagerPlugin({
|
new FileManagerPlugin({
|
||||||
@@ -233,6 +235,7 @@ module.exports = (env) => {
|
|||||||
{
|
{
|
||||||
loader: 'url-loader',
|
loader: 'url-loader',
|
||||||
options: {
|
options: {
|
||||||
|
limit: 10240,
|
||||||
mimetype: 'application/font-woff',
|
mimetype: 'application/font-woff',
|
||||||
emitFile: false,
|
emitFile: false,
|
||||||
name: 'Content/Fonts/[name].[ext]'
|
name: 'Content/Fonts/[name].[ext]'
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import IconButton from 'Components/Link/IconButton';
|
|||||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { icons } from 'Helpers/Props';
|
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||||
|
import { icons, tooltipPositions } from 'Helpers/Props';
|
||||||
import MovieFormats from 'Movie/MovieFormats';
|
import MovieFormats from 'Movie/MovieFormats';
|
||||||
import MovieLanguage from 'Movie/MovieLanguage';
|
import MovieLanguage from 'Movie/MovieLanguage';
|
||||||
import MovieQuality from 'Movie/MovieQuality';
|
import MovieQuality from 'Movie/MovieQuality';
|
||||||
@@ -176,7 +177,14 @@ class HistoryRow extends Component {
|
|||||||
key={name}
|
key={name}
|
||||||
className={styles.customFormatScore}
|
className={styles.customFormatScore}
|
||||||
>
|
>
|
||||||
{formatCustomFormatScore(customFormatScore)}
|
<Tooltip
|
||||||
|
anchor={formatCustomFormatScore(
|
||||||
|
customFormatScore,
|
||||||
|
customFormats.length
|
||||||
|
)}
|
||||||
|
tooltip={<MovieFormats formats={customFormats} />}
|
||||||
|
position={tooltipPositions.BOTTOM}
|
||||||
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -257,4 +265,8 @@ HistoryRow.propTypes = {
|
|||||||
onMarkAsFailedPress: PropTypes.func.isRequired
|
onMarkAsFailedPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HistoryRow.defaultProps = {
|
||||||
|
customFormats: []
|
||||||
|
};
|
||||||
|
|
||||||
export default HistoryRow;
|
export default HistoryRow;
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customFormatScore {
|
||||||
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
width: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Please do not change this file!
|
// Please do not change this file!
|
||||||
interface CssExports {
|
interface CssExports {
|
||||||
'actions': string;
|
'actions': string;
|
||||||
|
'customFormatScore': string;
|
||||||
'progress': string;
|
'progress': string;
|
||||||
'protocol': string;
|
'protocol': string;
|
||||||
'quality': string;
|
'quality': string;
|
||||||
|
|||||||
@@ -8,13 +8,15 @@ import ProgressBar from 'Components/ProgressBar';
|
|||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import { icons, kinds } from 'Helpers/Props';
|
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||||
|
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||||
import MovieFormats from 'Movie/MovieFormats';
|
import MovieFormats from 'Movie/MovieFormats';
|
||||||
import MovieLanguage from 'Movie/MovieLanguage';
|
import MovieLanguage from 'Movie/MovieLanguage';
|
||||||
import MovieQuality from 'Movie/MovieQuality';
|
import MovieQuality from 'Movie/MovieQuality';
|
||||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import QueueStatusCell from './QueueStatusCell';
|
import QueueStatusCell from './QueueStatusCell';
|
||||||
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
||||||
@@ -42,14 +44,14 @@ class QueueRow extends Component {
|
|||||||
this.setState({ isRemoveQueueItemModalOpen: true });
|
this.setState({ isRemoveQueueItemModalOpen: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemoveQueueItemModalConfirmed = (blocklist) => {
|
onRemoveQueueItemModalConfirmed = (blocklist, skipRedownload) => {
|
||||||
const {
|
const {
|
||||||
onRemoveQueueItemPress,
|
onRemoveQueueItemPress,
|
||||||
onQueueRowModalOpenOrClose
|
onQueueRowModalOpenOrClose
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
onQueueRowModalOpenOrClose(false);
|
onQueueRowModalOpenOrClose(false);
|
||||||
onRemoveQueueItemPress(blocklist);
|
onRemoveQueueItemPress(blocklist, skipRedownload);
|
||||||
|
|
||||||
this.setState({ isRemoveQueueItemModalOpen: false });
|
this.setState({ isRemoveQueueItemModalOpen: false });
|
||||||
};
|
};
|
||||||
@@ -88,6 +90,7 @@ class QueueRow extends Component {
|
|||||||
movie,
|
movie,
|
||||||
quality,
|
quality,
|
||||||
customFormats,
|
customFormats,
|
||||||
|
customFormatScore,
|
||||||
languages,
|
languages,
|
||||||
protocol,
|
protocol,
|
||||||
indexer,
|
indexer,
|
||||||
@@ -201,6 +204,24 @@ class QueueRow extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === 'customFormatScore') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.customFormatScore}
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
anchor={formatCustomFormatScore(
|
||||||
|
customFormatScore,
|
||||||
|
customFormats.length
|
||||||
|
)}
|
||||||
|
tooltip={<MovieFormats formats={customFormats} />}
|
||||||
|
position={tooltipPositions.BOTTOM}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'protocol') {
|
if (name === 'protocol') {
|
||||||
return (
|
return (
|
||||||
<TableRowCell key={name}>
|
<TableRowCell key={name}>
|
||||||
@@ -365,6 +386,7 @@ QueueRow.propTypes = {
|
|||||||
movie: PropTypes.object,
|
movie: PropTypes.object,
|
||||||
quality: PropTypes.object.isRequired,
|
quality: PropTypes.object.isRequired,
|
||||||
customFormats: PropTypes.arrayOf(PropTypes.object),
|
customFormats: PropTypes.arrayOf(PropTypes.object),
|
||||||
|
customFormatScore: PropTypes.number.isRequired,
|
||||||
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
|
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
protocol: PropTypes.string.isRequired,
|
protocol: PropTypes.string.isRequired,
|
||||||
indexer: PropTypes.string,
|
indexer: PropTypes.string,
|
||||||
@@ -390,6 +412,7 @@ QueueRow.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
QueueRow.defaultProps = {
|
QueueRow.defaultProps = {
|
||||||
|
customFormats: [],
|
||||||
isGrabbing: false,
|
isGrabbing: false,
|
||||||
isRemoving: false
|
isRemoving: false
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class RemoveQueueItemModal extends Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +33,8 @@ class RemoveQueueItemModal extends Component {
|
|||||||
resetState = function() {
|
resetState = function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,6 +49,10 @@ class RemoveQueueItemModal extends Component {
|
|||||||
this.setState({ blocklist: value });
|
this.setState({ blocklist: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSkipRedownloadChange = ({ value }) => {
|
||||||
|
this.setState({ skipRedownload: value });
|
||||||
|
};
|
||||||
|
|
||||||
onRemoveConfirmed = () => {
|
onRemoveConfirmed = () => {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
|
|
||||||
@@ -70,7 +76,7 @@ class RemoveQueueItemModal extends Component {
|
|||||||
isPending
|
isPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist, skipRedownload } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -118,6 +124,20 @@ class RemoveQueueItemModal extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
{
|
||||||
|
blocklist ?
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('SkipRedownload')}</FormLabel>
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="skipRedownload"
|
||||||
|
value={skipRedownload}
|
||||||
|
helpText={translate('SkipRedownloadHelpText')}
|
||||||
|
onChange={this.onSkipRedownloadChange}
|
||||||
|
/>
|
||||||
|
</FormGroup> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +34,8 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
resetState = function() {
|
resetState = function() {
|
||||||
this.setState({
|
this.setState({
|
||||||
remove: true,
|
remove: true,
|
||||||
blocklist: false
|
blocklist: false,
|
||||||
|
skipRedownload: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -48,6 +50,10 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
this.setState({ blocklist: value });
|
this.setState({ blocklist: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onSkipRedownloadChange = ({ value }) => {
|
||||||
|
this.setState({ skipRedownload: value });
|
||||||
|
};
|
||||||
|
|
||||||
onRemoveConfirmed = () => {
|
onRemoveConfirmed = () => {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
|
|
||||||
@@ -71,7 +77,7 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
allPending
|
allPending
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { remove, blocklist } = this.state;
|
const { remove, blocklist, skipRedownload } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@@ -122,6 +128,20 @@ class RemoveQueueItemsModal extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
{
|
||||||
|
blocklist ?
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('SkipRedownload')}</FormLabel>
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.CHECK}
|
||||||
|
name="skipRedownload"
|
||||||
|
value={skipRedownload}
|
||||||
|
helpText={translate('SkipRedownloadHelpText')}
|
||||||
|
onChange={this.onSkipRedownloadChange}
|
||||||
|
/>
|
||||||
|
</FormGroup> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
|||||||
@@ -18,17 +18,23 @@ import styles from './ImportMovieSelectFolder.css';
|
|||||||
const rootFolderColumns = [
|
const rootFolderColumns = [
|
||||||
{
|
{
|
||||||
name: 'path',
|
name: 'path',
|
||||||
label: translate('Path'),
|
get label() {
|
||||||
|
return translate('Path');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'freeSpace',
|
name: 'freeSpace',
|
||||||
label: translate('FreeSpace'),
|
get label() {
|
||||||
|
return translate('FreeSpace');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'unmappedFolders',
|
name: 'unmappedFolders',
|
||||||
label: translate('UnmappedFolders'),
|
get label() {
|
||||||
|
return translate('UnmappedFolders');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import Switch from 'Components/Router/Switch';
|
|||||||
import DiscoverMovieConnector from 'DiscoverMovie/DiscoverMovieConnector';
|
import DiscoverMovieConnector from 'DiscoverMovie/DiscoverMovieConnector';
|
||||||
import MovieDetailsPageConnector from 'Movie/Details/MovieDetailsPageConnector';
|
import MovieDetailsPageConnector from 'Movie/Details/MovieDetailsPageConnector';
|
||||||
import MovieIndex from 'Movie/Index/MovieIndex';
|
import MovieIndex from 'Movie/Index/MovieIndex';
|
||||||
import CustomFormatSettingsConnector from 'Settings/CustomFormats/CustomFormatSettingsConnector';
|
import CustomFormatSettingsPage from 'Settings/CustomFormats/CustomFormatSettingsPage';
|
||||||
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
|
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
|
||||||
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
|
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
|
||||||
import ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector';
|
import ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector';
|
||||||
@@ -148,7 +148,7 @@ function AppRoutes(props) {
|
|||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/settings/customformats"
|
path="/settings/customformats"
|
||||||
component={CustomFormatSettingsConnector}
|
component={CustomFormatSettingsPage}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import InteractiveImportAppState from 'App/State/InteractiveImportAppState';
|
import InteractiveImportAppState from 'App/State/InteractiveImportAppState';
|
||||||
import MovieFilesAppState from './MovieFilesAppState';
|
import MovieFilesAppState from './MovieFilesAppState';
|
||||||
import MoviesAppState, { MovieIndexAppState } from './MoviesAppState';
|
import MoviesAppState, { MovieIndexAppState } from './MoviesAppState';
|
||||||
|
import ParseAppState from './ParseAppState';
|
||||||
import QueueAppState from './QueueAppState';
|
import QueueAppState from './QueueAppState';
|
||||||
import SettingsAppState from './SettingsAppState';
|
import SettingsAppState from './SettingsAppState';
|
||||||
import TagsAppState from './TagsAppState';
|
import TagsAppState from './TagsAppState';
|
||||||
@@ -41,6 +42,7 @@ interface AppState {
|
|||||||
movieFiles: MovieFilesAppState;
|
movieFiles: MovieFilesAppState;
|
||||||
interactiveImport: InteractiveImportAppState;
|
interactiveImport: InteractiveImportAppState;
|
||||||
movieIndex: MovieIndexAppState;
|
movieIndex: MovieIndexAppState;
|
||||||
|
parse: ParseAppState;
|
||||||
settings: SettingsAppState;
|
settings: SettingsAppState;
|
||||||
movies: MoviesAppState;
|
movies: MoviesAppState;
|
||||||
tags: TagsAppState;
|
tags: TagsAppState;
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import ModelBase from 'App/ModelBase';
|
||||||
|
import { AppSectionItemState } from 'App/State/AppSectionState';
|
||||||
|
import Language from 'Language/Language';
|
||||||
|
import Movie from 'Movie/Movie';
|
||||||
|
import { QualityModel } from 'Quality/Quality';
|
||||||
|
import CustomFormat from 'typings/CustomFormat';
|
||||||
|
|
||||||
|
export interface ParsedMovieInfo {
|
||||||
|
releaseTitle: string;
|
||||||
|
originalTitle: string;
|
||||||
|
movieTitle: string;
|
||||||
|
movieTitles: string[];
|
||||||
|
year: number;
|
||||||
|
quality: QualityModel;
|
||||||
|
languages: Language[];
|
||||||
|
releaseHash: string;
|
||||||
|
releaseGroup?: string;
|
||||||
|
edition?: string;
|
||||||
|
tmdbId?: number;
|
||||||
|
imdbId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ParseModel extends ModelBase {
|
||||||
|
title: string;
|
||||||
|
parsedMovieInfo: ParsedMovieInfo;
|
||||||
|
movie?: Movie;
|
||||||
|
languages?: Language[];
|
||||||
|
customFormats?: CustomFormat[];
|
||||||
|
customFormatScore?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParseAppState = AppSectionItemState<ParseModel>;
|
||||||
|
|
||||||
|
export default ParseAppState;
|
||||||
@@ -28,7 +28,7 @@ function createMapStateToProps() {
|
|||||||
qualityProfileId: collection.qualityProfileId,
|
qualityProfileId: collection.qualityProfileId,
|
||||||
minimumAvailability: collection.minimumAvailability,
|
minimumAvailability: collection.minimumAvailability,
|
||||||
searchForMovie: collection.searchOnAdd,
|
searchForMovie: collection.searchOnAdd,
|
||||||
tags: []
|
tags: collection.tags || []
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class EditCollectionModalContent extends Component {
|
|||||||
minimumAvailability,
|
minimumAvailability,
|
||||||
// Id,
|
// Id,
|
||||||
rootFolderPath,
|
rootFolderPath,
|
||||||
|
tags,
|
||||||
searchOnAdd
|
searchOnAdd
|
||||||
} = item;
|
} = item;
|
||||||
|
|
||||||
@@ -126,6 +127,17 @@ class EditCollectionModalContent extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('Tags')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.TAG}
|
||||||
|
name="tags"
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...tags}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormLabel>{translate('SearchOnAdd')}</FormLabel>
|
<FormLabel>{translate('SearchOnAdd')}</FormLabel>
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ function createMapStateToProps() {
|
|||||||
qualityProfileId: collection.qualityProfileId,
|
qualityProfileId: collection.qualityProfileId,
|
||||||
minimumAvailability: collection.minimumAvailability,
|
minimumAvailability: collection.minimumAvailability,
|
||||||
rootFolderPath: collection.rootFolderPath,
|
rootFolderPath: collection.rootFolderPath,
|
||||||
|
tags: collection.tags,
|
||||||
searchOnAdd: collection.searchOnAdd
|
searchOnAdd: collection.searchOnAdd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ $hoverScale: 1.05;
|
|||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
background-color: var(--defaultColor);
|
background-color: var(--black);
|
||||||
}
|
}
|
||||||
|
|
||||||
.monitorToggleButton {
|
.monitorToggleButton {
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ CollectionOverviews.propTypes = {
|
|||||||
sortKey: PropTypes.string,
|
sortKey: PropTypes.string,
|
||||||
overviewOptions: PropTypes.object.isRequired,
|
overviewOptions: PropTypes.object.isRequired,
|
||||||
jumpToCharacter: PropTypes.string,
|
jumpToCharacter: PropTypes.string,
|
||||||
scrollTop: PropTypes.number.isRequired,
|
scrollTop: PropTypes.number,
|
||||||
scroller: PropTypes.instanceOf(Element).isRequired,
|
scroller: PropTypes.instanceOf(Element).isRequired,
|
||||||
showRelativeDates: PropTypes.bool.isRequired,
|
showRelativeDates: PropTypes.bool.isRequired,
|
||||||
shortDateFormat: PropTypes.string.isRequired,
|
shortDateFormat: PropTypes.string.isRequired,
|
||||||
|
|||||||
@@ -14,9 +14,24 @@ import { inputTypes } from 'Helpers/Props';
|
|||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
const posterSizeOptions = [
|
const posterSizeOptions = [
|
||||||
{ key: 'small', value: translate('Small') },
|
{
|
||||||
{ key: 'medium', value: translate('Medium') },
|
key: 'small',
|
||||||
{ key: 'large', value: translate('Large') }
|
get value() {
|
||||||
|
return translate('Small');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'medium',
|
||||||
|
get value() {
|
||||||
|
return translate('Medium');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'large',
|
||||||
|
get value() {
|
||||||
|
return translate('Large');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
class CollectionOverviewOptionsModalContent extends Component {
|
class CollectionOverviewOptionsModalContent extends Component {
|
||||||
|
|||||||
@@ -20,12 +20,16 @@ import styles from './FileBrowserModalContent.css';
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'type',
|
name: 'type',
|
||||||
label: translate('Type'),
|
get label() {
|
||||||
|
return translate('Type');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'name',
|
name: 'name',
|
||||||
label: translate('Name'),
|
get label() {
|
||||||
|
return translate('Name');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -10,12 +10,42 @@ import { NAME } from './FilterBuilderRowValue';
|
|||||||
import styles from './DateFilterBuilderRowValue.css';
|
import styles from './DateFilterBuilderRowValue.css';
|
||||||
|
|
||||||
const timeOptions = [
|
const timeOptions = [
|
||||||
{ key: 'seconds', value: translate('Seconds') },
|
{
|
||||||
{ key: 'minutes', value: translate('Minutes') },
|
key: 'seconds',
|
||||||
{ key: 'hours', value: translate('Hours') },
|
get value() {
|
||||||
{ key: 'days', value: translate('Days') },
|
return translate('Seconds');
|
||||||
{ key: 'weeks', value: translate('Weeks') },
|
}
|
||||||
{ key: 'months', value: translate('Months') }
|
},
|
||||||
|
{
|
||||||
|
key: 'minutes',
|
||||||
|
get value() {
|
||||||
|
return translate('Minutes');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'hours',
|
||||||
|
get value() {
|
||||||
|
return translate('Hours');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'days',
|
||||||
|
get value() {
|
||||||
|
return translate('Days');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'weeks',
|
||||||
|
get value() {
|
||||||
|
return translate('Weeks');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'months',
|
||||||
|
get value() {
|
||||||
|
return translate('Months');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function isInFilter(filterType) {
|
function isInFilter(filterType) {
|
||||||
|
|||||||
@@ -210,11 +210,13 @@ class FilterBuilderRow extends Component {
|
|||||||
const selectedFilterBuilderProp = this.selectedFilterBuilderProp;
|
const selectedFilterBuilderProp = this.selectedFilterBuilderProp;
|
||||||
|
|
||||||
const keyOptions = filterBuilderProps.map((availablePropFilter) => {
|
const keyOptions = filterBuilderProps.map((availablePropFilter) => {
|
||||||
|
const { name, label } = availablePropFilter;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: availablePropFilter.name,
|
key: name,
|
||||||
value: availablePropFilter.label
|
value: typeof label === 'function' ? label() : label
|
||||||
};
|
};
|
||||||
});
|
}).sort((a, b) => a.value.localeCompare(b.value));
|
||||||
|
|
||||||
const ValueComponent = getRowValueConnector(selectedFilterBuilderProp);
|
const ValueComponent = getRowValueConnector(selectedFilterBuilderProp);
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,24 @@ import translate from 'Utilities/String/translate';
|
|||||||
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||||
|
|
||||||
const protocols = [
|
const protocols = [
|
||||||
{ id: 'announced', name: translate('Announced') },
|
{
|
||||||
{ id: 'inCinemas', name: translate('InCinemas') },
|
id: 'announced',
|
||||||
{ id: 'released', name: translate('Released') }
|
get name() {
|
||||||
|
return translate('Announced');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'inCinemas',
|
||||||
|
get name() {
|
||||||
|
return translate('InCinemas');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'released',
|
||||||
|
get name() {
|
||||||
|
return translate('Released');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function MinimumAvailabilityFilterBuilderRowValue(props) {
|
function MinimumAvailabilityFilterBuilderRowValue(props) {
|
||||||
|
|||||||
@@ -4,10 +4,30 @@ import FilterBuilderRowValue from './FilterBuilderRowValue';
|
|||||||
|
|
||||||
const protocols = [
|
const protocols = [
|
||||||
{ id: 'tba', name: 'TBA' },
|
{ id: 'tba', name: 'TBA' },
|
||||||
{ id: 'announced', name: translate('Announced') },
|
{
|
||||||
{ id: 'inCinemas', name: translate('InCinemas') },
|
id: 'announced',
|
||||||
{ id: 'released', name: translate('Released') },
|
get name() {
|
||||||
{ id: 'deleted', name: translate('Deleted') }
|
return translate('Announced');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'inCinemas',
|
||||||
|
get name() {
|
||||||
|
return translate('InCinemas');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'released',
|
||||||
|
get name() {
|
||||||
|
return translate('Released');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'deleted',
|
||||||
|
get name() {
|
||||||
|
return translate('Deleted');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function ReleaseStatusFilterBuilderRowValue(props) {
|
function ReleaseStatusFilterBuilderRowValue(props) {
|
||||||
|
|||||||
@@ -4,9 +4,24 @@ import translate from 'Utilities/String/translate';
|
|||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
|
|
||||||
const availabilityOptions = [
|
const availabilityOptions = [
|
||||||
{ key: 'announced', value: translate('Announced') },
|
{
|
||||||
{ key: 'inCinemas', value: translate('InCinemas') },
|
key: 'announced',
|
||||||
{ key: 'released', value: translate('Released') }
|
get value() {
|
||||||
|
return translate('Announced');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'inCinemas',
|
||||||
|
get value() {
|
||||||
|
return translate('InCinemas');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'released',
|
||||||
|
get value() {
|
||||||
|
return translate('Released');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
function AvailabilitySelectInput(props) {
|
function AvailabilitySelectInput(props) {
|
||||||
@@ -20,7 +35,7 @@ function AvailabilitySelectInput(props) {
|
|||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
value: translate('NoChange'),
|
||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import monitorOptions from 'Utilities/Movie/monitorOptions';
|
import monitorOptions from 'Utilities/Movie/monitorOptions';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import SelectInput from './SelectInput';
|
import SelectInput from './SelectInput';
|
||||||
|
|
||||||
function MovieMonitoredSelectInput(props) {
|
function MovieMonitoredSelectInput(props) {
|
||||||
@@ -14,7 +15,7 @@ function MovieMonitoredSelectInput(props) {
|
|||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
value: translate('NoChange'),
|
||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ function getType({ type, selectOptionsProviderAction }) {
|
|||||||
return inputTypes.TEXT;
|
return inputTypes.TEXT;
|
||||||
case 'oAuth':
|
case 'oAuth':
|
||||||
return inputTypes.OAUTH;
|
return inputTypes.OAUTH;
|
||||||
|
case 'rootFolder':
|
||||||
|
return inputTypes.ROOT_FOLDER_SELECT;
|
||||||
default:
|
default:
|
||||||
return inputTypes.TEXT;
|
return inputTypes.TEXT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
|||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||||
import sortByName from 'Utilities/Array/sortByName';
|
import sortByName from 'Utilities/Array/sortByName';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import EnhancedSelectInput from './EnhancedSelectInput';
|
import EnhancedSelectInput from './EnhancedSelectInput';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
@@ -24,7 +25,7 @@ function createMapStateToProps() {
|
|||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
value: translate('NoChange'),
|
||||||
disabled: includeNoChangeDisabled
|
disabled: includeNoChangeDisabled
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -69,7 +70,7 @@ class QualityProfileSelectInputConnector extends Component {
|
|||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
onChange = ({ name, value }) => {
|
onChange = ({ name, value }) => {
|
||||||
this.props.onChange({ name, value: parseInt(value) });
|
this.props.onChange({ name, value: value === 'noChange' ? value : parseInt(value) });
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,6 +3,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 { addRootFolder } from 'Store/Actions/rootFolderActions';
|
import { addRootFolder } from 'Store/Actions/rootFolderActions';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
import RootFolderSelectInput from './RootFolderSelectInput';
|
import RootFolderSelectInput from './RootFolderSelectInput';
|
||||||
|
|
||||||
const ADD_NEW_KEY = 'addNew';
|
const ADD_NEW_KEY = 'addNew';
|
||||||
@@ -27,7 +28,7 @@ function createMapStateToProps() {
|
|||||||
if (includeNoChange) {
|
if (includeNoChange) {
|
||||||
values.unshift({
|
values.unshift({
|
||||||
key: 'noChange',
|
key: 'noChange',
|
||||||
value: 'No Change',
|
value: translate('NoChange'),
|
||||||
isDisabled: includeNoChangeDisabled,
|
isDisabled: includeNoChangeDisabled,
|
||||||
isMissing: false
|
isMissing: false
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class SelectInput extends Component {
|
|||||||
value={key}
|
value={key}
|
||||||
{...otherOptionProps}
|
{...otherOptionProps}
|
||||||
>
|
>
|
||||||
{optionValue}
|
{typeof optionValue === 'function' ? optionValue() : optionValue}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -75,7 +75,7 @@ SelectInput.propTypes = {
|
|||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
disabledClassName: PropTypes.string,
|
disabledClassName: PropTypes.string,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.func]).isRequired,
|
||||||
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
values: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
isDisabled: PropTypes.bool,
|
isDisabled: PropTypes.bool,
|
||||||
hasError: PropTypes.bool,
|
hasError: PropTypes.bool,
|
||||||
|
|||||||
@@ -75,6 +75,18 @@ class TagInput extends Component {
|
|||||||
//
|
//
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
|
onTagEdit = ({ value, ...otherProps }) => {
|
||||||
|
const currentValue = this.state.value;
|
||||||
|
|
||||||
|
if (currentValue && this.props.onTagReplace) {
|
||||||
|
this.props.onTagReplace(otherProps, { name: currentValue });
|
||||||
|
} else {
|
||||||
|
this.props.onTagDelete(otherProps);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ value });
|
||||||
|
};
|
||||||
|
|
||||||
onInputContainerPress = () => {
|
onInputContainerPress = () => {
|
||||||
this._autosuggestRef.input.focus();
|
this._autosuggestRef.input.focus();
|
||||||
};
|
};
|
||||||
@@ -188,6 +200,7 @@ class TagInput extends Component {
|
|||||||
const {
|
const {
|
||||||
tags,
|
tags,
|
||||||
kind,
|
kind,
|
||||||
|
canEdit,
|
||||||
tagComponent,
|
tagComponent,
|
||||||
onTagDelete
|
onTagDelete
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@@ -199,8 +212,10 @@ class TagInput extends Component {
|
|||||||
kind={kind}
|
kind={kind}
|
||||||
inputProps={inputProps}
|
inputProps={inputProps}
|
||||||
isFocused={this.state.isFocused}
|
isFocused={this.state.isFocused}
|
||||||
|
canEdit={canEdit}
|
||||||
tagComponent={tagComponent}
|
tagComponent={tagComponent}
|
||||||
onTagDelete={onTagDelete}
|
onTagDelete={onTagDelete}
|
||||||
|
onTagEdit={this.onTagEdit}
|
||||||
onInputContainerPress={this.onInputContainerPress}
|
onInputContainerPress={this.onInputContainerPress}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -223,7 +238,7 @@ class TagInput extends Component {
|
|||||||
<AutoSuggestInput
|
<AutoSuggestInput
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
forwardedRef={this._setAutosuggestRef}
|
forwardedRef={this._setAutosuggestRef}
|
||||||
className={styles.internalInput}
|
className={className}
|
||||||
inputContainerClassName={classNames(
|
inputContainerClassName={classNames(
|
||||||
inputContainerClassName,
|
inputContainerClassName,
|
||||||
isFocused && styles.isFocused
|
isFocused && styles.isFocused
|
||||||
@@ -258,11 +273,13 @@ TagInput.propTypes = {
|
|||||||
placeholder: PropTypes.string.isRequired,
|
placeholder: PropTypes.string.isRequired,
|
||||||
delimiters: PropTypes.arrayOf(PropTypes.string).isRequired,
|
delimiters: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
minQueryLength: PropTypes.number.isRequired,
|
minQueryLength: PropTypes.number.isRequired,
|
||||||
|
canEdit: PropTypes.bool,
|
||||||
hasError: PropTypes.bool,
|
hasError: PropTypes.bool,
|
||||||
hasWarning: PropTypes.bool,
|
hasWarning: PropTypes.bool,
|
||||||
tagComponent: PropTypes.elementType.isRequired,
|
tagComponent: PropTypes.elementType.isRequired,
|
||||||
onTagAdd: PropTypes.func.isRequired,
|
onTagAdd: PropTypes.func.isRequired,
|
||||||
onTagDelete: PropTypes.func.isRequired
|
onTagDelete: PropTypes.func.isRequired,
|
||||||
|
onTagReplace: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
TagInput.defaultProps = {
|
TagInput.defaultProps = {
|
||||||
@@ -273,6 +290,7 @@ TagInput.defaultProps = {
|
|||||||
placeholder: '',
|
placeholder: '',
|
||||||
delimiters: ['Tab', 'Enter', ' ', ','],
|
delimiters: ['Tab', 'Enter', ' ', ','],
|
||||||
minQueryLength: 1,
|
minQueryLength: 1,
|
||||||
|
canEdit: false,
|
||||||
tagComponent: TagInputTag
|
tagComponent: TagInputTag
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ class TagInputConnector extends Component {
|
|||||||
<TagInput
|
<TagInput
|
||||||
onTagAdd={this.onTagAdd}
|
onTagAdd={this.onTagAdd}
|
||||||
onTagDelete={this.onTagDelete}
|
onTagDelete={this.onTagDelete}
|
||||||
|
onTagReplace={this.onTagReplace}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,8 +28,10 @@ class TagInputInput extends Component {
|
|||||||
tags,
|
tags,
|
||||||
inputProps,
|
inputProps,
|
||||||
kind,
|
kind,
|
||||||
|
canEdit,
|
||||||
tagComponent: TagComponent,
|
tagComponent: TagComponent,
|
||||||
onTagDelete
|
onTagDelete,
|
||||||
|
onTagEdit
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -46,8 +48,10 @@ class TagInputInput extends Component {
|
|||||||
index={index}
|
index={index}
|
||||||
tag={tag}
|
tag={tag}
|
||||||
kind={kind}
|
kind={kind}
|
||||||
|
canEdit={canEdit}
|
||||||
isLastTag={index === tags.length - 1}
|
isLastTag={index === tags.length - 1}
|
||||||
onDelete={onTagDelete}
|
onDelete={onTagDelete}
|
||||||
|
onEdit={onTagEdit}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@@ -66,8 +70,10 @@ TagInputInput.propTypes = {
|
|||||||
inputProps: PropTypes.object.isRequired,
|
inputProps: PropTypes.object.isRequired,
|
||||||
kind: PropTypes.oneOf(kinds.all).isRequired,
|
kind: PropTypes.oneOf(kinds.all).isRequired,
|
||||||
isFocused: PropTypes.bool.isRequired,
|
isFocused: PropTypes.bool.isRequired,
|
||||||
|
canEdit: PropTypes.bool.isRequired,
|
||||||
tagComponent: PropTypes.elementType.isRequired,
|
tagComponent: PropTypes.elementType.isRequired,
|
||||||
onTagDelete: PropTypes.func.isRequired,
|
onTagDelete: PropTypes.func.isRequired,
|
||||||
|
onTagEdit: PropTypes.func.isRequired,
|
||||||
onInputContainerPress: PropTypes.func.isRequired
|
onInputContainerPress: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,40 @@
|
|||||||
.tag {
|
.tag {
|
||||||
composes: link from '~Components/Link/Link.css';
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 100%;
|
||||||
height: 31px;
|
height: 31px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
composes: link from '~Components/Link/Link.css';
|
||||||
|
|
||||||
|
max-width: 100%;
|
||||||
|
line-height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkWithEdit {
|
||||||
|
composes: link from '~Components/Link/Link.css';
|
||||||
|
|
||||||
|
max-width: calc(100% - 9px - 4px - 2px);
|
||||||
|
line-height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editContainer {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding-left: 2px;
|
||||||
|
border-left: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
composes: button from '~Components/Link/IconButton.css';
|
||||||
|
|
||||||
|
width: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
composes: label from '~Components/Label.css';
|
||||||
|
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
// This file is automatically generated.
|
// This file is automatically generated.
|
||||||
// Please do not change this file!
|
// Please do not change this file!
|
||||||
interface CssExports {
|
interface CssExports {
|
||||||
|
'editButton': string;
|
||||||
|
'editContainer': string;
|
||||||
|
'label': string;
|
||||||
|
'link': string;
|
||||||
|
'linkWithEdit': string;
|
||||||
'tag': string;
|
'tag': string;
|
||||||
}
|
}
|
||||||
export const cssExports: CssExports;
|
export const cssExports: CssExports;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Label from 'Components/Label';
|
import Label from 'Components/Label';
|
||||||
|
import IconButton from 'Components/Link/IconButton';
|
||||||
import Link from 'Components/Link/Link';
|
import Link from 'Components/Link/Link';
|
||||||
import { kinds } from 'Helpers/Props';
|
import { icons, kinds } from 'Helpers/Props';
|
||||||
import tagShape from 'Helpers/Props/Shapes/tagShape';
|
import tagShape from 'Helpers/Props/Shapes/tagShape';
|
||||||
import styles from './TagInputTag.css';
|
import styles from './TagInputTag.css';
|
||||||
|
|
||||||
@@ -24,24 +25,61 @@ class TagInputTag extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onEdit = () => {
|
||||||
|
const {
|
||||||
|
index,
|
||||||
|
tag,
|
||||||
|
onEdit
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
onEdit({
|
||||||
|
index,
|
||||||
|
id: tag.id,
|
||||||
|
value: tag.name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
tag,
|
tag,
|
||||||
kind
|
kind,
|
||||||
|
canEdit
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<div
|
||||||
className={styles.tag}
|
className={styles.tag}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onPress={this.onDelete}
|
|
||||||
>
|
>
|
||||||
<Label kind={kind}>
|
<Label
|
||||||
{tag.name}
|
className={styles.label}
|
||||||
|
kind={kind}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
className={canEdit ? styles.linkWithEdit : styles.link}
|
||||||
|
tabIndex={-1}
|
||||||
|
onPress={this.onDelete}
|
||||||
|
>
|
||||||
|
{tag.name}
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{
|
||||||
|
canEdit ?
|
||||||
|
<div className={styles.editContainer}>
|
||||||
|
<IconButton
|
||||||
|
className={styles.editButton}
|
||||||
|
name={icons.EDIT}
|
||||||
|
size={9}
|
||||||
|
onPress={this.onEdit}
|
||||||
|
/>
|
||||||
|
</div> :
|
||||||
|
null
|
||||||
|
}
|
||||||
</Label>
|
</Label>
|
||||||
</Link>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -50,7 +88,9 @@ TagInputTag.propTypes = {
|
|||||||
index: PropTypes.number.isRequired,
|
index: PropTypes.number.isRequired,
|
||||||
tag: PropTypes.shape(tagShape),
|
tag: PropTypes.shape(tagShape),
|
||||||
kind: PropTypes.oneOf(kinds.all).isRequired,
|
kind: PropTypes.oneOf(kinds.all).isRequired,
|
||||||
onDelete: PropTypes.func.isRequired
|
canEdit: PropTypes.bool.isRequired,
|
||||||
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
onEdit: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TagInputTag;
|
export default TagInputTag;
|
||||||
|
|||||||
@@ -71,6 +71,20 @@ class TextTagInputConnector extends Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onTagReplace = (tagToReplace, newTag) => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
valueArray,
|
||||||
|
onChange
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const newValue = [...valueArray];
|
||||||
|
newValue.splice(tagToReplace.index, 1);
|
||||||
|
newValue.push(newTag.name.trim());
|
||||||
|
|
||||||
|
onChange({ name, value: newValue });
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
@@ -80,6 +94,7 @@ class TextTagInputConnector extends Component {
|
|||||||
tagList={[]}
|
tagList={[]}
|
||||||
onTagAdd={this.onTagAdd}
|
onTagAdd={this.onTagAdd}
|
||||||
onTagDelete={this.onTagDelete}
|
onTagDelete={this.onTagDelete}
|
||||||
|
onTagReplace={this.onTagReplace}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Icon extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={containerClassName}
|
className={containerClassName}
|
||||||
title={title}
|
title={typeof title === 'function' ? title() : title}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</span>
|
</span>
|
||||||
@@ -58,7 +58,7 @@ Icon.propTypes = {
|
|||||||
name: PropTypes.object.isRequired,
|
name: PropTypes.object.isRequired,
|
||||||
kind: PropTypes.string.isRequired,
|
kind: PropTypes.string.isRequired,
|
||||||
size: PropTypes.number.isRequired,
|
size: PropTypes.number.isRequired,
|
||||||
title: PropTypes.string,
|
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
isSpinning: PropTypes.bool.isRequired,
|
isSpinning: PropTypes.bool.isRequired,
|
||||||
fixedWidth: PropTypes.bool.isRequired
|
fixedWidth: PropTypes.bool.isRequired
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class FilterMenuContent extends Component {
|
|||||||
selectedFilterKey={selectedFilterKey}
|
selectedFilterKey={selectedFilterKey}
|
||||||
onPress={onFilterSelect}
|
onPress={onFilterSelect}
|
||||||
>
|
>
|
||||||
{filter.label}
|
{typeof filter.label === 'function' ? filter.label() : filter.label}
|
||||||
</FilterMenuItem>
|
</FilterMenuItem>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ function ErrorPage(props) {
|
|||||||
const {
|
const {
|
||||||
version,
|
version,
|
||||||
isLocalStorageSupported,
|
isLocalStorageSupported,
|
||||||
|
translationsError,
|
||||||
moviesError,
|
moviesError,
|
||||||
customFiltersError,
|
customFiltersError,
|
||||||
tagsError,
|
tagsError,
|
||||||
@@ -20,6 +21,8 @@ function ErrorPage(props) {
|
|||||||
|
|
||||||
if (!isLocalStorageSupported) {
|
if (!isLocalStorageSupported) {
|
||||||
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
|
||||||
|
} else if (translationsError) {
|
||||||
|
errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API');
|
||||||
} else if (moviesError) {
|
} else if (moviesError) {
|
||||||
errorMessage = getErrorMessage(moviesError, 'Failed to load movie from API');
|
errorMessage = getErrorMessage(moviesError, 'Failed to load movie from API');
|
||||||
} else if (customFiltersError) {
|
} else if (customFiltersError) {
|
||||||
@@ -52,6 +55,7 @@ function ErrorPage(props) {
|
|||||||
ErrorPage.propTypes = {
|
ErrorPage.propTypes = {
|
||||||
version: PropTypes.string.isRequired,
|
version: PropTypes.string.isRequired,
|
||||||
isLocalStorageSupported: PropTypes.bool.isRequired,
|
isLocalStorageSupported: PropTypes.bool.isRequired,
|
||||||
|
translationsError: PropTypes.object,
|
||||||
moviesError: PropTypes.object,
|
moviesError: PropTypes.object,
|
||||||
customFiltersError: PropTypes.object,
|
customFiltersError: PropTypes.object,
|
||||||
tagsError: PropTypes.object,
|
tagsError: PropTypes.object,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
import { fetchTranslations, saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
||||||
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
||||||
import { fetchMovies } from 'Store/Actions/movieActions';
|
import { fetchMovies } from 'Store/Actions/movieActions';
|
||||||
import { fetchMovieCollections } from 'Store/Actions/movieCollectionActions';
|
import { fetchMovieCollections } from 'Store/Actions/movieCollectionActions';
|
||||||
@@ -53,6 +53,7 @@ const selectIsPopulated = createSelector(
|
|||||||
(state) => state.settings.importLists.isPopulated,
|
(state) => state.settings.importLists.isPopulated,
|
||||||
(state) => state.system.status.isPopulated,
|
(state) => state.system.status.isPopulated,
|
||||||
(state) => state.movieCollections.isPopulated,
|
(state) => state.movieCollections.isPopulated,
|
||||||
|
(state) => state.app.translations.isPopulated,
|
||||||
(
|
(
|
||||||
customFiltersIsPopulated,
|
customFiltersIsPopulated,
|
||||||
tagsIsPopulated,
|
tagsIsPopulated,
|
||||||
@@ -62,7 +63,8 @@ const selectIsPopulated = createSelector(
|
|||||||
indexerFlagsIsPopulated,
|
indexerFlagsIsPopulated,
|
||||||
importListsIsPopulated,
|
importListsIsPopulated,
|
||||||
systemStatusIsPopulated,
|
systemStatusIsPopulated,
|
||||||
movieCollectionsIsPopulated
|
movieCollectionsIsPopulated,
|
||||||
|
translationsIsPopulated
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
customFiltersIsPopulated &&
|
customFiltersIsPopulated &&
|
||||||
@@ -73,7 +75,8 @@ const selectIsPopulated = createSelector(
|
|||||||
indexerFlagsIsPopulated &&
|
indexerFlagsIsPopulated &&
|
||||||
importListsIsPopulated &&
|
importListsIsPopulated &&
|
||||||
systemStatusIsPopulated &&
|
systemStatusIsPopulated &&
|
||||||
movieCollectionsIsPopulated
|
movieCollectionsIsPopulated &&
|
||||||
|
translationsIsPopulated
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -88,6 +91,7 @@ const selectErrors = createSelector(
|
|||||||
(state) => state.settings.importLists.error,
|
(state) => state.settings.importLists.error,
|
||||||
(state) => state.system.status.error,
|
(state) => state.system.status.error,
|
||||||
(state) => state.movieCollections.error,
|
(state) => state.movieCollections.error,
|
||||||
|
(state) => state.app.translations.error,
|
||||||
(
|
(
|
||||||
customFiltersError,
|
customFiltersError,
|
||||||
tagsError,
|
tagsError,
|
||||||
@@ -97,7 +101,8 @@ const selectErrors = createSelector(
|
|||||||
indexerFlagsError,
|
indexerFlagsError,
|
||||||
importListsError,
|
importListsError,
|
||||||
systemStatusError,
|
systemStatusError,
|
||||||
movieCollectionsError
|
movieCollectionsError,
|
||||||
|
translationsError
|
||||||
) => {
|
) => {
|
||||||
const hasError = !!(
|
const hasError = !!(
|
||||||
customFiltersError ||
|
customFiltersError ||
|
||||||
@@ -108,7 +113,8 @@ const selectErrors = createSelector(
|
|||||||
indexerFlagsError ||
|
indexerFlagsError ||
|
||||||
importListsError ||
|
importListsError ||
|
||||||
systemStatusError ||
|
systemStatusError ||
|
||||||
movieCollectionsError
|
movieCollectionsError ||
|
||||||
|
translationsError
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -121,7 +127,8 @@ const selectErrors = createSelector(
|
|||||||
indexerFlagsError,
|
indexerFlagsError,
|
||||||
importListsError,
|
importListsError,
|
||||||
systemStatusError,
|
systemStatusError,
|
||||||
movieCollectionsError
|
movieCollectionsError,
|
||||||
|
translationsError
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -183,6 +190,9 @@ function createMapDispatchToProps(dispatch, props) {
|
|||||||
dispatchFetchStatus() {
|
dispatchFetchStatus() {
|
||||||
dispatch(fetchStatus());
|
dispatch(fetchStatus());
|
||||||
},
|
},
|
||||||
|
dispatchFetchTranslations() {
|
||||||
|
dispatch(fetchTranslations());
|
||||||
|
},
|
||||||
onResize(dimensions) {
|
onResize(dimensions) {
|
||||||
dispatch(saveDimensions(dimensions));
|
dispatch(saveDimensions(dimensions));
|
||||||
},
|
},
|
||||||
@@ -217,6 +227,7 @@ class PageConnector extends Component {
|
|||||||
this.props.dispatchFetchImportLists();
|
this.props.dispatchFetchImportLists();
|
||||||
this.props.dispatchFetchUISettings();
|
this.props.dispatchFetchUISettings();
|
||||||
this.props.dispatchFetchStatus();
|
this.props.dispatchFetchStatus();
|
||||||
|
this.props.dispatchFetchTranslations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +254,7 @@ class PageConnector extends Component {
|
|||||||
dispatchFetchImportLists,
|
dispatchFetchImportLists,
|
||||||
dispatchFetchUISettings,
|
dispatchFetchUISettings,
|
||||||
dispatchFetchStatus,
|
dispatchFetchStatus,
|
||||||
|
dispatchFetchTranslations,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@@ -284,6 +296,7 @@ PageConnector.propTypes = {
|
|||||||
dispatchFetchImportLists: PropTypes.func.isRequired,
|
dispatchFetchImportLists: PropTypes.func.isRequired,
|
||||||
dispatchFetchUISettings: PropTypes.func.isRequired,
|
dispatchFetchUISettings: PropTypes.func.isRequired,
|
||||||
dispatchFetchStatus: PropTypes.func.isRequired,
|
dispatchFetchStatus: PropTypes.func.isRequired,
|
||||||
|
dispatchFetchTranslations: PropTypes.func.isRequired,
|
||||||
onSidebarVisibleChange: PropTypes.func.isRequired
|
onSidebarVisibleChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { isLocked } from 'Utilities/scrollLock';
|
|||||||
import styles from './PageContentBody.css';
|
import styles from './PageContentBody.css';
|
||||||
|
|
||||||
interface PageContentBodyProps {
|
interface PageContentBodyProps {
|
||||||
className: string;
|
className?: string;
|
||||||
innerClassName: string;
|
innerClassName?: string;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
initialScrollTop?: number;
|
initialScrollTop?: number;
|
||||||
onScroll?: (payload: OnScroll) => void;
|
onScroll?: (payload: OnScroll) => void;
|
||||||
|
|||||||
@@ -21,24 +21,34 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth);
|
|||||||
const links = [
|
const links = [
|
||||||
{
|
{
|
||||||
iconName: icons.MOVIE_CONTINUING,
|
iconName: icons.MOVIE_CONTINUING,
|
||||||
title: translate('Movies'),
|
get title() {
|
||||||
|
return translate('Movies');
|
||||||
|
},
|
||||||
to: '/',
|
to: '/',
|
||||||
alias: '/movies',
|
alias: '/movies',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('AddNew'),
|
get title() {
|
||||||
|
return translate('AddNew');
|
||||||
|
},
|
||||||
to: '/add/new'
|
to: '/add/new'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('ImportLibrary'),
|
get title() {
|
||||||
|
return translate('ImportLibrary');
|
||||||
|
},
|
||||||
to: '/add/import'
|
to: '/add/import'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Collections'),
|
get title() {
|
||||||
|
return translate('Collections');
|
||||||
|
},
|
||||||
to: '/collections'
|
to: '/collections'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Discover'),
|
get title() {
|
||||||
|
return translate('Discover');
|
||||||
|
},
|
||||||
to: '/add/discover'
|
to: '/add/discover'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -46,26 +56,36 @@ const links = [
|
|||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.CALENDAR,
|
iconName: icons.CALENDAR,
|
||||||
title: translate('Calendar'),
|
get title() {
|
||||||
|
return translate('Calendar');
|
||||||
|
},
|
||||||
to: '/calendar'
|
to: '/calendar'
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.ACTIVITY,
|
iconName: icons.ACTIVITY,
|
||||||
title: translate('Activity'),
|
get title() {
|
||||||
|
return translate('Activity');
|
||||||
|
},
|
||||||
to: '/activity/queue',
|
to: '/activity/queue',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('Queue'),
|
get title() {
|
||||||
|
return translate('Queue');
|
||||||
|
},
|
||||||
to: '/activity/queue',
|
to: '/activity/queue',
|
||||||
statusComponent: QueueStatusConnector
|
statusComponent: QueueStatusConnector
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('History'),
|
get title() {
|
||||||
|
return translate('History');
|
||||||
|
},
|
||||||
to: '/activity/history'
|
to: '/activity/history'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Blocklist'),
|
get title() {
|
||||||
|
return translate('Blocklist');
|
||||||
|
},
|
||||||
to: '/activity/blocklist'
|
to: '/activity/blocklist'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -73,55 +93,81 @@ const links = [
|
|||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.SETTINGS,
|
iconName: icons.SETTINGS,
|
||||||
title: translate('Settings'),
|
get title() {
|
||||||
|
return translate('Settings');
|
||||||
|
},
|
||||||
to: '/settings',
|
to: '/settings',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('MediaManagement'),
|
get title() {
|
||||||
|
return translate('MediaManagement');
|
||||||
|
},
|
||||||
to: '/settings/mediamanagement'
|
to: '/settings/mediamanagement'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Profiles'),
|
get title() {
|
||||||
|
return translate('Profiles');
|
||||||
|
},
|
||||||
to: '/settings/profiles'
|
to: '/settings/profiles'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Quality'),
|
get title() {
|
||||||
|
return translate('Quality');
|
||||||
|
},
|
||||||
to: '/settings/quality'
|
to: '/settings/quality'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('CustomFormats'),
|
get title() {
|
||||||
|
return translate('CustomFormats');
|
||||||
|
},
|
||||||
to: '/settings/customformats'
|
to: '/settings/customformats'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Indexers'),
|
get title() {
|
||||||
|
return translate('Indexers');
|
||||||
|
},
|
||||||
to: '/settings/indexers'
|
to: '/settings/indexers'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('DownloadClients'),
|
get title() {
|
||||||
|
return translate('DownloadClients');
|
||||||
|
},
|
||||||
to: '/settings/downloadclients'
|
to: '/settings/downloadclients'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Lists'),
|
get title() {
|
||||||
|
return translate('Lists');
|
||||||
|
},
|
||||||
to: '/settings/importlists'
|
to: '/settings/importlists'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Connect'),
|
get title() {
|
||||||
|
return translate('Connect');
|
||||||
|
},
|
||||||
to: '/settings/connect'
|
to: '/settings/connect'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Metadata'),
|
get title() {
|
||||||
|
return translate('Metadata');
|
||||||
|
},
|
||||||
to: '/settings/metadata'
|
to: '/settings/metadata'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Tags'),
|
get title() {
|
||||||
|
return translate('Tags');
|
||||||
|
},
|
||||||
to: '/settings/tags'
|
to: '/settings/tags'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('General'),
|
get title() {
|
||||||
|
return translate('General');
|
||||||
|
},
|
||||||
to: '/settings/general'
|
to: '/settings/general'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('UI'),
|
get title() {
|
||||||
|
return translate('UI');
|
||||||
|
},
|
||||||
to: '/settings/ui'
|
to: '/settings/ui'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -129,32 +175,46 @@ const links = [
|
|||||||
|
|
||||||
{
|
{
|
||||||
iconName: icons.SYSTEM,
|
iconName: icons.SYSTEM,
|
||||||
title: translate('System'),
|
get title() {
|
||||||
|
return translate('System');
|
||||||
|
},
|
||||||
to: '/system/status',
|
to: '/system/status',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
title: translate('Status'),
|
get title() {
|
||||||
|
return translate('Status');
|
||||||
|
},
|
||||||
to: '/system/status',
|
to: '/system/status',
|
||||||
statusComponent: HealthStatusConnector
|
statusComponent: HealthStatusConnector
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Tasks'),
|
get title() {
|
||||||
|
return translate('Tasks');
|
||||||
|
},
|
||||||
to: '/system/tasks'
|
to: '/system/tasks'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Backup'),
|
get title() {
|
||||||
|
return translate('Backup');
|
||||||
|
},
|
||||||
to: '/system/backup'
|
to: '/system/backup'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Updates'),
|
get title() {
|
||||||
|
return translate('Updates');
|
||||||
|
},
|
||||||
to: '/system/updates'
|
to: '/system/updates'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('Events'),
|
get title() {
|
||||||
|
return translate('Events');
|
||||||
|
},
|
||||||
to: '/system/events'
|
to: '/system/events'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: translate('LogFiles'),
|
get title() {
|
||||||
|
return translate('LogFiles');
|
||||||
|
},
|
||||||
to: '/system/logs/files'
|
to: '/system/logs/files'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
type PropertyFunction<T> = () => T;
|
||||||
|
|
||||||
interface Column {
|
interface Column {
|
||||||
name: string;
|
name: string;
|
||||||
label: string | React.ReactNode;
|
label: string | PropertyFunction<string> | React.ReactNode;
|
||||||
columnLabel?: string;
|
columnLabel?: string;
|
||||||
isSortable?: boolean;
|
isSortable?: boolean;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ function Table(props) {
|
|||||||
{...getTableHeaderCellProps(otherProps)}
|
{...getTableHeaderCellProps(otherProps)}
|
||||||
{...column}
|
{...column}
|
||||||
>
|
>
|
||||||
{column.label}
|
{typeof column.label === 'function' ? column.label() : column.label}
|
||||||
</TableHeaderCell>
|
</TableHeaderCell>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class TableHeaderCell extends Component {
|
|||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
name,
|
name,
|
||||||
|
label,
|
||||||
columnLabel,
|
columnLabel,
|
||||||
isSortable,
|
isSortable,
|
||||||
isVisible,
|
isVisible,
|
||||||
@@ -53,7 +54,8 @@ class TableHeaderCell extends Component {
|
|||||||
{...otherProps}
|
{...otherProps}
|
||||||
component="th"
|
component="th"
|
||||||
className={className}
|
className={className}
|
||||||
title={columnLabel}
|
label={typeof label === 'function' ? label() : label}
|
||||||
|
title={typeof columnLabel === 'function' ? columnLabel() : columnLabel}
|
||||||
onPress={this.onPress}
|
onPress={this.onPress}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
@@ -77,7 +79,8 @@ class TableHeaderCell extends Component {
|
|||||||
TableHeaderCell.propTypes = {
|
TableHeaderCell.propTypes = {
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
columnLabel: PropTypes.string,
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.node]),
|
||||||
|
columnLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||||
isSortable: PropTypes.bool,
|
isSortable: PropTypes.bool,
|
||||||
isVisible: PropTypes.bool,
|
isVisible: PropTypes.bool,
|
||||||
isModifiable: PropTypes.bool,
|
isModifiable: PropTypes.bool,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function TableOptionsColumn(props) {
|
|||||||
isDisabled={isModifiable === false}
|
isDisabled={isModifiable === false}
|
||||||
onChange={onVisibleChange}
|
onChange={onVisibleChange}
|
||||||
/>
|
/>
|
||||||
{label}
|
{typeof label === 'function' ? label() : label}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ function TableOptionsColumn(props) {
|
|||||||
|
|
||||||
TableOptionsColumn.propTypes = {
|
TableOptionsColumn.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
|
||||||
isVisible: PropTypes.bool.isRequired,
|
isVisible: PropTypes.bool.isRequired,
|
||||||
isModifiable: PropTypes.bool.isRequired,
|
isModifiable: PropTypes.bool.isRequired,
|
||||||
index: PropTypes.number.isRequired,
|
index: PropTypes.number.isRequired,
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class TableOptionsColumnDragSource extends Component {
|
|||||||
|
|
||||||
<TableOptionsColumn
|
<TableOptionsColumn
|
||||||
name={name}
|
name={name}
|
||||||
label={label}
|
label={typeof label === 'function' ? label() : label}
|
||||||
isVisible={isVisible}
|
isVisible={isVisible}
|
||||||
isModifiable={isModifiable}
|
isModifiable={isModifiable}
|
||||||
index={index}
|
index={index}
|
||||||
@@ -138,7 +138,7 @@ class TableOptionsColumnDragSource extends Component {
|
|||||||
|
|
||||||
TableOptionsColumnDragSource.propTypes = {
|
TableOptionsColumnDragSource.propTypes = {
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
|
||||||
isVisible: PropTypes.bool.isRequired,
|
isVisible: PropTypes.bool.isRequired,
|
||||||
isModifiable: PropTypes.bool.isRequired,
|
isModifiable: PropTypes.bool.isRequired,
|
||||||
index: PropTypes.number.isRequired,
|
index: PropTypes.number.isRequired,
|
||||||
|
|||||||
@@ -6,47 +6,65 @@ import translate from 'Utilities/String/translate';
|
|||||||
export const shortcuts = {
|
export const shortcuts = {
|
||||||
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
|
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
|
||||||
key: '?',
|
key: '?',
|
||||||
name: translate('OpenThisModal')
|
get name() {
|
||||||
|
return translate('OpenThisModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
CLOSE_MODAL: {
|
CLOSE_MODAL: {
|
||||||
key: 'Esc',
|
key: 'Esc',
|
||||||
name: translate('CloseCurrentModal')
|
get name() {
|
||||||
|
return translate('CloseCurrentModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ACCEPT_CONFIRM_MODAL: {
|
ACCEPT_CONFIRM_MODAL: {
|
||||||
key: 'Enter',
|
key: 'Enter',
|
||||||
name: translate('AcceptConfirmationModal')
|
get name() {
|
||||||
|
return translate('AcceptConfirmationModal');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
MOVIE_SEARCH_INPUT: {
|
MOVIE_SEARCH_INPUT: {
|
||||||
key: 's',
|
key: 's',
|
||||||
name: translate('FocusSearchBox')
|
get name() {
|
||||||
|
return translate('FocusSearchBox');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SAVE_SETTINGS: {
|
SAVE_SETTINGS: {
|
||||||
key: 'mod+s',
|
key: 'mod+s',
|
||||||
name: translate('SaveSettings')
|
get name() {
|
||||||
|
return translate('SaveSettings');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SCROLL_TOP: {
|
SCROLL_TOP: {
|
||||||
key: 'mod+home',
|
key: 'mod+home',
|
||||||
name: translate('MovieIndexScrollTop')
|
get name() {
|
||||||
|
return translate('MovieIndexScrollTop');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SCROLL_BOTTOM: {
|
SCROLL_BOTTOM: {
|
||||||
key: 'mod+end',
|
key: 'mod+end',
|
||||||
name: translate('MovieIndexScrollBottom')
|
get name() {
|
||||||
|
return translate('MovieIndexScrollBottom');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DETAILS_NEXT: {
|
DETAILS_NEXT: {
|
||||||
key: '→',
|
key: '→',
|
||||||
name: translate('MovieDetailsNextMovie')
|
get name() {
|
||||||
|
return translate('MovieDetailsNextMovie');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
DETAILS_PREVIOUS: {
|
DETAILS_PREVIOUS: {
|
||||||
key: '←',
|
key: '←',
|
||||||
name: translate('MovieDetailsPreviousMovie')
|
get name() {
|
||||||
|
return translate('MovieDetailsPreviousMovie');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 611 B |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 337 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 623 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 592 B |
@@ -14,9 +14,24 @@ import { inputTypes } from 'Helpers/Props';
|
|||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
const posterSizeOptions = [
|
const posterSizeOptions = [
|
||||||
{ key: 'small', value: translate('Small') },
|
{
|
||||||
{ key: 'medium', value: translate('Medium') },
|
key: 'small',
|
||||||
{ key: 'large', value: translate('Large') }
|
get value() {
|
||||||
|
return translate('Small');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'medium',
|
||||||
|
get value() {
|
||||||
|
return translate('Medium');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'large',
|
||||||
|
get value() {
|
||||||
|
return translate('Large');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
class DiscoverMovieOverviewOptionsModalContent extends Component {
|
class DiscoverMovieOverviewOptionsModalContent extends Component {
|
||||||
|
|||||||
@@ -14,9 +14,24 @@ import { inputTypes } from 'Helpers/Props';
|
|||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
|
|
||||||
const posterSizeOptions = [
|
const posterSizeOptions = [
|
||||||
{ key: 'small', value: translate('Small') },
|
{
|
||||||
{ key: 'medium', value: translate('Medium') },
|
key: 'small',
|
||||||
{ key: 'large', value: translate('Large') }
|
get value() {
|
||||||
|
return translate('Small');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'medium',
|
||||||
|
get value() {
|
||||||
|
return translate('Medium');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'large',
|
||||||
|
get value() {
|
||||||
|
return translate('Large');
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
class DiscoverMoviePosterOptionsModalContent extends Component {
|
class DiscoverMoviePosterOptionsModalContent extends Component {
|
||||||
|
|||||||
@@ -39,6 +39,12 @@
|
|||||||
flex: 0 0 90px;
|
flex: 0 0 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popularity {
|
||||||
|
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
|
flex: 0 0 100px;
|
||||||
|
}
|
||||||
|
|
||||||
.lists {
|
.lists {
|
||||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface CssExports {
|
|||||||
'lists': string;
|
'lists': string;
|
||||||
'originalLanguage': string;
|
'originalLanguage': string;
|
||||||
'physicalRelease': string;
|
'physicalRelease': string;
|
||||||
|
'popularity': string;
|
||||||
'ratings': string;
|
'ratings': string;
|
||||||
'runtime': string;
|
'runtime': string;
|
||||||
'sortTitle': string;
|
'sortTitle': string;
|
||||||
|
|||||||
@@ -64,6 +64,12 @@
|
|||||||
flex: 0 0 90px;
|
flex: 0 0 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.popularity {
|
||||||
|
composes: cell;
|
||||||
|
|
||||||
|
flex: 0 0 100px;
|
||||||
|
}
|
||||||
|
|
||||||
.lists {
|
.lists {
|
||||||
composes: cell;
|
composes: cell;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ interface CssExports {
|
|||||||
'lists': string;
|
'lists': string;
|
||||||
'originalLanguage': string;
|
'originalLanguage': string;
|
||||||
'physicalRelease': string;
|
'physicalRelease': string;
|
||||||
|
'popularity': string;
|
||||||
'ratings': string;
|
'ratings': string;
|
||||||
'runtime': string;
|
'runtime': string;
|
||||||
'sortTitle': string;
|
'sortTitle': string;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
|
|||||||
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
|
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
|
||||||
import { icons } from 'Helpers/Props';
|
import { icons } from 'Helpers/Props';
|
||||||
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
||||||
|
import MoviePopularityIndex from 'Movie/MoviePopularityIndex';
|
||||||
import formatRuntime from 'Utilities/Date/formatRuntime';
|
import formatRuntime from 'Utilities/Date/formatRuntime';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import ListMovieStatusCell from './ListMovieStatusCell';
|
import ListMovieStatusCell from './ListMovieStatusCell';
|
||||||
@@ -73,6 +74,7 @@ class DiscoverMovieRow extends Component {
|
|||||||
images,
|
images,
|
||||||
genres,
|
genres,
|
||||||
ratings,
|
ratings,
|
||||||
|
popularity,
|
||||||
certification,
|
certification,
|
||||||
collection,
|
collection,
|
||||||
columns,
|
columns,
|
||||||
@@ -261,6 +263,14 @@ class DiscoverMovieRow extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === 'popularity') {
|
||||||
|
return (
|
||||||
|
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||||
|
<MoviePopularityIndex popularity={popularity} />
|
||||||
|
</VirtualTableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (name === 'certification') {
|
if (name === 'certification') {
|
||||||
return (
|
return (
|
||||||
<VirtualTableRowCell
|
<VirtualTableRowCell
|
||||||
@@ -384,6 +394,7 @@ DiscoverMovieRow.propTypes = {
|
|||||||
runtime: PropTypes.number,
|
runtime: PropTypes.number,
|
||||||
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
|
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
ratings: PropTypes.object.isRequired,
|
ratings: PropTypes.object.isRequired,
|
||||||
|
popularity: PropTypes.number.isRequired,
|
||||||
certification: PropTypes.string,
|
certification: PropTypes.string,
|
||||||
collection: PropTypes.object,
|
collection: PropTypes.object,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
faBug as fasBug,
|
faBug as fasBug,
|
||||||
faBuilding as fasBuilding,
|
faBuilding as fasBuilding,
|
||||||
faBullhorn as fasBullhorn,
|
faBullhorn as fasBullhorn,
|
||||||
|
faCalculator as fasCalculator,
|
||||||
faCalendarAlt as fasCalendarAlt,
|
faCalendarAlt as fasCalendarAlt,
|
||||||
faCaretDown as fasCaretDown,
|
faCaretDown as fasCaretDown,
|
||||||
faCheck as fasCheck,
|
faCheck as fasCheck,
|
||||||
@@ -61,6 +62,7 @@ import {
|
|||||||
faFileInvoice as farFileInvoice,
|
faFileInvoice as farFileInvoice,
|
||||||
faFilm as fasFilm,
|
faFilm as fasFilm,
|
||||||
faFilter as fasFilter,
|
faFilter as fasFilter,
|
||||||
|
faFire as fasFire,
|
||||||
faFlag as fasFlag,
|
faFlag as fasFlag,
|
||||||
faFolderOpen as fasFolderOpen,
|
faFolderOpen as fasFolderOpen,
|
||||||
faForward as fasForward,
|
faForward as fasForward,
|
||||||
@@ -188,10 +190,12 @@ export const PAGE_PREVIOUS = fasBackward;
|
|||||||
export const PAGE_NEXT = fasForward;
|
export const PAGE_NEXT = fasForward;
|
||||||
export const PAGE_LAST = fasFastForward;
|
export const PAGE_LAST = fasFastForward;
|
||||||
export const PARENT = fasLevelUpAlt;
|
export const PARENT = fasLevelUpAlt;
|
||||||
|
export const PARSE = fasCalculator;
|
||||||
export const PAUSED = fasPause;
|
export const PAUSED = fasPause;
|
||||||
export const PENDING = farClock;
|
export const PENDING = farClock;
|
||||||
export const PLAY = fasPlay;
|
export const PLAY = fasPlay;
|
||||||
export const PROFILE = fasUser;
|
export const PROFILE = fasUser;
|
||||||
|
export const POPULAR = fasFire;
|
||||||
export const POSTER = fasTh;
|
export const POSTER = fasTh;
|
||||||
export const QUEUED = fasCloud;
|
export const QUEUED = fasCloud;
|
||||||
export const QUICK = fasRocket;
|
export const QUICK = fasRocket;
|
||||||
|
|||||||
@@ -25,11 +25,15 @@ import styles from './InteractiveImportSelectFolderModalContent.css';
|
|||||||
const recentFoldersColumns = [
|
const recentFoldersColumns = [
|
||||||
{
|
{
|
||||||
name: 'folder',
|
name: 'folder',
|
||||||
label: translate('Folder'),
|
get label() {
|
||||||
|
return translate('Folder');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'lastUsed',
|
name: 'lastUsed',
|
||||||
label: translate('LastUsed'),
|
get label() {
|
||||||
|
return translate('LastUsed');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'actions',
|
name: 'actions',
|
||||||
|
|||||||
@@ -71,36 +71,48 @@ type OnSelectedChangeCallback = React.ComponentProps<
|
|||||||
const COLUMNS = [
|
const COLUMNS = [
|
||||||
{
|
{
|
||||||
name: 'relativePath',
|
name: 'relativePath',
|
||||||
label: translate('RelativePath'),
|
get label() {
|
||||||
|
return translate('RelativePath');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'movie',
|
name: 'movie',
|
||||||
label: translate('Movie'),
|
get label() {
|
||||||
|
return translate('Movie');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'releaseGroup',
|
name: 'releaseGroup',
|
||||||
label: translate('ReleaseGroup'),
|
get label() {
|
||||||
|
return translate('ReleaseGroup');
|
||||||
|
},
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'quality',
|
name: 'quality',
|
||||||
label: translate('Quality'),
|
get label() {
|
||||||
|
return translate('Quality');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'languages',
|
name: 'languages',
|
||||||
label: translate('Languages'),
|
get label() {
|
||||||
|
return translate('Languages');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
label: translate('Size'),
|
get label() {
|
||||||
|
return translate('Size');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
@@ -108,7 +120,7 @@ const COLUMNS = [
|
|||||||
name: 'customFormats',
|
name: 'customFormats',
|
||||||
label: React.createElement(Icon, {
|
label: React.createElement(Icon, {
|
||||||
name: icons.INTERACTIVE,
|
name: icons.INTERACTIVE,
|
||||||
title: translate('CustomFormat'),
|
title: () => translate('CustomFormat'),
|
||||||
}),
|
}),
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
@@ -127,11 +139,23 @@ const COLUMNS = [
|
|||||||
const importModeOptions = [
|
const importModeOptions = [
|
||||||
{
|
{
|
||||||
key: 'chooseImportMode',
|
key: 'chooseImportMode',
|
||||||
value: translate('ChooseImportMode'),
|
get value() {
|
||||||
|
return translate('ChooseImportMode');
|
||||||
|
},
|
||||||
disabled: true,
|
disabled: true,
|
||||||
},
|
},
|
||||||
{ key: 'move', value: translate('MoveFiles') },
|
{
|
||||||
{ key: 'copy', value: translate('HardlinkCopyFiles') },
|
key: 'move',
|
||||||
|
get value() {
|
||||||
|
return translate('MoveFiles');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'copy',
|
||||||
|
get value() {
|
||||||
|
return translate('HardlinkCopyFiles');
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function isSameMovieFile(
|
function isSameMovieFile(
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
import { SelectStateInputProps } from 'typings/props';
|
import { SelectStateInputProps } from 'typings/props';
|
||||||
import Rejection from 'typings/Rejection';
|
import Rejection from 'typings/Rejection';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import InteractiveImportRowCellPlaceholder from './InteractiveImportRowCellPlaceholder';
|
import InteractiveImportRowCellPlaceholder from './InteractiveImportRowCellPlaceholder';
|
||||||
import styles from './InteractiveImportRow.css';
|
import styles from './InteractiveImportRow.css';
|
||||||
@@ -45,6 +46,7 @@ interface InteractiveImportRowProps {
|
|||||||
languages?: Language[];
|
languages?: Language[];
|
||||||
size: number;
|
size: number;
|
||||||
customFormats?: object[];
|
customFormats?: object[];
|
||||||
|
customFormatScore?: number;
|
||||||
rejections: Rejection[];
|
rejections: Rejection[];
|
||||||
columns: Column[];
|
columns: Column[];
|
||||||
movieFileId?: number;
|
movieFileId?: number;
|
||||||
@@ -66,6 +68,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
|
|||||||
releaseGroup,
|
releaseGroup,
|
||||||
size,
|
size,
|
||||||
customFormats,
|
customFormats,
|
||||||
|
customFormatScore,
|
||||||
rejections,
|
rejections,
|
||||||
isSelected,
|
isSelected,
|
||||||
modalTitle,
|
modalTitle,
|
||||||
@@ -293,8 +296,11 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
|
|||||||
<TableRowCell>
|
<TableRowCell>
|
||||||
{customFormats?.length ? (
|
{customFormats?.length ? (
|
||||||
<Popover
|
<Popover
|
||||||
anchor={<Icon name={icons.INTERACTIVE} />}
|
anchor={formatCustomFormatScore(
|
||||||
title={translate('Formats')}
|
customFormatScore,
|
||||||
|
customFormats.length
|
||||||
|
)}
|
||||||
|
title={translate('CustomFormats')}
|
||||||
body={
|
body={
|
||||||
<div className={styles.customFormatTooltip}>
|
<div className={styles.customFormatTooltip}>
|
||||||
<MovieFormats formats={customFormats} />
|
<MovieFormats formats={customFormats} />
|
||||||
|
|||||||
@@ -29,22 +29,30 @@ import styles from './SelectMovieModalContent.css';
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
label: translate('Title'),
|
get label() {
|
||||||
|
return translate('Title');
|
||||||
|
},
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'year',
|
name: 'year',
|
||||||
label: translate('Year'),
|
get label() {
|
||||||
|
return translate('Year');
|
||||||
|
},
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'imdbId',
|
name: 'imdbId',
|
||||||
label: translate('ImdbId'),
|
get label() {
|
||||||
|
return translate('ImdbId');
|
||||||
|
},
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'tmdbId',
|
name: 'tmdbId',
|
||||||
label: translate('TmdbId'),
|
get label() {
|
||||||
|
return translate('TmdbId');
|
||||||
|
},
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,12 +4,8 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filteredMessage {
|
.alert {
|
||||||
|
composes: alert from '~Components/Alert.css';
|
||||||
|
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blankpad {
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
padding-left: 2em;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
// This file is automatically generated.
|
// This file is automatically generated.
|
||||||
// Please do not change this file!
|
// Please do not change this file!
|
||||||
interface CssExports {
|
interface CssExports {
|
||||||
'blankpad': string;
|
'alert': string;
|
||||||
'filterMenuContainer': string;
|
'filterMenuContainer': string;
|
||||||
'filteredMessage': string;
|
|
||||||
}
|
}
|
||||||
export const cssExports: CssExports;
|
export const cssExports: CssExports;
|
||||||
export default cssExports;
|
export default cssExports;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Alert from 'Components/Alert';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import { icons, sortDirections } from 'Helpers/Props';
|
import { icons, kinds, sortDirections } from 'Helpers/Props';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import InteractiveSearchRowConnector from './InteractiveSearchRowConnector';
|
import InteractiveSearchRowConnector from './InteractiveSearchRowConnector';
|
||||||
import styles from './InteractiveSearchContent.css';
|
import styles from './InteractiveSearchContent.css';
|
||||||
@@ -12,13 +13,17 @@ import styles from './InteractiveSearchContent.css';
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'protocol',
|
name: 'protocol',
|
||||||
label: translate('Source'),
|
get label() {
|
||||||
|
return translate('Source');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'age',
|
name: 'age',
|
||||||
label: translate('Age'),
|
get label() {
|
||||||
|
return translate('Age');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
@@ -38,50 +43,66 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
label: translate('Title'),
|
get label() {
|
||||||
|
return translate('Title');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'indexer',
|
name: 'indexer',
|
||||||
label: translate('Indexer'),
|
get label() {
|
||||||
|
return translate('Indexer');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'history',
|
name: 'history',
|
||||||
label: translate('History'),
|
get label() {
|
||||||
|
return translate('History');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
fixedSortDirection: sortDirections.ASCENDING,
|
fixedSortDirection: sortDirections.ASCENDING,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
label: translate('Size'),
|
get label() {
|
||||||
|
return translate('Size');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'peers',
|
name: 'peers',
|
||||||
label: translate('Peers'),
|
get label() {
|
||||||
|
return translate('Peers');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'languages',
|
name: 'languages',
|
||||||
label: translate('Language'),
|
get label() {
|
||||||
|
return translate('Language');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'qualityWeight',
|
name: 'qualityWeight',
|
||||||
label: translate('Quality'),
|
get label() {
|
||||||
|
return translate('Quality');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'customFormat',
|
name: 'customFormat',
|
||||||
label: translate('Formats'),
|
get label() {
|
||||||
|
return translate('Formats');
|
||||||
|
},
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
@@ -89,7 +110,7 @@ const columns = [
|
|||||||
name: 'customFormatScore',
|
name: 'customFormatScore',
|
||||||
label: React.createElement(Icon, {
|
label: React.createElement(Icon, {
|
||||||
name: icons.SCORE,
|
name: icons.SCORE,
|
||||||
title: translate('CustomFormatScore')
|
title: () => translate('CustomFormatScore')
|
||||||
}),
|
}),
|
||||||
isSortable: true,
|
isSortable: true,
|
||||||
isVisible: true
|
isVisible: true
|
||||||
@@ -127,23 +148,23 @@ function InteractiveSearchContent(props) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
!isFetching && !!error &&
|
!isFetching && !!error &&
|
||||||
<div className={styles.blankpad}>
|
<Alert kind={kinds.DANGER} className={styles.alert}>
|
||||||
{translate('UnableToLoadResultsIntSearch')}
|
{translate('UnableToLoadResultsIntSearch')}
|
||||||
</div>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
!isFetching && isPopulated && !totalReleasesCount &&
|
!isFetching && isPopulated && !totalReleasesCount &&
|
||||||
<div className={styles.blankpad}>
|
<Alert kind={kinds.INFO} className={styles.alert}>
|
||||||
{translate('NoResultsFound')}
|
{translate('NoResultsFound')}
|
||||||
</div>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
!!totalReleasesCount && isPopulated && !items.length &&
|
!!totalReleasesCount && isPopulated && !items.length &&
|
||||||
<div className={styles.blankpad}>
|
<Alert kind={kinds.WARNING} className={styles.alert}>
|
||||||
{translate('AllResultsHiddenFilter')}
|
{translate('AllResultsHiddenFilter')}
|
||||||
</div>
|
</Alert>
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -175,9 +196,9 @@ function InteractiveSearchContent(props) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
totalReleasesCount !== items.length && !!items.length &&
|
totalReleasesCount !== items.length && !!items.length &&
|
||||||
<div className={styles.filteredMessage}>
|
<Alert kind={kinds.INFO} className={styles.alert}>
|
||||||
{translate('SomeResultsHiddenFilter')}
|
{translate('SomeResultsHiddenFilter')}
|
||||||
</div>
|
</Alert>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ function createMapDispatchToProps(dispatch, props) {
|
|||||||
dispatch(
|
dispatch(
|
||||||
deleteMovie({
|
deleteMovie({
|
||||||
id: props.movieId,
|
id: props.movieId,
|
||||||
|
collectionTmdbId: this.collection?.tmdbId,
|
||||||
deleteFiles,
|
deleteFiles,
|
||||||
addImportExclusion
|
addImportExclusion
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,17 +10,23 @@ import styles from './MovieTitlesTableContent.css';
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
name: 'altTitle',
|
name: 'altTitle',
|
||||||
label: translate('AlternativeTitle'),
|
get label() {
|
||||||
|
return translate('AlternativeTitle');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'language',
|
name: 'language',
|
||||||
label: translate('Language'),
|
get label() {
|
||||||
|
return translate('Language');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'sourceType',
|
name: 'sourceType',
|
||||||
label: translate('Type'),
|
get label() {
|
||||||
|
return translate('Type');
|
||||||
|
},
|
||||||
isVisible: true
|
isVisible: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,3 +3,9 @@
|
|||||||
|
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tagInternalInput {
|
||||||
|
composes: internalInput from '~Components/Form/TagInput.css';
|
||||||
|
|
||||||
|
flex: 0 0 100%;
|
||||||
|
}
|
||||||
|
|||||||