mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-11 15:20:34 -04:00
Compare commits
1 Commits
aphrodite
...
tweak-refr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6df45eb6af |
221
.editorconfig
221
.editorconfig
@@ -2,12 +2,6 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
# NOTE: Requires **VS2019 16.3** or later
|
||||
|
||||
# Stylecop.ruleset
|
||||
# Description: Rules for Radarr
|
||||
|
||||
# Code files
|
||||
[*.cs]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
@@ -44,221 +38,6 @@ csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
|
||||
# Stylecop Rules
|
||||
dotnet_diagnostic.SA0001.severity = none
|
||||
dotnet_diagnostic.SA1005.severity = none
|
||||
dotnet_diagnostic.SA1025.severity = none
|
||||
dotnet_diagnostic.SA1101.severity = none
|
||||
dotnet_diagnostic.SA1116.severity = none
|
||||
dotnet_diagnostic.SA1118.severity = none
|
||||
dotnet_diagnostic.SA1122.severity = none
|
||||
dotnet_diagnostic.SA1201.severity = suggestion
|
||||
dotnet_diagnostic.SA1202.severity = suggestion
|
||||
dotnet_diagnostic.SA1204.severity = suggestion
|
||||
dotnet_diagnostic.SA1300.severity = none
|
||||
dotnet_diagnostic.SA1303.severity = none
|
||||
dotnet_diagnostic.SA1304.severity = none
|
||||
dotnet_diagnostic.SA1306.severity = none
|
||||
dotnet_diagnostic.SA1309.severity = none
|
||||
dotnet_diagnostic.SA1310.severity = none
|
||||
dotnet_diagnostic.SA1401.severity = none
|
||||
dotnet_diagnostic.SA1402.severity = none
|
||||
dotnet_diagnostic.SA1404.severity = suggestion
|
||||
dotnet_diagnostic.SA1405.severity = suggestion
|
||||
dotnet_diagnostic.SA1406.severity = suggestion
|
||||
dotnet_diagnostic.SA1410.severity = suggestion
|
||||
dotnet_diagnostic.SA1411.severity = suggestion
|
||||
dotnet_diagnostic.SA1413.severity = none
|
||||
dotnet_diagnostic.SA1516.severity = none
|
||||
dotnet_diagnostic.SA1600.severity = none
|
||||
dotnet_diagnostic.SA1601.severity = none
|
||||
dotnet_diagnostic.SA1602.severity = none
|
||||
dotnet_diagnostic.SA1604.severity = none
|
||||
dotnet_diagnostic.SA1605.severity = none
|
||||
dotnet_diagnostic.SA1606.severity = none
|
||||
dotnet_diagnostic.SA1607.severity = none
|
||||
dotnet_diagnostic.SA1608.severity = none
|
||||
dotnet_diagnostic.SA1610.severity = none
|
||||
dotnet_diagnostic.SA1611.severity = none
|
||||
dotnet_diagnostic.SA1612.severity = none
|
||||
dotnet_diagnostic.SA1613.severity = none
|
||||
dotnet_diagnostic.SA1614.severity = none
|
||||
dotnet_diagnostic.SA1615.severity = none
|
||||
dotnet_diagnostic.SA1616.severity = none
|
||||
dotnet_diagnostic.SA1617.severity = none
|
||||
dotnet_diagnostic.SA1618.severity = none
|
||||
dotnet_diagnostic.SA1619.severity = none
|
||||
dotnet_diagnostic.SA1620.severity = none
|
||||
dotnet_diagnostic.SA1621.severity = none
|
||||
dotnet_diagnostic.SA1622.severity = none
|
||||
dotnet_diagnostic.SA1623.severity = none
|
||||
dotnet_diagnostic.SA1624.severity = none
|
||||
dotnet_diagnostic.SA1625.severity = none
|
||||
dotnet_diagnostic.SA1626.severity = none
|
||||
dotnet_diagnostic.SA1627.severity = none
|
||||
dotnet_diagnostic.SA1629.severity = none
|
||||
dotnet_diagnostic.SA1633.severity = none
|
||||
dotnet_diagnostic.SA1634.severity = none
|
||||
dotnet_diagnostic.SA1635.severity = none
|
||||
dotnet_diagnostic.SA1636.severity = none
|
||||
dotnet_diagnostic.SA1637.severity = none
|
||||
dotnet_diagnostic.SA1638.severity = none
|
||||
dotnet_diagnostic.SA1640.severity = none
|
||||
dotnet_diagnostic.SA1641.severity = none
|
||||
dotnet_diagnostic.SA1642.severity = none
|
||||
dotnet_diagnostic.SA1643.severity = none
|
||||
dotnet_diagnostic.SA1648.severity = none
|
||||
dotnet_diagnostic.SA1649.severity = none
|
||||
dotnet_diagnostic.SA1651.severity = none
|
||||
dotnet_diagnostic.SX1101.severity = warning
|
||||
dotnet_diagnostic.SX1309.severity = warning
|
||||
|
||||
# Microsoft Analyzers that fail and need to be sorted thru
|
||||
dotnet_diagnostic.ASP0000.severity = suggestion
|
||||
dotnet_diagnostic.CA1000.severity = suggestion
|
||||
dotnet_diagnostic.CA1001.severity = suggestion
|
||||
dotnet_diagnostic.CA1003.severity = suggestion
|
||||
dotnet_diagnostic.CA1008.severity = suggestion
|
||||
dotnet_diagnostic.CA1010.severity = suggestion
|
||||
dotnet_diagnostic.CA1012.severity = suggestion
|
||||
dotnet_diagnostic.CA1014.severity = suggestion
|
||||
dotnet_diagnostic.CA1016.severity = suggestion
|
||||
dotnet_diagnostic.CA1017.severity = suggestion
|
||||
dotnet_diagnostic.CA1018.severity = suggestion
|
||||
dotnet_diagnostic.CA1019.severity = suggestion
|
||||
dotnet_diagnostic.CA1021.severity = suggestion
|
||||
dotnet_diagnostic.CA1024.severity = suggestion
|
||||
dotnet_diagnostic.CA1027.severity = suggestion
|
||||
dotnet_diagnostic.CA1028.severity = suggestion
|
||||
dotnet_diagnostic.CA1030.severity = suggestion
|
||||
dotnet_diagnostic.CA1031.severity = suggestion
|
||||
dotnet_diagnostic.CA1032.severity = suggestion
|
||||
dotnet_diagnostic.CA1033.severity = suggestion
|
||||
dotnet_diagnostic.CA1034.severity = suggestion
|
||||
dotnet_diagnostic.CA1036.severity = suggestion
|
||||
dotnet_diagnostic.CA1040.severity = suggestion
|
||||
dotnet_diagnostic.CA1041.severity = suggestion
|
||||
dotnet_diagnostic.CA1043.severity = suggestion
|
||||
dotnet_diagnostic.CA1044.severity = suggestion
|
||||
dotnet_diagnostic.CA1050.severity = suggestion
|
||||
dotnet_diagnostic.CA1051.severity = suggestion
|
||||
dotnet_diagnostic.CA1052.severity = suggestion
|
||||
dotnet_diagnostic.CA1054.severity = suggestion
|
||||
dotnet_diagnostic.CA1055.severity = suggestion
|
||||
dotnet_diagnostic.CA1056.severity = suggestion
|
||||
dotnet_diagnostic.CA1058.severity = suggestion
|
||||
dotnet_diagnostic.CA1060.severity = suggestion
|
||||
dotnet_diagnostic.CA1061.severity = suggestion
|
||||
dotnet_diagnostic.CA1062.severity = suggestion
|
||||
dotnet_diagnostic.CA1063.severity = suggestion
|
||||
dotnet_diagnostic.CA1064.severity = suggestion
|
||||
dotnet_diagnostic.CA1065.severity = suggestion
|
||||
dotnet_diagnostic.CA1066.severity = suggestion
|
||||
dotnet_diagnostic.CA1067.severity = suggestion
|
||||
dotnet_diagnostic.CA1068.severity = suggestion
|
||||
dotnet_diagnostic.CA1069.severity = suggestion
|
||||
dotnet_diagnostic.CA1200.severity = suggestion
|
||||
dotnet_diagnostic.CA1303.severity = suggestion
|
||||
dotnet_diagnostic.CA1304.severity = suggestion
|
||||
dotnet_diagnostic.CA1305.severity = suggestion
|
||||
dotnet_diagnostic.CA1307.severity = suggestion
|
||||
dotnet_diagnostic.CA1308.severity = suggestion
|
||||
dotnet_diagnostic.CA1401.severity = suggestion
|
||||
dotnet_diagnostic.CA1507.severity = suggestion
|
||||
dotnet_diagnostic.CA1707.severity = suggestion
|
||||
dotnet_diagnostic.CA1710.severity = suggestion
|
||||
dotnet_diagnostic.CA1712.severity = suggestion
|
||||
dotnet_diagnostic.CA1714.severity = suggestion
|
||||
dotnet_diagnostic.CA1715.severity = suggestion
|
||||
dotnet_diagnostic.CA1716.severity = suggestion
|
||||
dotnet_diagnostic.CA1717.severity = suggestion
|
||||
dotnet_diagnostic.CA1720.severity = suggestion
|
||||
dotnet_diagnostic.CA1721.severity = suggestion
|
||||
dotnet_diagnostic.CA1724.severity = suggestion
|
||||
dotnet_diagnostic.CA1801.severity = suggestion
|
||||
dotnet_diagnostic.CA1802.severity = suggestion
|
||||
dotnet_diagnostic.CA1805.severity = suggestion
|
||||
dotnet_diagnostic.CA1806.severity = suggestion
|
||||
dotnet_diagnostic.CA1810.severity = suggestion
|
||||
dotnet_diagnostic.CA1812.severity = suggestion
|
||||
dotnet_diagnostic.CA1814.severity = suggestion
|
||||
dotnet_diagnostic.CA1815.severity = suggestion
|
||||
dotnet_diagnostic.CA1816.severity = suggestion
|
||||
dotnet_diagnostic.CA1819.severity = suggestion
|
||||
dotnet_diagnostic.CA1820.severity = suggestion
|
||||
dotnet_diagnostic.CA1821.severity = suggestion
|
||||
dotnet_diagnostic.CA1822.severity = suggestion
|
||||
dotnet_diagnostic.CA1823.severity = suggestion
|
||||
dotnet_diagnostic.CA1824.severity = suggestion
|
||||
dotnet_diagnostic.CA1825.severity = suggestion
|
||||
dotnet_diagnostic.CA1826.severity = suggestion
|
||||
dotnet_diagnostic.CA1827.severity = suggestion
|
||||
dotnet_diagnostic.CA1828.severity = suggestion
|
||||
dotnet_diagnostic.CA1829.severity = suggestion
|
||||
dotnet_diagnostic.CA1834.severity = suggestion
|
||||
dotnet_diagnostic.CA2000.severity = suggestion
|
||||
dotnet_diagnostic.CA2002.severity = suggestion
|
||||
dotnet_diagnostic.CA2007.severity = suggestion
|
||||
dotnet_diagnostic.CA2008.severity = suggestion
|
||||
dotnet_diagnostic.CA2009.severity = suggestion
|
||||
dotnet_diagnostic.CA2010.severity = suggestion
|
||||
dotnet_diagnostic.CA2011.severity = suggestion
|
||||
dotnet_diagnostic.CA2012.severity = suggestion
|
||||
dotnet_diagnostic.CA2013.severity = suggestion
|
||||
dotnet_diagnostic.CA2100.severity = suggestion
|
||||
dotnet_diagnostic.CA2101.severity = suggestion
|
||||
dotnet_diagnostic.CA2119.severity = suggestion
|
||||
dotnet_diagnostic.CA2153.severity = suggestion
|
||||
dotnet_diagnostic.CA2200.severity = suggestion
|
||||
dotnet_diagnostic.CA2207.severity = suggestion
|
||||
dotnet_diagnostic.CA2208.severity = suggestion
|
||||
dotnet_diagnostic.CA2211.severity = suggestion
|
||||
dotnet_diagnostic.CA2213.severity = suggestion
|
||||
dotnet_diagnostic.CA2214.severity = suggestion
|
||||
dotnet_diagnostic.CA2215.severity = suggestion
|
||||
dotnet_diagnostic.CA2216.severity = suggestion
|
||||
dotnet_diagnostic.CA2219.severity = suggestion
|
||||
dotnet_diagnostic.CA2225.severity = suggestion
|
||||
dotnet_diagnostic.CA2226.severity = suggestion
|
||||
dotnet_diagnostic.CA2227.severity = suggestion
|
||||
dotnet_diagnostic.CA2229.severity = suggestion
|
||||
dotnet_diagnostic.CA2231.severity = suggestion
|
||||
dotnet_diagnostic.CA2234.severity = suggestion
|
||||
dotnet_diagnostic.CA2235.severity = suggestion
|
||||
dotnet_diagnostic.CA2237.severity = suggestion
|
||||
dotnet_diagnostic.CA2241.severity = suggestion
|
||||
dotnet_diagnostic.CA2242.severity = suggestion
|
||||
dotnet_diagnostic.CA2243.severity = suggestion
|
||||
dotnet_diagnostic.CA2244.severity = suggestion
|
||||
dotnet_diagnostic.CA2245.severity = suggestion
|
||||
dotnet_diagnostic.CA2246.severity = suggestion
|
||||
dotnet_diagnostic.CA3061.severity = suggestion
|
||||
dotnet_diagnostic.CA3075.severity = suggestion
|
||||
dotnet_diagnostic.CA3076.severity = suggestion
|
||||
dotnet_diagnostic.CA3077.severity = suggestion
|
||||
dotnet_diagnostic.CA3147.severity = suggestion
|
||||
dotnet_diagnostic.CA5350.severity = suggestion
|
||||
dotnet_diagnostic.CA5351.severity = suggestion
|
||||
dotnet_diagnostic.CA5359.severity = suggestion
|
||||
dotnet_diagnostic.CA5360.severity = suggestion
|
||||
dotnet_diagnostic.CA5363.severity = suggestion
|
||||
dotnet_diagnostic.CA5364.severity = suggestion
|
||||
dotnet_diagnostic.CA5365.severity = suggestion
|
||||
dotnet_diagnostic.CA5366.severity = suggestion
|
||||
dotnet_diagnostic.CA5368.severity = suggestion
|
||||
dotnet_diagnostic.CA5369.severity = suggestion
|
||||
dotnet_diagnostic.CA5370.severity = suggestion
|
||||
dotnet_diagnostic.CA5371.severity = suggestion
|
||||
dotnet_diagnostic.CA5372.severity = suggestion
|
||||
dotnet_diagnostic.CA5373.severity = suggestion
|
||||
dotnet_diagnostic.CA5374.severity = suggestion
|
||||
dotnet_diagnostic.CA5379.severity = suggestion
|
||||
dotnet_diagnostic.CA5384.severity = suggestion
|
||||
dotnet_diagnostic.CA5385.severity = suggestion
|
||||
dotnet_diagnostic.CA5397.severity = suggestion
|
||||
|
||||
|
||||
|
||||
[*.{js,html,js,hbs,less,css}]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
1
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,7 +6,6 @@ YES | NO
|
||||
|
||||
#### Todos
|
||||
- [ ] Tests
|
||||
- [ ] Translation Keys
|
||||
|
||||
#### Issues Fixed or Closed by this PR
|
||||
|
||||
|
||||
21
README.md
21
README.md
@@ -13,31 +13,28 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
|
||||
## Getting Started
|
||||
|
||||
[](https://github.com/Radarr/Radarr/wiki/Installation)
|
||||
[](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||
[](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||
[](https://github.com/Radarr/Radarr/wiki/Setup-Guide)
|
||||
[](https://github.com/Radarr/Radarr/wiki/FAQ)
|
||||
|
||||
|
||||
If you are using Docker please ensure your Docker paths are setup correctly using [this guide to facilitate](https://old.reddit.com/r/usenet/wiki/docker) hardlinks and minimize permissions issues.
|
||||
|
||||
* [Install Radarr for your desired OS](https://github.com/Radarr/Radarr/wiki/Installation) *or* use [Docker](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||
* *For Linux users*, run `radarr` and *optionally* have [Radarr start automatically](https://github.com/Radarr/Radarr/wiki/Autostart-on-Linux)
|
||||
* Connect to the UI through <http://localhost:7878> or <http://your-ip:7878> in your web browser
|
||||
* See the [Setup Guide](https://github.com/Radarr/Radarr/wiki/Setup-Guide) for further configuration
|
||||
|
||||
## Downloads
|
||||
Please note that v0.2 will only have critical bugs resolved as of August 2020. Any additional development or features will be soley in V3.
|
||||
|
||||
| Release Type | Branch: develop (stable) | Branch: nightly (semi-unstable) | Branch: aphrodite (very-unstable) |
|
||||
|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Binary Releases | [](https://github.com/Radarr/Radarr/releases) | [](https://ci.appveyor.com/project/galli-leo/radarr-usby1/branch/develop/artifacts) | |
|
||||
| Docker - lsio | [](https://hub.docker.com/r/linuxserver/radarr) | [](https://hub.docker.com/r/linuxserver/radarr) | [](https://hub.docker.com/r/linuxserver/radarr) |
|
||||
| Docker - hotio | [](https://hub.docker.com/r/hotio/radarr) | [](https://hub.docker.com/r/hotio/radarr) | [](https://hub.docker.com/r/hotio/radarr) |
|
||||
| Docker | [](https://hub.docker.com/r/linuxserver/radarr) | [](https://hub.docker.com/r/linuxserver/radarr) | [](https://hub.docker.com/r/linuxserver/radarr) |
|
||||
| Docker | [](https://hub.docker.com/r/hotio/radarr) | [](https://hub.docker.com/r/hotio/radarr) | [](https://hub.docker.com/r/hotio/radarr) |
|
||||
|
||||
## Support
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](http://feathub.com/Radarr/Radarr)
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/wiki)
|
||||
|
||||
@@ -75,14 +72,18 @@ Radarr is currently undergoing rapid development and pull requests are actively
|
||||
* New TorrentPotato Indexer
|
||||
* Torznab Indexer now supports Movies (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
* Scanning PreDB to know when a new release is available
|
||||
* Importing movies from various online sources, such as IMDb Watchlists or Trakt (v3) (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
||||
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
||||
* Full integration with Kodi, Plex (notification, library update)
|
||||
* And a new beautiful UI (v3)
|
||||
* And a beautiful UI
|
||||
* Importing Metadata such as trailers or subtitles
|
||||
* Adding metadata such as posters and information for Kodi and others to use
|
||||
* Advanced customization for profiles, such that Radarr will always download the copy you want
|
||||
|
||||
#### [Feature Requests](https://github.com/Radarr/Radarr/issues/new?assignees=&labels=feature+request&template=feature_request.md&title=)
|
||||
### Planned Features
|
||||
|
||||
See the [Roadmap blogpost](https://blog.radarr.video/development/update/2018/11/11/roadmap-update.html) for an overview of planned features.
|
||||
|
||||
#### [Feature Requests](http://feathub.com/Radarr/Radarr)
|
||||
|
||||
## Configuring the Development Environment
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@ variables:
|
||||
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
||||
sentryOrg: 'servarr'
|
||||
sentryUrl: 'https://sentry.servarr.com'
|
||||
dotnetVersion: '3.1.401'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
dotnetVersion: '3.1.302'
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
@@ -69,9 +68,6 @@ stages:
|
||||
|
||||
pool:
|
||||
vmImage: $(imageName)
|
||||
variables:
|
||||
# Disable stylecop here - linting errors get caught by the analyze task
|
||||
EnableAnalyzers: 'false'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
@@ -140,19 +136,10 @@ stages:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
fetchDepth: 1
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: 'yarn | "$(osName)" | yarn.lock'
|
||||
restoreKeys: |
|
||||
yarn | "$(osName)"
|
||||
yarn
|
||||
path: $(yarnCacheFolder)
|
||||
displayName: Cache Yarn packages
|
||||
- bash: ./build.sh --frontend
|
||||
displayName: Build Radarr Frontend
|
||||
env:
|
||||
FORCE_COLOR: 0
|
||||
YARN_CACHE_FOLDER: $(yarnCacheFolder)
|
||||
- publish: $(outputFolder)
|
||||
artifact: '$(osName)Frontend'
|
||||
displayName: Publish Frontend
|
||||
@@ -415,6 +402,10 @@ stages:
|
||||
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
|
||||
strategy:
|
||||
matrix:
|
||||
mono508:
|
||||
testName: 'Mono 5.8'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-5.8
|
||||
mono520:
|
||||
testName: 'Mono 5.20'
|
||||
artifactName: LinuxTests
|
||||
@@ -564,6 +555,11 @@ stages:
|
||||
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
|
||||
strategy:
|
||||
matrix:
|
||||
mono508:
|
||||
testName: 'Mono 5.8'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-5.8
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
mono520:
|
||||
testName: 'Mono 5.20'
|
||||
artifactName: LinuxTests
|
||||
@@ -581,7 +577,7 @@ stages:
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
alpine:
|
||||
testName: 'Musl Net Core'
|
||||
artifactName: LinuxMuslCoreTests
|
||||
artifactName: LinuxCoreTests
|
||||
containerImage: servarr/testimages:alpine
|
||||
pattern: 'Radarr.**.linux-musl-core-x64.tar.gz'
|
||||
pool:
|
||||
@@ -646,14 +642,14 @@ stages:
|
||||
failBuild: true
|
||||
Mac:
|
||||
osName: 'Mac'
|
||||
imageName: 'macos-10.14'
|
||||
imageName: 'macos-10.14' # Fails due to firefox not being installed on image
|
||||
pattern: 'Radarr.**.osx-core-x64.tar.gz'
|
||||
failBuild: true
|
||||
failBuild: false
|
||||
Windows:
|
||||
osName: 'Windows'
|
||||
imageName: 'windows-2019'
|
||||
pattern: 'Radarr.**.windows-core-x64.zip'
|
||||
failBuild: true
|
||||
failBuild: $(failOnAutomationFailure)
|
||||
|
||||
pool:
|
||||
vmImage: $(imageName)
|
||||
@@ -688,9 +684,9 @@ stages:
|
||||
displayName: Move Package Contents
|
||||
- bash: |
|
||||
if [[ $OSNAME == "Mac" ]]; then
|
||||
url=https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-macos.tar.gz
|
||||
url=https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-macos.tar.gz
|
||||
elif [[ $OSNAME == "Linux" ]]; then
|
||||
url=https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-linux64.tar.gz
|
||||
url=https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz
|
||||
else
|
||||
echo "Unhandled OS"
|
||||
exit 1
|
||||
@@ -703,7 +699,7 @@ stages:
|
||||
- bash: |
|
||||
chmod a+x ${TESTSFOLDER}/test.sh
|
||||
${TESTSFOLDER}/test.sh ${OSNAME} Automation Test
|
||||
displayName: Run Automation Tests
|
||||
displayName: Run Integration Tests
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFormat: 'NUnit'
|
||||
@@ -751,19 +747,10 @@ stages:
|
||||
- checkout: self
|
||||
submodules: true
|
||||
fetchDepth: 1
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: 'yarn | "$(osName)" | yarn.lock'
|
||||
restoreKeys: |
|
||||
yarn | "$(osName)"
|
||||
yarn
|
||||
path: $(yarnCacheFolder)
|
||||
displayName: Cache Yarn packages
|
||||
- bash: ./build.sh --lint
|
||||
displayName: Lint Radarr Frontend
|
||||
env:
|
||||
FORCE_COLOR: 0
|
||||
YARN_CACHE_FOLDER: $(yarnCacheFolder)
|
||||
|
||||
- job: Analyze_Frontend
|
||||
displayName: Frontend
|
||||
|
||||
2
build.sh
2
build.sh
@@ -235,7 +235,7 @@ PackageTests()
|
||||
# geckodriver.exe isn't copied by dotnet publish
|
||||
if [ "$runtime" = "win-x64" ];
|
||||
then
|
||||
curl -Lso gecko.zip "https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-win64.zip"
|
||||
curl -Lso gecko.zip "https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-win64.zip"
|
||||
unzip -o gecko.zip
|
||||
cp geckodriver.exe "$testPackageFolder/$framework/win-x64/publish"
|
||||
fi
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"checkJs": false,
|
||||
"baseUrl": "src",
|
||||
"jsx": "react",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"paths": {
|
||||
"*": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
]
|
||||
}
|
||||
@@ -33,7 +33,7 @@ class Blacklist extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('Blacklist')}>
|
||||
<PageContent title="Blacklist">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
@@ -65,15 +65,13 @@ class Blacklist extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
{translate('UnableToLoadBlacklist')}
|
||||
</div>
|
||||
<div>Unable to load blacklist</div>
|
||||
}
|
||||
|
||||
{
|
||||
isPopulated && !error && !items.length &&
|
||||
<div>
|
||||
{translate('NoHistory')}
|
||||
No history blacklist
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
class BlacklistDetailsModal extends Component {
|
||||
|
||||
@@ -40,19 +39,19 @@ class BlacklistDetailsModal extends Component {
|
||||
<ModalBody>
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('Protocol')}
|
||||
title="Protocol"
|
||||
data={protocol}
|
||||
/>
|
||||
|
||||
{
|
||||
!!message &&
|
||||
<DescriptionListItem
|
||||
title={translate('Indexer')}
|
||||
title="Indexer"
|
||||
data={indexer}
|
||||
/>
|
||||
}
|
||||
@@ -60,7 +59,7 @@ class BlacklistDetailsModal extends Component {
|
||||
{
|
||||
!!message &&
|
||||
<DescriptionListItem
|
||||
title={translate('Message')}
|
||||
title="Message"
|
||||
data={message}
|
||||
/>
|
||||
}
|
||||
@@ -69,7 +68,7 @@ class BlacklistDetailsModal extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -9,7 +9,6 @@ import MovieFormats from 'Movie/MovieFormats';
|
||||
import MovieLanguage from 'Movie/MovieLanguage';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import BlacklistDetailsModal from './BlacklistDetailsModal';
|
||||
import styles from './BlacklistRow.css';
|
||||
|
||||
@@ -156,7 +155,7 @@ class BlacklistRow extends Component {
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
title={translate('RemoveFromBlacklist')}
|
||||
title="Remove from blacklist"
|
||||
name={icons.REMOVE}
|
||||
kind={kinds.DANGER}
|
||||
onPress={onRemovePress}
|
||||
|
||||
@@ -7,7 +7,6 @@ import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionList
|
||||
import Link from 'Components/Link/Link';
|
||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||
import formatAge from 'Utilities/Number/formatAge';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './HistoryDetails.css';
|
||||
|
||||
function HistoryDetails(props) {
|
||||
@@ -36,14 +35,14 @@ function HistoryDetails(props) {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
{
|
||||
!!indexer &&
|
||||
<DescriptionListItem
|
||||
title={translate('Indexer')}
|
||||
title="Indexer"
|
||||
data={indexer}
|
||||
/>
|
||||
}
|
||||
@@ -52,7 +51,7 @@ function HistoryDetails(props) {
|
||||
!!releaseGroup &&
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('ReleaseGroup')}
|
||||
title="Release Group"
|
||||
data={releaseGroup}
|
||||
/>
|
||||
}
|
||||
@@ -73,7 +72,7 @@ function HistoryDetails(props) {
|
||||
{
|
||||
!!downloadClient &&
|
||||
<DescriptionListItem
|
||||
title={translate('DownloadClient')}
|
||||
title="Download Client"
|
||||
data={downloadClient}
|
||||
/>
|
||||
}
|
||||
@@ -81,7 +80,7 @@ function HistoryDetails(props) {
|
||||
{
|
||||
!!downloadId &&
|
||||
<DescriptionListItem
|
||||
title={translate('GrabID')}
|
||||
title="Grab ID"
|
||||
data={downloadId}
|
||||
/>
|
||||
}
|
||||
@@ -89,7 +88,7 @@ function HistoryDetails(props) {
|
||||
{
|
||||
!!indexer &&
|
||||
<DescriptionListItem
|
||||
title={translate('AgeWhenGrabbed')}
|
||||
title="Age (when grabbed)"
|
||||
data={formatAge(age, ageHours, ageMinutes)}
|
||||
/>
|
||||
}
|
||||
@@ -97,7 +96,7 @@ function HistoryDetails(props) {
|
||||
{
|
||||
!!publishedDate &&
|
||||
<DescriptionListItem
|
||||
title={translate('PublishedDate')}
|
||||
title="Published Date"
|
||||
data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })}
|
||||
/>
|
||||
}
|
||||
@@ -114,14 +113,14 @@ function HistoryDetails(props) {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
{
|
||||
!!message &&
|
||||
<DescriptionListItem
|
||||
title={translate('Message')}
|
||||
title="Message"
|
||||
data={message}
|
||||
/>
|
||||
}
|
||||
@@ -139,7 +138,7 @@ function HistoryDetails(props) {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
@@ -147,7 +146,7 @@ function HistoryDetails(props) {
|
||||
!!droppedPath &&
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Source')}
|
||||
title="Source"
|
||||
data={droppedPath}
|
||||
/>
|
||||
}
|
||||
@@ -156,7 +155,7 @@ function HistoryDetails(props) {
|
||||
!!importedPath &&
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('ImportedTo')}
|
||||
title="Imported To"
|
||||
data={importedPath}
|
||||
/>
|
||||
}
|
||||
@@ -188,12 +187,12 @@ function HistoryDetails(props) {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('Reason')}
|
||||
title="Reason"
|
||||
data={reasonMessage}
|
||||
/>
|
||||
</DescriptionList>
|
||||
@@ -211,22 +210,22 @@ function HistoryDetails(props) {
|
||||
return (
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
title={translate('SourcePath')}
|
||||
title="Source Path"
|
||||
data={sourcePath}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('SourceRelativePath')}
|
||||
title="Source Relative Path"
|
||||
data={sourceRelativePath}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('DestinationPath')}
|
||||
title="Destination Path"
|
||||
data={path}
|
||||
/>
|
||||
|
||||
<DescriptionListItem
|
||||
title={translate('DestinationRelativePath')}
|
||||
title="Destination Relative Path"
|
||||
data={relativePath}
|
||||
/>
|
||||
</DescriptionList>
|
||||
@@ -242,14 +241,14 @@ function HistoryDetails(props) {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
|
||||
{
|
||||
!!message &&
|
||||
<DescriptionListItem
|
||||
title={translate('Message')}
|
||||
title="Message"
|
||||
data={message}
|
||||
/>
|
||||
}
|
||||
@@ -261,7 +260,7 @@ function HistoryDetails(props) {
|
||||
<DescriptionList>
|
||||
<DescriptionListItem
|
||||
descriptionClassName={styles.description}
|
||||
title={translate('Name')}
|
||||
title="Name"
|
||||
data={sourceTitle}
|
||||
/>
|
||||
</DescriptionList>
|
||||
|
||||
@@ -8,7 +8,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import HistoryDetails from './HistoryDetails';
|
||||
import styles from './HistoryDetailsModal.css';
|
||||
|
||||
@@ -80,7 +79,7 @@ function HistoryDetailsModal(props) {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -43,7 +43,7 @@ class History extends Component {
|
||||
const hasError = error || moviesError;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('History')}>
|
||||
<PageContent title="History">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
@@ -83,9 +83,7 @@ class History extends Component {
|
||||
|
||||
{
|
||||
!isFetchingAny && hasError &&
|
||||
<div>
|
||||
{translate('UnableToLoadHistory')}
|
||||
</div>
|
||||
<div>Unable to load history</div>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -149,7 +149,7 @@ class Queue extends Component {
|
||||
const disableSelectedActions = selectedCount === 0;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('Queue')}>
|
||||
<PageContent title="Queue">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
@@ -162,7 +162,7 @@ class Queue extends Component {
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('GrabSelected')}
|
||||
label="Grab Selected"
|
||||
iconName={icons.DOWNLOAD}
|
||||
isDisabled={disableSelectedActions || !isPendingSelected}
|
||||
isSpinning={isGrabbing}
|
||||
@@ -170,7 +170,7 @@ class Queue extends Component {
|
||||
/>
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('RemoveSelected')}
|
||||
label="Remove Selected"
|
||||
iconName={icons.REMOVE}
|
||||
isDisabled={disableSelectedActions}
|
||||
isSpinning={isRemoving}
|
||||
|
||||
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function QueueDetails(props) {
|
||||
const {
|
||||
@@ -24,7 +23,7 @@ function QueueDetails(props) {
|
||||
return (
|
||||
<Icon
|
||||
name={icons.PENDING}
|
||||
title={translate('ReleaseWillBeProcessedInterp', [moment(estimatedCompletionTime).fromNow()])}
|
||||
title={`Release will be processed ${moment(estimatedCompletionTime).fromNow()}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -35,7 +34,7 @@ function QueueDetails(props) {
|
||||
<Icon
|
||||
name={icons.DOWNLOAD}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('ImportFailedInterp', [errorMessage])}
|
||||
title={`Import failed: ${errorMessage}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -48,7 +47,7 @@ function QueueDetails(props) {
|
||||
<Icon
|
||||
name={icons.DOWNLOADING}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DownloadFailedInterp', [errorMessage])}
|
||||
title={`Download failed: ${errorMessage}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -58,7 +57,7 @@ function QueueDetails(props) {
|
||||
<Icon
|
||||
name={icons.DOWNLOADING}
|
||||
kind={kinds.DANGER}
|
||||
title={translate('DownloadFailedCheckDownloadClientForMoreDetails')}
|
||||
title="Download failed: check download client for more details"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -68,7 +67,7 @@ function QueueDetails(props) {
|
||||
<Icon
|
||||
name={icons.DOWNLOADING}
|
||||
kind={kinds.WARNING}
|
||||
title={translate('DownloadWarningCheckDownloadClientForMoreDetails')}
|
||||
title="Download warning: check download client for more details"
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -77,7 +76,7 @@ function QueueDetails(props) {
|
||||
return (
|
||||
<Icon
|
||||
name={icons.DOWNLOADING}
|
||||
title={translate('MovieIsDownloadingInterp', [progress.toFixed(1), title])}
|
||||
title={`Movie is downloading - ${progress.toFixed(1)}% ${title}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
class QueueOptions extends Component {
|
||||
|
||||
@@ -55,13 +54,13 @@ class QueueOptions extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowUnknownMovieItems')}</FormLabel>
|
||||
<FormLabel>Show Unknown Movie Items</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="includeUnknownMovieItems"
|
||||
value={includeUnknownMovieItems}
|
||||
helpText={translate('IncludeUnknownMovieItemsHelpText')}
|
||||
helpText="Show items without a movie in the queue, this could include removed movie, movies or anything else in Radarr's category"
|
||||
onChange={this.onOptionChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
@@ -15,7 +15,6 @@ import MovieLanguage from 'Movie/MovieLanguage';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import QueueStatusCell from './QueueStatusCell';
|
||||
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
||||
import TimeleftCell from './TimeleftCell';
|
||||
@@ -295,7 +294,7 @@ class QueueRow extends Component {
|
||||
}
|
||||
|
||||
<SpinnerIconButton
|
||||
title={translate('RemoveFromQueue')}
|
||||
title="Remove from queue"
|
||||
name={icons.REMOVE}
|
||||
isSpinning={isRemoving}
|
||||
onPress={this.onRemoveQueueItemPress}
|
||||
|
||||
@@ -4,7 +4,6 @@ import Icon from 'Components/Icon';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './QueueStatusCell.css';
|
||||
|
||||
function getDetailedPopoverBody(statusMessages) {
|
||||
@@ -50,34 +49,34 @@ function QueueStatusCell(props) {
|
||||
// status === 'downloading'
|
||||
let iconName = icons.DOWNLOADING;
|
||||
let iconKind = kinds.DEFAULT;
|
||||
let title = translate('Downloading');
|
||||
let title = 'Downloading';
|
||||
|
||||
if (status === 'paused') {
|
||||
iconName = icons.PAUSED;
|
||||
title = translate('Paused');
|
||||
title = 'Paused';
|
||||
}
|
||||
|
||||
if (status === 'queued') {
|
||||
iconName = icons.QUEUED;
|
||||
title = translate('Queued');
|
||||
title = 'Queued';
|
||||
}
|
||||
|
||||
if (status === 'completed') {
|
||||
iconName = icons.DOWNLOADED;
|
||||
title = translate('Downloaded');
|
||||
title = 'Downloaded';
|
||||
|
||||
if (trackedDownloadState === 'importPending') {
|
||||
title += ` - ${translate('WaitingToImport')}`;
|
||||
title += ' - Waiting to Import';
|
||||
iconKind = kinds.PURPLE;
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'importing') {
|
||||
title += ` - ${translate('Importing')}`;
|
||||
title += ' - Importing';
|
||||
iconKind = kinds.PURPLE;
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'failedPending') {
|
||||
title += ` - ${translate('WaitingToProcess')}`;
|
||||
title += ' - Waiting to Process';
|
||||
iconKind = kinds.DANGER;
|
||||
}
|
||||
}
|
||||
@@ -88,37 +87,36 @@ function QueueStatusCell(props) {
|
||||
|
||||
if (status === 'delay') {
|
||||
iconName = icons.PENDING;
|
||||
title = translate('Pending');
|
||||
title = 'Pending';
|
||||
}
|
||||
|
||||
if (status === 'DownloadClientUnavailable') {
|
||||
iconName = icons.PENDING;
|
||||
iconKind = kinds.WARNING;
|
||||
title = `${translate('Pending')} - ${translate('DownloadClientUnavailable')}`;
|
||||
title = 'Pending - Download client is unavailable';
|
||||
}
|
||||
|
||||
if (status === 'failed') {
|
||||
iconName = icons.DOWNLOADING;
|
||||
iconKind = kinds.DANGER;
|
||||
title = translate('DownloadFailed');
|
||||
title = 'Download failed';
|
||||
}
|
||||
|
||||
if (status === 'warning') {
|
||||
iconName = icons.DOWNLOADING;
|
||||
iconKind = kinds.WARNING;
|
||||
const warningMessage = errorMessage || translate('CheckDownloadClientForDetails');
|
||||
title = translate('DownloadWarning', [warningMessage]);
|
||||
title = `Download warning: ${errorMessage || 'check download client for more details'}`;
|
||||
}
|
||||
|
||||
if (hasError) {
|
||||
if (status === 'completed') {
|
||||
iconName = icons.DOWNLOAD;
|
||||
iconKind = kinds.DANGER;
|
||||
title = translate('ImportFailed', [sourceTitle]);
|
||||
title = `Import failed: ${sourceTitle}`;
|
||||
} else {
|
||||
iconName = icons.DOWNLOADING;
|
||||
iconKind = kinds.DANGER;
|
||||
title = translate('DownloadFailed');
|
||||
title = 'Download failed';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,8 +148,8 @@ QueueStatusCell.propTypes = {
|
||||
};
|
||||
|
||||
QueueStatusCell.defaultProps = {
|
||||
trackedDownloadStatus: translate('Ok'),
|
||||
trackedDownloadState: translate('Downloading')
|
||||
trackedDownloadStatus: 'Ok',
|
||||
trackedDownloadState: 'Downloading'
|
||||
};
|
||||
|
||||
export default QueueStatusCell;
|
||||
|
||||
@@ -10,7 +10,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
class RemoveQueueItemModal extends Component {
|
||||
|
||||
@@ -90,25 +89,25 @@ class RemoveQueueItemModal extends Component {
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('RemoveFromDownloadClient')}</FormLabel>
|
||||
<FormLabel>Remove From Download Client</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('BlacklistRelease')}</FormLabel>
|
||||
<FormLabel>Blacklist Release</FormLabel>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="blacklist"
|
||||
value={blacklist}
|
||||
helpText={translate('BlacklistHelpText')}
|
||||
helpText="Starts a search for this movie again and prevents this release from being grabbed again"
|
||||
onChange={this.onBlacklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -117,7 +116,7 @@ class RemoveQueueItemModal extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={this.onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -10,7 +10,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './RemoveQueueItemsModal.css';
|
||||
|
||||
class RemoveQueueItemsModal extends Component {
|
||||
@@ -91,13 +90,13 @@ class RemoveQueueItemsModal extends Component {
|
||||
</div>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('RemoveFromDownloadClient')}</FormLabel>
|
||||
<FormLabel>Remove From Download Client</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="remove"
|
||||
value={remove}
|
||||
helpTextWarning={translate('RemoveHelpTextWarning')}
|
||||
helpTextWarning="Removing will remove the download and the file(s) from the download client."
|
||||
isDisabled={!canIgnore}
|
||||
onChange={this.onRemoveChange}
|
||||
/>
|
||||
@@ -112,7 +111,7 @@ class RemoveQueueItemsModal extends Component {
|
||||
type={inputTypes.CHECK}
|
||||
name="blacklist"
|
||||
value={blacklist}
|
||||
helpText={translate('BlacklistHelpText')}
|
||||
helpText="Prevents Radarr from automatically grabbing this movie again"
|
||||
onChange={this.onBlacklistChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -121,7 +120,7 @@ class RemoveQueueItemsModal extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={this.onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -5,7 +5,6 @@ import formatTime from 'Utilities/Date/formatTime';
|
||||
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
|
||||
import getRelativeDate from 'Utilities/Date/getRelativeDate';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './TimeleftCell.css';
|
||||
|
||||
function TimeleftCell(props) {
|
||||
@@ -27,7 +26,7 @@ function TimeleftCell(props) {
|
||||
return (
|
||||
<TableRowCell
|
||||
className={styles.timeleft}
|
||||
title={translate('DelayingDownloadUntilInterp', [date, time])}
|
||||
title={`Delaying download until ${date} at ${time}`}
|
||||
>
|
||||
-
|
||||
</TableRowCell>
|
||||
@@ -41,7 +40,7 @@ function TimeleftCell(props) {
|
||||
return (
|
||||
<TableRowCell
|
||||
className={styles.timeleft}
|
||||
title={translate('RetryingDownloadInterp', [date, time])}
|
||||
title={`Retrying download ${date} at ${time}`}
|
||||
>
|
||||
-
|
||||
</TableRowCell>
|
||||
|
||||
@@ -88,7 +88,7 @@ class AddNewMovie extends Component {
|
||||
const isFetching = this.state.isFetching;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('AddNewMovie')}>
|
||||
<PageContent title="Add New Movie">
|
||||
<PageContentBody>
|
||||
<div className={styles.searchContainer}>
|
||||
<div className={styles.searchIconContainer}>
|
||||
@@ -127,7 +127,7 @@ class AddNewMovie extends Component {
|
||||
!isFetching && !!error ?
|
||||
<div className={styles.message}>
|
||||
<div className={styles.helpText}>
|
||||
{translate('FailedLoadingSearchResults')}
|
||||
Failed to load search results, please try again.
|
||||
</div>
|
||||
<div>{getErrorMessage(error)}</div>
|
||||
</div> : null
|
||||
@@ -152,15 +152,11 @@ class AddNewMovie extends Component {
|
||||
{
|
||||
!isFetching && !error && !items.length && !!term &&
|
||||
<div className={styles.message}>
|
||||
<div className={styles.noResults}>
|
||||
{translate('CouldNotFindResults', [term])}
|
||||
</div>
|
||||
<div>
|
||||
{translate('YouCanAlsoSearch')}
|
||||
</div>
|
||||
<div className={styles.noResults}>Couldn't find any results for '{term}'</div>
|
||||
<div>You can also search using TMDB ID or IMDB ID of a movie. eg. tmdb:71663</div>
|
||||
<div>
|
||||
<Link to="https://github.com/Radarr/Radarr/wiki/FAQ#why-cant-i-add-a-new-movie-when-i-know-the-tmdb-id">
|
||||
{translate('CantFindMovie')}
|
||||
Why can't I find my movie?
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
@@ -173,9 +169,7 @@ class AddNewMovie extends Component {
|
||||
<div className={styles.helpText}>
|
||||
{translate('AddNewMessage')}
|
||||
</div>
|
||||
<div>
|
||||
{translate('AddNewTmdbIdMessage')}
|
||||
</div>
|
||||
<div>{translate('AddNewTmdbIdMessage')}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -183,14 +177,14 @@ class AddNewMovie extends Component {
|
||||
!term && !hasExistingMovies ?
|
||||
<div className={styles.message}>
|
||||
<div className={styles.noMoviesText}>
|
||||
{translate('HaveNotAddedMovies')}
|
||||
You haven't added any movies yet, do you want to import some or all of your movies first?
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
to="/add/import"
|
||||
kind={kinds.PRIMARY}
|
||||
>
|
||||
{translate('ImportExistingMovies')}
|
||||
Import Existing Movies
|
||||
</Button>
|
||||
</div>
|
||||
</div> :
|
||||
|
||||
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
|
||||
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
|
||||
import parseUrl from 'Utilities/String/parseUrl';
|
||||
import AddNewMovie from './AddNewMovie';
|
||||
|
||||
@@ -29,7 +29,7 @@ const mapDispatchToProps = {
|
||||
lookupMovie,
|
||||
clearAddMovie,
|
||||
fetchRootFolders,
|
||||
fetchImportExclusions
|
||||
fetchNetImportExclusions
|
||||
};
|
||||
|
||||
class AddNewMovieConnector extends Component {
|
||||
@@ -45,7 +45,7 @@ class AddNewMovieConnector extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.fetchRootFolders();
|
||||
this.props.fetchImportExclusions();
|
||||
this.props.fetchNetImportExclusions();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@@ -102,7 +102,7 @@ AddNewMovieConnector.propTypes = {
|
||||
lookupMovie: PropTypes.func.isRequired,
|
||||
clearAddMovie: PropTypes.func.isRequired,
|
||||
fetchRootFolders: PropTypes.func.isRequired,
|
||||
fetchImportExclusions: PropTypes.func.isRequired
|
||||
fetchNetImportExclusions: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector);
|
||||
|
||||
@@ -12,7 +12,6 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './AddNewMovieModalContent.css';
|
||||
|
||||
class AddNewMovieModalContent extends Component {
|
||||
@@ -96,7 +95,7 @@ class AddNewMovieModalContent extends Component {
|
||||
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('RootFolder')}</FormLabel>
|
||||
<FormLabel>Root Folder</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.ROOT_FOLDER_SELECT}
|
||||
@@ -109,7 +108,7 @@ class AddNewMovieModalContent extends Component {
|
||||
movieFolder: folder,
|
||||
isWindows
|
||||
}}
|
||||
helpText={translate('SubfolderWillBeCreatedAutomaticallyInterp', [folder])}
|
||||
helpText={`'${folder}' subfolder will be created automatically`}
|
||||
onChange={onInputChange}
|
||||
{...rootFolderPath}
|
||||
/>
|
||||
@@ -129,7 +128,7 @@ class AddNewMovieModalContent extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('MinimumAvailability')}</FormLabel>
|
||||
<FormLabel>Minimum Availability</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.AVAILABILITY_SELECT}
|
||||
@@ -140,7 +139,7 @@ class AddNewMovieModalContent extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('QualityProfile')}</FormLabel>
|
||||
<FormLabel>Quality Profile</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.QUALITY_PROFILE_SELECT}
|
||||
@@ -151,7 +150,7 @@ class AddNewMovieModalContent extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Tags')}</FormLabel>
|
||||
<FormLabel>Tags</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
|
||||
@@ -34,20 +34,10 @@
|
||||
|
||||
.content {
|
||||
flex: 0 1 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.titleRow {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.titleContainer {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
font-weight: 300;
|
||||
font-size: 36px;
|
||||
}
|
||||
@@ -57,12 +47,10 @@
|
||||
color: $disabledColor;
|
||||
}
|
||||
|
||||
.icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex: 1 0 auto;
|
||||
height: 55px;
|
||||
.externalLink {
|
||||
margin-top: 5px;
|
||||
margin-left: auto;
|
||||
color: $textColor;
|
||||
}
|
||||
|
||||
.alreadyExistsIcon {
|
||||
@@ -80,15 +68,3 @@
|
||||
.overview {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-left: 8px;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $breakpointMedium) {
|
||||
.titleRow {
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,8 @@ import HeartRating from 'Components/HeartRating';
|
||||
import Icon from 'Components/Icon';
|
||||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||
import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
|
||||
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import AddNewMovieModal from './AddNewMovieModal';
|
||||
import styles from './AddNewMovieSearchResult.css';
|
||||
|
||||
@@ -53,7 +50,6 @@ class AddNewMovieSearchResult extends Component {
|
||||
const {
|
||||
tmdbId,
|
||||
imdbId,
|
||||
youTubeTrailerId,
|
||||
title,
|
||||
titleSlug,
|
||||
year,
|
||||
@@ -94,43 +90,69 @@ class AddNewMovieSearchResult extends Component {
|
||||
}
|
||||
|
||||
<div className={styles.content}>
|
||||
<div className={styles.titleRow}>
|
||||
<div className={styles.titleContainer}>
|
||||
<div className={styles.title}>
|
||||
{title}
|
||||
<div className={styles.title}>
|
||||
{title}
|
||||
|
||||
{
|
||||
!title.contains(year) && !!year ?
|
||||
<span className={styles.year}>
|
||||
({year})
|
||||
</span> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
!title.contains(year) && !!year &&
|
||||
<span className={styles.year}>({year})</span>
|
||||
}
|
||||
|
||||
<div className={styles.icons}>
|
||||
{
|
||||
isExistingMovie &&
|
||||
<Icon
|
||||
className={styles.alreadyExistsIcon}
|
||||
name={icons.CHECK_CIRCLE}
|
||||
size={36}
|
||||
title="Already in your library"
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
isExistingMovie &&
|
||||
<Icon
|
||||
className={styles.alreadyExistsIcon}
|
||||
name={icons.CHECK_CIRCLE}
|
||||
size={36}
|
||||
title={translate('AlreadyInYourLibrary')}
|
||||
/>
|
||||
}
|
||||
{
|
||||
isExclusionMovie &&
|
||||
<Icon
|
||||
className={styles.exclusionIcon}
|
||||
name={icons.DANGER}
|
||||
size={36}
|
||||
title="Movie is on Net Import Exclusion List"
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
isExclusionMovie &&
|
||||
<Icon
|
||||
className={styles.exclusionIcon}
|
||||
name={icons.DANGER}
|
||||
size={36}
|
||||
title={translate('MovieIsOnImportExclusionList')}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
{
|
||||
isSmallScreen ?
|
||||
null :
|
||||
<div className={styles.externalLink}>
|
||||
<Link
|
||||
to={`https://www.themoviedb.org/movie/${tmdbId}`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
TMDb
|
||||
</Label>
|
||||
</Link>
|
||||
|
||||
{
|
||||
imdbId &&
|
||||
<Link
|
||||
to={`https://www.imdb.com/title/${imdbId}`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
IMDb
|
||||
</Label>
|
||||
</Link>
|
||||
}
|
||||
|
||||
<Link
|
||||
to={`https://trakt.tv/search/tmdb/${tmdbId}?id_type=movie`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
Trakt
|
||||
</Label>
|
||||
</Link>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -148,32 +170,6 @@ class AddNewMovieSearchResult extends Component {
|
||||
</Label>
|
||||
}
|
||||
|
||||
<Tooltip
|
||||
anchor={
|
||||
<Label
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={13}
|
||||
/>
|
||||
|
||||
<span className={styles.links}>
|
||||
Links
|
||||
</span>
|
||||
</Label>
|
||||
}
|
||||
tooltip={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
imdbId={imdbId}
|
||||
/>
|
||||
}
|
||||
kind={kinds.INVERSE}
|
||||
position={tooltipPositions.BOTTOM}
|
||||
/>
|
||||
|
||||
{
|
||||
status === 'ended' &&
|
||||
<Label
|
||||
@@ -185,6 +181,42 @@ class AddNewMovieSearchResult extends Component {
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
isSmallScreen ?
|
||||
<div className={styles.externalLink}>
|
||||
<Link
|
||||
to={`https://www.themoviedb.org/movie/${tmdbId}`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
TMDb
|
||||
</Label>
|
||||
</Link>
|
||||
|
||||
{
|
||||
imdbId &&
|
||||
<Link
|
||||
to={`https://www.imdb.com/title/${imdbId}`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
IMDb
|
||||
</Label>
|
||||
</Link>
|
||||
}
|
||||
|
||||
<Link
|
||||
to={`https://trakt.tv/search/tmdb/${tmdbId}?id_type=movie`}
|
||||
onPress={this.onExternalLinkPress}
|
||||
>
|
||||
<Label size={sizes.LARGE}>
|
||||
Trakt
|
||||
</Label>
|
||||
</Link>
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
|
||||
<div className={styles.overview}>
|
||||
{overview}
|
||||
</div>
|
||||
@@ -209,7 +241,6 @@ class AddNewMovieSearchResult extends Component {
|
||||
AddNewMovieSearchResult.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
youTubeTrailerId: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
|
||||
@@ -3,7 +3,6 @@ import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
@@ -81,7 +80,6 @@ class ImportMovie extends Component {
|
||||
path,
|
||||
rootFoldersFetching,
|
||||
rootFoldersError,
|
||||
rootFoldersPopulated,
|
||||
unmappedFolders
|
||||
} = this.props;
|
||||
|
||||
@@ -93,7 +91,7 @@ class ImportMovie extends Component {
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('ImportMovies')}>
|
||||
<PageContent title="Import Movies">
|
||||
<PageContentBody
|
||||
registerScroller={this.setScrollerRef}
|
||||
onScroll={this.onScroll}
|
||||
@@ -104,16 +102,13 @@ class ImportMovie extends Component {
|
||||
|
||||
{
|
||||
!rootFoldersFetching && !!rootFoldersError ?
|
||||
<div>
|
||||
{translate('UnableToLoadRootFolders')}
|
||||
</div> :
|
||||
<div>Unable to load root folders</div> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!rootFoldersError &&
|
||||
!rootFoldersFetching &&
|
||||
rootFoldersPopulated &&
|
||||
!unmappedFolders.length ?
|
||||
<div>
|
||||
All movies in {path} have been imported
|
||||
@@ -124,7 +119,6 @@ class ImportMovie extends Component {
|
||||
{
|
||||
!rootFoldersError &&
|
||||
!rootFoldersFetching &&
|
||||
rootFoldersPopulated &&
|
||||
!!unmappedFolders.length &&
|
||||
scroller ?
|
||||
<ImportMovieTableConnector
|
||||
|
||||
@@ -31,7 +31,3 @@
|
||||
margin: 0 10px 0 12px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.importError {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,11 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
// import CheckInput from 'Components/Form/CheckInput';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import Icon from 'Components/Icon';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContentFooter from 'Components/Page/PageContentFooter';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import { icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import styles from './ImportMovieFooter.css';
|
||||
|
||||
const MIXED = 'mixed';
|
||||
@@ -95,10 +93,7 @@ class ImportMovieFooter extends Component {
|
||||
isMonitorMixed,
|
||||
isQualityProfileIdMixed,
|
||||
isMinimumAvailabilityMixed,
|
||||
hasUnsearchedItems,
|
||||
importError,
|
||||
onImportPress,
|
||||
onLookupPress,
|
||||
onCancelLookupPress
|
||||
} = this.props;
|
||||
|
||||
@@ -172,71 +167,27 @@ class ImportMovieFooter extends Component {
|
||||
</SpinnerButton>
|
||||
|
||||
{
|
||||
isLookingUpMovie ?
|
||||
isLookingUpMovie &&
|
||||
<Button
|
||||
className={styles.loadingButton}
|
||||
kind={kinds.WARNING}
|
||||
onPress={onCancelLookupPress}
|
||||
>
|
||||
Cancel Processing
|
||||
</Button> :
|
||||
null
|
||||
</Button>
|
||||
}
|
||||
|
||||
{
|
||||
hasUnsearchedItems ?
|
||||
<Button
|
||||
className={styles.loadingButton}
|
||||
kind={kinds.SUCCESS}
|
||||
onPress={onLookupPress}
|
||||
>
|
||||
Start Processing
|
||||
</Button> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
isLookingUpMovie ?
|
||||
isLookingUpMovie &&
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
size={24}
|
||||
/> :
|
||||
null
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
isLookingUpMovie ?
|
||||
'Processing Folders' :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
importError ?
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
className={styles.importError}
|
||||
name={icons.WARNING}
|
||||
kind={kinds.WARNING}
|
||||
/>
|
||||
}
|
||||
title="Import Errors"
|
||||
body={
|
||||
<ul>
|
||||
{
|
||||
importError.responseJSON.map((error, index) => {
|
||||
return (
|
||||
<li key={index}>
|
||||
{error.errorMessage}
|
||||
</li>
|
||||
);
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/> :
|
||||
null
|
||||
isLookingUpMovie &&
|
||||
'Processing Folders'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -255,11 +206,8 @@ ImportMovieFooter.propTypes = {
|
||||
isMonitorMixed: PropTypes.bool.isRequired,
|
||||
isQualityProfileIdMixed: PropTypes.bool.isRequired,
|
||||
isMinimumAvailabilityMixed: PropTypes.bool.isRequired,
|
||||
hasUnsearchedItems: PropTypes.bool.isRequired,
|
||||
importError: PropTypes.object,
|
||||
onInputChange: PropTypes.func.isRequired,
|
||||
onImportPress: PropTypes.func.isRequired,
|
||||
onLookupPress: PropTypes.func.isRequired,
|
||||
onCancelLookupPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { cancelLookupMovie, lookupUnsearchedMovies } from 'Store/Actions/importMovieActions';
|
||||
import { cancelLookupMovie } from 'Store/Actions/importMovieActions';
|
||||
import ImportMovieFooter from './ImportMovieFooter';
|
||||
|
||||
function isMixed(items, selectedIds, defaultValue, key) {
|
||||
@@ -25,14 +25,12 @@ function createMapStateToProps() {
|
||||
const {
|
||||
isLookingUpMovie,
|
||||
isImporting,
|
||||
items,
|
||||
importError
|
||||
items
|
||||
} = importMovie;
|
||||
|
||||
const isMonitorMixed = isMixed(items, selectedIds, defaultMonitor, 'monitor');
|
||||
const isQualityProfileIdMixed = isMixed(items, selectedIds, defaultQualityProfileId, 'qualityProfileId');
|
||||
const isMinimumAvailabilityMixed = isMixed(items, selectedIds, defaultMinimumAvailability, 'minimumAvailability');
|
||||
const hasUnsearchedItems = !isLookingUpMovie && items.some((item) => !item.isPopulated);
|
||||
|
||||
return {
|
||||
selectedCount: selectedIds.length,
|
||||
@@ -43,16 +41,13 @@ function createMapStateToProps() {
|
||||
defaultMinimumAvailability,
|
||||
isMonitorMixed,
|
||||
isQualityProfileIdMixed,
|
||||
isMinimumAvailabilityMixed,
|
||||
importError,
|
||||
hasUnsearchedItems
|
||||
isMinimumAvailabilityMixed
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
onLookupPress: lookupUnsearchedMovies,
|
||||
onCancelLookupPress: cancelLookupMovie
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './ImportMovieRootFolderRow.css';
|
||||
|
||||
function ImportMovieRootFolderRow(props) {
|
||||
@@ -41,7 +40,7 @@ function ImportMovieRootFolderRow(props) {
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
<IconButton
|
||||
title={translate('RemoveRootFolder')}
|
||||
title="Remove root folder"
|
||||
name={icons.REMOVE}
|
||||
onPress={onDeletePress}
|
||||
/>
|
||||
|
||||
@@ -17,17 +17,17 @@ import styles from './ImportMovieSelectFolder.css';
|
||||
const rootFolderColumns = [
|
||||
{
|
||||
name: 'path',
|
||||
label: translate('Path'),
|
||||
label: 'Path',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'freeSpace',
|
||||
label: translate('FreeSpace'),
|
||||
label: 'Free Space',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'unmappedFolders',
|
||||
label: translate('UnmappedFolders'),
|
||||
label: 'Unmapped Folders',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
@@ -77,7 +77,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('ImportMovies')}>
|
||||
<PageContent title="Import Movies">
|
||||
<PageContentBody>
|
||||
{
|
||||
isFetching && !isPopulated &&
|
||||
@@ -86,9 +86,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
{translate('UnableToLoadRootFolders')}
|
||||
</div>
|
||||
<div>Unable to load root folders</div>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -113,7 +111,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
{
|
||||
items.length > 0 ?
|
||||
<div className={styles.recentFolders}>
|
||||
<FieldSet legend={translate('RecentFolders')}>
|
||||
<FieldSet legend="Recent Folders">
|
||||
<Table
|
||||
columns={rootFolderColumns}
|
||||
>
|
||||
|
||||
@@ -15,10 +15,10 @@ import MovieIndexConnector from 'Movie/Index/MovieIndexConnector';
|
||||
import CustomFormatSettingsConnector from 'Settings/CustomFormats/CustomFormatSettingsConnector';
|
||||
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
|
||||
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
|
||||
import ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector';
|
||||
import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector';
|
||||
import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector';
|
||||
import MetadataSettings from 'Settings/Metadata/MetadataSettings';
|
||||
import NetImportSettingsConnector from 'Settings/NetImport/NetImportSettingsConnector';
|
||||
import NotificationSettings from 'Settings/Notifications/NotificationSettings';
|
||||
import Profiles from 'Settings/Profiles/Profiles';
|
||||
import Quality from 'Settings/Quality/Quality';
|
||||
@@ -156,8 +156,8 @@ function AppRoutes(props) {
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/settings/importlists"
|
||||
component={ImportListSettingsConnector}
|
||||
path="/settings/netimports"
|
||||
component={NetImportSettingsConnector}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
||||
@@ -8,7 +8,6 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import UpdateChanges from 'System/Updates/UpdateChanges';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './AppUpdatedModalContent.css';
|
||||
|
||||
function AppUpdatedModalContent(props) {
|
||||
@@ -50,12 +49,12 @@ function AppUpdatedModalContent(props) {
|
||||
</div>
|
||||
|
||||
<UpdateChanges
|
||||
title={translate('New')}
|
||||
title="New"
|
||||
changes={update.changes.new}
|
||||
/>
|
||||
|
||||
<UpdateChanges
|
||||
title={translate('Fixed')}
|
||||
title="Fixed"
|
||||
changes={update.changes.fixed}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './ConnectionLostModal.css';
|
||||
|
||||
function ConnectionLostModal(props) {
|
||||
@@ -23,16 +22,16 @@ function ConnectionLostModal(props) {
|
||||
>
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{translate('ConnectionLost')}
|
||||
Connnection Lost
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<div>
|
||||
{translate('ConnectionLostMessage')}
|
||||
Radarr has lost it's connection to the backend and will need to be reloaded to restore functionality.
|
||||
</div>
|
||||
|
||||
<div className={styles.automatic}>
|
||||
{translate('ConnectionLostAutomaticMessage')}
|
||||
Radarr will try to connect automatically, or you can click reload below.
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
@@ -40,7 +39,7 @@ function ConnectionLostModal(props) {
|
||||
kind={kinds.PRIMARY}
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Reload')}
|
||||
Reload
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
composes: link from '~Calendar/Events/CalendarEvent.css';
|
||||
}
|
||||
|
||||
.eventWrapper {
|
||||
display: flex;
|
||||
flex: 1 0 1px;
|
||||
@@ -34,8 +30,7 @@
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.movieTitle,
|
||||
.genres {
|
||||
.movieTitle {
|
||||
@add-mixin truncate;
|
||||
|
||||
flex: 0 1 300px;
|
||||
@@ -66,10 +61,6 @@
|
||||
composes: missing from '~Calendar/Events/CalendarEvent.css';
|
||||
}
|
||||
|
||||
.unreleased {
|
||||
composes: unreleased from '~Calendar/Events/CalendarEvent.css';
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $breakpointSmall) {
|
||||
.event {
|
||||
flex-direction: column;
|
||||
@@ -90,8 +81,3 @@
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.dateIcon {
|
||||
display: inline;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import getStatusStyle from 'Calendar/getStatusStyle';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import styles from './AgendaEvent.css';
|
||||
|
||||
class AgendaEvent extends Component {
|
||||
@@ -41,65 +41,35 @@ class AgendaEvent extends Component {
|
||||
movieFile,
|
||||
title,
|
||||
titleSlug,
|
||||
genres,
|
||||
isAvailable,
|
||||
inCinemas,
|
||||
digitalRelease,
|
||||
physicalRelease,
|
||||
monitored,
|
||||
hasFile,
|
||||
grabbed,
|
||||
queueItem,
|
||||
showDate,
|
||||
showMovieInformation,
|
||||
showCutoffUnmetIcon,
|
||||
longDateFormat,
|
||||
colorImpairedMode,
|
||||
startDate,
|
||||
endDate
|
||||
colorImpairedMode
|
||||
} = this.props;
|
||||
|
||||
const agendaStart = Date.parse(startDate);
|
||||
const agendaEnd = Date.parse(endDate);
|
||||
const cinemaDate = Date.parse(inCinemas);
|
||||
const digitalDate = Date.parse(digitalRelease);
|
||||
let startTime = physicalRelease;
|
||||
let releaseIcon = icons.DISC;
|
||||
|
||||
if (digitalDate >= agendaStart && digitalDate <= agendaEnd) {
|
||||
startTime = digitalRelease;
|
||||
releaseIcon = icons.MOVIE_FILE;
|
||||
}
|
||||
|
||||
if (cinemaDate >= agendaStart && cinemaDate <= agendaEnd) {
|
||||
startTime = inCinemas;
|
||||
releaseIcon = icons.IN_CINEMAS;
|
||||
}
|
||||
|
||||
startTime = moment(startTime);
|
||||
const startTime = moment(inCinemas);
|
||||
const downloading = !!(queueItem || grabbed);
|
||||
const isMonitored = monitored;
|
||||
const statusStyle = getStatusStyle(hasFile, downloading, isAvailable, isMonitored);
|
||||
const joinedGenres = genres.slice(0, 2).join(', ');
|
||||
const link = `/movie/${titleSlug}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Link
|
||||
className={classNames(
|
||||
styles.event,
|
||||
styles.link
|
||||
)}
|
||||
to={link}
|
||||
className={styles.event}
|
||||
component="div"
|
||||
onPress={this.onPress}
|
||||
>
|
||||
<div className={styles.date}>
|
||||
<div className={styles.dateIcon}>
|
||||
<Icon
|
||||
name={releaseIcon}
|
||||
kind={kinds.DEFAULT}
|
||||
/>
|
||||
</div>
|
||||
{(showDate) ? startTime.format(longDateFormat) : null}
|
||||
{
|
||||
showDate &&
|
||||
startTime.format(longDateFormat)
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -110,16 +80,12 @@ class AgendaEvent extends Component {
|
||||
)}
|
||||
>
|
||||
<div className={styles.movieTitle}>
|
||||
{title}
|
||||
<MovieTitleLink
|
||||
titleSlug={titleSlug}
|
||||
title={title}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
showMovieInformation &&
|
||||
<div className={styles.genres}>
|
||||
{joinedGenres}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!queueItem &&
|
||||
<span className={styles.statusIcon}>
|
||||
@@ -134,7 +100,7 @@ class AgendaEvent extends Component {
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.DOWNLOADING}
|
||||
title={translate('MovieIsDownloading')}
|
||||
title="Movie is downloading"
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -146,7 +112,7 @@ class AgendaEvent extends Component {
|
||||
className={styles.statusIcon}
|
||||
name={icons.MOVIE_FILE}
|
||||
kind={kinds.WARNING}
|
||||
title={translate('QualityCutoffHasNotBeenMet')}
|
||||
title="Quality cutoff has not been met"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
@@ -161,27 +127,17 @@ AgendaEvent.propTypes = {
|
||||
movieFile: PropTypes.object,
|
||||
title: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
genres: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
isAvailable: PropTypes.bool.isRequired,
|
||||
inCinemas: PropTypes.string,
|
||||
digitalRelease: PropTypes.string,
|
||||
physicalRelease: PropTypes.string,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
hasFile: PropTypes.bool.isRequired,
|
||||
grabbed: PropTypes.bool,
|
||||
queueItem: PropTypes.object,
|
||||
showDate: PropTypes.bool.isRequired,
|
||||
showMovieInformation: PropTypes.bool.isRequired,
|
||||
showCutoffUnmetIcon: PropTypes.bool.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
colorImpairedMode: PropTypes.bool.isRequired,
|
||||
startDate: PropTypes.date,
|
||||
endDate: PropTypes.date
|
||||
};
|
||||
|
||||
AgendaEvent.defaultProps = {
|
||||
genres: []
|
||||
colorImpairedMode: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default AgendaEvent;
|
||||
|
||||
@@ -13,9 +13,7 @@ function createMapStateToProps() {
|
||||
createMovieFileSelector(),
|
||||
createQueueItemSelector(),
|
||||
createUISettingsSelector(),
|
||||
(state) => state.calendar.start,
|
||||
(state) => state.calendar.end,
|
||||
(calendarOptions, movie, movieFile, queueItem, uiSettings, startDate, endDate) => {
|
||||
(calendarOptions, movie, movieFile, queueItem, uiSettings) => {
|
||||
return {
|
||||
movie,
|
||||
movieFile,
|
||||
@@ -23,9 +21,7 @@ function createMapStateToProps() {
|
||||
...calendarOptions,
|
||||
timeFormat: uiSettings.timeFormat,
|
||||
longDateFormat: uiSettings.longDateFormat,
|
||||
colorImpairedMode: uiSettings.enableColorImpairedMode,
|
||||
startDate,
|
||||
endDate
|
||||
colorImpairedMode: uiSettings.enableColorImpairedMode
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import AgendaConnector from './Agenda/AgendaConnector';
|
||||
import * as calendarViews from './calendarViews';
|
||||
import CalendarDaysConnector from './Day/CalendarDaysConnector';
|
||||
@@ -31,9 +30,7 @@ class Calendar extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
{translate('UnableToLoadTheCalendar')}
|
||||
</div>
|
||||
<div>Unable to load the calendar</div>
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -76,15 +76,16 @@ class CalendarConnector extends Component {
|
||||
} = this.props;
|
||||
|
||||
if (hasDifferentItems(prevProps.items, items)) {
|
||||
const movieIds = selectUniqueIds(items, 'id');
|
||||
const movieFileIds = selectUniqueIds(items, 'movieFileId');
|
||||
|
||||
if (items.length) {
|
||||
this.props.fetchQueueDetails({ movieIds });
|
||||
}
|
||||
|
||||
if (movieFileIds.length) {
|
||||
this.props.fetchMovieFiles({ movieFileIds });
|
||||
}
|
||||
|
||||
if (items.length) {
|
||||
this.props.fetchQueueDetails();
|
||||
}
|
||||
}
|
||||
|
||||
if (prevProps.time !== time) {
|
||||
|
||||
@@ -98,7 +98,7 @@ class CalendarPage extends Component {
|
||||
const isMeasured = this.state.width > 0;
|
||||
|
||||
return (
|
||||
<PageContent title={translate('Calendar')}>
|
||||
<PageContent title="Calendar">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
@@ -110,7 +110,7 @@ class CalendarPage extends Component {
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('RSSSync')}
|
||||
label={translate('RssSync')}
|
||||
iconName={icons.RSS}
|
||||
isSpinning={isRssSyncExecuting}
|
||||
onPress={onRssSyncPress}
|
||||
|
||||
@@ -6,7 +6,6 @@ import getStatusStyle from 'Calendar/getStatusStyle';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import CalendarEventQueueDetails from './CalendarEventQueueDetails';
|
||||
import styles from './CalendarEvent.css';
|
||||
|
||||
@@ -86,7 +85,7 @@ class CalendarEvent extends Component {
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.DOWNLOADING}
|
||||
title={translate('MovieIsDownloading')}
|
||||
title="movie is downloading"
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -98,7 +97,7 @@ class CalendarEvent extends Component {
|
||||
className={styles.statusIcon}
|
||||
name={icons.MOVIE_FILE}
|
||||
kind={kinds.WARNING}
|
||||
title={translate('QualityCutoffHasNotBeenMet')}
|
||||
title="Quality cutoff has not been met"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,6 @@ import React from 'react';
|
||||
import QueueDetails from 'Activity/Queue/QueueDetails';
|
||||
import CircularProgressBar from 'Components/CircularProgressBar';
|
||||
import colors from 'Styles/Variables/colors';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function CalendarEventQueueDetails(props) {
|
||||
const {
|
||||
@@ -26,7 +25,7 @@ function CalendarEventQueueDetails(props) {
|
||||
status={status}
|
||||
errorMessage={errorMessage}
|
||||
progressBar={
|
||||
<div title={translate('MovieIsDownloadingInterp', [progress.toFixed(1), title])}>
|
||||
<div title={`Movie is downloading - ${progress.toFixed(1)}% ${title}`}>
|
||||
<CircularProgressBar
|
||||
progress={progress}
|
||||
size={20}
|
||||
|
||||
@@ -12,7 +12,6 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import { firstDayOfWeekOptions, timeFormatOptions, weekColumnOptions } from 'Settings/UI/UISettings';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
class CalendarOptionsModalContent extends Component {
|
||||
|
||||
@@ -111,38 +110,38 @@ class CalendarOptionsModalContent extends Component {
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
<FieldSet legend={translate('Local')}>
|
||||
<FieldSet legend="Local">
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowMovieInformation')}</FormLabel>
|
||||
<FormLabel>Show Movie Information</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="showMovieInformation"
|
||||
value={showMovieInformation}
|
||||
helpText={translate('ShowMovieInformationHelpText')}
|
||||
helpText="Show movie genres and certification"
|
||||
onChange={this.onOptionInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('IconForCutoffUnmet')}</FormLabel>
|
||||
<FormLabel>Icon for Cutoff Unmet</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="showCutoffUnmetIcon"
|
||||
value={showCutoffUnmetIcon}
|
||||
helpText={translate('ShowCutoffUnmetIconHelpText')}
|
||||
helpText="Show icon for files when the cutoff hasn't been met"
|
||||
onChange={this.onOptionInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</FieldSet>
|
||||
|
||||
<FieldSet legend={translate('Global')}>
|
||||
<FieldSet legend="Global">
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('FirstDayOfWeek')}</FormLabel>
|
||||
<FormLabel>First Day of Week</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
@@ -154,7 +153,7 @@ class CalendarOptionsModalContent extends Component {
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('WeekColumnHeader')}</FormLabel>
|
||||
<FormLabel>Week Column Header</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
@@ -162,12 +161,12 @@ class CalendarOptionsModalContent extends Component {
|
||||
values={weekColumnOptions}
|
||||
value={calendarWeekColumnHeader}
|
||||
onChange={this.onGlobalInputChange}
|
||||
helpText={translate('HelpText')}
|
||||
helpText="Shown above each column when week is the active view"
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('TimeFormat')}</FormLabel>
|
||||
<FormLabel>Time Format</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.SELECT}
|
||||
@@ -177,13 +176,13 @@ class CalendarOptionsModalContent extends Component {
|
||||
onChange={this.onGlobalInputChange}
|
||||
/>
|
||||
</FormGroup><FormGroup>
|
||||
<FormLabel>{translate('EnableColorImpairedMode')}</FormLabel>
|
||||
<FormLabel>Enable Color-Impaired Mode</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="enableColorImpairedMode"
|
||||
value={enableColorImpairedMode}
|
||||
helpText={translate('EnableColorImpairedModeHelpText')}
|
||||
helpText="Altered style to allow color-impaired users to better distinguish color coded information"
|
||||
onChange={this.onGlobalInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -194,7 +193,7 @@ class CalendarOptionsModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -13,7 +13,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { icons, inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function getUrls(state) {
|
||||
const {
|
||||
@@ -115,37 +114,37 @@ class CalendarLinkModalContent extends Component {
|
||||
<ModalBody>
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('IncludeUnmonitored')}</FormLabel>
|
||||
<FormLabel>Include Unmonitored</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="unmonitored"
|
||||
value={unmonitored}
|
||||
helpText={translate('UnmonitoredHelpText')}
|
||||
helpText="Include unmonitored movies in the iCal feed"
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('ShowAsAllDayEvents')}</FormLabel>
|
||||
<FormLabel>Show as All-Day Events</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="asAllDay"
|
||||
value={asAllDay}
|
||||
helpText={translate('AsAllDayHelpText')}
|
||||
helpText="Events will appear as all-day events in your calendar"
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Tags')}</FormLabel>
|
||||
<FormLabel>Tags</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TAG}
|
||||
name="tags"
|
||||
value={tags}
|
||||
helpText={translate('TagsHelpText')}
|
||||
helpText="Feed will only contain movies with at least one matching tag"
|
||||
onChange={this.onInputChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -153,14 +152,14 @@ class CalendarLinkModalContent extends Component {
|
||||
<FormGroup
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
<FormLabel>{translate('ICalFeed')}</FormLabel>
|
||||
<FormLabel>iCal Feed</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.TEXT}
|
||||
name="iCalHttpUrl"
|
||||
value={iCalHttpUrl}
|
||||
readOnly={true}
|
||||
helpText={translate('ICalHttpUrlHelpText')}
|
||||
helpText="Copy this URL to your client(s) or click to subscribe if your browser supports webcal"
|
||||
buttons={[
|
||||
<ClipboardButton
|
||||
key="copy"
|
||||
@@ -187,7 +186,7 @@ class CalendarLinkModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -16,4 +16,3 @@ export const RENAME_MOVIE = 'RenameMovie';
|
||||
export const RESET_API_KEY = 'ResetApiKey';
|
||||
export const RSS_SYNC = 'RssSync';
|
||||
export const MOVIE_SEARCH = 'MoviesSearch';
|
||||
export const IMPORT_LIST_SYNC = 'ImportListSync';
|
||||
|
||||
@@ -14,19 +14,18 @@ import Scroller from 'Components/Scroller/Scroller';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { kinds, scrollDirections } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import FileBrowserRow from './FileBrowserRow';
|
||||
import styles from './FileBrowserModalContent.css';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'type',
|
||||
label: translate('Type'),
|
||||
label: 'Type',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: translate('Name'),
|
||||
label: 'Name',
|
||||
isVisible: true
|
||||
}
|
||||
];
|
||||
@@ -135,7 +134,7 @@ class FileBrowserModalContent extends Component {
|
||||
|
||||
<PathInput
|
||||
className={styles.pathInput}
|
||||
placeholder={translate('StartTypingOrSelectAPathBelow')}
|
||||
placeholder="Start typing or select a path below"
|
||||
hasFileBrowser={false}
|
||||
{...otherProps}
|
||||
value={this.state.currentPath}
|
||||
@@ -149,9 +148,7 @@ class FileBrowserModalContent extends Component {
|
||||
>
|
||||
{
|
||||
!!error &&
|
||||
<div>
|
||||
{translate('ErrorLoadingContents')}
|
||||
</div>
|
||||
<div>Error loading contents</div>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -226,13 +223,13 @@ class FileBrowserModalContent extends Component {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Cancel')}
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onPress={this.onOkPress}
|
||||
>
|
||||
{translate('Ok')}
|
||||
Ok
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||
import NumberInput from 'Components/Form/NumberInput';
|
||||
import SelectInput from 'Components/Form/SelectInput';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import { IN_LAST, IN_NEXT, NOT_IN_LAST, NOT_IN_NEXT } from 'Helpers/Props/filterTypes';
|
||||
import { IN_LAST, IN_NEXT } from 'Helpers/Props/filterTypes';
|
||||
import isString from 'Utilities/String/isString';
|
||||
import { NAME } from './FilterBuilderRowValue';
|
||||
import styles from './DateFilterBuilderRowValue.css';
|
||||
@@ -18,12 +18,7 @@ const timeOptions = [
|
||||
];
|
||||
|
||||
function isInFilter(filterType) {
|
||||
return (
|
||||
filterType === IN_LAST ||
|
||||
filterType === NOT_IN_LAST ||
|
||||
filterType === IN_NEXT ||
|
||||
filterType === NOT_IN_NEXT
|
||||
);
|
||||
return filterType === IN_LAST || filterType === IN_NEXT;
|
||||
}
|
||||
|
||||
class DateFilterBuilderRowValue extends Component {
|
||||
|
||||
@@ -8,7 +8,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import FilterBuilderRow from './FilterBuilderRow';
|
||||
import styles from './FilterBuilderModalContent.css';
|
||||
|
||||
@@ -193,7 +192,7 @@ class FilterBuilderModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onCancelPress}>
|
||||
{translate('Cancel')}
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<SpinnerErrorButton
|
||||
@@ -201,7 +200,7 @@ class FilterBuilderModalContent extends Component {
|
||||
error={saveError}
|
||||
onPress={this.onSaveFilterPress}
|
||||
>
|
||||
{translate('Save')}
|
||||
Save
|
||||
</SpinnerErrorButton>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Prop
|
||||
import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
|
||||
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
|
||||
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
|
||||
import ImportListFilterBuilderRowValueConnector from './ImportListFilterBuilderRowValueConnector';
|
||||
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
|
||||
import MovieStatusFilterBuilderRowValue from './MovieStatusFilterBuilderRowValue';
|
||||
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
|
||||
@@ -75,9 +74,6 @@ function getRowValueConnector(selectedFilterBuilderProp) {
|
||||
case filterBuilderValueTypes.TAG:
|
||||
return TagFilterBuilderRowValueConnector;
|
||||
|
||||
case filterBuilderValueTypes.IMPORTLIST:
|
||||
return ImportListFilterBuilderRowValueConnector;
|
||||
|
||||
default:
|
||||
return FilterBuilderRowValueConnector;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createImportListSelector from 'Store/Selectors/createImportListSelector';
|
||||
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportListSelector(),
|
||||
(importLists) => {
|
||||
return {
|
||||
tagList: importLists.map((importList) => {
|
||||
const {
|
||||
id,
|
||||
name
|
||||
} = importList;
|
||||
|
||||
return {
|
||||
id,
|
||||
name
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(FilterBuilderRowValue);
|
||||
@@ -3,7 +3,6 @@ import React, { Component } from 'react';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './CustomFilter.css';
|
||||
|
||||
class CustomFilter extends Component {
|
||||
@@ -90,7 +89,7 @@ class CustomFilter extends Component {
|
||||
/>
|
||||
|
||||
<SpinnerIconButton
|
||||
title={translate('RemoveFilter')}
|
||||
title="Remove filter"
|
||||
name={icons.REMOVE}
|
||||
isSpinning={this.state.isDeleting}
|
||||
onPress={this.onRemovePress}
|
||||
|
||||
@@ -59,7 +59,7 @@ function CustomFiltersModalContent(props) {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -8,28 +8,16 @@ import DeviceInput from './DeviceInput';
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { value }) => value,
|
||||
(state, { name }) => name,
|
||||
(state) => state.providerOptions,
|
||||
(value, name, devices) => {
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
items
|
||||
} = devices;
|
||||
(value, devices) => {
|
||||
|
||||
return {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
items: items[name] || [],
|
||||
...devices,
|
||||
selectedDevices: value.map((valueDevice) => {
|
||||
const sectionItems = items[name] || [];
|
||||
|
||||
// Disable equality ESLint rule so we don't need to worry about
|
||||
// a type mismatch between the value items and the device ID.
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const device = sectionItems.find((d) => d.id == valueDevice);
|
||||
const device = devices.items.find((d) => d.id == valueDevice);
|
||||
|
||||
if (device) {
|
||||
return {
|
||||
@@ -73,14 +61,11 @@ class DeviceInputConnector extends Component {
|
||||
const {
|
||||
provider,
|
||||
providerData,
|
||||
dispatchFetchOptions,
|
||||
requestAction,
|
||||
name
|
||||
dispatchFetchOptions
|
||||
} = this.props;
|
||||
|
||||
dispatchFetchOptions({
|
||||
action: requestAction,
|
||||
itemSection: name,
|
||||
action: 'getDevices',
|
||||
provider,
|
||||
providerData
|
||||
});
|
||||
@@ -109,7 +94,6 @@ class DeviceInputConnector extends Component {
|
||||
DeviceInputConnector.propTypes = {
|
||||
provider: PropTypes.string.isRequired,
|
||||
providerData: PropTypes.object.isRequired,
|
||||
requestAction: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
dispatchFetchOptions: PropTypes.func.isRequired,
|
||||
|
||||
@@ -20,7 +20,6 @@ import QualityProfileSelectInputConnector from './QualityProfileSelectInputConne
|
||||
import RootFolderSelectInputConnector from './RootFolderSelectInputConnector';
|
||||
import TagInputConnector from './TagInputConnector';
|
||||
import TagSelectInputConnector from './TagSelectInputConnector';
|
||||
import TextArea from './TextArea';
|
||||
import TextInput from './TextInput';
|
||||
import TextTagInputConnector from './TextTagInputConnector';
|
||||
import styles from './FormInputGroup.css';
|
||||
@@ -72,9 +71,6 @@ function getComponent(type) {
|
||||
case inputTypes.TAG:
|
||||
return TagInputConnector;
|
||||
|
||||
case inputTypes.TEXT_AREA:
|
||||
return TextArea;
|
||||
|
||||
case inputTypes.TEXT_TAG:
|
||||
return TextTagInputConnector;
|
||||
|
||||
@@ -157,7 +153,7 @@ function FormInputGroup(props) {
|
||||
<Icon
|
||||
name={icons.UNSAVED_SETTING}
|
||||
className={styles.pendingChangesIcon}
|
||||
title={translate('ChangeHasNotBeenSavedYet')}
|
||||
title="Change has not been saved yet"
|
||||
/>
|
||||
}
|
||||
</div> */}
|
||||
@@ -211,7 +207,7 @@ function FormInputGroup(props) {
|
||||
key={index}
|
||||
text={error.message}
|
||||
link={error.link}
|
||||
tooltip={error.detailedMessage}
|
||||
linkTooltip={error.detailedMessage}
|
||||
isError={true}
|
||||
isCheckInput={checkInput}
|
||||
/>
|
||||
@@ -226,7 +222,7 @@ function FormInputGroup(props) {
|
||||
key={index}
|
||||
text={warning.message}
|
||||
link={warning.link}
|
||||
tooltip={warning.detailedMessage}
|
||||
linkTooltip={warning.detailedMessage}
|
||||
isWarning={true}
|
||||
isCheckInput={checkInput}
|
||||
/>
|
||||
|
||||
@@ -37,7 +37,3 @@
|
||||
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.details {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function FormInputHelpText(props) {
|
||||
className,
|
||||
text,
|
||||
link,
|
||||
tooltip,
|
||||
linkTooltip,
|
||||
isError,
|
||||
isWarning,
|
||||
isCheckInput
|
||||
@@ -28,27 +28,16 @@ function FormInputHelpText(props) {
|
||||
{text}
|
||||
|
||||
{
|
||||
link ?
|
||||
!!link &&
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={link}
|
||||
title={tooltip}
|
||||
title={linkTooltip}
|
||||
>
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
/>
|
||||
</Link> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!link && tooltip ?
|
||||
<Icon
|
||||
containerClassName={styles.details}
|
||||
name={icons.INFO}
|
||||
title={tooltip}
|
||||
/> :
|
||||
null
|
||||
</Link>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
@@ -58,7 +47,7 @@ FormInputHelpText.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
link: PropTypes.string,
|
||||
tooltip: PropTypes.string,
|
||||
linkTooltip: PropTypes.string,
|
||||
isError: PropTypes.bool,
|
||||
isWarning: PropTypes.bool,
|
||||
isCheckInput: PropTypes.bool
|
||||
|
||||
@@ -62,7 +62,6 @@ function ProviderFieldFormGroup(props) {
|
||||
value,
|
||||
type,
|
||||
advanced,
|
||||
requestAction,
|
||||
hidden,
|
||||
pending,
|
||||
errors,
|
||||
@@ -99,7 +98,6 @@ function ProviderFieldFormGroup(props) {
|
||||
pending={pending}
|
||||
includeFiles={type === 'filePath' ? true : undefined}
|
||||
onChange={onChange}
|
||||
requestAction={requestAction}
|
||||
{...otherProps}
|
||||
/>
|
||||
</FormGroup>
|
||||
@@ -120,7 +118,6 @@ ProviderFieldFormGroup.propTypes = {
|
||||
value: PropTypes.any,
|
||||
type: PropTypes.string.isRequired,
|
||||
advanced: PropTypes.bool.isRequired,
|
||||
requestAction: PropTypes.string,
|
||||
hidden: PropTypes.string,
|
||||
pending: PropTypes.bool.isRequired,
|
||||
errors: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
.input {
|
||||
composes: input from '~Components/Form/Input.css';
|
||||
|
||||
flex-grow: 1;
|
||||
min-height: 200px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.readOnly {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.hasError {
|
||||
composes: hasError from '~Components/Form/Input.css';
|
||||
}
|
||||
|
||||
.hasWarning {
|
||||
composes: hasWarning from '~Components/Form/Input.css';
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import styles from './TextArea.css';
|
||||
|
||||
class TextArea extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this._input = null;
|
||||
this._selectionStart = null;
|
||||
this._selectionEnd = null;
|
||||
this._selectionTimeout = null;
|
||||
this._isMouseTarget = false;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('mouseup', this.onDocumentMouseUp);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('mouseup', this.onDocumentMouseUp);
|
||||
|
||||
if (this._selectionTimeout) {
|
||||
this._selectionTimeout = clearTimeout(this._selectionTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Control
|
||||
|
||||
setInputRef = (ref) => {
|
||||
this._input = ref;
|
||||
}
|
||||
|
||||
selectionChange() {
|
||||
if (this._selectionTimeout) {
|
||||
this._selectionTimeout = clearTimeout(this._selectionTimeout);
|
||||
}
|
||||
|
||||
this._selectionTimeout = setTimeout(() => {
|
||||
const selectionStart = this._input.selectionStart;
|
||||
const selectionEnd = this._input.selectionEnd;
|
||||
|
||||
const selectionChanged = (
|
||||
this._selectionStart !== selectionStart ||
|
||||
this._selectionEnd !== selectionEnd
|
||||
);
|
||||
|
||||
this._selectionStart = selectionStart;
|
||||
this._selectionEnd = selectionEnd;
|
||||
|
||||
if (this.props.onSelectionChange && selectionChanged) {
|
||||
this.props.onSelectionChange(selectionStart, selectionEnd);
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onChange = (event) => {
|
||||
const {
|
||||
name,
|
||||
onChange
|
||||
} = this.props;
|
||||
|
||||
const payload = {
|
||||
name,
|
||||
value: event.target.value
|
||||
};
|
||||
|
||||
onChange(payload);
|
||||
}
|
||||
|
||||
onFocus = (event) => {
|
||||
if (this.props.onFocus) {
|
||||
this.props.onFocus(event);
|
||||
}
|
||||
|
||||
this.selectionChange();
|
||||
}
|
||||
|
||||
onKeyUp = () => {
|
||||
this.selectionChange();
|
||||
}
|
||||
|
||||
onMouseDown = () => {
|
||||
this._isMouseTarget = true;
|
||||
}
|
||||
|
||||
onMouseUp = () => {
|
||||
this.selectionChange();
|
||||
}
|
||||
|
||||
onDocumentMouseUp = () => {
|
||||
if (this._isMouseTarget) {
|
||||
this.selectionChange();
|
||||
}
|
||||
|
||||
this._isMouseTarget = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
readOnly,
|
||||
autoFocus,
|
||||
placeholder,
|
||||
name,
|
||||
value,
|
||||
hasError,
|
||||
hasWarning,
|
||||
onBlur
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<textarea
|
||||
ref={this.setInputRef}
|
||||
readOnly={readOnly}
|
||||
autoFocus={autoFocus}
|
||||
placeholder={placeholder}
|
||||
className={classNames(
|
||||
className,
|
||||
readOnly && styles.readOnly,
|
||||
hasError && styles.hasError,
|
||||
hasWarning && styles.hasWarning
|
||||
)}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={onBlur}
|
||||
onKeyUp={this.onKeyUp}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onMouseUp={this.onMouseUp}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TextArea.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
readOnly: PropTypes.bool,
|
||||
autoFocus: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array]).isRequired,
|
||||
hasError: PropTypes.bool,
|
||||
hasWarning: PropTypes.bool,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
onSelectionChange: PropTypes.func
|
||||
};
|
||||
|
||||
TextArea.defaultProps = {
|
||||
className: styles.input,
|
||||
type: 'text',
|
||||
readOnly: false,
|
||||
autoFocus: false,
|
||||
value: ''
|
||||
};
|
||||
|
||||
export default TextArea;
|
||||
@@ -4,17 +4,14 @@ import Icon from 'Components/Icon';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import styles from './HeartRating.css';
|
||||
|
||||
function HeartRating({ rating, iconSize, hideHeart }) {
|
||||
function HeartRating({ rating, iconSize }) {
|
||||
return (
|
||||
<span>
|
||||
{
|
||||
!hideHeart &&
|
||||
<Icon
|
||||
className={styles.heart}
|
||||
name={icons.HEART}
|
||||
size={iconSize}
|
||||
/>
|
||||
}
|
||||
<Icon
|
||||
className={styles.heart}
|
||||
name={icons.HEART}
|
||||
size={iconSize}
|
||||
/>
|
||||
|
||||
{rating * 10}%
|
||||
</span>
|
||||
@@ -23,8 +20,7 @@ function HeartRating({ rating, iconSize, hideHeart }) {
|
||||
|
||||
HeartRating.propTypes = {
|
||||
rating: PropTypes.number.isRequired,
|
||||
iconSize: PropTypes.number.isRequired,
|
||||
hideHeart: PropTypes.bool
|
||||
iconSize: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
HeartRating.defaultProps = {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.lists {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds, sizes } from 'Helpers/Props';
|
||||
import Label from './Label';
|
||||
import styles from './ImportListList.css';
|
||||
|
||||
function ImportListList({ lists, importListList }) {
|
||||
return (
|
||||
<div className={styles.lists}>
|
||||
{
|
||||
lists.map((t) => {
|
||||
const list = _.find(importListList, { id: t });
|
||||
|
||||
if (!list) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Label
|
||||
key={list.id}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.MEDIUM}
|
||||
>
|
||||
{list.name}
|
||||
</Label>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ImportListList.propTypes = {
|
||||
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
importListList: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
ImportListList.defaultProps = {
|
||||
lists: []
|
||||
};
|
||||
|
||||
export default ImportListList;
|
||||
@@ -1,17 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createImportListSelector from 'Store/Selectors/createImportListSelector';
|
||||
import ImportListList from './ImportListList';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createImportListSelector(),
|
||||
(importListList) => {
|
||||
return {
|
||||
importListList
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(ImportListList);
|
||||
@@ -87,15 +87,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.queue {
|
||||
border-color: $queueColor;
|
||||
background-color: $queueColor;
|
||||
|
||||
&.outline {
|
||||
color: $queueColor;
|
||||
}
|
||||
}
|
||||
|
||||
/** Sizes **/
|
||||
|
||||
.small {
|
||||
|
||||
@@ -17,7 +17,6 @@ class ClipboardButton extends Component {
|
||||
|
||||
this._id = getUniqueElememtId();
|
||||
this._successTimeout = null;
|
||||
this._testResultTimeout = null;
|
||||
|
||||
this.state = {
|
||||
showSuccess: false,
|
||||
@@ -27,8 +26,7 @@ class ClipboardButton extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this._clipboard = new Clipboard(`#${this._id}`, {
|
||||
text: () => this.props.value,
|
||||
container: document.getElementById(this._id)
|
||||
text: () => this.props.value
|
||||
});
|
||||
|
||||
this._clipboard.on('success', this.onSuccess);
|
||||
@@ -49,10 +47,6 @@ class ClipboardButton extends Component {
|
||||
if (this._clipboard) {
|
||||
this._clipboard.destroy();
|
||||
}
|
||||
|
||||
if (this._testResultTimeout) {
|
||||
clearTimeout(this._testResultTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -86,7 +80,6 @@ class ClipboardButton extends Component {
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
className,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
@@ -102,7 +95,7 @@ class ClipboardButton extends Component {
|
||||
return (
|
||||
<FormInputButton
|
||||
id={this._id}
|
||||
className={className}
|
||||
className={styles.button}
|
||||
{...otherProps}
|
||||
>
|
||||
<span className={showStateIcon ? styles.showStateIcon : undefined}>
|
||||
@@ -128,12 +121,7 @@ class ClipboardButton extends Component {
|
||||
}
|
||||
|
||||
ClipboardButton.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
value: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
ClipboardButton.defaultProps = {
|
||||
className: styles.button
|
||||
};
|
||||
|
||||
export default ClipboardButton;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import styles from './LoadingIndicator.css';
|
||||
@@ -14,7 +13,7 @@ function LoadingIndicator({ className, rippleClassName, size }) {
|
||||
style={{ height }}
|
||||
>
|
||||
<div
|
||||
className={classNames(styles.rippleContainer, 'followingBalls')}
|
||||
className={styles.rippleContainer}
|
||||
style={{ width, height }}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -9,7 +9,6 @@ class Marquee extends Component {
|
||||
|
||||
static propTypes = {
|
||||
text: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
hoverToStop: PropTypes.bool,
|
||||
loop: PropTypes.bool,
|
||||
className: PropTypes.string
|
||||
@@ -17,7 +16,6 @@ class Marquee extends Component {
|
||||
|
||||
static defaultProps = {
|
||||
text: '',
|
||||
title: '',
|
||||
hoverToStop: true,
|
||||
loop: false
|
||||
};
|
||||
@@ -146,7 +144,7 @@ class Marquee extends Component {
|
||||
this.text = el;
|
||||
}}
|
||||
style={style}
|
||||
title={(this.props.title && (this.props.text !== this.props.title)) ? `Original Title: ${this.props.title}` : this.props.text}
|
||||
title={this.props.text}
|
||||
>
|
||||
{this.props.text}
|
||||
</span>
|
||||
@@ -169,7 +167,7 @@ class Marquee extends Component {
|
||||
this.text = el;
|
||||
}}
|
||||
style={style}
|
||||
title={(this.props.title && (this.props.text !== this.props.title)) ? `Original Title: ${this.props.title}` : this.props.text}
|
||||
title={this.props.text}
|
||||
>
|
||||
{this.props.text}
|
||||
</span>
|
||||
|
||||
@@ -6,7 +6,6 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './ModalError.css';
|
||||
|
||||
function ModalError(props) {
|
||||
@@ -34,7 +33,7 @@ function ModalError(props) {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>);
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './NotFound.css';
|
||||
|
||||
function NotFound({ message }) {
|
||||
return (
|
||||
<PageContent title={translate('MIA')}>
|
||||
<PageContent title="MIA">
|
||||
<div className={styles.container}>
|
||||
<div className={styles.message}>
|
||||
{message}
|
||||
|
||||
@@ -6,7 +6,6 @@ import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './KeyboardShortcutsModalContent.css';
|
||||
|
||||
function getShortcuts() {
|
||||
@@ -20,26 +19,18 @@ function getShortcuts() {
|
||||
}
|
||||
|
||||
function getShortcutKey(combo, isOsx) {
|
||||
const comboMatch = combo.match(/(.+?)\+(.*)/);
|
||||
const comboMatch = combo.match(/(.+?)\+(.)/);
|
||||
|
||||
if (!comboMatch) {
|
||||
return combo;
|
||||
}
|
||||
|
||||
const modifier = comboMatch[1];
|
||||
let key = comboMatch[2];
|
||||
const key = comboMatch[2];
|
||||
let osModifier = modifier;
|
||||
|
||||
if (modifier === 'mod') {
|
||||
osModifier = isOsx ? 'cmd' : 'Ctrl';
|
||||
}
|
||||
|
||||
if (key === 'home') {
|
||||
key = isOsx ? '↑' : 'Home';
|
||||
}
|
||||
|
||||
if (key === 'end') {
|
||||
key = isOsx ? '↓' : 'End';
|
||||
osModifier = isOsx ? 'cmd' : 'ctrl';
|
||||
}
|
||||
|
||||
return `${osModifier} + ${key}`;
|
||||
@@ -84,7 +75,7 @@ function KeyboardShortcutsModalContent(props) {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
margin-top: 18px;
|
||||
margin-bottom: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
composes: ripple from '~Components/Loading/LoadingIndicator.css';
|
||||
|
||||
border: 1px solid $toolbarColor;
|
||||
border: 2px solid $toolbarColor;
|
||||
}
|
||||
|
||||
.input {
|
||||
|
||||
@@ -11,7 +11,9 @@ import FuseWorker from './fuse.worker';
|
||||
import MovieSearchResult from './MovieSearchResult';
|
||||
import styles from './MovieSearchInput.css';
|
||||
|
||||
const LOADING_TYPE = 'suggestionsLoading';
|
||||
const ADD_NEW_TYPE = 'addNew';
|
||||
const workerInstance = new FuseWorker();
|
||||
|
||||
class MovieSearchInput extends Component {
|
||||
|
||||
@@ -22,7 +24,6 @@ class MovieSearchInput extends Component {
|
||||
super(props, context);
|
||||
|
||||
this._autosuggest = null;
|
||||
this._worker = null;
|
||||
|
||||
this.state = {
|
||||
value: '',
|
||||
@@ -32,23 +33,7 @@ class MovieSearchInput extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.bindShortcut(shortcuts.MOVIE_SEARCH_INPUT.key, this.focusInput);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._worker) {
|
||||
this._worker.removeEventListener('message', this.onSuggestionsReceived, false);
|
||||
this._worker.terminate();
|
||||
this._worker = null;
|
||||
}
|
||||
}
|
||||
|
||||
getWorker() {
|
||||
if (!this._worker) {
|
||||
this._worker = new FuseWorker();
|
||||
this._worker.addEventListener('message', this.onSuggestionsReceived, false);
|
||||
}
|
||||
|
||||
return this._worker;
|
||||
workerInstance.addEventListener('message', this.onSuggestionsReceived, false);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -71,15 +56,6 @@ class MovieSearchInput extends Component {
|
||||
return (
|
||||
<div className={styles.sectionTitle}>
|
||||
{section.title}
|
||||
|
||||
{
|
||||
section.loading &&
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
rippleClassName={styles.ripple}
|
||||
size={20}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -97,6 +73,16 @@ class MovieSearchInput extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (item.type === LOADING_TYPE) {
|
||||
return (
|
||||
<LoadingIndicator
|
||||
className={styles.loading}
|
||||
rippleClassName={styles.ripple}
|
||||
size={30}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<MovieSearchResult
|
||||
{...item.item}
|
||||
@@ -113,8 +99,7 @@ class MovieSearchInput extends Component {
|
||||
reset() {
|
||||
this.setState({
|
||||
value: '',
|
||||
suggestions: [],
|
||||
loading: false
|
||||
suggestions: []
|
||||
});
|
||||
}
|
||||
|
||||
@@ -130,15 +115,6 @@ class MovieSearchInput extends Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event) => {
|
||||
if (event.shiftKey || event.altKey || event.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key !== 'Tab' && event.key !== 'Enter') {
|
||||
return;
|
||||
}
|
||||
@@ -179,74 +155,35 @@ class MovieSearchInput extends Component {
|
||||
}
|
||||
|
||||
onSuggestionsFetchRequested = ({ value }) => {
|
||||
if (!this.state.loading) {
|
||||
this.setState({
|
||||
loading: true
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
suggestions: [
|
||||
{
|
||||
type: LOADING_TYPE,
|
||||
title: value
|
||||
}
|
||||
]
|
||||
});
|
||||
this.requestSuggestions(value);
|
||||
};
|
||||
|
||||
requestSuggestions = _.debounce((value) => {
|
||||
if (!this.state.loading) {
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
value,
|
||||
movies: this.props.movies
|
||||
};
|
||||
|
||||
const requestLoading = this.state.requestLoading;
|
||||
|
||||
this.setState({
|
||||
requestValue: value,
|
||||
requestLoading: true
|
||||
});
|
||||
|
||||
if (!requestLoading) {
|
||||
const payload = {
|
||||
value,
|
||||
movies: this.props.movies
|
||||
};
|
||||
|
||||
this.getWorker().postMessage(payload);
|
||||
}
|
||||
workerInstance.postMessage(payload);
|
||||
}, 250);
|
||||
|
||||
onSuggestionsReceived = (message) => {
|
||||
const {
|
||||
value,
|
||||
suggestions
|
||||
} = message.data;
|
||||
|
||||
if (!this.state.loading) {
|
||||
this.setState({
|
||||
requestValue: null,
|
||||
requestLoading: false
|
||||
});
|
||||
} else if (value === this.state.requestValue) {
|
||||
this.setState({
|
||||
suggestions,
|
||||
requestValue: null,
|
||||
requestLoading: false,
|
||||
loading: false
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
suggestions,
|
||||
requestLoading: true
|
||||
});
|
||||
|
||||
const payload = {
|
||||
value: this.state.requestValue,
|
||||
movies: this.props.movies
|
||||
};
|
||||
|
||||
this.getWorker().postMessage(payload);
|
||||
}
|
||||
this.setState({
|
||||
suggestions: message.data
|
||||
});
|
||||
}
|
||||
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.setState({
|
||||
suggestions: [],
|
||||
loading: false
|
||||
suggestions: []
|
||||
});
|
||||
}
|
||||
|
||||
@@ -264,22 +201,20 @@ class MovieSearchInput extends Component {
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
loading,
|
||||
suggestions
|
||||
} = this.state;
|
||||
|
||||
const suggestionGroups = [];
|
||||
|
||||
if (suggestions.length || loading) {
|
||||
if (suggestions.length) {
|
||||
suggestionGroups.push({
|
||||
title: translate('ExistingMovies'),
|
||||
loading,
|
||||
title: 'Existing Movie',
|
||||
suggestions
|
||||
});
|
||||
}
|
||||
|
||||
suggestionGroups.push({
|
||||
title: translate('AddNewMovie'),
|
||||
title: 'Add New Movie',
|
||||
suggestions: [
|
||||
{
|
||||
type: ADD_NEW_TYPE,
|
||||
|
||||
@@ -21,9 +21,8 @@
|
||||
}
|
||||
|
||||
.logoFull {
|
||||
margin-left: 15px;
|
||||
width: 120px;
|
||||
height: 40px;
|
||||
width: 144px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
|
||||
@@ -4,7 +4,6 @@ import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
||||
import MovieSearchInputConnector from './MovieSearchInputConnector';
|
||||
import PageHeaderActionsMenuConnector from './PageHeaderActionsMenuConnector';
|
||||
@@ -80,7 +79,7 @@ class PageHeader extends Component {
|
||||
/>
|
||||
<IconButton
|
||||
className={styles.translate}
|
||||
title={translate('SuggestTranslationChange')}
|
||||
title="Suggest translation change"
|
||||
name={icons.TRANSLATE}
|
||||
to="https://translate.servarr.com/projects/radarr/radarr/"
|
||||
size={24}
|
||||
|
||||
@@ -7,7 +7,6 @@ import MenuContent from 'Components/Menu/MenuContent';
|
||||
import MenuItem from 'Components/Menu/MenuItem';
|
||||
import MenuItemSeparator from 'Components/Menu/MenuItemSeparator';
|
||||
import { align, icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './PageHeaderActionsMenu.css';
|
||||
|
||||
function PageHeaderActionsMenu(props) {
|
||||
@@ -33,7 +32,7 @@ function PageHeaderActionsMenu(props) {
|
||||
className={styles.itemIcon}
|
||||
name={icons.KEYBOARD}
|
||||
/>
|
||||
{translate('KeyboardShortcuts')}
|
||||
Keyboard Shortcuts
|
||||
</MenuItem>
|
||||
|
||||
<MenuItemSeparator />
|
||||
@@ -43,7 +42,7 @@ function PageHeaderActionsMenu(props) {
|
||||
className={styles.itemIcon}
|
||||
name={icons.RESTART}
|
||||
/>
|
||||
{translate('Restart')}
|
||||
Restart
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem onPress={onShutdownPress}>
|
||||
@@ -52,7 +51,7 @@ function PageHeaderActionsMenu(props) {
|
||||
name={icons.SHUTDOWN}
|
||||
kind={kinds.DANGER}
|
||||
/>
|
||||
{translate('Shutdown')}
|
||||
Shutdown
|
||||
</MenuItem>
|
||||
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ function getSuggestions(movies, value) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
onmessage = function(e) {
|
||||
self.addEventListener('message', (e) => {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
@@ -57,12 +57,5 @@ onmessage = function(e) {
|
||||
value
|
||||
} = e.data;
|
||||
|
||||
const suggestions = getSuggestions(movies, value);
|
||||
|
||||
const results = {
|
||||
value,
|
||||
suggestions
|
||||
};
|
||||
|
||||
self.postMessage(results);
|
||||
};
|
||||
self.postMessage(getSuggestions(movies, value));
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createSelector } from 'reselect';
|
||||
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
||||
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
||||
import { fetchMovies } from 'Store/Actions/movieActions';
|
||||
import { fetchImportLists, fetchLanguages, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
|
||||
import { fetchLanguages, fetchNetImports, fetchQualityProfiles, fetchUISettings } from 'Store/Actions/settingsActions';
|
||||
import { fetchStatus } from 'Store/Actions/systemActions';
|
||||
import { fetchTags } from 'Store/Actions/tagActions';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
@@ -48,7 +48,7 @@ const selectIsPopulated = createSelector(
|
||||
(state) => state.settings.ui.isPopulated,
|
||||
(state) => state.settings.qualityProfiles.isPopulated,
|
||||
(state) => state.settings.languages.isPopulated,
|
||||
(state) => state.settings.importLists.isPopulated,
|
||||
(state) => state.settings.netImports.isPopulated,
|
||||
(state) => state.system.status.isPopulated,
|
||||
(
|
||||
customFiltersIsPopulated,
|
||||
@@ -56,7 +56,7 @@ const selectIsPopulated = createSelector(
|
||||
uiSettingsIsPopulated,
|
||||
qualityProfilesIsPopulated,
|
||||
languagesIsPopulated,
|
||||
importListsIsPopulated,
|
||||
netImportsIsPopulated,
|
||||
systemStatusIsPopulated
|
||||
) => {
|
||||
return (
|
||||
@@ -65,7 +65,7 @@ const selectIsPopulated = createSelector(
|
||||
uiSettingsIsPopulated &&
|
||||
qualityProfilesIsPopulated &&
|
||||
languagesIsPopulated &&
|
||||
importListsIsPopulated &&
|
||||
netImportsIsPopulated &&
|
||||
systemStatusIsPopulated
|
||||
);
|
||||
}
|
||||
@@ -77,7 +77,7 @@ const selectErrors = createSelector(
|
||||
(state) => state.settings.ui.error,
|
||||
(state) => state.settings.qualityProfiles.error,
|
||||
(state) => state.settings.languages.error,
|
||||
(state) => state.settings.importLists.error,
|
||||
(state) => state.settings.netImports.error,
|
||||
(state) => state.system.status.error,
|
||||
(
|
||||
customFiltersError,
|
||||
@@ -85,7 +85,7 @@ const selectErrors = createSelector(
|
||||
uiSettingsError,
|
||||
qualityProfilesError,
|
||||
languagesError,
|
||||
importListsError,
|
||||
netImportsError,
|
||||
systemStatusError
|
||||
) => {
|
||||
const hasError = !!(
|
||||
@@ -94,7 +94,7 @@ const selectErrors = createSelector(
|
||||
uiSettingsError ||
|
||||
qualityProfilesError ||
|
||||
languagesError ||
|
||||
importListsError ||
|
||||
netImportsError ||
|
||||
systemStatusError
|
||||
);
|
||||
|
||||
@@ -105,7 +105,7 @@ const selectErrors = createSelector(
|
||||
uiSettingsError,
|
||||
qualityProfilesError,
|
||||
languagesError,
|
||||
importListsError,
|
||||
netImportsError,
|
||||
systemStatusError
|
||||
};
|
||||
}
|
||||
@@ -153,8 +153,8 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatchFetchLanguages() {
|
||||
dispatch(fetchLanguages());
|
||||
},
|
||||
dispatchFetchImportLists() {
|
||||
dispatch(fetchImportLists());
|
||||
dispatchFetchNetImports() {
|
||||
dispatch(fetchNetImports());
|
||||
},
|
||||
dispatchFetchUISettings() {
|
||||
dispatch(fetchUISettings());
|
||||
@@ -191,7 +191,7 @@ class PageConnector extends Component {
|
||||
this.props.dispatchFetchTags();
|
||||
this.props.dispatchFetchQualityProfiles();
|
||||
this.props.dispatchFetchLanguages();
|
||||
this.props.dispatchFetchImportLists();
|
||||
this.props.dispatchFetchNetImports();
|
||||
this.props.dispatchFetchUISettings();
|
||||
this.props.dispatchFetchStatus();
|
||||
}
|
||||
@@ -215,7 +215,7 @@ class PageConnector extends Component {
|
||||
dispatchFetchTags,
|
||||
dispatchFetchQualityProfiles,
|
||||
dispatchFetchLanguages,
|
||||
dispatchFetchImportLists,
|
||||
dispatchFetchNetImports,
|
||||
dispatchFetchUISettings,
|
||||
dispatchFetchStatus,
|
||||
...otherProps
|
||||
@@ -254,7 +254,7 @@ PageConnector.propTypes = {
|
||||
dispatchFetchTags: PropTypes.func.isRequired,
|
||||
dispatchFetchQualityProfiles: PropTypes.func.isRequired,
|
||||
dispatchFetchLanguages: PropTypes.func.isRequired,
|
||||
dispatchFetchImportLists: PropTypes.func.isRequired,
|
||||
dispatchFetchNetImports: PropTypes.func.isRequired,
|
||||
dispatchFetchUISettings: PropTypes.func.isRequired,
|
||||
dispatchFetchStatus: PropTypes.func.isRequired,
|
||||
onSidebarVisibleChange: PropTypes.func.isRequired
|
||||
|
||||
@@ -98,7 +98,7 @@ const links = [
|
||||
},
|
||||
{
|
||||
title: translate('Lists'),
|
||||
to: '/settings/importlists'
|
||||
to: '/settings/netimports'
|
||||
},
|
||||
{
|
||||
title: translate('Connect'),
|
||||
@@ -117,7 +117,7 @@ const links = [
|
||||
to: '/settings/general'
|
||||
},
|
||||
{
|
||||
title: translate('UI'),
|
||||
title: translate('Ui'),
|
||||
to: '/settings/ui'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -73,10 +73,6 @@
|
||||
background-color: $infoColor;
|
||||
}
|
||||
|
||||
.queue {
|
||||
background-color: $queueColor;
|
||||
}
|
||||
|
||||
.small {
|
||||
height: $progressBarSmallHeight;
|
||||
|
||||
|
||||
@@ -5,14 +5,12 @@ import styles from './VirtualTableRowCell.css';
|
||||
function VirtualTableRowCell(props) {
|
||||
const {
|
||||
className,
|
||||
children,
|
||||
title
|
||||
children
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
title={title}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
@@ -21,13 +19,11 @@ function VirtualTableRowCell(props) {
|
||||
|
||||
VirtualTableRowCell.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
children: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
||||
title: PropTypes.string
|
||||
children: PropTypes.oneOfType([PropTypes.string, PropTypes.node])
|
||||
};
|
||||
|
||||
VirtualTableRowCell.defaultProps = {
|
||||
className: styles.cell,
|
||||
title: ''
|
||||
className: styles.cell
|
||||
};
|
||||
|
||||
export default VirtualTableRowCell;
|
||||
|
||||
@@ -52,7 +52,6 @@ function Table(props) {
|
||||
scrollDirections.HORIZONTAL :
|
||||
scrollDirections.NONE
|
||||
}
|
||||
autoFocus={false}
|
||||
>
|
||||
<table className={className}>
|
||||
<TableHeader>
|
||||
|
||||
@@ -15,7 +15,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import TableOptionsColumn from './TableOptionsColumn';
|
||||
import TableOptionsColumnDragPreview from './TableOptionsColumnDragPreview';
|
||||
import TableOptionsColumnDragSource from './TableOptionsColumnDragSource';
|
||||
@@ -137,7 +136,7 @@ class TableOptionsModal extends Component {
|
||||
isOpen ?
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{translate('TableOptions')}
|
||||
Table Options
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody>
|
||||
@@ -145,13 +144,13 @@ class TableOptionsModal extends Component {
|
||||
{
|
||||
hasPageSize ?
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('PageSize')}</FormLabel>
|
||||
<FormLabel>Page Size</FormLabel>
|
||||
|
||||
<FormInputGroup
|
||||
type={inputTypes.NUMBER}
|
||||
name="pageSize"
|
||||
value={pageSize || 0}
|
||||
helpText={translate('PageSizeHelpText')}
|
||||
helpText="Number of items to show on each page"
|
||||
errors={pageSizeError ? [{ message: pageSizeError }] : undefined}
|
||||
onChange={this.onPageSizeChange}
|
||||
/>
|
||||
@@ -169,11 +168,11 @@ class TableOptionsModal extends Component {
|
||||
{
|
||||
canModifyColumns ?
|
||||
<FormGroup>
|
||||
<FormLabel>{translate('Columns')}</FormLabel>
|
||||
<FormLabel>Columns</FormLabel>
|
||||
|
||||
<div>
|
||||
<FormInputHelpText
|
||||
text={translate('TableOptionsColumnsMessage')}
|
||||
text="Choose which columns are visible and which order they appear in"
|
||||
/>
|
||||
|
||||
<div className={styles.columns}>
|
||||
@@ -232,7 +231,7 @@ class TableOptionsModal extends Component {
|
||||
<Button
|
||||
onPress={onModalClose}
|
||||
>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent> :
|
||||
|
||||
@@ -56,7 +56,7 @@ class Tooltip extends Component {
|
||||
} else if ((/^right/).test(data.placement)) {
|
||||
data.styles.maxWidth = windowWidth - right - 50;
|
||||
} else {
|
||||
data.styles.maxWidth = left - 35;
|
||||
data.styles.maxWidth = left - 30;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
@@ -1,52 +1,31 @@
|
||||
import Mousetrap from 'mousetrap';
|
||||
import React, { Component } from 'react';
|
||||
import getDisplayName from 'Helpers/getDisplayName';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
export const shortcuts = {
|
||||
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
|
||||
key: '?',
|
||||
name: translate('OpenThisModal')
|
||||
name: 'Open This Modal'
|
||||
},
|
||||
|
||||
CLOSE_MODAL: {
|
||||
key: 'Esc',
|
||||
name: translate('CloseCurrentModal')
|
||||
name: 'Close Current Modal'
|
||||
},
|
||||
|
||||
ACCEPT_CONFIRM_MODAL: {
|
||||
key: 'Enter',
|
||||
name: translate('AcceptConfirmationModal')
|
||||
name: 'Accept Confirmation Modal'
|
||||
},
|
||||
|
||||
MOVIE_SEARCH_INPUT: {
|
||||
key: 's',
|
||||
name: translate('FocusSearchBox')
|
||||
name: 'Focus Search Box'
|
||||
},
|
||||
|
||||
SAVE_SETTINGS: {
|
||||
key: 'mod+s',
|
||||
name: translate('SaveSettings')
|
||||
},
|
||||
|
||||
SCROLL_TOP: {
|
||||
key: 'mod+home',
|
||||
name: translate('MovieIndexScrollTop')
|
||||
},
|
||||
|
||||
SCROLL_BOTTOM: {
|
||||
key: 'mod+end',
|
||||
name: translate('MovieIndexScrollBottom')
|
||||
},
|
||||
|
||||
DETAILS_NEXT: {
|
||||
key: '→',
|
||||
name: translate('MovieDetailsNextMovie')
|
||||
},
|
||||
|
||||
DETAILS_PREVIOUS: {
|
||||
key: '←',
|
||||
name: translate('MovieDetailsPreviousMovie')
|
||||
name: 'Save Settings'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ function createMapStateToProps() {
|
||||
);
|
||||
}
|
||||
|
||||
class DiscoverMovieItemConnector extends Component {
|
||||
class AddListMovieItemConnector extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
@@ -52,9 +52,9 @@ class DiscoverMovieItemConnector extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
DiscoverMovieItemConnector.propTypes = {
|
||||
AddListMovieItemConnector.propTypes = {
|
||||
tmdbId: PropTypes.number,
|
||||
component: PropTypes.elementType.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(DiscoverMovieItemConnector);
|
||||
export default connect(createMapStateToProps)(AddListMovieItemConnector);
|
||||
@@ -18,27 +18,26 @@ import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import DiscoverMovieFooterConnector from './DiscoverMovieFooterConnector';
|
||||
import DiscoverMovieFilterMenu from './Menus/DiscoverMovieFilterMenu';
|
||||
import DiscoverMovieSortMenu from './Menus/DiscoverMovieSortMenu';
|
||||
import DiscoverMovieViewMenu from './Menus/DiscoverMovieViewMenu';
|
||||
import AddListMovieFilterMenu from './Menus/AddListMovieFilterMenu';
|
||||
import AddListMovieSortMenu from './Menus/AddListMovieSortMenu';
|
||||
import AddListMovieViewMenu from './Menus/AddListMovieViewMenu';
|
||||
import NoDiscoverMovie from './NoDiscoverMovie';
|
||||
import DiscoverMovieOverviewsConnector from './Overview/DiscoverMovieOverviewsConnector';
|
||||
import DiscoverMovieOverviewOptionsModal from './Overview/Options/DiscoverMovieOverviewOptionsModal';
|
||||
import DiscoverMoviePostersConnector from './Posters/DiscoverMoviePostersConnector';
|
||||
import DiscoverMoviePosterOptionsModal from './Posters/Options/DiscoverMoviePosterOptionsModal';
|
||||
import DiscoverMovieTableConnector from './Table/DiscoverMovieTableConnector';
|
||||
import DiscoverMovieTableOptionsConnector from './Table/DiscoverMovieTableOptionsConnector';
|
||||
import AddListMovieOverviewsConnector from './Overview/AddListMovieOverviewsConnector';
|
||||
import AddListMovieOverviewOptionsModal from './Overview/Options/AddListMovieOverviewOptionsModal';
|
||||
import AddListMoviePostersConnector from './Posters/AddListMoviePostersConnector';
|
||||
import AddListMoviePosterOptionsModal from './Posters/Options/AddListMoviePosterOptionsModal';
|
||||
import AddListMovieTableConnector from './Table/AddListMovieTableConnector';
|
||||
|
||||
function getViewComponent(view) {
|
||||
if (view === 'posters') {
|
||||
return DiscoverMoviePostersConnector;
|
||||
return AddListMoviePostersConnector;
|
||||
}
|
||||
|
||||
if (view === 'overview') {
|
||||
return DiscoverMovieOverviewsConnector;
|
||||
return AddListMovieOverviewsConnector;
|
||||
}
|
||||
|
||||
return DiscoverMovieTableConnector;
|
||||
return AddListMovieTableConnector;
|
||||
}
|
||||
|
||||
class DiscoverMovie extends Component {
|
||||
@@ -213,10 +212,6 @@ class DiscoverMovie extends Component {
|
||||
this.onSelectAllChange({ value: !this.state.allSelected });
|
||||
}
|
||||
|
||||
onImportListSyncPress = () => {
|
||||
this.props.onImportListSyncPress();
|
||||
}
|
||||
|
||||
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
||||
this.setState((state) => {
|
||||
return toggleSelected(state, this.props.items, id, value, shiftKey, 'tmdbId');
|
||||
@@ -253,7 +248,6 @@ class DiscoverMovie extends Component {
|
||||
onViewSelect,
|
||||
onScroll,
|
||||
onAddMoviesPress,
|
||||
isSyncingLists,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
@@ -279,14 +273,7 @@ class DiscoverMovie extends Component {
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label='Refresh Lists'
|
||||
iconName={icons.REFRESH}
|
||||
isSpinning={isSyncingLists}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onImportListSyncPress}
|
||||
/>
|
||||
<PageToolbarButton
|
||||
label={allSelected ? translate('UnselectAll') : translate('SelectAll')}
|
||||
label={allSelected ? 'Unselect All' : 'Select All'}
|
||||
iconName={icons.CHECK_SQUARE}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onSelectAllPress}
|
||||
@@ -302,7 +289,6 @@ class DiscoverMovie extends Component {
|
||||
<TableOptionsModalWrapper
|
||||
{...otherProps}
|
||||
columns={columns}
|
||||
optionsComponent={DiscoverMovieTableOptionsConnector}
|
||||
>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
@@ -317,6 +303,7 @@ class DiscoverMovie extends Component {
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
iconName={icons.POSTER}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onPosterOptionsPress}
|
||||
/> :
|
||||
null
|
||||
@@ -327,6 +314,7 @@ class DiscoverMovie extends Component {
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
iconName={icons.OVERVIEW}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onOverviewOptionsPress}
|
||||
/> :
|
||||
null
|
||||
@@ -337,20 +325,20 @@ class DiscoverMovie extends Component {
|
||||
<PageToolbarSeparator />
|
||||
}
|
||||
|
||||
<DiscoverMovieViewMenu
|
||||
<AddListMovieViewMenu
|
||||
view={view}
|
||||
isDisabled={hasNoMovie}
|
||||
onViewSelect={onViewSelect}
|
||||
/>
|
||||
|
||||
<DiscoverMovieSortMenu
|
||||
<AddListMovieSortMenu
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
isDisabled={hasNoMovie}
|
||||
onSortSelect={onSortSelect}
|
||||
/>
|
||||
|
||||
<DiscoverMovieFilterMenu
|
||||
<AddListMovieFilterMenu
|
||||
selectedFilterKey={selectedFilterKey}
|
||||
filters={filters}
|
||||
customFilters={customFilters}
|
||||
@@ -374,9 +362,7 @@ class DiscoverMovie extends Component {
|
||||
|
||||
{
|
||||
!isFetching && !!error &&
|
||||
<div>
|
||||
{translate('UnableToLoadMovies')}
|
||||
</div>
|
||||
<div>Unable to load movies</div>
|
||||
}
|
||||
|
||||
{
|
||||
@@ -423,12 +409,12 @@ class DiscoverMovie extends Component {
|
||||
/>
|
||||
}
|
||||
|
||||
<DiscoverMoviePosterOptionsModal
|
||||
<AddListMoviePosterOptionsModal
|
||||
isOpen={isPosterOptionsModalOpen}
|
||||
onModalClose={this.onPosterOptionsModalClose}
|
||||
/>
|
||||
|
||||
<DiscoverMovieOverviewOptionsModal
|
||||
<AddListMovieOverviewOptionsModal
|
||||
isOpen={isOverviewOptionsModalOpen}
|
||||
onModalClose={this.onOverviewOptionsModalClose}
|
||||
/>
|
||||
@@ -450,15 +436,13 @@ DiscoverMovie.propTypes = {
|
||||
sortKey: PropTypes.string,
|
||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
||||
view: PropTypes.string.isRequired,
|
||||
isSyncingLists: PropTypes.bool.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
onSortSelect: PropTypes.func.isRequired,
|
||||
onFilterSelect: PropTypes.func.isRequired,
|
||||
onViewSelect: PropTypes.func.isRequired,
|
||||
onScroll: PropTypes.func.isRequired,
|
||||
onAddMoviesPress: PropTypes.func.isRequired,
|
||||
onExcludeMoviesPress: PropTypes.func.isRequired,
|
||||
onImportListSyncPress: PropTypes.func.isRequired
|
||||
onExcludeMoviesPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DiscoverMovie;
|
||||
|
||||
@@ -2,14 +2,11 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import withScrollPosition from 'Components/withScrollPosition';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import { addImportExclusions, addMovies, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions';
|
||||
import { addMovies, addNetImportExclusions, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
|
||||
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
|
||||
import scrollPositions from 'Store/scrollPositions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createDiscoverMovieClientSideCollectionItemsSelector from 'Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
@@ -18,16 +15,13 @@ import DiscoverMovie from './DiscoverMovie';
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createDiscoverMovieClientSideCollectionItemsSelector('discoverMovie'),
|
||||
createCommandExecutingSelector(commandNames.IMPORT_LIST_SYNC),
|
||||
createDimensionsSelector(),
|
||||
(
|
||||
movies,
|
||||
isSyncingLists,
|
||||
dimensionsState
|
||||
) => {
|
||||
return {
|
||||
...movies,
|
||||
isSyncingLists,
|
||||
isSmallScreen: dimensionsState.isSmallScreen
|
||||
};
|
||||
}
|
||||
@@ -40,8 +34,8 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(fetchRootFolders());
|
||||
},
|
||||
|
||||
dispatchFetchImportExclusions() {
|
||||
dispatch(fetchImportExclusions());
|
||||
dispatchFetchNetImportExclusions() {
|
||||
dispatch(fetchNetImportExclusions());
|
||||
},
|
||||
|
||||
dispatchClearListMovie() {
|
||||
@@ -72,14 +66,8 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(addMovies({ ids, addOptions }));
|
||||
},
|
||||
|
||||
dispatchAddImportExclusions(exclusions) {
|
||||
dispatch(addImportExclusions(exclusions));
|
||||
},
|
||||
|
||||
onImportListSyncPress() {
|
||||
dispatch(executeCommand({
|
||||
name: commandNames.IMPORT_LIST_SYNC
|
||||
}));
|
||||
dispatchAddNetImportExclusions(exclusions) {
|
||||
dispatch(addNetImportExclusions(exclusions));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -92,7 +80,7 @@ class DiscoverMovieConnector extends Component {
|
||||
componentDidMount() {
|
||||
registerPagePopulator(this.repopulate);
|
||||
this.props.dispatchFetchRootFolders();
|
||||
this.props.dispatchFetchImportExclusions();
|
||||
this.props.dispatchFetchNetImportExclusions();
|
||||
this.props.dispatchFetchListMovies();
|
||||
}
|
||||
|
||||
@@ -117,7 +105,7 @@ class DiscoverMovieConnector extends Component {
|
||||
}
|
||||
|
||||
onExcludeMoviesPress =({ ids }) => {
|
||||
this.props.dispatchAddImportExclusions({ ids });
|
||||
this.props.dispatchAddNetImportExclusions({ ids });
|
||||
}
|
||||
|
||||
//
|
||||
@@ -131,7 +119,6 @@ class DiscoverMovieConnector extends Component {
|
||||
onScroll={this.onScroll}
|
||||
onAddMoviesPress={this.onAddMoviesPress}
|
||||
onExcludeMoviesPress={this.onExcludeMoviesPress}
|
||||
onSyncListsPress={this.onSyncListsPress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -140,13 +127,13 @@ class DiscoverMovieConnector extends Component {
|
||||
DiscoverMovieConnector.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
view: PropTypes.string.isRequired,
|
||||
dispatchFetchImportExclusions: PropTypes.func.isRequired,
|
||||
dispatchFetchNetImportExclusions: PropTypes.func.isRequired,
|
||||
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
||||
dispatchFetchListMovies: PropTypes.func.isRequired,
|
||||
dispatchClearListMovie: PropTypes.func.isRequired,
|
||||
dispatchSetListMovieView: PropTypes.func.isRequired,
|
||||
dispatchAddMovies: PropTypes.func.isRequired,
|
||||
dispatchAddImportExclusions: PropTypes.func.isRequired
|
||||
dispatchAddNetImportExclusions: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default withScrollPosition(
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
.excludeSelectedButton {
|
||||
composes: button from '~Components/Link/SpinnerButton.css';
|
||||
|
||||
margin-left: 25px;
|
||||
margin-left: 50px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ class DiscoverMovieFooter extends Component {
|
||||
<PageContentFooter>
|
||||
<div className={styles.inputContainer}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('MonitorMovie')}
|
||||
label="Monitor Movie"
|
||||
isSaving={isAdding}
|
||||
/>
|
||||
|
||||
@@ -161,7 +161,7 @@ class DiscoverMovieFooter extends Component {
|
||||
|
||||
<div className={styles.inputContainer}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('QualityProfile')}
|
||||
label="Quality Profile"
|
||||
isSaving={isAdding}
|
||||
/>
|
||||
|
||||
@@ -175,7 +175,7 @@ class DiscoverMovieFooter extends Component {
|
||||
|
||||
<div className={styles.inputContainer}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('MinimumAvailability')}
|
||||
label="Minimum Availability"
|
||||
isSaving={isAdding}
|
||||
/>
|
||||
|
||||
@@ -189,7 +189,7 @@ class DiscoverMovieFooter extends Component {
|
||||
|
||||
<div className={styles.inputContainer}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('RootFolder')}
|
||||
label="Root Folder"
|
||||
isSaving={isAdding}
|
||||
/>
|
||||
|
||||
@@ -204,7 +204,7 @@ class DiscoverMovieFooter extends Component {
|
||||
|
||||
<div className={styles.inputContainer}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('SearchOnAdd')}
|
||||
label="Search on Add"
|
||||
isSaving={isAdding}
|
||||
/>
|
||||
|
||||
@@ -219,7 +219,7 @@ class DiscoverMovieFooter extends Component {
|
||||
<div className={styles.buttonContainer}>
|
||||
<div className={styles.buttonContainerContent}>
|
||||
<DiscoverMovieFooterLabel
|
||||
label={translate('MoviesSelectedInterp', [selectedCount])}
|
||||
label={`${selectedCount} Movie(s) Selected`}
|
||||
isSaving={false}
|
||||
/>
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import DiscoverMovieFooter from './DiscoverMovieFooter';
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie,
|
||||
(state) => state.settings.importExclusions,
|
||||
(state) => state.settings.netImportExclusions,
|
||||
(state, { selectedIds }) => selectedIds,
|
||||
(discoverMovie, importExclusions, selectedIds) => {
|
||||
(discoverMovie, netImportExclusions, selectedIds) => {
|
||||
const {
|
||||
monitor: defaultMonitor,
|
||||
qualityProfileId: defaultQualityProfileId,
|
||||
@@ -25,7 +25,7 @@ function createMapStateToProps() {
|
||||
|
||||
const {
|
||||
isSaving
|
||||
} = importExclusions;
|
||||
} = netImportExclusions;
|
||||
|
||||
return {
|
||||
selectedCount: selectedIds.length,
|
||||
|
||||
@@ -6,7 +6,6 @@ import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './ExcludeMovieModalContent.css';
|
||||
|
||||
class ExcludeMovieModalContent extends Component {
|
||||
@@ -45,7 +44,7 @@ class ExcludeMovieModalContent extends Component {
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
Close
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { addImportExclusions } from 'Store/Actions/discoverMovieActions';
|
||||
import { addNetImportExclusions } from 'Store/Actions/discoverMovieActions';
|
||||
import ExcludeMovieModalContent from './ExcludeMovieModalContent';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
addImportExclusions
|
||||
addNetImportExclusions
|
||||
};
|
||||
|
||||
class ExcludeMovieModalContentConnector extends Component {
|
||||
@@ -14,7 +14,11 @@ class ExcludeMovieModalContentConnector extends Component {
|
||||
// Listeners
|
||||
|
||||
onExcludePress = () => {
|
||||
this.props.addImportExclusions({ ids: [this.props.tmdbId] });
|
||||
this.props.addNetImportExclusions([{
|
||||
tmdbId: this.props.tmdbId,
|
||||
movieTitle: this.props.title,
|
||||
movieYear: this.props.year
|
||||
}]);
|
||||
|
||||
this.props.onModalClose(true);
|
||||
}
|
||||
@@ -37,7 +41,7 @@ ExcludeMovieModalContentConnector.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired,
|
||||
addImportExclusions: PropTypes.func.isRequired
|
||||
addNetImportExclusions: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(undefined, mapDispatchToProps)(ExcludeMovieModalContentConnector);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import DiscoverMovieFilterModalConnector from 'DiscoverMovie/DiscoverMovieFilterModalConnector';
|
||||
import AddListMovieFilterModalConnector from 'DiscoverMovie/AddListMovieFilterModalConnector';
|
||||
import { align } from 'Helpers/Props';
|
||||
|
||||
function DiscoverMovieFilterMenu(props) {
|
||||
function AddListMovieFilterMenu(props) {
|
||||
const {
|
||||
selectedFilterKey,
|
||||
filters,
|
||||
@@ -20,13 +20,13 @@ function DiscoverMovieFilterMenu(props) {
|
||||
selectedFilterKey={selectedFilterKey}
|
||||
filters={filters}
|
||||
customFilters={customFilters}
|
||||
filterModalConnectorComponent={DiscoverMovieFilterModalConnector}
|
||||
filterModalConnectorComponent={AddListMovieFilterModalConnector}
|
||||
onFilterSelect={onFilterSelect}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
DiscoverMovieFilterMenu.propTypes = {
|
||||
AddListMovieFilterMenu.propTypes = {
|
||||
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
@@ -34,8 +34,8 @@ DiscoverMovieFilterMenu.propTypes = {
|
||||
onFilterSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
DiscoverMovieFilterMenu.defaultProps = {
|
||||
AddListMovieFilterMenu.defaultProps = {
|
||||
showCustomFilters: false
|
||||
};
|
||||
|
||||
export default DiscoverMovieFilterMenu;
|
||||
export default AddListMovieFilterMenu;
|
||||
@@ -5,7 +5,7 @@ import SortMenu from 'Components/Menu/SortMenu';
|
||||
import SortMenuItem from 'Components/Menu/SortMenuItem';
|
||||
import { align, sortDirections } from 'Helpers/Props';
|
||||
|
||||
function DiscoverMovieSortMenu(props) {
|
||||
function AddListMovieSortMenu(props) {
|
||||
const {
|
||||
sortKey,
|
||||
sortDirection,
|
||||
@@ -64,24 +64,6 @@ function DiscoverMovieSortMenu(props) {
|
||||
Physical Release
|
||||
</SortMenuItem>
|
||||
|
||||
<SortMenuItem
|
||||
name="digitalRelease"
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onPress={onSortSelect}
|
||||
>
|
||||
Digital Release
|
||||
</SortMenuItem>
|
||||
|
||||
<SortMenuItem
|
||||
name="runtime"
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onPress={onSortSelect}
|
||||
>
|
||||
Runtime
|
||||
</SortMenuItem>
|
||||
|
||||
<SortMenuItem
|
||||
name="ratings"
|
||||
sortKey={sortKey}
|
||||
@@ -104,11 +86,11 @@ function DiscoverMovieSortMenu(props) {
|
||||
);
|
||||
}
|
||||
|
||||
DiscoverMovieSortMenu.propTypes = {
|
||||
AddListMovieSortMenu.propTypes = {
|
||||
sortKey: PropTypes.string,
|
||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
onSortSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DiscoverMovieSortMenu;
|
||||
export default AddListMovieSortMenu;
|
||||
@@ -5,7 +5,7 @@ import ViewMenu from 'Components/Menu/ViewMenu';
|
||||
import ViewMenuItem from 'Components/Menu/ViewMenuItem';
|
||||
import { align } from 'Helpers/Props';
|
||||
|
||||
function DiscoverMovieViewMenu(props) {
|
||||
function AddListMovieViewMenu(props) {
|
||||
const {
|
||||
view,
|
||||
isDisabled,
|
||||
@@ -46,10 +46,10 @@ function DiscoverMovieViewMenu(props) {
|
||||
);
|
||||
}
|
||||
|
||||
DiscoverMovieViewMenu.propTypes = {
|
||||
AddListMovieViewMenu.propTypes = {
|
||||
view: PropTypes.string.isRequired,
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
onViewSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DiscoverMovieViewMenu;
|
||||
export default AddListMovieViewMenu;
|
||||
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Button from 'Components/Link/Button';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './NoDiscoverMovie.css';
|
||||
|
||||
function NoDiscoverMovie(props) {
|
||||
@@ -12,7 +11,7 @@ function NoDiscoverMovie(props) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.message}>
|
||||
{translate('AllMoviesHiddenDueToFilter')}
|
||||
All movies are hidden due to the applied filter.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -29,7 +28,7 @@ function NoDiscoverMovie(props) {
|
||||
to="/add/import"
|
||||
kind={kinds.PRIMARY}
|
||||
>
|
||||
{translate('ImportExistingMovies')}
|
||||
Import Existing Movies
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -38,16 +37,16 @@ function NoDiscoverMovie(props) {
|
||||
to="/add/new"
|
||||
kind={kinds.PRIMARY}
|
||||
>
|
||||
{translate('AddNewMovie')}
|
||||
Add New Movie
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className={styles.buttonContainer}>
|
||||
<Button
|
||||
to="/settings/importlists"
|
||||
to="/settings/netimports"
|
||||
kind={kinds.PRIMARY}
|
||||
>
|
||||
{translate('AddList')}
|
||||
Add List
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -32,12 +32,6 @@ $hoverScale: 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
.alreadyExistsIcon {
|
||||
margin-left: 10px;
|
||||
color: #37bc9b;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.exclusionIcon {
|
||||
margin-left: 10px;
|
||||
color: $dangerColor;
|
||||
@@ -56,15 +50,10 @@ $hoverScale: 1.05;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 10px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.lists {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
@add-mixin truncate;
|
||||
composes: link;
|
||||
@@ -72,7 +61,6 @@ $hoverScale: 1.05;
|
||||
flex: 1 0 1px;
|
||||
font-weight: 300;
|
||||
font-size: 30px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.actions {
|
||||
@@ -3,30 +3,26 @@ import React, { Component } from 'react';
|
||||
import TextTruncate from 'react-text-truncate';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import Icon from 'Components/Icon';
|
||||
import ImportListListConnector from 'Components/ImportListListConnector';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
|
||||
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import fonts from 'Styles/Variables/fonts';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import DiscoverMovieOverviewInfo from './DiscoverMovieOverviewInfo';
|
||||
import styles from './DiscoverMovieOverview.css';
|
||||
import styles from './AddListMovieOverview.css';
|
||||
|
||||
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
|
||||
const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen);
|
||||
const defaultFontSize = parseInt(fonts.defaultFontSize);
|
||||
const lineHeight = parseFloat(fonts.lineHeight);
|
||||
|
||||
// Hardcoded height beased on line-height of 32 + bottom margin of 10. 19 + 5 for List Row
|
||||
// Hardcoded height beased on line-height of 32 + bottom margin of 10.
|
||||
// Less side-effecty than using react-measure.
|
||||
const titleRowHeight = 66;
|
||||
const titleRowHeight = 42;
|
||||
|
||||
function getContentHeight(rowHeight, isSmallScreen) {
|
||||
const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding;
|
||||
@@ -34,7 +30,7 @@ function getContentHeight(rowHeight, isSmallScreen) {
|
||||
return rowHeight - padding;
|
||||
}
|
||||
|
||||
class DiscoverMovieOverview extends Component {
|
||||
class AddListMovieOverview extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
@@ -85,21 +81,18 @@ class DiscoverMovieOverview extends Component {
|
||||
imdbId,
|
||||
youTubeTrailerId,
|
||||
title,
|
||||
titleSlug,
|
||||
folder,
|
||||
year,
|
||||
overview,
|
||||
images,
|
||||
lists,
|
||||
posterWidth,
|
||||
posterHeight,
|
||||
rowHeight,
|
||||
isSmallScreen,
|
||||
isExisting,
|
||||
isExcluded,
|
||||
isRecommendation,
|
||||
isSelected,
|
||||
overviewOptions,
|
||||
...otherProps
|
||||
isSelected
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -112,7 +105,7 @@ class DiscoverMovieOverview extends Component {
|
||||
height: `${posterHeight}px`
|
||||
};
|
||||
|
||||
const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onPress };
|
||||
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
|
||||
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
|
||||
const overviewHeight = contentHeight - titleRowHeight;
|
||||
@@ -148,24 +141,15 @@ class DiscoverMovieOverview extends Component {
|
||||
className={styles.title}
|
||||
{...linkProps}
|
||||
>
|
||||
{title}
|
||||
{title}({year})
|
||||
|
||||
{
|
||||
isExisting ?
|
||||
<Icon
|
||||
className={styles.alreadyExistsIcon}
|
||||
name={icons.CHECK_CIRCLE}
|
||||
size={30}
|
||||
title={translate('AlreadyInYourLibrary')}
|
||||
/> : null
|
||||
}
|
||||
{
|
||||
isExcluded &&
|
||||
<Icon
|
||||
className={styles.exclusionIcon}
|
||||
name={icons.DANGER}
|
||||
size={30}
|
||||
title='Movie is on Import Exclusion List'
|
||||
size={36}
|
||||
title='Movie is on Net Import Exclusion List'
|
||||
/>
|
||||
}
|
||||
</Link>
|
||||
@@ -179,7 +163,7 @@ class DiscoverMovieOverview extends Component {
|
||||
size={12}
|
||||
/>
|
||||
}
|
||||
title={translate('Links')}
|
||||
title="Links"
|
||||
body={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
@@ -192,45 +176,17 @@ class DiscoverMovieOverview extends Component {
|
||||
|
||||
<IconButton
|
||||
name={icons.REMOVE}
|
||||
title={isExcluded ? translate('MovieAlreadyExcluded') : translate('ExcludeMovie')}
|
||||
title={isExcluded ? 'Movie already Excluded' : 'Exclude Movie'}
|
||||
onPress={this.onExcludeMoviePress}
|
||||
isDisabled={isExcluded}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.lists}>
|
||||
{
|
||||
isRecommendation ?
|
||||
<Label
|
||||
kind={kinds.INFO}
|
||||
>
|
||||
<Icon
|
||||
name={icons.RECOMMENDED}
|
||||
size={10}
|
||||
/>
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
<ImportListListConnector
|
||||
lists={lists}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.details}>
|
||||
<div className={styles.overview}>
|
||||
<TextTruncate
|
||||
line={Math.floor(overviewHeight / (defaultFontSize * lineHeight))}
|
||||
text={overview}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<DiscoverMovieOverviewInfo
|
||||
height={overviewHeight}
|
||||
year={year}
|
||||
{...overviewOptions}
|
||||
{...otherProps}
|
||||
<TextTruncate
|
||||
line={Math.floor(overviewHeight / (defaultFontSize * lineHeight))}
|
||||
text={overview}
|
||||
/>
|
||||
|
||||
</div>
|
||||
@@ -260,7 +216,7 @@ class DiscoverMovieOverview extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
DiscoverMovieOverview.propTypes = {
|
||||
AddListMovieOverview.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
youTubeTrailerId: PropTypes.string,
|
||||
@@ -269,6 +225,7 @@ DiscoverMovieOverview.propTypes = {
|
||||
year: PropTypes.number.isRequired,
|
||||
overview: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
posterWidth: PropTypes.number.isRequired,
|
||||
posterHeight: PropTypes.number.isRequired,
|
||||
@@ -281,14 +238,8 @@ DiscoverMovieOverview.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
isExisting: PropTypes.bool.isRequired,
|
||||
isExcluded: PropTypes.bool.isRequired,
|
||||
isRecommendation: PropTypes.bool.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
DiscoverMovieOverview.defaultProps = {
|
||||
lists: []
|
||||
};
|
||||
|
||||
export default DiscoverMovieOverview;
|
||||
export default AddListMovieOverview;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import DiscoverMovieOverview from './DiscoverMovieOverview';
|
||||
import AddListMovieOverview from './AddListMovieOverview';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
@@ -14,4 +14,4 @@ function createMapStateToProps() {
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(DiscoverMovieOverview);
|
||||
export default connect(createMapStateToProps)(AddListMovieOverview);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user