mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-06 13:31:28 -05:00
Compare commits
3 Commits
tweak-refr
...
async-test
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38c5989695 | ||
|
|
9ca03ba450 | ||
|
|
d283967523 |
18
DEVELOPMENT.md
Normal file
18
DEVELOPMENT.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# New UI Development
|
||||
|
||||
This document should provide an overview of current UI development, progress and blockers.
|
||||
|
||||
## Current Focus
|
||||
|
||||
Our current focus is creating a foundation for the UI, so that everything can be built upon it.
|
||||
|
||||
We are trialing the Sonarr V3 UI as our foundation. So far it has been working great and we already have a working build running.
|
||||
|
||||
## Performance Issues
|
||||
|
||||
You can download a database with 40k movies here: https://radarr.video/dev/radarr.db (Version where the next refresh movie scan is in a year. The refresh movie scan will lag the UI and other stuff. https://radarr.video/dev/radarr_no_scan.db). Just place it in your AppData Directory while Radarr is not running and make sure it's named radarr.db (https://github.com/Radarr/Radarr/wiki/AppData-Directory).
|
||||
You will have to message me (@galli-leo) via Discord or Reddit for the username and password (just as a precaution).
|
||||
|
||||
## Tasks
|
||||
|
||||
The actual tasks that are not related to the foundation of the new UI are all listed here https://github.com/Radarr/Radarr/projects/4. They are sorted according to different priorities. Some issues are also issues that shouldn't need anything extra, just a correct implementation in the new UI.
|
||||
31
README.md
31
README.md
@@ -1,15 +1,13 @@
|
||||
# Radarr
|
||||
|
||||
[](https://dev.azure.com/Radarr/Radarr/_build/latest?definitionId=1&branchName=develop)
|
||||
[](https://translate.servarr.com/engage/radarr/?utm_source=widget)
|
||||
[](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||

|
||||
[](#backers) [](#sponsors)
|
||||
**New UI Development:** For an overview of the new UI development see [DEVELOPMENT.md](https://github.com/Radarr/Radarr/blob/aphrodite/DEVELOPMENT.md).
|
||||
|
||||
Radarr is an __independent__ fork of [Sonarr](https://github.com/Sonarr/Sonarr) reworked for automatically downloading movies via Usenet and BitTorrent.
|
||||
|
||||
The project was inspired by other Usenet/BitTorrent movie downloaders such as CouchPotato.
|
||||
|
||||
See the [Roadmap blogpost](https://blog.radarr.video/development/update/2018/11/11/roadmap-update.html) for an overview of planned features.
|
||||
|
||||
## Getting Started
|
||||
|
||||
[](https://github.com/Radarr/Radarr/wiki/Installation)
|
||||
@@ -32,6 +30,10 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
|
||||
|
||||
## Support
|
||||
|
||||
[](#backers)
|
||||
[](#flexible-sponsors)
|
||||
[](#sponsors)
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](http://feathub.com/Radarr/Radarr)
|
||||
@@ -43,13 +45,23 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/pulls)
|
||||
[](http://www.gnu.org/licenses/gpl.html)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radarr/Radarr/releases/)
|
||||
[](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
[](/CHANGELOG.md#unreleased)
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/Radarr/Radarr) | [](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
### [Site and API Status](https://status.radarr.video)
|
||||
|
||||
| API | Updates | Sites |
|
||||
|-------|:----:|:----:|
|
||||
| [](https://api.radarr.video/v2/) | [](https://radarr.aeonlucid.com) | [](https://mappings.radarr.video/)
|
||||
| [](https://staging.api.radarr.video/) | [](https://api.github.com/v3/) | [](https://radarr.video/)
|
||||
|
||||
Radarr is currently undergoing rapid development and pull requests are actively added into the repository.
|
||||
|
||||
## Features
|
||||
@@ -98,6 +110,7 @@ See the [Roadmap blogpost](https://blog.radarr.video/development/update/2018/11/
|
||||
|
||||
* Make sure all the required software mentioned above are installed
|
||||
* Clone the repository into your development machine ([*info*](https://help.github.com/desktop/guides/contributing/working-with-your-remote-repository-on-github-or-github-enterprise))
|
||||
* Grab the submodules `git submodule init && git submodule update`
|
||||
* Install the required Node Packages `yarn install`
|
||||
* Start gulp to monitor your dev environment for any changes that need post processing using `yarn start` command.
|
||||
|
||||
@@ -112,9 +125,9 @@ See the [Roadmap blogpost](https://blog.radarr.video/development/update/2018/11/
|
||||
|
||||
### Development
|
||||
|
||||
* Open `Radarr.sln` in Visual Studio 2019 or run the build.sh script, if Mono is installed. Alternatively you can use Jetbrains Rider, since it works on all Platforms.
|
||||
* Open `Radarr.sln` in Visual Studio 2017 or run the build.sh script, if Mono is installed. Alternatively you can use Jetbrains Rider, since it works on all Platforms.
|
||||
* Make sure `NzbDrone.Console` is set as the startup project
|
||||
* Run `build.sh` before running, or build in VS
|
||||
* Run `build.sh` before running
|
||||
|
||||
## Supporters
|
||||
|
||||
@@ -144,4 +157,4 @@ Thank you to [<img src="/Logo/jetbrains.svg" alt="JetBrains" width="32"> JetBrai
|
||||
## License
|
||||
|
||||
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
* Copyright 2010-2020
|
||||
* Copyright 2010-2019
|
||||
|
||||
3
appveyor.yml
Normal file
3
appveyor.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/**'
|
||||
@@ -13,7 +13,7 @@ variables:
|
||||
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
||||
sentryOrg: 'servarr'
|
||||
sentryUrl: 'https://sentry.servarr.com'
|
||||
dotnetVersion: '3.1.302'
|
||||
dotnetVersion: '3.1.300'
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
@@ -101,10 +101,6 @@ stages:
|
||||
artifact: LinuxCoreTests
|
||||
displayName: Publish Linux Test Package
|
||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
||||
- publish: '$(testsFolder)/netcoreapp3.1/linux-musl-x64/publish'
|
||||
artifact: LinuxMuslCoreTests
|
||||
displayName: Publish Linux Musl Test Package
|
||||
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
|
||||
- publish: '$(testsFolder)/netcoreapp3.1/osx-x64/publish'
|
||||
artifact: MacCoreTests
|
||||
displayName: Publish MacOS Test Package
|
||||
@@ -247,14 +243,6 @@ stages:
|
||||
tarCompression: 'gz'
|
||||
includeRootFolder: false
|
||||
rootFolderOrFile: $(artifactsFolder)/linux-x64/netcoreapp3.1
|
||||
- task: ArchiveFiles@2
|
||||
displayName: Create Linux Musl Core tar
|
||||
inputs:
|
||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-x64.tar.gz'
|
||||
archiveType: 'tar'
|
||||
tarCompression: 'gz'
|
||||
includeRootFolder: false
|
||||
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/netcoreapp3.1
|
||||
- task: ArchiveFiles@2
|
||||
displayName: Create ARM32 Linux Core tar
|
||||
inputs:
|
||||
@@ -271,14 +259,6 @@ stages:
|
||||
tarCompression: 'gz'
|
||||
includeRootFolder: false
|
||||
rootFolderOrFile: $(artifactsFolder)/linux-arm64/netcoreapp3.1
|
||||
- task: ArchiveFiles@2
|
||||
displayName: Create ARM64 Linux Musl Core tar
|
||||
inputs:
|
||||
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm64.tar.gz'
|
||||
archiveType: 'tar'
|
||||
tarCompression: 'gz'
|
||||
includeRootFolder: false
|
||||
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/netcoreapp3.1
|
||||
- publish: $(Build.ArtifactStagingDirectory)
|
||||
artifact: 'Packages'
|
||||
displayName: Publish Packages
|
||||
@@ -402,26 +382,18 @@ 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
|
||||
mono510:
|
||||
testName: 'Mono 5.10'
|
||||
containerImage: servarr/testimages:mono-5.10
|
||||
mono520:
|
||||
testName: 'Mono 5.20'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-5.20
|
||||
mono608:
|
||||
testName: 'Mono 6.8'
|
||||
containerImage: servarr/testimages:mono-6.8
|
||||
mono610:
|
||||
testName: 'Mono 6.10'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-6.10
|
||||
mono612:
|
||||
testName: 'Mono 6.12'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-6.12
|
||||
alpine:
|
||||
testName: 'Musl Net Core'
|
||||
artifactName: LinuxMuslCoreTests
|
||||
containerImage: servarr/testimages:alpine
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
@@ -431,6 +403,8 @@ stages:
|
||||
timeoutInMinutes: 10
|
||||
|
||||
steps:
|
||||
- bash: mono --version
|
||||
displayName: Check Mono version
|
||||
- task: UseDotNet@2
|
||||
displayName: 'Install .net core'
|
||||
inputs:
|
||||
@@ -440,14 +414,10 @@ stages:
|
||||
displayName: Download Test Artifact
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: $(artifactName)
|
||||
artifactName: LinuxTests
|
||||
targetPath: $(testsFolder)
|
||||
- bash: find ${TESTSFOLDER} -name "Radarr.Test.Dummy" -exec chmod a+x {} \;
|
||||
displayName: Make Test Dummy Executable
|
||||
condition: and(succeeded(), ne(variables['osName'], 'Windows'))
|
||||
- bash: |
|
||||
chmod a+x ${TESTSFOLDER}/test.sh
|
||||
ls -lR ${TESTSFOLDER}
|
||||
${TESTSFOLDER}/test.sh Linux Unit Test
|
||||
displayName: Run Tests
|
||||
- task: PublishTestResults@2
|
||||
@@ -555,31 +525,22 @@ 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'
|
||||
mono510:
|
||||
testName: 'Mono 5.10'
|
||||
containerImage: servarr/testimages:mono-5.10
|
||||
mono520:
|
||||
testName: 'Mono 5.20'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-5.20
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
mono608:
|
||||
testName: 'Mono 6.8'
|
||||
containerImage: servarr/testimages:mono-6.8
|
||||
mono610:
|
||||
testName: 'Mono 6.10'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-6.10
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
mono612:
|
||||
testName: 'Mono 6.12'
|
||||
artifactName: LinuxTests
|
||||
containerImage: servarr/testimages:mono-6.12
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
alpine:
|
||||
testName: 'Musl Net Core'
|
||||
artifactName: LinuxCoreTests
|
||||
containerImage: servarr/testimages:alpine
|
||||
pattern: 'Radarr.**.linux-musl-core-x64.tar.gz'
|
||||
|
||||
variables:
|
||||
pattern: 'Radarr.**.linux.tar.gz'
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
|
||||
@@ -588,6 +549,8 @@ stages:
|
||||
timeoutInMinutes: 15
|
||||
|
||||
steps:
|
||||
- bash: mono --version
|
||||
displayName: Check Mono version
|
||||
- task: UseDotNet@2
|
||||
displayName: 'Install .net core'
|
||||
inputs:
|
||||
@@ -597,7 +560,7 @@ stages:
|
||||
displayName: Download Test Artifact
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: $(artifactName)
|
||||
artifactName: LinuxTests
|
||||
targetPath: $(testsFolder)
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Build Artifact
|
||||
|
||||
5
build.sh
5
build.sh
@@ -71,7 +71,7 @@ Build()
|
||||
YarnInstall()
|
||||
{
|
||||
ProgressStart 'yarn install'
|
||||
yarn install --frozen-lockfile --network-timeout 120000
|
||||
yarn install --frozen-lockfile
|
||||
ProgressEnd 'yarn install'
|
||||
}
|
||||
|
||||
@@ -319,7 +319,6 @@ then
|
||||
then
|
||||
PackageTests "netcoreapp3.1" "win-x64"
|
||||
PackageTests "netcoreapp3.1" "linux-x64"
|
||||
PackageTests "netcoreapp3.1" "linux-musl-x64"
|
||||
PackageTests "netcoreapp3.1" "osx-x64"
|
||||
PackageTests "net462" "linux-x64"
|
||||
else
|
||||
@@ -351,9 +350,7 @@ then
|
||||
then
|
||||
Package "netcoreapp3.1" "win-x64"
|
||||
Package "netcoreapp3.1" "linux-x64"
|
||||
Package "netcoreapp3.1" "linux-musl-x64"
|
||||
Package "netcoreapp3.1" "linux-arm64"
|
||||
Package "netcoreapp3.1" "linux-musl-arm64"
|
||||
Package "netcoreapp3.1" "linux-arm"
|
||||
Package "netcoreapp3.1" "osx-x64"
|
||||
Package "net462" "linux-x64"
|
||||
|
||||
293
frontend/.eslintrc
Normal file
293
frontend/.eslintrc
Normal file
@@ -0,0 +1,293 @@
|
||||
{
|
||||
"parser": "babel-eslint",
|
||||
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"expect": false,
|
||||
"chai": false,
|
||||
"sinon": false
|
||||
},
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"modules": true,
|
||||
"impliedStrict": true
|
||||
}
|
||||
},
|
||||
|
||||
"plugins": [
|
||||
"filenames",
|
||||
"react"
|
||||
],
|
||||
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"filenames/match-exported": ["error"],
|
||||
|
||||
# ECMAScript 6
|
||||
|
||||
"arrow-body-style": [0],
|
||||
"arrow-parens": ["error", "always"],
|
||||
"arrow-spacing": ["error", { "before": true, "after": true }],
|
||||
"constructor-super": "error",
|
||||
"generator-star-spacing": "off",
|
||||
"no-class-assign": "error",
|
||||
"no-confusing-arrow": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-new-symbol": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-var": "warn",
|
||||
"object-shorthand": ["error", "properties"],
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "warn",
|
||||
"prefer-reflect": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "warn",
|
||||
"prefer-template": "error",
|
||||
"require-yield": "off",
|
||||
"template-curly-spacing": ["error", "never"],
|
||||
"yield-star-spacing": "off",
|
||||
|
||||
# Possible Errors
|
||||
|
||||
"comma-dangle": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-console": "off",
|
||||
"no-constant-condition": "warn",
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "off",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-empty": "warn",
|
||||
"no-empty-character-class": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-parens": ["error", "functions"],
|
||||
"no-extra-semi": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-inner-declarations": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-negated-in-lhs": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-unreachable": "warn",
|
||||
"no-unsafe-finally": "error",
|
||||
"use-isnan": "error",
|
||||
"valid-jsdoc": "off",
|
||||
"valid-typeof": "error",
|
||||
|
||||
# Best Practices
|
||||
|
||||
"accessor-pairs": "off",
|
||||
"array-callback-return": "warn",
|
||||
"block-scoped-var": "warn",
|
||||
"consistent-return": "off",
|
||||
"curly": "error",
|
||||
"default-case": "error",
|
||||
"dot-location": ["error", "property"],
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": ["error", "smart"],
|
||||
"guard-for-in": "error",
|
||||
"no-alert": "warn",
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-div-regex": "error",
|
||||
"no-else-return": "error",
|
||||
"no-empty-function": ["error", {"allow": ["arrowFunctions"]}],
|
||||
"no-empty-pattern": "error",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implicit-coercion": ["error", {
|
||||
"boolean": false,
|
||||
"number": true,
|
||||
"string": true,
|
||||
"allow": [/* "!!", "~", "*", "+" */]
|
||||
}],
|
||||
"no-implicit-globals": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-invalid-this": "off",
|
||||
"no-iterator": "error",
|
||||
"no-labels": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-loop-func": "error",
|
||||
"no-magic-numbers": ["off", {"ignoreArrayIndexes": true, "ignore": [0, 1] }],
|
||||
"no-multi-spaces": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-native-reassign": ["error", {"exceptions": ["console"]}],
|
||||
"no-new": "off",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-octal": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "off",
|
||||
"no-process-env": "off",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-return-assign": "warn",
|
||||
"no-script-url": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "off",
|
||||
"no-with": "error",
|
||||
"radix": ["error", "as-needed"],
|
||||
"vars-on-top": "off",
|
||||
"wrap-iife": ["error", "inside"],
|
||||
"yoda": "error",
|
||||
|
||||
# Strict Mode
|
||||
|
||||
"strict": ["error", "never"],
|
||||
|
||||
# Variables
|
||||
|
||||
"init-declarations": ["error", "always"],
|
||||
"no-catch-shadow": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-label-var": "error",
|
||||
"no-restricted-globals": "off",
|
||||
"no-shadow": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-undef": "error",
|
||||
"no-undef-init": "off",
|
||||
"no-undefined": "off",
|
||||
"no-unused-vars": ["error", { "args": "none", "ignoreRestSiblings": true }],
|
||||
"no-use-before-define": "error",
|
||||
|
||||
# Node.js and CommonJS
|
||||
|
||||
"callback-return": "warn",
|
||||
"global-require": "error",
|
||||
"handle-callback-err": "warn",
|
||||
"no-mixed-requires": "error",
|
||||
"no-new-require": "error",
|
||||
"no-path-concat": "error",
|
||||
"no-process-exit": "error",
|
||||
|
||||
# Stylistic Issues
|
||||
|
||||
"array-bracket-spacing": ["error", "never"],
|
||||
"block-spacing": ["error", "always"],
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": false }],
|
||||
"camelcase": "off",
|
||||
"comma-spacing": ["error", {"before": false, "after": true}],
|
||||
"comma-style": ["error", "last"],
|
||||
"computed-property-spacing": ["error", "never"],
|
||||
"consistent-this": ["error", "self"],
|
||||
"eol-last": "error",
|
||||
"func-names": "off",
|
||||
"func-style": ["error", "declaration"],
|
||||
"indent": ["error", 2, {"SwitchCase": 1}],
|
||||
"key-spacing": ["error", {"beforeColon": false, "afterColon": true}],
|
||||
"keyword-spacing": ["error", { "before": true, "after": true}],
|
||||
"lines-around-comment": ["error", { "beforeBlockComment": true, "afterBlockComment": false }],
|
||||
"max-depth": ["error", {"maximum": 5}],
|
||||
"max-nested-callbacks": ["error", 4],
|
||||
"max-statements": "off",
|
||||
"max-statements-per-line": ["error", { "max": 1 }],
|
||||
"new-cap": ["error", {"capIsNewExceptions": ["$.Deferred", "DragDropContext", "DragLayer", "DragSource", "DropTarget"]}],
|
||||
"new-parens": "error",
|
||||
"newline-after-var": "off",
|
||||
"newline-before-return": "off",
|
||||
"newline-per-chained-call": "off",
|
||||
"no-array-constructor": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-continue": "error",
|
||||
"no-inline-comments": "off",
|
||||
"no-lonely-if": "warn",
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
||||
"no-negated-condition": "warn",
|
||||
"no-nested-ternary": "error",
|
||||
"no-new-object": "error",
|
||||
"no-plusplus": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
"no-spaced-func": "error",
|
||||
"no-ternary": "off",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"one-var": ["error", "never"],
|
||||
"one-var-declaration-per-line": ["error", "always"],
|
||||
"operator-assignment": ["off", "never"],
|
||||
"operator-linebreak": ["error", "after"],
|
||||
"quote-props": ["error", "as-needed"],
|
||||
"quotes": ["error", "single"],
|
||||
"require-jsdoc": "off",
|
||||
"semi": "error",
|
||||
"semi-spacing": ["error", { "before": false, "after": true }],
|
||||
"sort-vars": "off",
|
||||
"space-before-blocks": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "never"],
|
||||
"space-in-parens": "off",
|
||||
"space-infix-ops": "off",
|
||||
"space-unary-ops": "off",
|
||||
"spaced-comment": "error",
|
||||
"wrap-regex": "error",
|
||||
|
||||
# React
|
||||
|
||||
"react/jsx-boolean-value": [2, "always"],
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/jsx-closing-bracket-location": 2,
|
||||
"react/jsx-tag-spacing": ["error"],
|
||||
"react/jsx-curly-spacing": [2, "never"],
|
||||
"react/jsx-equals-spacing": [2, "never"],
|
||||
"react/jsx-indent-props": [2, 2],
|
||||
"react/jsx-indent": [2, 2, { "indentLogicalExpressions": true }],
|
||||
"react/jsx-key": 2,
|
||||
"react/jsx-no-bind": [2, { "allowArrowFunctions": true }],
|
||||
"react/jsx-no-duplicate-props": [2, { "ignoreCase": true }],
|
||||
"react/jsx-max-props-per-line": [2, { "maximum": 2 }],
|
||||
"react/jsx-handler-names": [2, { "eventHandlerPrefix": "(on|dispatch)", "eventHandlerPropPrefix": "on" }],
|
||||
"react/jsx-no-undef": 2,
|
||||
"react/jsx-pascal-case": 2,
|
||||
"react/jsx-uses-react": 2,
|
||||
// Explicitly disabled in case we want to enable them again
|
||||
"react/no-did-mount-set-state": 0,
|
||||
"react/no-did-update-set-state": 0,
|
||||
"react/no-direct-mutation-state": 2,
|
||||
"react/no-multi-comp": [2, { "ignoreStateless": true }],
|
||||
"react/no-unknown-property": 2,
|
||||
"react/prefer-es6-class": 2,
|
||||
"react/prop-types": 2,
|
||||
"react/react-in-jsx-scope": 2,
|
||||
"react/self-closing-comp": 2,
|
||||
"react/sort-comp": 2,
|
||||
"react/jsx-wrap-multilines": 2
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const dirs = fs
|
||||
.readdirSync('frontend/src', { withFileTypes: true })
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name)
|
||||
.join('|');
|
||||
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
commonjs: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
|
||||
globals: {
|
||||
expect: false,
|
||||
chai: false,
|
||||
sinon: false
|
||||
},
|
||||
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
modules: true,
|
||||
impliedStrict: true
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
'filenames',
|
||||
'react',
|
||||
'simple-import-sort',
|
||||
'import'
|
||||
],
|
||||
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect'
|
||||
}
|
||||
},
|
||||
|
||||
rules: {
|
||||
'filenames/match-exported': ['error'],
|
||||
|
||||
// ECMAScript 6
|
||||
|
||||
'arrow-body-style': [0],
|
||||
'arrow-parens': ['error', 'always'],
|
||||
'arrow-spacing': ['error', { before: true, after: true }],
|
||||
'constructor-super': 'error',
|
||||
'generator-star-spacing': 'off',
|
||||
'no-class-assign': 'error',
|
||||
'no-confusing-arrow': 'error',
|
||||
'no-const-assign': 'error',
|
||||
'no-dupe-class-members': 'error',
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-new-symbol': 'error',
|
||||
'no-this-before-super': 'error',
|
||||
'no-useless-escape': 'error',
|
||||
'no-useless-computed-key': 'error',
|
||||
'no-useless-constructor': 'error',
|
||||
'no-var': 'warn',
|
||||
'object-shorthand': ['error', 'properties'],
|
||||
'prefer-arrow-callback': 'error',
|
||||
'prefer-const': 'warn',
|
||||
'prefer-reflect': 'off',
|
||||
'prefer-rest-params': 'off',
|
||||
'prefer-spread': 'warn',
|
||||
'prefer-template': 'error',
|
||||
'require-yield': 'off',
|
||||
'template-curly-spacing': ['error', 'never'],
|
||||
'yield-star-spacing': 'off',
|
||||
|
||||
// Possible Errors
|
||||
|
||||
'comma-dangle': 'error',
|
||||
'no-cond-assign': 'error',
|
||||
'no-console': 'off',
|
||||
'no-constant-condition': 'warn',
|
||||
'no-control-regex': 'error',
|
||||
'no-debugger': 'off',
|
||||
'no-dupe-args': 'error',
|
||||
'no-dupe-keys': 'error',
|
||||
'no-duplicate-case': 'error',
|
||||
'no-empty': 'warn',
|
||||
'no-empty-character-class': 'error',
|
||||
'no-ex-assign': 'error',
|
||||
'no-extra-boolean-cast': 'error',
|
||||
'no-extra-parens': ['error', 'functions'],
|
||||
'no-extra-semi': 'error',
|
||||
'no-func-assign': 'error',
|
||||
'no-inner-declarations': 'error',
|
||||
'no-invalid-regexp': 'error',
|
||||
'no-irregular-whitespace': 'error',
|
||||
'no-negated-in-lhs': 'error',
|
||||
'no-obj-calls': 'error',
|
||||
'no-regex-spaces': 'error',
|
||||
'no-sparse-arrays': 'error',
|
||||
'no-unexpected-multiline': 'error',
|
||||
'no-unreachable': 'warn',
|
||||
'no-unsafe-finally': 'error',
|
||||
'use-isnan': 'error',
|
||||
'valid-jsdoc': 'off',
|
||||
'valid-typeof': 'error',
|
||||
|
||||
// Best Practices
|
||||
|
||||
'accessor-pairs': 'off',
|
||||
'array-callback-return': 'warn',
|
||||
'block-scoped-var': 'warn',
|
||||
'consistent-return': 'off',
|
||||
curly: 'error',
|
||||
'default-case': 'error',
|
||||
'dot-location': ['error', 'property'],
|
||||
'dot-notation': 'error',
|
||||
eqeqeq: ['error', 'smart'],
|
||||
'guard-for-in': 'error',
|
||||
'no-alert': 'warn',
|
||||
'no-caller': 'error',
|
||||
'no-case-declarations': 'error',
|
||||
'no-div-regex': 'error',
|
||||
'no-else-return': 'error',
|
||||
'no-empty-function': ['error', { allow: ['arrowFunctions'] }],
|
||||
'no-empty-pattern': 'error',
|
||||
'no-eval': 'error',
|
||||
'no-extend-native': 'error',
|
||||
'no-extra-bind': 'error',
|
||||
'no-fallthrough': 'error',
|
||||
'no-floating-decimal': 'error',
|
||||
'no-implicit-coercion': ['error', {
|
||||
boolean: false,
|
||||
number: true,
|
||||
string: true,
|
||||
allow: [/* "!!", "~", "*", "+" */]
|
||||
}],
|
||||
'no-implicit-globals': 'error',
|
||||
'no-implied-eval': 'error',
|
||||
'no-invalid-this': 'off',
|
||||
'no-iterator': 'error',
|
||||
'no-labels': 'error',
|
||||
'no-lone-blocks': 'error',
|
||||
'no-loop-func': 'error',
|
||||
'no-magic-numbers': ['off', { ignoreArrayIndexes: true, ignore: [0, 1] }],
|
||||
'no-multi-spaces': 'error',
|
||||
'no-multi-str': 'error',
|
||||
'no-native-reassign': ['error', { exceptions: ['console'] }],
|
||||
'no-new': 'off',
|
||||
'no-new-func': 'error',
|
||||
'no-new-wrappers': 'error',
|
||||
'no-octal': 'error',
|
||||
'no-octal-escape': 'error',
|
||||
'no-param-reassign': 'off',
|
||||
'no-process-env': 'off',
|
||||
'no-proto': 'error',
|
||||
'no-redeclare': 'error',
|
||||
'no-return-assign': 'warn',
|
||||
'no-script-url': 'error',
|
||||
'no-self-assign': 'error',
|
||||
'no-self-compare': 'error',
|
||||
'no-sequences': 'error',
|
||||
'no-throw-literal': 'error',
|
||||
'no-unmodified-loop-condition': 'error',
|
||||
'no-unused-expressions': 'error',
|
||||
'no-unused-labels': 'error',
|
||||
'no-useless-call': 'error',
|
||||
'no-useless-concat': 'error',
|
||||
'no-void': 'error',
|
||||
'no-warning-comments': 'off',
|
||||
'no-with': 'error',
|
||||
radix: ['error', 'as-needed'],
|
||||
'vars-on-top': 'off',
|
||||
'wrap-iife': ['error', 'inside'],
|
||||
yoda: 'error',
|
||||
|
||||
// Strict Mode
|
||||
|
||||
strict: ['error', 'never'],
|
||||
|
||||
// Variables
|
||||
|
||||
'init-declarations': ['error', 'always'],
|
||||
'no-catch-shadow': 'error',
|
||||
'no-delete-var': 'error',
|
||||
'no-label-var': 'error',
|
||||
'no-restricted-globals': 'off',
|
||||
'no-shadow': 'error',
|
||||
'no-shadow-restricted-names': 'error',
|
||||
'no-undef': 'error',
|
||||
'no-undef-init': 'off',
|
||||
'no-undefined': 'off',
|
||||
'no-unused-vars': ['error', { args: 'none', ignoreRestSiblings: true }],
|
||||
'no-use-before-define': 'error',
|
||||
|
||||
// Node.js and CommonJS
|
||||
|
||||
'callback-return': 'warn',
|
||||
'global-require': 'error',
|
||||
'handle-callback-err': 'warn',
|
||||
'no-mixed-requires': 'error',
|
||||
'no-new-require': 'error',
|
||||
'no-path-concat': 'error',
|
||||
'no-process-exit': 'error',
|
||||
|
||||
// Stylistic Issues
|
||||
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
'block-spacing': ['error', 'always'],
|
||||
'brace-style': ['error', '1tbs', { allowSingleLine: false }],
|
||||
camelcase: 'off',
|
||||
'comma-spacing': ['error', { before: false, after: true }],
|
||||
'comma-style': ['error', 'last'],
|
||||
'computed-property-spacing': ['error', 'never'],
|
||||
'consistent-this': ['error', 'self'],
|
||||
'eol-last': 'error',
|
||||
'func-names': 'off',
|
||||
'func-style': ['error', 'declaration'],
|
||||
indent: ['error', 2, { SwitchCase: 1 }],
|
||||
'key-spacing': ['error', { beforeColon: false, afterColon: true }],
|
||||
'keyword-spacing': ['error', { before: true, after: true }],
|
||||
'lines-around-comment': ['error', { beforeBlockComment: true, afterBlockComment: false }],
|
||||
'max-depth': ['error', { maximum: 5 }],
|
||||
'max-nested-callbacks': ['error', 4],
|
||||
'max-statements': 'off',
|
||||
'max-statements-per-line': ['error', { max: 1 }],
|
||||
'new-cap': ['error', { capIsNewExceptions: ['$.Deferred', 'DragDropContext', 'DragLayer', 'DragSource', 'DropTarget'] }],
|
||||
'new-parens': 'error',
|
||||
'newline-after-var': 'off',
|
||||
'newline-before-return': 'off',
|
||||
'newline-per-chained-call': 'off',
|
||||
'no-array-constructor': 'error',
|
||||
'no-bitwise': 'error',
|
||||
'no-continue': 'error',
|
||||
'no-inline-comments': 'off',
|
||||
'no-lonely-if': 'warn',
|
||||
'no-mixed-spaces-and-tabs': 'error',
|
||||
'no-multiple-empty-lines': ['error', { max: 1 }],
|
||||
'no-negated-condition': 'warn',
|
||||
'no-nested-ternary': 'error',
|
||||
'no-new-object': 'error',
|
||||
'no-plusplus': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'no-spaced-func': 'error',
|
||||
'no-ternary': 'off',
|
||||
'no-trailing-spaces': 'error',
|
||||
'no-underscore-dangle': ['error', { allowAfterThis: true }],
|
||||
'no-unneeded-ternary': 'error',
|
||||
'no-whitespace-before-property': 'error',
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'one-var': ['error', 'never'],
|
||||
'one-var-declaration-per-line': ['error', 'always'],
|
||||
'operator-assignment': ['off', 'never'],
|
||||
'operator-linebreak': ['error', 'after'],
|
||||
'quote-props': ['error', 'as-needed'],
|
||||
quotes: ['error', 'single'],
|
||||
'require-jsdoc': 'off',
|
||||
semi: 'error',
|
||||
'semi-spacing': ['error', { before: false, after: true }],
|
||||
'sort-vars': 'off',
|
||||
'space-before-blocks': ['error', 'always'],
|
||||
'space-before-function-paren': ['error', 'never'],
|
||||
'space-in-parens': 'off',
|
||||
'space-infix-ops': 'off',
|
||||
'space-unary-ops': 'off',
|
||||
'spaced-comment': 'error',
|
||||
'wrap-regex': 'error',
|
||||
|
||||
// ImportSort
|
||||
|
||||
'simple-import-sort/sort': 'error',
|
||||
'import/newline-after-import': 'error',
|
||||
|
||||
// React
|
||||
|
||||
'react/jsx-boolean-value': [2, 'always'],
|
||||
'react/jsx-uses-vars': 2,
|
||||
'react/jsx-closing-bracket-location': 2,
|
||||
'react/jsx-tag-spacing': ['error'],
|
||||
'react/jsx-curly-spacing': [2, 'never'],
|
||||
'react/jsx-equals-spacing': [2, 'never'],
|
||||
'react/jsx-indent-props': [2, 2],
|
||||
'react/jsx-indent': [2, 2, { indentLogicalExpressions: true }],
|
||||
'react/jsx-key': 2,
|
||||
'react/jsx-no-bind': [2, { allowArrowFunctions: true }],
|
||||
'react/jsx-no-duplicate-props': [2, { ignoreCase: true }],
|
||||
'react/jsx-max-props-per-line': [2, { maximum: 2 }],
|
||||
'react/jsx-handler-names': [2, { eventHandlerPrefix: '(on|dispatch)', eventHandlerPropPrefix: 'on' }],
|
||||
'react/jsx-no-undef': 2,
|
||||
'react/jsx-pascal-case': 2,
|
||||
'react/jsx-uses-react': 2,
|
||||
// Explicitly disabled in case we want to enable them again
|
||||
'react/no-did-mount-set-state': 0,
|
||||
'react/no-did-update-set-state': 0,
|
||||
'react/no-direct-mutation-state': 2,
|
||||
'react/no-multi-comp': [2, { ignoreStateless: true }],
|
||||
'react/no-unknown-property': 2,
|
||||
'react/prefer-es6-class': 2,
|
||||
'react/prop-types': 2,
|
||||
'react/react-in-jsx-scope': 2,
|
||||
'react/self-closing-comp': 2,
|
||||
'react/sort-comp': 2,
|
||||
'react/jsx-wrap-multilines': 2
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
'simple-import-sort/sort': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
// Packages
|
||||
// Absolute Paths
|
||||
// Relative Paths
|
||||
// Css
|
||||
['^@?\\w', `^(${dirs})(/.*|$)`, '^\\.', '^\\..*css$']
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -24,7 +24,7 @@
|
||||
"ignoreAtRules": [
|
||||
"/^add\\-mixin$/",
|
||||
"/^define\\-mixin$/"
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"at-rule-no-vendor-prefix": true,
|
||||
|
||||
@@ -10,7 +10,8 @@ gulp.task('build',
|
||||
'webpack',
|
||||
'copyHtml',
|
||||
'copyFonts',
|
||||
'copyImages'
|
||||
'copyImages',
|
||||
'copyJs'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -5,6 +5,17 @@ const cache = require('gulp-cached');
|
||||
const livereload = require('gulp-livereload');
|
||||
const paths = require('./helpers/paths.js');
|
||||
|
||||
gulp.task('copyJs', () => {
|
||||
return gulp.src(
|
||||
[
|
||||
path.join(paths.src.root, 'polyfills.js')
|
||||
], { base: paths.src.root })
|
||||
.pipe(cache('copyJs'))
|
||||
.pipe(print())
|
||||
.pipe(gulp.dest(paths.dest.root))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('copyHtml', () => {
|
||||
return gulp.src(paths.src.html, { base: paths.src.root })
|
||||
.pipe(cache('copyHtml'))
|
||||
|
||||
@@ -4,7 +4,6 @@ const livereload = require('gulp-livereload');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const errorHandler = require('./helpers/errorHandler');
|
||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
@@ -14,7 +13,6 @@ const frontendFolder = path.join(__dirname, '..');
|
||||
const srcFolder = path.join(frontendFolder, 'src');
|
||||
const isProduction = process.argv.indexOf('--production') > -1;
|
||||
const isProfiling = isProduction && process.argv.indexOf('--profile') > -1;
|
||||
const inlineWebWorkers = true;
|
||||
|
||||
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
|
||||
|
||||
@@ -48,8 +46,6 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, assets, assetT
|
||||
};
|
||||
|
||||
const plugins = [
|
||||
new OptimizeCssAssetsPlugin({}),
|
||||
|
||||
new webpack.DefinePlugin({
|
||||
__DEV__: !isProduction,
|
||||
'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development')
|
||||
@@ -125,9 +121,7 @@ const config = {
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
name: '[name].js',
|
||||
inline: inlineWebWorkers,
|
||||
fallback: !inlineWebWorkers
|
||||
name: '[name].js'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -257,7 +251,7 @@ gulp.task('webpack', () => {
|
||||
gulp.task('webpackWatch', () => {
|
||||
config.watch = true;
|
||||
|
||||
return webpackStream(config, webpack)
|
||||
return webpackStream(config)
|
||||
.on('error', errorHandler)
|
||||
.pipe(gulp.dest('_output/UI'))
|
||||
.on('error', errorHandler)
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import BlacklistRowConnector from './BlacklistRowConnector';
|
||||
|
||||
class Blacklist extends Component {
|
||||
@@ -37,7 +36,7 @@ class Blacklist extends Component {
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label={translate('Clear')}
|
||||
label="Clear"
|
||||
iconName={icons.CLEAR}
|
||||
isSpinning={isClearingBlacklistExecuting}
|
||||
onPress={onClearBlacklistPress}
|
||||
@@ -50,14 +49,14 @@ class Blacklist extends Component {
|
||||
columns={columns}
|
||||
>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.TABLE}
|
||||
/>
|
||||
</TableOptionsModalWrapper>
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
|
||||
<PageContentBody>
|
||||
<PageContentBodyConnector>
|
||||
{
|
||||
isFetching && !isPopulated &&
|
||||
<LoadingIndicator />
|
||||
@@ -104,7 +103,7 @@ class Blacklist extends Component {
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ 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 { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import * as blacklistActions from 'Store/Actions/blacklistActions';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import Blacklist from './Blacklist';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Button from 'Components/Link/Button';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
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 ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
|
||||
class BlacklistDetailsModal extends Component {
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieFormats from 'Movie/MovieFormats';
|
||||
import MovieLanguage from 'Movie/MovieLanguage';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import BlacklistDetailsModal from './BlacklistDetailsModal';
|
||||
import styles from './BlacklistRow.css';
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription';
|
||||
import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
|
||||
import Link from 'Components/Link/Link';
|
||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||
import formatAge from 'Utilities/Number/formatAge';
|
||||
import Link from 'Components/Link/Link';
|
||||
import DescriptionList from 'Components/DescriptionList/DescriptionList';
|
||||
import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
|
||||
import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
|
||||
import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription';
|
||||
import styles from './HistoryDetails.css';
|
||||
|
||||
function HistoryDetails(props) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
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 { kinds } from 'Helpers/Props';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import HistoryDetails from './HistoryDetails';
|
||||
import styles from './HistoryDetailsModal.css';
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import HistoryRowConnector from './HistoryRowConnector';
|
||||
|
||||
class History extends Component {
|
||||
@@ -47,7 +46,7 @@ class History extends Component {
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label={translate('Refresh')}
|
||||
label="Refresh"
|
||||
iconName={icons.REFRESH}
|
||||
isSpinning={isFetching}
|
||||
onPress={onFirstPagePress}
|
||||
@@ -60,7 +59,7 @@ class History extends Component {
|
||||
columns={columns}
|
||||
>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.TABLE}
|
||||
/>
|
||||
</TableOptionsModalWrapper>
|
||||
@@ -75,7 +74,7 @@ class History extends Component {
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
|
||||
<PageContentBody>
|
||||
<PageContentBodyConnector>
|
||||
{
|
||||
isFetchingAny && !isAllPopulated &&
|
||||
<LoadingIndicator />
|
||||
@@ -126,7 +125,7 @@ class History extends Component {
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import * as historyActions from 'Store/Actions/historyActions';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import History from './History';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import styles from './HistoryEventTypeCell.css';
|
||||
|
||||
function getIconName(eventType) {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieFormats from 'Movie/MovieFormats';
|
||||
import MovieLanguage from 'Movie/MovieLanguage';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import HistoryDetailsModal from './Details/HistoryDetailsModal';
|
||||
import HistoryEventTypeCell from './HistoryEventTypeCell';
|
||||
import HistoryDetailsModal from './Details/HistoryDetailsModal';
|
||||
import styles from './HistoryRow.css';
|
||||
|
||||
class HistoryRow extends Component {
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import getRemovedItems from 'Utilities/Object/getRemovedItems';
|
||||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import TablePager from 'Components/Table/TablePager';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import RemoveQueueItemsModal from './RemoveQueueItemsModal';
|
||||
import QueueOptionsConnector from './QueueOptionsConnector';
|
||||
import QueueRowConnector from './QueueRowConnector';
|
||||
import RemoveQueueItemsModal from './RemoveQueueItemsModal';
|
||||
|
||||
class Queue extends Component {
|
||||
|
||||
@@ -153,7 +152,7 @@ class Queue extends Component {
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label={translate('Refresh')}
|
||||
label="Refresh"
|
||||
iconName={icons.REFRESH}
|
||||
isSpinning={isRefreshing}
|
||||
onPress={onRefreshPress}
|
||||
@@ -187,14 +186,14 @@ class Queue extends Component {
|
||||
optionsComponent={QueueOptionsConnector}
|
||||
>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.TABLE}
|
||||
/>
|
||||
</TableOptionsModalWrapper>
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
|
||||
<PageContentBody>
|
||||
<PageContentBodyConnector>
|
||||
{
|
||||
isRefreshing && !isAllPopulated &&
|
||||
<LoadingIndicator />
|
||||
@@ -251,7 +250,7 @@ class Queue extends Component {
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
|
||||
<RemoveQueueItemsModal
|
||||
isOpen={isConfirmRemoveModalOpen}
|
||||
|
||||
@@ -2,12 +2,12 @@ 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 { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import * as queueActions from 'Store/Actions/queueActions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import Queue from './Queue';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
|
||||
function QueueDetails(props) {
|
||||
const {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
|
||||
class QueueOptions extends Component {
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||
import ProgressBar from 'Components/ProgressBar';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
// import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import MovieFormats from 'Movie/MovieFormats';
|
||||
import MovieLanguage from 'Movie/MovieLanguage';
|
||||
import MovieQuality from 'Movie/MovieQuality';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import QueueStatusCell from './QueueStatusCell';
|
||||
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
||||
import TimeleftCell from './TimeleftCell';
|
||||
import RemoveQueueItemModal from './RemoveQueueItemModal';
|
||||
import styles from './QueueRow.css';
|
||||
|
||||
class QueueRow extends Component {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
||||
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 styles from './QueueStatusCell.css';
|
||||
|
||||
function getDetailedPopoverBody(statusMessages) {
|
||||
@@ -51,6 +51,10 @@ function QueueStatusCell(props) {
|
||||
let iconKind = kinds.DEFAULT;
|
||||
let title = 'Downloading';
|
||||
|
||||
if (hasWarning) {
|
||||
iconKind = kinds.WARNING;
|
||||
}
|
||||
|
||||
if (status === 'paused') {
|
||||
iconName = icons.PAUSED;
|
||||
title = 'Paused';
|
||||
@@ -67,24 +71,17 @@ function QueueStatusCell(props) {
|
||||
|
||||
if (trackedDownloadState === 'importPending') {
|
||||
title += ' - Waiting to Import';
|
||||
iconKind = kinds.PURPLE;
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'importing') {
|
||||
title += ' - Importing';
|
||||
iconKind = kinds.PURPLE;
|
||||
}
|
||||
|
||||
if (trackedDownloadState === 'failedPending') {
|
||||
title += ' - Waiting to Process';
|
||||
iconKind = kinds.DANGER;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasWarning) {
|
||||
iconKind = kinds.WARNING;
|
||||
}
|
||||
|
||||
if (status === 'delay') {
|
||||
iconName = icons.PENDING;
|
||||
title = 'Pending';
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
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 ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
|
||||
class RemoveQueueItemModal extends Component {
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
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 ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import styles from './RemoveQueueItemsModal.css';
|
||||
|
||||
class RemoveQueueItemsModal extends Component {
|
||||
|
||||
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus';
|
||||
import { fetchQueueStatus } from 'Store/Actions/queueActions';
|
||||
import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
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 TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import styles from './TimeleftCell.css';
|
||||
|
||||
function TimeleftCell(props) {
|
||||
@@ -19,7 +19,7 @@ function TimeleftCell(props) {
|
||||
timeFormat
|
||||
} = props;
|
||||
|
||||
if (status === 'delay') {
|
||||
if (status === 'Delay') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
@@ -33,7 +33,7 @@ function TimeleftCell(props) {
|
||||
);
|
||||
}
|
||||
|
||||
if (status === 'downloadClientUnavailable') {
|
||||
if (status === 'DownloadClientUnavailable') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
@@ -47,7 +47,7 @@ function TimeleftCell(props) {
|
||||
);
|
||||
}
|
||||
|
||||
if (!timeleft || status === 'completed' || status === 'failed') {
|
||||
if (!timeleft) {
|
||||
return (
|
||||
<TableRowCell className={styles.timeleft}>
|
||||
-
|
||||
|
||||
@@ -2,19 +2,18 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import withScrollPosition from 'Components/withScrollPosition';
|
||||
import { addMovies, addNetImportExclusions, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
|
||||
import scrollPositions from 'Store/scrollPositions';
|
||||
import createAddMovieClientSideCollectionItemsSelector from 'Store/Selectors/createAddMovieClientSideCollectionItemsSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createDiscoverMovieClientSideCollectionItemsSelector from 'Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchDiscoverMovies, clearAddMovie, setListMovieSort, setListMovieFilter, setListMovieView, setListMovieTableOption } from 'Store/Actions/addMovieActions';
|
||||
import scrollPositions from 'Store/scrollPositions';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import DiscoverMovie from './DiscoverMovie';
|
||||
import withScrollPosition from 'Components/withScrollPosition';
|
||||
import AddListMovie from './AddListMovie';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createDiscoverMovieClientSideCollectionItemsSelector('discoverMovie'),
|
||||
createAddMovieClientSideCollectionItemsSelector('addMovie'),
|
||||
createDimensionsSelector(),
|
||||
(
|
||||
movies,
|
||||
@@ -34,10 +33,6 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(fetchRootFolders());
|
||||
},
|
||||
|
||||
dispatchFetchNetImportExclusions() {
|
||||
dispatch(fetchNetImportExclusions());
|
||||
},
|
||||
|
||||
dispatchClearListMovie() {
|
||||
dispatch(clearAddMovie());
|
||||
},
|
||||
@@ -60,19 +55,11 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
|
||||
dispatchSetListMovieView(view) {
|
||||
dispatch(setListMovieView({ view }));
|
||||
},
|
||||
|
||||
dispatchAddMovies(ids, addOptions) {
|
||||
dispatch(addMovies({ ids, addOptions }));
|
||||
},
|
||||
|
||||
dispatchAddNetImportExclusions(exclusions) {
|
||||
dispatch(addNetImportExclusions(exclusions));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class DiscoverMovieConnector extends Component {
|
||||
class AddDiscoverMovieConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
@@ -80,7 +67,6 @@ class DiscoverMovieConnector extends Component {
|
||||
componentDidMount() {
|
||||
registerPagePopulator(this.repopulate);
|
||||
this.props.dispatchFetchRootFolders();
|
||||
this.props.dispatchFetchNetImportExclusions();
|
||||
this.props.dispatchFetchListMovies();
|
||||
}
|
||||
|
||||
@@ -97,15 +83,7 @@ class DiscoverMovieConnector extends Component {
|
||||
}
|
||||
|
||||
onScroll = ({ scrollTop }) => {
|
||||
scrollPositions.discoverMovie = scrollTop;
|
||||
}
|
||||
|
||||
onAddMoviesPress = ({ ids, addOptions }) => {
|
||||
this.props.dispatchAddMovies(ids, addOptions);
|
||||
}
|
||||
|
||||
onExcludeMoviesPress =({ ids }) => {
|
||||
this.props.dispatchAddNetImportExclusions({ ids });
|
||||
scrollPositions.addMovie = scrollTop;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -113,30 +91,26 @@ class DiscoverMovieConnector extends Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DiscoverMovie
|
||||
<AddListMovie
|
||||
{...this.props}
|
||||
onViewSelect={this.onViewSelect}
|
||||
onScroll={this.onScroll}
|
||||
onAddMoviesPress={this.onAddMoviesPress}
|
||||
onExcludeMoviesPress={this.onExcludeMoviesPress}
|
||||
onSaveSelected={this.onSaveSelected}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DiscoverMovieConnector.propTypes = {
|
||||
AddDiscoverMovieConnector.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
view: PropTypes.string.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,
|
||||
dispatchAddNetImportExclusions: PropTypes.func.isRequired
|
||||
dispatchSetListMovieView: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default withScrollPosition(
|
||||
connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieConnector),
|
||||
'discoverMovie'
|
||||
connect(createMapStateToProps, createMapDispatchToProps)(AddDiscoverMovieConnector),
|
||||
'addMovie'
|
||||
);
|
||||
@@ -1,32 +1,26 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItems';
|
||||
import { align, icons, sortDirections } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import PageJumpBar from 'Components/Page/PageJumpBar';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||
import { align, icons, sortDirections } from 'Helpers/Props';
|
||||
import styles from 'Movie/Index/MovieIndex.css';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import DiscoverMovieFooterConnector from './DiscoverMovieFooterConnector';
|
||||
import AddListMovieFilterMenu from './Menus/AddListMovieFilterMenu';
|
||||
import AddListMovieSortMenu from './Menus/AddListMovieSortMenu';
|
||||
import AddListMovieViewMenu from './Menus/AddListMovieViewMenu';
|
||||
import NoDiscoverMovie from './NoDiscoverMovie';
|
||||
import AddListMovieOverviewsConnector from './Overview/AddListMovieOverviewsConnector';
|
||||
import AddListMovieOverviewOptionsModal from './Overview/Options/AddListMovieOverviewOptionsModal';
|
||||
import AddListMoviePostersConnector from './Posters/AddListMoviePostersConnector';
|
||||
import AddListMoviePosterOptionsModal from './Posters/Options/AddListMoviePosterOptionsModal';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import AddListMovieTableConnector from './Table/AddListMovieTableConnector';
|
||||
import AddListMoviePosterOptionsModal from './Posters/Options/AddListMoviePosterOptionsModal';
|
||||
import AddListMoviePostersConnector from './Posters/AddListMoviePostersConnector';
|
||||
import AddListMovieOverviewOptionsModal from './Overview/Options/AddListMovieOverviewOptionsModal';
|
||||
import AddListMovieOverviewsConnector from './Overview/AddListMovieOverviewsConnector';
|
||||
import AddListMovieFilterMenu from 'AddMovie/AddListMovie/Menus/AddListMovieFilterMenu';
|
||||
import AddListMovieSortMenu from 'AddMovie/AddListMovie/Menus/AddListMovieSortMenu';
|
||||
import AddListMovieViewMenu from 'AddMovie/AddListMovie/Menus/AddListMovieViewMenu';
|
||||
import styles from 'Movie/Index/MovieIndex.css';
|
||||
|
||||
function getViewComponent(view) {
|
||||
if (view === 'posters') {
|
||||
@@ -40,7 +34,7 @@ function getViewComponent(view) {
|
||||
return AddListMovieTableConnector;
|
||||
}
|
||||
|
||||
class DiscoverMovie extends Component {
|
||||
class AddListMovie extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
@@ -56,16 +50,12 @@ class DiscoverMovie extends Component {
|
||||
isOverviewOptionsModalOpen: false,
|
||||
isConfirmSearchModalOpen: false,
|
||||
searchType: null,
|
||||
allSelected: false,
|
||||
allUnselected: false,
|
||||
lastToggled: null,
|
||||
selectedState: {}
|
||||
lastToggled: null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setJumpBarItems();
|
||||
this.setSelectedState();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -80,7 +70,6 @@ class DiscoverMovie extends Component {
|
||||
hasDifferentItemsOrOrder(prevProps.items, items)
|
||||
) {
|
||||
this.setJumpBarItems();
|
||||
this.setSelectedState();
|
||||
}
|
||||
|
||||
if (this.state.jumpToCharacter != null) {
|
||||
@@ -95,48 +84,6 @@ class DiscoverMovie extends Component {
|
||||
this.setState({ scroller: ref });
|
||||
}
|
||||
|
||||
getSelectedIds = () => {
|
||||
if (this.state.allUnselected) {
|
||||
return [];
|
||||
}
|
||||
return getSelectedIds(this.state.selectedState);
|
||||
}
|
||||
|
||||
setSelectedState() {
|
||||
const {
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
selectedState
|
||||
} = this.state;
|
||||
|
||||
const newSelectedState = {};
|
||||
|
||||
items.forEach((movie) => {
|
||||
const isItemSelected = selectedState[movie.tmdbId];
|
||||
|
||||
if (isItemSelected) {
|
||||
newSelectedState[movie.tmdbId] = isItemSelected;
|
||||
} else {
|
||||
newSelectedState[movie.tmdbId] = false;
|
||||
}
|
||||
});
|
||||
|
||||
const selectedCount = getSelectedIds(newSelectedState).length;
|
||||
const newStateCount = Object.keys(newSelectedState).length;
|
||||
let isAllSelected = false;
|
||||
let isAllUnselected = false;
|
||||
|
||||
if (selectedCount === 0) {
|
||||
isAllUnselected = true;
|
||||
} else if (selectedCount === newStateCount) {
|
||||
isAllSelected = true;
|
||||
}
|
||||
|
||||
this.setState({ selectedState: newSelectedState, allSelected: isAllSelected, allUnselected: isAllUnselected });
|
||||
}
|
||||
|
||||
setJumpBarItems() {
|
||||
const {
|
||||
items,
|
||||
@@ -204,28 +151,6 @@ class DiscoverMovie extends Component {
|
||||
this.setState({ jumpToCharacter });
|
||||
}
|
||||
|
||||
onSelectAllChange = ({ value }) => {
|
||||
this.setState(selectAll(this.state.selectedState, value));
|
||||
}
|
||||
|
||||
onSelectAllPress = () => {
|
||||
this.onSelectAllChange({ value: !this.state.allSelected });
|
||||
}
|
||||
|
||||
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
||||
this.setState((state) => {
|
||||
return toggleSelected(state, this.props.items, id, value, shiftKey, 'tmdbId');
|
||||
});
|
||||
}
|
||||
|
||||
onAddMoviesPress = ({ addOptions }) => {
|
||||
this.props.onAddMoviesPress({ ids: this.getSelectedIds(), addOptions });
|
||||
}
|
||||
|
||||
onExcludeMoviesPress = () => {
|
||||
this.props.onExcludeMoviesPress({ ids: this.getSelectedIds() });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
@@ -247,7 +172,6 @@ class DiscoverMovie extends Component {
|
||||
onFilterSelect,
|
||||
onViewSelect,
|
||||
onScroll,
|
||||
onAddMoviesPress,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
@@ -256,14 +180,9 @@ class DiscoverMovie extends Component {
|
||||
jumpBarItems,
|
||||
jumpToCharacter,
|
||||
isPosterOptionsModalOpen,
|
||||
isOverviewOptionsModalOpen,
|
||||
selectedState,
|
||||
allSelected,
|
||||
allUnselected
|
||||
isOverviewOptionsModalOpen
|
||||
} = this.state;
|
||||
|
||||
const selectedMovieIds = this.getSelectedIds();
|
||||
|
||||
const ViewComponent = getViewComponent(view);
|
||||
const isLoaded = !!(!error && isPopulated && items.length && scroller);
|
||||
const hasNoMovie = !totalItems;
|
||||
@@ -271,15 +190,6 @@ class DiscoverMovie extends Component {
|
||||
return (
|
||||
<PageContent>
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label={allSelected ? 'Unselect All' : 'Select All'}
|
||||
iconName={icons.CHECK_SQUARE}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onSelectAllPress}
|
||||
/>
|
||||
</PageToolbarSection>
|
||||
|
||||
<PageToolbarSection
|
||||
alignContent={align.RIGHT}
|
||||
collapseButtons={false}
|
||||
@@ -291,7 +201,7 @@ class DiscoverMovie extends Component {
|
||||
columns={columns}
|
||||
>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.TABLE}
|
||||
/>
|
||||
</TableOptionsModalWrapper> :
|
||||
@@ -301,7 +211,7 @@ class DiscoverMovie extends Component {
|
||||
{
|
||||
view === 'posters' ?
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.POSTER}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onPosterOptionsPress}
|
||||
@@ -312,7 +222,7 @@ class DiscoverMovie extends Component {
|
||||
{
|
||||
view === 'overview' ?
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.OVERVIEW}
|
||||
isDisabled={hasNoMovie}
|
||||
onPress={this.onOverviewOptionsPress}
|
||||
@@ -349,7 +259,7 @@ class DiscoverMovie extends Component {
|
||||
</PageToolbar>
|
||||
|
||||
<div className={styles.pageContentBodyWrapper}>
|
||||
<PageContentBody
|
||||
<PageContentBodyConnector
|
||||
registerScroller={this.setScrollerRef}
|
||||
className={styles.contentBody}
|
||||
innerClassName={styles[`${view}InnerContentBody`]}
|
||||
@@ -375,11 +285,6 @@ class DiscoverMovie extends Component {
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
jumpToCharacter={jumpToCharacter}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
onSelectAllChange={this.onSelectAllChange}
|
||||
selectedState={selectedState}
|
||||
{...otherProps}
|
||||
/>
|
||||
</div>
|
||||
@@ -387,9 +292,11 @@ class DiscoverMovie extends Component {
|
||||
|
||||
{
|
||||
!error && isPopulated && !items.length &&
|
||||
<NoDiscoverMovie totalItems={totalItems} />
|
||||
<div className={styles.message}>
|
||||
<div className={styles.noResults}>Couldn't find any results</div>
|
||||
</div>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
|
||||
{
|
||||
isLoaded && !!jumpBarItems.order.length &&
|
||||
@@ -400,15 +307,6 @@ class DiscoverMovie extends Component {
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
isLoaded &&
|
||||
<DiscoverMovieFooterConnector
|
||||
selectedIds={selectedMovieIds}
|
||||
onAddMoviesPress={this.onAddMoviesPress}
|
||||
onExcludeMoviesPress={this.onExcludeMoviesPress}
|
||||
/>
|
||||
}
|
||||
|
||||
<AddListMoviePosterOptionsModal
|
||||
isOpen={isPosterOptionsModalOpen}
|
||||
onModalClose={this.onPosterOptionsModalClose}
|
||||
@@ -423,7 +321,7 @@ class DiscoverMovie extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
DiscoverMovie.propTypes = {
|
||||
AddListMovie.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
@@ -440,9 +338,7 @@ DiscoverMovie.propTypes = {
|
||||
onSortSelect: PropTypes.func.isRequired,
|
||||
onFilterSelect: PropTypes.func.isRequired,
|
||||
onViewSelect: PropTypes.func.isRequired,
|
||||
onScroll: PropTypes.func.isRequired,
|
||||
onAddMoviesPress: PropTypes.func.isRequired,
|
||||
onExcludeMoviesPress: PropTypes.func.isRequired
|
||||
onScroll: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default DiscoverMovie;
|
||||
export default AddListMovie;
|
||||
113
frontend/src/AddMovie/AddListMovie/AddListMovieConnector.js
Normal file
113
frontend/src/AddMovie/AddListMovie/AddListMovieConnector.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createAddMovieClientSideCollectionItemsSelector from 'Store/Selectors/createAddMovieClientSideCollectionItemsSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchListMovies, clearAddMovie, setListMovieSort, setListMovieFilter, setListMovieView, setListMovieTableOption } from 'Store/Actions/addMovieActions';
|
||||
import scrollPositions from 'Store/scrollPositions';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import withScrollPosition from 'Components/withScrollPosition';
|
||||
import AddListMovie from './AddListMovie';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createAddMovieClientSideCollectionItemsSelector('addMovie'),
|
||||
createDimensionsSelector(),
|
||||
(
|
||||
movies,
|
||||
dimensionsState
|
||||
) => {
|
||||
return {
|
||||
...movies,
|
||||
isSmallScreen: dimensionsState.isSmallScreen
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
dispatchFetchRootFolders() {
|
||||
dispatch(fetchRootFolders());
|
||||
},
|
||||
|
||||
dispatchFetchListMovies() {
|
||||
dispatch(fetchListMovies());
|
||||
},
|
||||
|
||||
onTableOptionChange(payload) {
|
||||
dispatch(setListMovieTableOption(payload));
|
||||
},
|
||||
|
||||
onSortSelect(sortKey) {
|
||||
dispatch(setListMovieSort({ sortKey }));
|
||||
},
|
||||
|
||||
onFilterSelect(selectedFilterKey) {
|
||||
dispatch(setListMovieFilter({ selectedFilterKey }));
|
||||
},
|
||||
|
||||
dispatchSetListMovieView(view) {
|
||||
dispatch(setListMovieView({ view }));
|
||||
},
|
||||
|
||||
dispatchClearListMovie() {
|
||||
dispatch(clearAddMovie());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class AddListMovieConnector extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
registerPagePopulator(this.repopulate);
|
||||
this.props.dispatchFetchRootFolders();
|
||||
this.props.dispatchFetchListMovies();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.dispatchClearListMovie();
|
||||
unregisterPagePopulator(this.repopulate);
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onViewSelect = (view) => {
|
||||
this.props.dispatchSetListMovieView(view);
|
||||
}
|
||||
|
||||
onScroll = ({ scrollTop }) => {
|
||||
scrollPositions.addMovie = scrollTop;
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<AddListMovie
|
||||
{...this.props}
|
||||
onViewSelect={this.onViewSelect}
|
||||
onScroll={this.onScroll}
|
||||
onSaveSelected={this.onSaveSelected}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddListMovieConnector.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
view: PropTypes.string.isRequired,
|
||||
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
||||
dispatchFetchListMovies: PropTypes.func.isRequired,
|
||||
dispatchClearListMovie: PropTypes.func.isRequired,
|
||||
dispatchSetListMovieView: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default withScrollPosition(
|
||||
connect(createMapStateToProps, createMapDispatchToProps)(AddListMovieConnector),
|
||||
'addMovie'
|
||||
);
|
||||
@@ -1,17 +1,17 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setListMovieFilter } from 'Store/Actions/addMovieActions';
|
||||
import FilterModal from 'Components/Filter/FilterModal';
|
||||
import { setListMovieFilter } from 'Store/Actions/discoverMovieActions';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie.items,
|
||||
(state) => state.discoverMovie.filterBuilderProps,
|
||||
(state) => state.addMovie.items,
|
||||
(state) => state.addMovie.filterBuilderProps,
|
||||
(sectionItems, filterBuilderProps) => {
|
||||
return {
|
||||
sectionItems,
|
||||
filterBuilderProps,
|
||||
customFilterType: 'discoverMovie'
|
||||
customFilterType: 'addMovie'
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -2,13 +2,16 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createDiscoverMovieSelector from 'Store/Selectors/createDiscoverMovieSelector';
|
||||
import createAddListMovieSelector from 'Store/Selectors/createAddListMovieSelector';
|
||||
import createMovieQualityProfileSelector from 'Store/Selectors/createMovieQualityProfileSelector';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createDiscoverMovieSelector(),
|
||||
createAddListMovieSelector(),
|
||||
createMovieQualityProfileSelector(),
|
||||
(
|
||||
movie
|
||||
movie,
|
||||
qualityProfile
|
||||
) => {
|
||||
|
||||
// If a movie is deleted this selector may fire before the parent
|
||||
@@ -21,12 +24,16 @@ function createMapStateToProps() {
|
||||
}
|
||||
|
||||
return {
|
||||
...movie
|
||||
...movie,
|
||||
qualityProfile
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
};
|
||||
|
||||
class AddListMovieItemConnector extends Component {
|
||||
|
||||
//
|
||||
@@ -57,4 +64,4 @@ AddListMovieItemConnector.propTypes = {
|
||||
component: PropTypes.elementType.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(AddListMovieItemConnector);
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(AddListMovieItemConnector);
|
||||
@@ -1,8 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import AddListMovieFilterModalConnector from 'DiscoverMovie/AddListMovieFilterModalConnector';
|
||||
import { align } from 'Helpers/Props';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import AddListMovieFilterModalConnector from 'AddMovie/AddListMovie/AddListMovieFilterModalConnector';
|
||||
|
||||
function AddListMovieFilterMenu(props) {
|
||||
const {
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import MenuContent from 'Components/Menu/MenuContent';
|
||||
import SortMenu from 'Components/Menu/SortMenu';
|
||||
import SortMenuItem from 'Components/Menu/SortMenuItem';
|
||||
import { align, sortDirections } from 'Helpers/Props';
|
||||
import SortMenu from 'Components/Menu/SortMenu';
|
||||
import MenuContent from 'Components/Menu/MenuContent';
|
||||
import SortMenuItem from 'Components/Menu/SortMenuItem';
|
||||
|
||||
function AddListMovieSortMenu(props) {
|
||||
const {
|
||||
@@ -63,24 +63,6 @@ function AddListMovieSortMenu(props) {
|
||||
>
|
||||
Physical Release
|
||||
</SortMenuItem>
|
||||
|
||||
<SortMenuItem
|
||||
name="ratings"
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onPress={onSortSelect}
|
||||
>
|
||||
Rating
|
||||
</SortMenuItem>
|
||||
|
||||
<SortMenuItem
|
||||
name="certification"
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onPress={onSortSelect}
|
||||
>
|
||||
Certification
|
||||
</SortMenuItem>
|
||||
</MenuContent>
|
||||
</SortMenu>
|
||||
);
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import MenuContent from 'Components/Menu/MenuContent';
|
||||
import ViewMenu from 'Components/Menu/ViewMenu';
|
||||
import ViewMenuItem from 'Components/Menu/ViewMenuItem';
|
||||
import { align } from 'Helpers/Props';
|
||||
import ViewMenu from 'Components/Menu/ViewMenu';
|
||||
import MenuContent from 'Components/Menu/MenuContent';
|
||||
import ViewMenuItem from 'Components/Menu/ViewMenuItem';
|
||||
|
||||
function AddListMovieViewMenu(props) {
|
||||
const {
|
||||
@@ -1,5 +1,13 @@
|
||||
$hoverScale: 1.05;
|
||||
|
||||
.container {
|
||||
&:hover {
|
||||
.content {
|
||||
background-color: $tableRowHoverBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
@@ -9,13 +17,6 @@ $hoverScale: 1.05;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.editorSelect {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 5px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.posterContainer {
|
||||
position: relative;
|
||||
}
|
||||
@@ -32,10 +33,17 @@ $hoverScale: 1.05;
|
||||
}
|
||||
}
|
||||
|
||||
.exclusionIcon {
|
||||
margin-left: 10px;
|
||||
color: $dangerColor;
|
||||
pointer-events: all;
|
||||
.ended {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: 0 25px 25px 0;
|
||||
border-style: solid;
|
||||
border-color: transparent $dangerColor transparent transparent;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.info {
|
||||
@@ -51,6 +59,8 @@ $hoverScale: 1.05;
|
||||
justify-content: space-between;
|
||||
flex: 0 0 auto;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 300;
|
||||
font-size: 30px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import TextTruncate from 'react-text-truncate';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import Icon from 'Components/Icon';
|
||||
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 } 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 MoviePoster from 'Movie/MoviePoster';
|
||||
import Link from 'Components/Link/Link';
|
||||
import AddNewMovieModal from 'AddMovie/AddNewMovie/AddNewMovieModal';
|
||||
import styles from './AddListMovieOverview.css';
|
||||
|
||||
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
|
||||
@@ -39,8 +32,7 @@ class AddListMovieOverview extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isNewAddMovieModalOpen: false,
|
||||
isExcludeMovieModalOpen: false
|
||||
isNewAddMovieModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -55,31 +47,12 @@ class AddListMovieOverview extends Component {
|
||||
this.setState({ isNewAddMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onExcludeMoviePress = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: true });
|
||||
}
|
||||
|
||||
onExcludeMovieModalClose = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onChange = ({ value, shiftKey }) => {
|
||||
const {
|
||||
tmdbId,
|
||||
onSelectedChange
|
||||
} = this.props;
|
||||
|
||||
onSelectedChange({ id: tmdbId, value, shiftKey });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
tmdbId,
|
||||
imdbId,
|
||||
youTubeTrailerId,
|
||||
title,
|
||||
titleSlug,
|
||||
folder,
|
||||
@@ -90,14 +63,11 @@ class AddListMovieOverview extends Component {
|
||||
posterHeight,
|
||||
rowHeight,
|
||||
isSmallScreen,
|
||||
isExisting,
|
||||
isExcluded,
|
||||
isSelected
|
||||
isExistingMovie
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
isNewAddMovieModalOpen,
|
||||
isExcludeMovieModalOpen
|
||||
isNewAddMovieModalOpen
|
||||
} = this.state;
|
||||
|
||||
const elementStyle = {
|
||||
@@ -105,24 +75,19 @@ class AddListMovieOverview extends Component {
|
||||
height: `${posterHeight}px`
|
||||
};
|
||||
|
||||
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
|
||||
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
|
||||
const overviewHeight = contentHeight - titleRowHeight;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
<Link
|
||||
className={styles.content}
|
||||
{...linkProps}
|
||||
>
|
||||
<div className={styles.poster}>
|
||||
<div className={styles.posterContainer}>
|
||||
<div className={styles.editorSelect}>
|
||||
<CheckInput
|
||||
className={styles.checkInput}
|
||||
name={tmdbId.toString()}
|
||||
value={isSelected}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<MoviePoster
|
||||
className={styles.poster}
|
||||
@@ -137,50 +102,7 @@ class AddListMovieOverview extends Component {
|
||||
|
||||
<div className={styles.info} style={{ maxHeight: contentHeight }}>
|
||||
<div className={styles.titleRow}>
|
||||
<Link
|
||||
className={styles.title}
|
||||
{...linkProps}
|
||||
>
|
||||
{title}({year})
|
||||
|
||||
{
|
||||
isExcluded &&
|
||||
<Icon
|
||||
className={styles.exclusionIcon}
|
||||
name={icons.DANGER}
|
||||
size={36}
|
||||
title='Movie is on Net Import Exclusion List'
|
||||
/>
|
||||
}
|
||||
</Link>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<span className={styles.externalLinks}>
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={12}
|
||||
/>
|
||||
}
|
||||
title="Links"
|
||||
body={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
imdbId={imdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
|
||||
<IconButton
|
||||
name={icons.REMOVE}
|
||||
title={isExcluded ? 'Movie already Excluded' : 'Exclude Movie'}
|
||||
onPress={this.onExcludeMoviePress}
|
||||
isDisabled={isExcluded}
|
||||
/>
|
||||
</div>
|
||||
{title} ({year})
|
||||
</div>
|
||||
|
||||
<div className={styles.details}>
|
||||
@@ -191,10 +113,10 @@ class AddListMovieOverview extends Component {
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<AddNewDiscoverMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExisting}
|
||||
<AddNewMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExistingMovie}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
@@ -203,14 +125,6 @@ class AddListMovieOverview extends Component {
|
||||
images={images}
|
||||
onModalClose={this.onAddMovieModalClose}
|
||||
/>
|
||||
|
||||
<ExcludeMovieModal
|
||||
isOpen={isExcludeMovieModalOpen}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
onModalClose={this.onExcludeMovieModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -218,12 +132,11 @@ class AddListMovieOverview extends Component {
|
||||
|
||||
AddListMovieOverview.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
youTubeTrailerId: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
folder: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
overview: PropTypes.string.isRequired,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
@@ -236,10 +149,8 @@ AddListMovieOverview.propTypes = {
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
isExisting: PropTypes.bool.isRequired,
|
||||
isExcluded: PropTypes.bool.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
isExistingMovie: PropTypes.bool.isRequired,
|
||||
isExclusionMovie: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default AddListMovieOverview;
|
||||
@@ -1,13 +1,19 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector';
|
||||
import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddListMovieOverview from './AddListMovieOverview';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingMovieSelector(),
|
||||
createExclusionMovieSelector(),
|
||||
createDimensionsSelector(),
|
||||
(dimensions) => {
|
||||
(isExistingMovie, isExclusionMovie, dimensions) => {
|
||||
return {
|
||||
isExistingMovie,
|
||||
isExclusionMovie,
|
||||
isSmallScreen: dimensions.isSmallScreen
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { Grid, WindowScroller } from 'react-virtualized';
|
||||
import Measure from 'Components/Measure';
|
||||
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItems';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import Measure from 'Components/Measure';
|
||||
import AddListMovieItemConnector from 'AddMovie/AddListMovie/AddListMovieItemConnector';
|
||||
import AddListMovieOverviewConnector from './AddListMovieOverviewConnector';
|
||||
import styles from './AddListMovieOverviews.css';
|
||||
|
||||
@@ -81,7 +81,7 @@ class AddListMovieOverviews extends Component {
|
||||
if (this._grid &&
|
||||
(prevState.width !== width ||
|
||||
prevState.rowHeight !== rowHeight ||
|
||||
hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId'))) {
|
||||
hasDifferentItemsOrOrder(prevProps.items, items))) {
|
||||
// recomputeGridSize also forces Grid to discard its cache of rendered cells
|
||||
this._grid.recomputeGridSize();
|
||||
}
|
||||
@@ -133,9 +133,7 @@ class AddListMovieOverviews extends Component {
|
||||
shortDateFormat,
|
||||
longDateFormat,
|
||||
timeFormat,
|
||||
isSmallScreen,
|
||||
selectedState,
|
||||
onSelectedChange
|
||||
isSmallScreen
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -157,7 +155,7 @@ class AddListMovieOverviews extends Component {
|
||||
style={style}
|
||||
>
|
||||
<AddListMovieItemConnector
|
||||
key={movie.tmdbId}
|
||||
key={movie.id}
|
||||
component={AddListMovieOverviewConnector}
|
||||
sortKey={sortKey}
|
||||
posterWidth={posterWidth}
|
||||
@@ -170,8 +168,6 @@ class AddListMovieOverviews extends Component {
|
||||
timeFormat={timeFormat}
|
||||
isSmallScreen={isSmallScreen}
|
||||
movieId={movie.tmdbId}
|
||||
isSelected={selectedState[movie.tmdbId]}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -191,8 +187,7 @@ class AddListMovieOverviews extends Component {
|
||||
const {
|
||||
isSmallScreen,
|
||||
scroller,
|
||||
items,
|
||||
selectedState
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -229,7 +224,6 @@ class AddListMovieOverviews extends Component {
|
||||
scrollTop={scrollTop}
|
||||
overscanRowCount={2}
|
||||
cellRenderer={this.cellRenderer}
|
||||
selectedState={selectedState}
|
||||
scrollToAlignment={'start'}
|
||||
isScrollingOptout={true}
|
||||
/>
|
||||
@@ -253,9 +247,7 @@ AddListMovieOverviews.propTypes = {
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
selectedState: PropTypes.object.isRequired,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
timeFormat: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default AddListMovieOverviews;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddListMovieOverviews from './AddListMovieOverviews';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie.overviewOptions,
|
||||
(state) => state.addMovie.overviewOptions,
|
||||
createUISettingsSelector(),
|
||||
createDimensionsSelector(),
|
||||
(overviewOptions, uiSettings, dimensions) => {
|
||||
@@ -1,16 +1,16 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import Button from 'Components/Link/Button';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
|
||||
const posterSizeOptions = [
|
||||
{ key: 'small', value: 'Small' },
|
||||
@@ -1,13 +1,13 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setListMovieOverviewOption } from 'Store/Actions/discoverMovieActions';
|
||||
import { setListMovieOverviewOption } from 'Store/Actions/addMovieActions';
|
||||
import AddListMovieOverviewOptionsModalContent from './AddListMovieOverviewOptionsModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie,
|
||||
(discoverMovie) => {
|
||||
return discoverMovie.overviewOptions;
|
||||
(state) => state.addMovie,
|
||||
(addMovie) => {
|
||||
return addMovie.overviewOptions;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
$hoverScale: 1.05;
|
||||
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
transition: all 200ms ease-in;
|
||||
|
||||
@@ -27,11 +31,6 @@ $hoverScale: 1.05;
|
||||
background-color: $defaultColor;
|
||||
}
|
||||
|
||||
.externalLinks {
|
||||
margin-right: 0.5em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.overlayTitle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -55,11 +54,10 @@ $hoverScale: 1.05;
|
||||
font-size: $smallFontSize;
|
||||
}
|
||||
|
||||
.excluded {
|
||||
.ended {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: 0 25px 25px 0;
|
||||
@@ -81,13 +79,6 @@ $hoverScale: 1.05;
|
||||
transition: opacity 0;
|
||||
}
|
||||
|
||||
.editorSelect {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.action {
|
||||
composes: button from '~Components/Link/IconButton.css';
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import Icon from 'Components/Icon';
|
||||
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 } from 'Helpers/Props';
|
||||
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import AddNewMovieModal from 'AddMovie/AddNewMovie/AddNewMovieModal';
|
||||
import styles from './AddListMoviePoster.css';
|
||||
|
||||
class AddListMoviePoster extends Component {
|
||||
@@ -23,8 +15,7 @@ class AddListMoviePoster extends Component {
|
||||
|
||||
this.state = {
|
||||
hasPosterError: false,
|
||||
isNewAddMovieModalOpen: false,
|
||||
isExcludeMovieModalOpen: false
|
||||
isNewAddMovieModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,14 +30,6 @@ class AddListMoviePoster extends Component {
|
||||
this.setState({ isNewAddMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onExcludeMoviePress = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: true });
|
||||
}
|
||||
|
||||
onExcludeMovieModalClose = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onPosterLoad = () => {
|
||||
if (this.state.hasPosterError) {
|
||||
this.setState({ hasPosterError: false });
|
||||
@@ -59,44 +42,31 @@ class AddListMoviePoster extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
onChange = ({ value, shiftKey }) => {
|
||||
const {
|
||||
tmdbId,
|
||||
onSelectedChange
|
||||
} = this.props;
|
||||
|
||||
onSelectedChange({ id: tmdbId, value, shiftKey });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
tmdbId,
|
||||
imdbId,
|
||||
youTubeTrailerId,
|
||||
title,
|
||||
year,
|
||||
overview,
|
||||
folder,
|
||||
status,
|
||||
titleSlug,
|
||||
images,
|
||||
posterWidth,
|
||||
posterHeight,
|
||||
showTitle,
|
||||
isExisting,
|
||||
isExcluded,
|
||||
isSelected
|
||||
isExistingMovie
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
hasPosterError,
|
||||
isNewAddMovieModalOpen,
|
||||
isExcludeMovieModalOpen
|
||||
isNewAddMovieModalOpen
|
||||
} = this.state;
|
||||
|
||||
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
|
||||
const elementStyle = {
|
||||
width: `${posterWidth}px`,
|
||||
@@ -107,49 +77,10 @@ class AddListMoviePoster extends Component {
|
||||
<div className={styles.content}>
|
||||
<div className={styles.posterContainer}>
|
||||
{
|
||||
<div className={styles.editorSelect}>
|
||||
<CheckInput
|
||||
className={styles.checkInput}
|
||||
name={tmdbId.toString()}
|
||||
value={isSelected}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<Label className={styles.controls}>
|
||||
<IconButton
|
||||
className={styles.action}
|
||||
name={icons.REMOVE}
|
||||
title={isExcluded ? 'Movie already Excluded' : 'Exclude Movie'}
|
||||
onPress={this.onExcludeMoviePress}
|
||||
isDisabled={isExcluded}
|
||||
/>
|
||||
<span className={styles.externalLinks}>
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={12}
|
||||
/>
|
||||
}
|
||||
title="Links"
|
||||
body={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
imdbId={imdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
</Label>
|
||||
|
||||
{
|
||||
isExcluded &&
|
||||
status === 'ended' &&
|
||||
<div
|
||||
className={styles.excluded}
|
||||
title="Exluded"
|
||||
className={styles.ended}
|
||||
title="Ended"
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -185,8 +116,8 @@ class AddListMoviePoster extends Component {
|
||||
</div>
|
||||
}
|
||||
|
||||
<AddNewDiscoverMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExisting}
|
||||
<AddNewMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExistingMovie}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
@@ -195,14 +126,6 @@ class AddListMoviePoster extends Component {
|
||||
images={images}
|
||||
onModalClose={this.onAddMovieModalClose}
|
||||
/>
|
||||
|
||||
<ExcludeMovieModal
|
||||
isOpen={isExcludeMovieModalOpen}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
onModalClose={this.onExcludeMovieModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -210,8 +133,6 @@ class AddListMoviePoster extends Component {
|
||||
|
||||
AddListMoviePoster.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
youTubeTrailerId: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
overview: PropTypes.string.isRequired,
|
||||
@@ -225,10 +146,14 @@ AddListMoviePoster.propTypes = {
|
||||
showRelativeDates: PropTypes.bool.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
isExisting: PropTypes.bool.isRequired,
|
||||
isExcluded: PropTypes.bool.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
isExistingMovie: PropTypes.bool.isRequired,
|
||||
isExclusionMovie: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
AddListMoviePoster.defaultProps = {
|
||||
statistics: {
|
||||
movieFileCount: 0
|
||||
}
|
||||
};
|
||||
|
||||
export default AddListMoviePoster;
|
||||
@@ -1,13 +1,19 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector';
|
||||
import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddListMoviePoster from './AddListMoviePoster';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingMovieSelector(),
|
||||
createExclusionMovieSelector(),
|
||||
createDimensionsSelector(),
|
||||
( dimensions) => {
|
||||
(isExistingMovie, isExclusionMovie, dimensions) => {
|
||||
return {
|
||||
isExistingMovie,
|
||||
isExclusionMovie,
|
||||
isSmallScreen: dimensions.isSmallScreen
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.grid {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { Grid, WindowScroller } from 'react-virtualized';
|
||||
import Measure from 'Components/Measure';
|
||||
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
|
||||
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItems';
|
||||
import dimensions from 'Styles/Variables/dimensions';
|
||||
import Measure from 'Components/Measure';
|
||||
import AddListMovieItemConnector from 'AddMovie/AddListMovie/AddListMovieItemConnector';
|
||||
import AddListMoviePosterConnector from './AddListMoviePosterConnector';
|
||||
import styles from './AddListMoviePosters.css';
|
||||
|
||||
@@ -36,7 +36,9 @@ function calculateColumnWidth(width, posterSize, isSmallScreen) {
|
||||
function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions) {
|
||||
const {
|
||||
detailedProgressBar,
|
||||
showTitle
|
||||
showTitle,
|
||||
showMonitored,
|
||||
showQualityProfile
|
||||
} = posterOptions;
|
||||
|
||||
const nextAiringHeight = 19;
|
||||
@@ -52,6 +54,14 @@ function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions)
|
||||
heights.push(19);
|
||||
}
|
||||
|
||||
if (showMonitored) {
|
||||
heights.push(19);
|
||||
}
|
||||
|
||||
if (showQualityProfile) {
|
||||
heights.push(19);
|
||||
}
|
||||
|
||||
switch (sortKey) {
|
||||
case 'studio':
|
||||
default:
|
||||
@@ -84,7 +94,6 @@ class AddListMoviePosters extends Component {
|
||||
|
||||
this._isInitialized = false;
|
||||
this._grid = null;
|
||||
this._padding = props.isSmallScreen ? columnPaddingSmallScreen : columnPadding;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
@@ -92,9 +101,7 @@ class AddListMoviePosters extends Component {
|
||||
items,
|
||||
sortKey,
|
||||
posterOptions,
|
||||
jumpToCharacter,
|
||||
isSmallScreen,
|
||||
selectedState
|
||||
jumpToCharacter
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -106,7 +113,7 @@ class AddListMoviePosters extends Component {
|
||||
|
||||
if (prevProps.sortKey !== sortKey ||
|
||||
prevProps.posterOptions !== posterOptions) {
|
||||
this.calculateGrid(width, isSmallScreen);
|
||||
this.calculateGrid();
|
||||
}
|
||||
|
||||
if (this._grid &&
|
||||
@@ -114,8 +121,7 @@ class AddListMoviePosters extends Component {
|
||||
prevState.columnWidth !== columnWidth ||
|
||||
prevState.columnCount !== columnCount ||
|
||||
prevState.rowHeight !== rowHeight ||
|
||||
prevProps.selectedState !== selectedState ||
|
||||
hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId'))) {
|
||||
hasDifferentItemsOrOrder(prevProps.items, items))) {
|
||||
// recomputeGridSize also forces Grid to discard its cache of rendered cells
|
||||
this._grid.recomputeGridSize();
|
||||
}
|
||||
@@ -147,9 +153,10 @@ class AddListMoviePosters extends Component {
|
||||
posterOptions
|
||||
} = this.props;
|
||||
|
||||
const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding;
|
||||
const columnWidth = calculateColumnWidth(width, posterOptions.size, isSmallScreen);
|
||||
const columnCount = Math.max(Math.floor(width / columnWidth), 1);
|
||||
const posterWidth = columnWidth - this._padding * 2;
|
||||
const posterWidth = columnWidth - padding;
|
||||
const posterHeight = calculatePosterHeight(posterWidth);
|
||||
const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions);
|
||||
|
||||
@@ -170,9 +177,7 @@ class AddListMoviePosters extends Component {
|
||||
posterOptions,
|
||||
showRelativeDates,
|
||||
shortDateFormat,
|
||||
timeFormat,
|
||||
selectedState,
|
||||
onSelectedChange
|
||||
timeFormat
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -185,8 +190,7 @@ class AddListMoviePosters extends Component {
|
||||
showTitle
|
||||
} = posterOptions;
|
||||
|
||||
const movieIdx = rowIndex * columnCount + columnIndex;
|
||||
const movie = items[movieIdx];
|
||||
const movie = items[rowIndex * columnCount + columnIndex];
|
||||
|
||||
if (!movie) {
|
||||
return null;
|
||||
@@ -194,15 +198,11 @@ class AddListMoviePosters extends Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
key={key}
|
||||
style={{
|
||||
...style,
|
||||
padding: this._padding
|
||||
}}
|
||||
style={style}
|
||||
>
|
||||
<AddListMovieItemConnector
|
||||
key={movie.tmdbId}
|
||||
key={movie.id}
|
||||
component={AddListMoviePosterConnector}
|
||||
sortKey={sortKey}
|
||||
posterWidth={posterWidth}
|
||||
@@ -212,8 +212,6 @@ class AddListMoviePosters extends Component {
|
||||
shortDateFormat={shortDateFormat}
|
||||
timeFormat={timeFormat}
|
||||
movieId={movie.tmdbId}
|
||||
isSelected={selectedState[movie.tmdbId]}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -233,8 +231,7 @@ class AddListMoviePosters extends Component {
|
||||
const {
|
||||
isSmallScreen,
|
||||
scroller,
|
||||
items,
|
||||
selectedState
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@@ -275,7 +272,6 @@ class AddListMoviePosters extends Component {
|
||||
scrollTop={scrollTop}
|
||||
overscanRowCount={2}
|
||||
cellRenderer={this.cellRenderer}
|
||||
selectedState={selectedState}
|
||||
scrollToAlignment={'start'}
|
||||
isScrollingOptOut={true}
|
||||
/>
|
||||
@@ -298,9 +294,7 @@ AddListMoviePosters.propTypes = {
|
||||
showRelativeDates: PropTypes.bool.isRequired,
|
||||
shortDateFormat: PropTypes.string.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
selectedState: PropTypes.object.isRequired,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
timeFormat: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default AddListMoviePosters;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddListMoviePosters from './AddListMoviePosters';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie.posterOptions,
|
||||
(state) => state.addMovie.posterOptions,
|
||||
createUISettingsSelector(),
|
||||
createDimensionsSelector(),
|
||||
(posterOptions, uiSettings, dimensions) => {
|
||||
@@ -1,16 +1,16 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import Button from 'Components/Link/Button';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
|
||||
const posterSizeOptions = [
|
||||
{ key: 'small', value: 'Small' },
|
||||
@@ -1,13 +1,13 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setListMoviePosterOption } from 'Store/Actions/discoverMovieActions';
|
||||
import { setListMoviePosterOption } from 'Store/Actions/addMovieActions';
|
||||
import AddListMoviePosterOptionsModalContent from './AddListMoviePosterOptionsModalContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.discoverMovie,
|
||||
(discoverMovie) => {
|
||||
return discoverMovie.posterOptions;
|
||||
(state) => state.addMovie,
|
||||
(addMovie) => {
|
||||
return addMovie.posterOptions;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal';
|
||||
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
|
||||
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
|
||||
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import TableOptionsModal from 'Components/Table/TableOptions/TableOptionsModal';
|
||||
import styles from './AddListMovieHeader.css';
|
||||
|
||||
class AddListMovieHeader extends Component {
|
||||
@@ -39,21 +38,11 @@ class AddListMovieHeader extends Component {
|
||||
const {
|
||||
columns,
|
||||
onTableOptionChange,
|
||||
allSelected,
|
||||
allUnselected,
|
||||
onSelectAllChange,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<VirtualTableHeader>
|
||||
<VirtualTableSelectAllHeaderCell
|
||||
key={name}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
/>
|
||||
|
||||
{
|
||||
columns.map((column) => {
|
||||
const {
|
||||
@@ -111,10 +100,7 @@ class AddListMovieHeader extends Component {
|
||||
|
||||
AddListMovieHeader.propTypes = {
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onTableOptionChange: PropTypes.func.isRequired,
|
||||
allSelected: PropTypes.bool.isRequired,
|
||||
allUnselected: PropTypes.bool.isRequired,
|
||||
onSelectAllChange: PropTypes.func.isRequired
|
||||
onTableOptionChange: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddListMovieHeader;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { setListMovieTableOption } from 'Store/Actions/discoverMovieActions';
|
||||
import { setListMovieTableOption } from 'Store/Actions/addMovieActions';
|
||||
import AddListMovieHeader from './AddListMovieHeader';
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
56
frontend/src/AddMovie/AddListMovie/Table/AddListMovieRow.css
Normal file
56
frontend/src/AddMovie/AddListMovie/Table/AddListMovieRow.css
Normal file
@@ -0,0 +1,56 @@
|
||||
.status {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
|
||||
.sortTitle {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 4 0 110px;
|
||||
}
|
||||
|
||||
.studio {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 2 0 90px;
|
||||
}
|
||||
|
||||
.inCinemas,
|
||||
.physicalRelease,
|
||||
.genres {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 0 0 180px;
|
||||
}
|
||||
|
||||
.movieStatus,
|
||||
.certification {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.ratings {
|
||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
flex: 0 0 80px;
|
||||
}
|
||||
|
||||
.tags {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 1 0 60px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
|
||||
|
||||
flex: 0 1 90px;
|
||||
}
|
||||
|
||||
.checkInput {
|
||||
composes: input from '~Components/Form/CheckInput.css';
|
||||
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -1,18 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import HeartRating from 'Components/HeartRating';
|
||||
import Icon from 'Components/Icon';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
|
||||
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
|
||||
import ListMovieStatusCell from './ListMovieStatusCell';
|
||||
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
|
||||
import MovieStatusCell from './MovieStatusCell';
|
||||
import Link from 'Components/Link/Link';
|
||||
import AddNewMovieModal from 'AddMovie/AddNewMovie/AddNewMovieModal';
|
||||
import styles from './AddListMovieRow.css';
|
||||
|
||||
class AddListMovieRow extends Component {
|
||||
@@ -24,15 +17,14 @@ class AddListMovieRow extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isNewAddMovieModalOpen: false,
|
||||
isExcludeMovieModalOpen: false
|
||||
isNewAddMovieModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onAddMoviePress = () => {
|
||||
onPress = () => {
|
||||
this.setState({ isNewAddMovieModalOpen: true });
|
||||
}
|
||||
|
||||
@@ -40,14 +32,6 @@ class AddListMovieRow extends Component {
|
||||
this.setState({ isNewAddMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onExcludeMoviePress = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: true });
|
||||
}
|
||||
|
||||
onExcludeMovieModalClose = () => {
|
||||
this.setState({ isExcludeMovieModalOpen: false });
|
||||
}
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
@@ -55,8 +39,6 @@ class AddListMovieRow extends Component {
|
||||
const {
|
||||
status,
|
||||
tmdbId,
|
||||
imdbId,
|
||||
youTubeTrailerId,
|
||||
title,
|
||||
titleSlug,
|
||||
studio,
|
||||
@@ -70,30 +52,17 @@ class AddListMovieRow extends Component {
|
||||
ratings,
|
||||
certification,
|
||||
columns,
|
||||
isExisting,
|
||||
isExcluded,
|
||||
isSelected,
|
||||
onSelectedChange
|
||||
isExistingMovie
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
isNewAddMovieModalOpen,
|
||||
isExcludeMovieModalOpen
|
||||
isNewAddMovieModalOpen
|
||||
} = this.state;
|
||||
|
||||
const linkProps = isExisting ? { to: `/movie/${titleSlug}` } : { onPress: this.onAddMoviePress };
|
||||
const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
|
||||
|
||||
return (
|
||||
<>
|
||||
<VirtualTableSelectCell
|
||||
inputClassName={styles.checkInput}
|
||||
id={tmdbId}
|
||||
key={name}
|
||||
isSelected={isSelected}
|
||||
isDisabled={false}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
|
||||
{
|
||||
columns.map((column) => {
|
||||
const {
|
||||
@@ -107,11 +76,10 @@ class AddListMovieRow extends Component {
|
||||
|
||||
if (name === 'status') {
|
||||
return (
|
||||
<ListMovieStatusCell
|
||||
<MovieStatusCell
|
||||
key={name}
|
||||
className={styles[name]}
|
||||
status={status}
|
||||
isExclusion={isExcluded}
|
||||
component={VirtualTableRowCell}
|
||||
/>
|
||||
);
|
||||
@@ -204,47 +172,12 @@ class AddListMovieRow extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'actions') {
|
||||
return (
|
||||
<VirtualTableRowCell
|
||||
key={name}
|
||||
className={styles[name]}
|
||||
>
|
||||
<span className={styles.externalLinks}>
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={12}
|
||||
/>
|
||||
}
|
||||
title="Links"
|
||||
body={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
imdbId={imdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
|
||||
<IconButton
|
||||
name={icons.REMOVE}
|
||||
title={isExcluded ? 'Movie already Excluded' : 'Exclude Movie'}
|
||||
onPress={this.onExcludeMoviePress}
|
||||
isDisabled={isExcluded}
|
||||
/>
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
}
|
||||
|
||||
<AddNewDiscoverMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExisting}
|
||||
<AddNewMovieModal
|
||||
isOpen={isNewAddMovieModalOpen && !isExistingMovie}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
@@ -253,14 +186,6 @@ class AddListMovieRow extends Component {
|
||||
images={images}
|
||||
onModalClose={this.onAddMovieModalClose}
|
||||
/>
|
||||
|
||||
<ExcludeMovieModal
|
||||
isOpen={isExcludeMovieModalOpen}
|
||||
tmdbId={tmdbId}
|
||||
title={title}
|
||||
year={year}
|
||||
onModalClose={this.onExcludeMovieModalClose}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -268,8 +193,6 @@ class AddListMovieRow extends Component {
|
||||
|
||||
AddListMovieRow.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
youTubeTrailerId: PropTypes.string,
|
||||
status: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
@@ -284,10 +207,7 @@ AddListMovieRow.propTypes = {
|
||||
ratings: PropTypes.object.isRequired,
|
||||
certification: PropTypes.string,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
isExisting: PropTypes.bool.isRequired,
|
||||
isExcluded: PropTypes.bool.isRequired,
|
||||
isSelected: PropTypes.bool,
|
||||
onSelectedChange: PropTypes.func.isRequired
|
||||
isExistingMovie: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
AddListMovieRow.defaultProps = {
|
||||
@@ -0,0 +1,23 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector';
|
||||
import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddListMovieRow from './AddListMovieRow';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
createExistingMovieSelector(),
|
||||
createExclusionMovieSelector(),
|
||||
createDimensionsSelector(),
|
||||
(isExistingMovie, isExclusionMovie, dimensions) => {
|
||||
return {
|
||||
isExistingMovie,
|
||||
isExclusionMovie,
|
||||
isSmallScreen: dimensions.isSmallScreen
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(createMapStateToProps)(AddListMovieRow);
|
||||
@@ -1,10 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
|
||||
import { sortDirections } from 'Helpers/Props';
|
||||
import VirtualTable from 'Components/Table/VirtualTable';
|
||||
import VirtualTableRow from 'Components/Table/VirtualTableRow';
|
||||
import AddListMovieItemConnector from 'DiscoverMovie/AddListMovieItemConnector';
|
||||
import { sortDirections } from 'Helpers/Props';
|
||||
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
|
||||
import AddListMovieItemConnector from 'AddMovie/AddListMovie/AddListMovieItemConnector';
|
||||
import AddListMovieHeaderConnector from './AddListMovieHeaderConnector';
|
||||
import AddListMovieRowConnector from './AddListMovieRowConnector';
|
||||
import styles from './AddListMovieTable.css';
|
||||
@@ -46,9 +46,7 @@ class AddListMovieTable extends Component {
|
||||
rowRenderer = ({ key, rowIndex, style }) => {
|
||||
const {
|
||||
items,
|
||||
columns,
|
||||
selectedState,
|
||||
onSelectedChange
|
||||
columns
|
||||
} = this.props;
|
||||
|
||||
const movie = items[rowIndex];
|
||||
@@ -59,12 +57,10 @@ class AddListMovieTable extends Component {
|
||||
style={style}
|
||||
>
|
||||
<AddListMovieItemConnector
|
||||
key={movie.tmdbId}
|
||||
key={movie.id}
|
||||
component={AddListMovieRowConnector}
|
||||
columns={columns}
|
||||
movieId={movie.tmdbId}
|
||||
isSelected={selectedState[movie.tmdbId]}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
</VirtualTableRow>
|
||||
);
|
||||
@@ -79,13 +75,8 @@ class AddListMovieTable extends Component {
|
||||
columns,
|
||||
sortKey,
|
||||
sortDirection,
|
||||
isSmallScreen,
|
||||
onSortPress,
|
||||
scroller,
|
||||
allSelected,
|
||||
allUnselected,
|
||||
onSelectAllChange,
|
||||
selectedState
|
||||
onSortPress
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@@ -93,7 +84,6 @@ class AddListMovieTable extends Component {
|
||||
className={styles.tableContainer}
|
||||
items={items}
|
||||
scrollIndex={this.state.scrollIndex}
|
||||
isSmallScreen={isSmallScreen}
|
||||
scroller={scroller}
|
||||
rowHeight={38}
|
||||
overscanRowCount={2}
|
||||
@@ -104,12 +94,8 @@ class AddListMovieTable extends Component {
|
||||
sortKey={sortKey}
|
||||
sortDirection={sortDirection}
|
||||
onSortPress={onSortPress}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
onSelectAllChange={onSelectAllChange}
|
||||
/>
|
||||
}
|
||||
selectedState={selectedState}
|
||||
columns={columns}
|
||||
/>
|
||||
);
|
||||
@@ -122,14 +108,8 @@ AddListMovieTable.propTypes = {
|
||||
sortKey: PropTypes.string,
|
||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
||||
jumpToCharacter: PropTypes.string,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
scroller: PropTypes.instanceOf(Element).isRequired,
|
||||
onSortPress: PropTypes.func.isRequired,
|
||||
allSelected: PropTypes.bool.isRequired,
|
||||
allUnselected: PropTypes.bool.isRequired,
|
||||
selectedState: PropTypes.object.isRequired,
|
||||
onSelectedChange: PropTypes.func.isRequired,
|
||||
onSelectAllChange: PropTypes.func.isRequired
|
||||
onSortPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddListMovieTable;
|
||||
@@ -1,12 +1,12 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { setListMovieSort } from 'Store/Actions/discoverMovieActions';
|
||||
import { setListMovieSort } from 'Store/Actions/addMovieActions';
|
||||
import AddListMovieTable from './AddListMovieTable';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.app.dimensions,
|
||||
(state) => state.discoverMovie.columns,
|
||||
(state) => state.addMovie.columns,
|
||||
(dimensions, columns) => {
|
||||
return {
|
||||
isSmallScreen: dimensions.isSmallScreen,
|
||||
@@ -7,7 +7,3 @@
|
||||
.statusIcon {
|
||||
width: 20px !important;
|
||||
}
|
||||
|
||||
.exclusionIcon {
|
||||
color: $dangerColor;
|
||||
}
|
||||
62
frontend/src/AddMovie/AddListMovie/Table/MovieStatusCell.js
Normal file
62
frontend/src/AddMovie/AddListMovie/Table/MovieStatusCell.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import styles from './MovieStatusCell.css';
|
||||
|
||||
function MovieStatusCell(props) {
|
||||
const {
|
||||
className,
|
||||
status,
|
||||
component: Component,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Component
|
||||
className={className}
|
||||
{...otherProps}
|
||||
>
|
||||
{
|
||||
status === 'announced' ?
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.ANNOUNCED}
|
||||
title={'Movie is announced'}
|
||||
/> : null
|
||||
}
|
||||
|
||||
{
|
||||
status === 'inCinemas' ?
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.IN_CINEMAS}
|
||||
title={'Movie is in Cinemas'}
|
||||
/> : null
|
||||
}
|
||||
|
||||
{
|
||||
status === 'released' ?
|
||||
<Icon
|
||||
className={styles.statusIcon}
|
||||
name={icons.MOVIE_FILE}
|
||||
title={'Movie is released'}
|
||||
/> : null
|
||||
}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
MovieStatusCell.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
component: PropTypes.elementType
|
||||
};
|
||||
|
||||
MovieStatusCell.defaultProps = {
|
||||
className: styles.status,
|
||||
component: VirtualTableRowCell
|
||||
};
|
||||
|
||||
export default MovieStatusCell;
|
||||
@@ -1,15 +1,14 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import Icon from 'Components/Icon';
|
||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Link from 'Components/Link/Link';
|
||||
import Icon from 'Components/Icon';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import AddNewMovieSearchResultConnector from './AddNewMovieSearchResultConnector';
|
||||
import styles from './AddNewMovie.css';
|
||||
|
||||
@@ -89,7 +88,7 @@ class AddNewMovie extends Component {
|
||||
|
||||
return (
|
||||
<PageContent title="Add New Movie">
|
||||
<PageContentBody>
|
||||
<PageContentBodyConnector>
|
||||
<div className={styles.searchContainer}>
|
||||
<div className={styles.searchIconContainer}>
|
||||
<Icon
|
||||
@@ -167,9 +166,9 @@ class AddNewMovie extends Component {
|
||||
null :
|
||||
<div className={styles.message}>
|
||||
<div className={styles.helpText}>
|
||||
{translate('AddNewMessage')}
|
||||
It's easy to add a new movie, just start typing the name the movie you want to add.
|
||||
</div>
|
||||
<div>{translate('AddNewTmdbIdMessage')}</div>
|
||||
<div>You can also search using TMDB ID of a movie. eg. tmdb:71663</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -192,7 +191,7 @@ class AddNewMovie extends Component {
|
||||
}
|
||||
|
||||
<div />
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
|
||||
import parseUrl from 'Utilities/String/parseUrl';
|
||||
import { lookupMovie, clearAddMovie } from 'Store/Actions/addMovieActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { fetchNetImportExclusions } from 'Store/Actions/Settings/netImportExclusions';
|
||||
import parseUrl from 'Utilities/String/parseUrl';
|
||||
import AddNewMovie from './AddNewMovie';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import { kinds, inputTypes } from 'Helpers/Props';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import CheckInput from 'Components/Form/CheckInput';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import styles from './AddNewMovieModalContent.css';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { addMovie, setAddMovieDefault } from 'Store/Actions/addMovieActions';
|
||||
import { setAddMovieDefault, addMovie } from 'Store/Actions/addMovieActions';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
|
||||
import selectSettings from 'Store/Selectors/selectSettings';
|
||||
|
||||
@@ -47,12 +47,18 @@
|
||||
color: $disabledColor;
|
||||
}
|
||||
|
||||
.externalLink {
|
||||
margin-top: 5px;
|
||||
.tmdbLink {
|
||||
composes: link from '~Components/Link/Link.css';
|
||||
|
||||
margin-top: -4px;
|
||||
margin-left: auto;
|
||||
color: $textColor;
|
||||
}
|
||||
|
||||
.tmdbLinkIcon {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.alreadyExistsIcon {
|
||||
margin-left: 10px;
|
||||
color: #37bc9b;
|
||||
@@ -61,7 +67,7 @@
|
||||
|
||||
.exclusionIcon {
|
||||
margin-left: 10px;
|
||||
color: $dangerColor;
|
||||
color: #bc3737;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import HeartRating from 'Components/HeartRating';
|
||||
import Icon from 'Components/Icon';
|
||||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import AddNewMovieModal from './AddNewMovieModal';
|
||||
import styles from './AddNewMovieSearchResult.css';
|
||||
@@ -39,7 +39,7 @@ class AddNewMovieSearchResult extends Component {
|
||||
this.setState({ isNewAddMovieModalOpen: false });
|
||||
}
|
||||
|
||||
onExternalLinkPress = (event) => {
|
||||
onTMDBLinkPress = (event) => {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ class AddNewMovieSearchResult extends Component {
|
||||
render() {
|
||||
const {
|
||||
tmdbId,
|
||||
imdbId,
|
||||
title,
|
||||
titleSlug,
|
||||
year,
|
||||
@@ -118,41 +117,17 @@ class AddNewMovieSearchResult extends Component {
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
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>
|
||||
}
|
||||
<Link
|
||||
className={styles.tmdbLink}
|
||||
to={`https://www.themoviedb.org/movie/${tmdbId}`}
|
||||
onPress={this.onTMDBLinkPress}
|
||||
>
|
||||
<Icon
|
||||
className={styles.tmdbLinkIcon}
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={28}
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -181,42 +156,6 @@ 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>
|
||||
@@ -240,7 +179,6 @@ class AddNewMovieSearchResult extends Component {
|
||||
|
||||
AddNewMovieSearchResult.propTypes = {
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
imdbId: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector';
|
||||
import createExistingMovieSelector from 'Store/Selectors/createExistingMovieSelector';
|
||||
import createExclusionMovieSelector from 'Store/Selectors/createExclusionMovieSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import AddNewMovieSearchResult from './AddNewMovieSearchResult';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import ImportMovieFooterConnector from './ImportMovieFooterConnector';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import ImportMovieTableConnector from './ImportMovieTableConnector';
|
||||
import ImportMovieFooterConnector from './ImportMovieFooterConnector';
|
||||
|
||||
class ImportMovie extends Component {
|
||||
|
||||
@@ -79,6 +79,7 @@ class ImportMovie extends Component {
|
||||
rootFolderId,
|
||||
path,
|
||||
rootFoldersFetching,
|
||||
rootFoldersPopulated,
|
||||
rootFoldersError,
|
||||
unmappedFolders
|
||||
} = this.props;
|
||||
@@ -92,35 +93,29 @@ class ImportMovie extends Component {
|
||||
|
||||
return (
|
||||
<PageContent title="Import Movies">
|
||||
<PageContentBody
|
||||
<PageContentBodyConnector
|
||||
registerScroller={this.setScrollerRef}
|
||||
onScroll={this.onScroll}
|
||||
>
|
||||
{
|
||||
rootFoldersFetching ? <LoadingIndicator /> : null
|
||||
rootFoldersFetching && !rootFoldersPopulated &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
{
|
||||
!rootFoldersFetching && !!rootFoldersError ?
|
||||
<div>Unable to load root folders</div> :
|
||||
null
|
||||
!rootFoldersFetching && !!rootFoldersError &&
|
||||
<div>Unable to load root folders</div>
|
||||
}
|
||||
|
||||
{
|
||||
!rootFoldersError &&
|
||||
!rootFoldersFetching &&
|
||||
!unmappedFolders.length ?
|
||||
!rootFoldersError && rootFoldersPopulated && !unmappedFolders.length &&
|
||||
<div>
|
||||
All movies in {path} have been imported
|
||||
</div> :
|
||||
null
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!rootFoldersError &&
|
||||
!rootFoldersFetching &&
|
||||
!!unmappedFolders.length &&
|
||||
scroller ?
|
||||
!rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length && scroller &&
|
||||
<ImportMovieTableConnector
|
||||
rootFolderId={rootFolderId}
|
||||
unmappedFolders={unmappedFolders}
|
||||
@@ -131,21 +126,17 @@ class ImportMovie extends Component {
|
||||
onSelectAllChange={this.onSelectAllChange}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
onRemoveSelectedStateItem={this.onRemoveSelectedStateItem}
|
||||
/> :
|
||||
null
|
||||
/>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
|
||||
{
|
||||
!rootFoldersError &&
|
||||
!rootFoldersFetching &&
|
||||
!!unmappedFolders.length ?
|
||||
!rootFoldersError && rootFoldersPopulated && !!unmappedFolders.length &&
|
||||
<ImportMovieFooterConnector
|
||||
selectedIds={this.getSelectedIds()}
|
||||
onInputChange={this.onInputChange}
|
||||
onImportPress={this.onImportPress}
|
||||
/> :
|
||||
null
|
||||
/>
|
||||
}
|
||||
</PageContent>
|
||||
);
|
||||
|
||||
@@ -3,10 +3,10 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createRouteMatchShape from 'Helpers/Props/Shapes/createRouteMatchShape';
|
||||
import { setAddMovieDefault } from 'Store/Actions/addMovieActions';
|
||||
import { clearImportMovie, importMovie, setImportMovieValue } from 'Store/Actions/importMovieActions';
|
||||
import { setImportMovieValue, importMovie, clearImportMovie } from 'Store/Actions/importMovieActions';
|
||||
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { setAddMovieDefault } from 'Store/Actions/addMovieActions';
|
||||
import createRouteMatchShape from 'Helpers/Props/Shapes/createRouteMatchShape';
|
||||
import ImportMovie from './ImportMovie';
|
||||
|
||||
function createMapStateToProps() {
|
||||
@@ -71,14 +71,15 @@ class ImportMovieConnector extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
rootFolderId,
|
||||
qualityProfiles,
|
||||
defaultQualityProfileId,
|
||||
dispatchFetchRootFolders,
|
||||
dispatchSetAddMovieDefault
|
||||
} = this.props;
|
||||
|
||||
dispatchFetchRootFolders({ id: rootFolderId, timeout: false });
|
||||
if (!this.props.rootFoldersPopulated) {
|
||||
dispatchFetchRootFolders();
|
||||
}
|
||||
|
||||
let setDefaults = false;
|
||||
const setDefaultPayload = {};
|
||||
@@ -138,8 +139,6 @@ const routeMatchShape = createRouteMatchShape({
|
||||
|
||||
ImportMovieConnector.propTypes = {
|
||||
match: routeMatchShape.isRequired,
|
||||
rootFolderId: PropTypes.number.isRequired,
|
||||
rootFoldersFetching: PropTypes.bool.isRequired,
|
||||
rootFoldersPopulated: PropTypes.bool.isRequired,
|
||||
qualityProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
defaultQualityProfileId: PropTypes.number.isRequired,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
// import CheckInput from 'Components/Form/CheckInput';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
// import CheckInput from 'Components/Form/CheckInput';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import PageContentFooter from 'Components/Page/PageContentFooter';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import styles from './ImportMovieFooter.css';
|
||||
|
||||
const MIXED = 'mixed';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
|
||||
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
|
||||
import { inputTypes } from 'Helpers/Props';
|
||||
import ImportMovieSelectMovieConnector from './SelectMovie/ImportMovieSelectMovieConnector';
|
||||
import styles from './ImportMovieRow.css';
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { Manager, Popper, Reference } from 'react-popper';
|
||||
import FormInputButton from 'Components/Form/FormInputButton';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Icon from 'Components/Icon';
|
||||
import Portal from 'Components/Portal';
|
||||
import FormInputButton from 'Components/Form/FormInputButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Portal from 'Components/Portal';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import ImportMovieSearchResultConnector from './ImportMovieSearchResultConnector';
|
||||
import ImportMovieTitle from './ImportMovieTitle';
|
||||
import styles from './ImportMovieSelectMovie.css';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Label from 'Components/Label';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Label from 'Components/Label';
|
||||
import styles from './ImportMovieTitle.css';
|
||||
|
||||
function ImportMovieTitle(props) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Route } from 'react-router-dom';
|
||||
import ImportMovieConnector from 'AddMovie/ImportMovie/Import/ImportMovieConnector';
|
||||
import ImportMovieSelectFolderConnector from 'AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector';
|
||||
import Switch from 'Components/Router/Switch';
|
||||
import ImportMovieSelectFolderConnector from 'AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector';
|
||||
import ImportMovieConnector from 'AddMovie/ImportMovie/Import/ImportMovieConnector';
|
||||
|
||||
class ImportMovies extends Component {
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
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 TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import styles from './ImportMovieRootFolderRow.css';
|
||||
|
||||
function ImportMovieRootFolderRow(props) {
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal';
|
||||
import Icon from 'Components/Icon';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import Icon from 'Components/Icon';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import ImportMovieRootFolderRowConnector from './ImportMovieRootFolderRowConnector';
|
||||
import styles from './ImportMovieSelectFolder.css';
|
||||
|
||||
@@ -78,7 +77,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
|
||||
return (
|
||||
<PageContent title="Import Movies">
|
||||
<PageContentBody>
|
||||
<PageContentBodyConnector>
|
||||
{
|
||||
isFetching && !isPopulated &&
|
||||
<LoadingIndicator />
|
||||
@@ -93,11 +92,11 @@ class ImportMovieSelectFolder extends Component {
|
||||
!error && isPopulated &&
|
||||
<div>
|
||||
<div className={styles.header}>
|
||||
{translate('ImportHeader')}
|
||||
Import movies you already have
|
||||
</div>
|
||||
|
||||
<div className={styles.tips}>
|
||||
{translate('ImportTipsMessage')}
|
||||
Some tips to ensure the import goes smoothly:
|
||||
<ul>
|
||||
<li className={styles.tip}>
|
||||
Make sure that your files include the quality in their filenames. eg. <span className={styles.code}>movie.2008.bluray.mkv</span>
|
||||
@@ -142,7 +141,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
className={styles.importButtonIcon}
|
||||
name={icons.DRIVE}
|
||||
/>
|
||||
{translate('ChooseAnotherFolder')}
|
||||
Choose another folder
|
||||
</Button>
|
||||
</div> :
|
||||
|
||||
@@ -170,7 +169,7 @@ class ImportMovieSelectFolder extends Component {
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { push } from 'connected-react-router';
|
||||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { addRootFolder, deleteRootFolder, fetchRootFolders } from 'Store/Actions/rootFolderActions';
|
||||
import { push } from 'connected-react-router';
|
||||
import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
|
||||
import { fetchRootFolders, addRootFolder, deleteRootFolder } from 'Store/Actions/rootFolderActions';
|
||||
import ImportMovieSelectFolder from './ImportMovieSelectFolder';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ConnectedRouter } from 'connected-react-router';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import { Provider } from 'react-redux';
|
||||
import { ConnectedRouter } from 'connected-react-router';
|
||||
import PageConnector from 'Components/Page/PageConnector';
|
||||
import AppRoutes from './AppRoutes';
|
||||
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
import BlacklistConnector from 'Activity/Blacklist/BlacklistConnector';
|
||||
import HistoryConnector from 'Activity/History/HistoryConnector';
|
||||
import QueueConnector from 'Activity/Queue/QueueConnector';
|
||||
import AddNewMovieConnector from 'AddMovie/AddNewMovie/AddNewMovieConnector';
|
||||
import ImportMovies from 'AddMovie/ImportMovie/ImportMovies';
|
||||
import CalendarPageConnector from 'Calendar/CalendarPageConnector';
|
||||
import { Route, Redirect } from 'react-router-dom';
|
||||
import getPathWithUrlBase from 'Utilities/getPathWithUrlBase';
|
||||
import NotFound from 'Components/NotFound';
|
||||
import Switch from 'Components/Router/Switch';
|
||||
import DiscoverMovieConnector from 'DiscoverMovie/DiscoverMovieConnector';
|
||||
import MovieDetailsPageConnector from 'Movie/Details/MovieDetailsPageConnector';
|
||||
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 IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector';
|
||||
import AddNewMovieConnector from 'AddMovie/AddNewMovie/AddNewMovieConnector';
|
||||
import AddListMovieConnector from 'AddMovie/AddListMovie/AddListMovieConnector';
|
||||
import AddDiscoverMovieConnector from 'AddMovie/AddListMovie/AddDiscoverMovieConnector';
|
||||
import ImportMovies from 'AddMovie/ImportMovie/ImportMovies';
|
||||
import MovieDetailsPageConnector from 'Movie/Details/MovieDetailsPageConnector';
|
||||
import CalendarPageConnector from 'Calendar/CalendarPageConnector';
|
||||
import HistoryConnector from 'Activity/History/HistoryConnector';
|
||||
import QueueConnector from 'Activity/Queue/QueueConnector';
|
||||
import BlacklistConnector from 'Activity/Blacklist/BlacklistConnector';
|
||||
import Settings from 'Settings/Settings';
|
||||
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';
|
||||
import Settings from 'Settings/Settings';
|
||||
import CustomFormatSettingsConnector from 'Settings/CustomFormats/CustomFormatSettingsConnector';
|
||||
import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector';
|
||||
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
|
||||
import NetImportSettingsConnector from 'Settings/NetImport/NetImportSettingsConnector';
|
||||
import NotificationSettings from 'Settings/Notifications/NotificationSettings';
|
||||
import MetadataSettings from 'Settings/Metadata/MetadataSettings';
|
||||
import TagSettings from 'Settings/Tags/TagSettings';
|
||||
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
|
||||
import UISettingsConnector from 'Settings/UI/UISettingsConnector';
|
||||
import BackupsConnector from 'System/Backup/BackupsConnector';
|
||||
import LogsTableConnector from 'System/Events/LogsTableConnector';
|
||||
import Logs from 'System/Logs/Logs';
|
||||
import Status from 'System/Status/Status';
|
||||
import Tasks from 'System/Tasks/Tasks';
|
||||
import BackupsConnector from 'System/Backup/BackupsConnector';
|
||||
import UpdatesConnector from 'System/Updates/UpdatesConnector';
|
||||
import getPathWithUrlBase from 'Utilities/getPathWithUrlBase';
|
||||
import LogsTableConnector from 'System/Events/LogsTableConnector';
|
||||
import Logs from 'System/Logs/Logs';
|
||||
|
||||
function AppRoutes(props) {
|
||||
const {
|
||||
@@ -77,9 +78,14 @@ function AppRoutes(props) {
|
||||
component={ImportMovies}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/add/list"
|
||||
component={AddListMovieConnector}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/add/discover"
|
||||
component={DiscoverMovieConnector}
|
||||
component={AddDiscoverMovieConnector}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Button from 'Components/Link/Button';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
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 { kinds } from 'Helpers/Props';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Button from 'Components/Link/Button';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import UpdateChanges from 'System/Updates/UpdateChanges';
|
||||
import styles from './AppUpdatedModalContent.css';
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Button from 'Components/Link/Button';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
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 { kinds } from 'Helpers/Props';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import styles from './ConnectionLostModal.css';
|
||||
|
||||
function ConnectionLostModal(props) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import classNames from 'classnames';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import CalendarEventQueueDetails from 'Calendar/Events/CalendarEventQueueDetails';
|
||||
import classNames from 'classnames';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import getStatusStyle from 'Calendar/getStatusStyle';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import CalendarEventQueueDetails from 'Calendar/Events/CalendarEventQueueDetails';
|
||||
import MovieTitleLink from 'Movie/MovieTitleLink';
|
||||
import styles from './AgendaEvent.css';
|
||||
|
||||
@@ -41,7 +41,6 @@ class AgendaEvent extends Component {
|
||||
movieFile,
|
||||
title,
|
||||
titleSlug,
|
||||
isAvailable,
|
||||
inCinemas,
|
||||
monitored,
|
||||
hasFile,
|
||||
@@ -56,7 +55,7 @@ class AgendaEvent extends Component {
|
||||
const startTime = moment(inCinemas);
|
||||
const downloading = !!(queueItem || grabbed);
|
||||
const isMonitored = monitored;
|
||||
const statusStyle = getStatusStyle(hasFile, downloading, isAvailable, isMonitored);
|
||||
const statusStyle = getStatusStyle(hasFile, downloading, startTime, isMonitored);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -127,8 +126,7 @@ AgendaEvent.propTypes = {
|
||||
movieFile: PropTypes.object,
|
||||
title: PropTypes.string.isRequired,
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
isAvailable: PropTypes.bool.isRequired,
|
||||
inCinemas: PropTypes.string,
|
||||
inCinemas: PropTypes.string.isRequired,
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
hasFile: PropTypes.bool.isRequired,
|
||||
grabbed: PropTypes.bool,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import AgendaConnector from './Agenda/AgendaConnector';
|
||||
import * as calendarViews from './calendarViews';
|
||||
import CalendarDaysConnector from './Day/CalendarDaysConnector';
|
||||
import DaysOfWeekConnector from './Day/DaysOfWeekConnector';
|
||||
import CalendarHeaderConnector from './Header/CalendarHeaderConnector';
|
||||
import DaysOfWeekConnector from './Day/DaysOfWeekConnector';
|
||||
import CalendarDaysConnector from './Day/CalendarDaysConnector';
|
||||
import AgendaConnector from './Agenda/AgendaConnector';
|
||||
import styles from './Calendar.css';
|
||||
|
||||
class Calendar extends Component {
|
||||
|
||||
@@ -2,14 +2,14 @@ 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 * as calendarActions from 'Store/Actions/calendarActions';
|
||||
import { clearMovieFiles, fetchMovieFiles } from 'Store/Actions/movieFileActions';
|
||||
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
|
||||
import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
|
||||
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
|
||||
import * as calendarActions from 'Store/Actions/calendarActions';
|
||||
import { fetchMovieFiles, clearMovieFiles } from 'Store/Actions/movieFileActions';
|
||||
import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import Calendar from './Calendar';
|
||||
|
||||
const UPDATE_DELAY = 3600000; // 1 hour
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Measure from 'Components/Measure';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import Measure from 'Components/Measure';
|
||||
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
|
||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||
import { align, icons } from 'Helpers/Props';
|
||||
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import NoMovie from 'Movie/NoMovie';
|
||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import CalendarConnector from './CalendarConnector';
|
||||
import CalendarLinkModal from './iCal/CalendarLinkModal';
|
||||
import LegendConnector from './Legend/LegendConnector';
|
||||
import CalendarOptionsModal from './Options/CalendarOptionsModal';
|
||||
import LegendConnector from './Legend/LegendConnector';
|
||||
import CalendarConnector from './CalendarConnector';
|
||||
import styles from './CalendarPage.css';
|
||||
|
||||
const MINIMUM_DAY_WIDTH = 120;
|
||||
@@ -80,8 +78,6 @@ class CalendarPage extends Component {
|
||||
filters,
|
||||
hasMovie,
|
||||
movieError,
|
||||
movieIsFetching,
|
||||
movieIsPopulated,
|
||||
missingMovieIds,
|
||||
isRssSyncExecuting,
|
||||
isSearchingForMissing,
|
||||
@@ -96,13 +92,14 @@ class CalendarPage extends Component {
|
||||
} = this.state;
|
||||
|
||||
const isMeasured = this.state.width > 0;
|
||||
const PageComponent = hasMovie ? CalendarConnector : NoMovie;
|
||||
|
||||
return (
|
||||
<PageContent title="Calendar">
|
||||
<PageToolbar>
|
||||
<PageToolbarSection>
|
||||
<PageToolbarButton
|
||||
label={translate('iCalLink')}
|
||||
label="iCal Link"
|
||||
iconName={icons.CALENDAR}
|
||||
onPress={this.onGetCalendarLinkPress}
|
||||
/>
|
||||
@@ -110,14 +107,14 @@ class CalendarPage extends Component {
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('RssSync')}
|
||||
label="RSS Sync"
|
||||
iconName={icons.RSS}
|
||||
isSpinning={isRssSyncExecuting}
|
||||
onPress={onRssSyncPress}
|
||||
/>
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('SearchForMissing')}
|
||||
label="Search for Missing"
|
||||
iconName={icons.SEARCH}
|
||||
isDisabled={!missingMovieIds.length}
|
||||
isSpinning={isSearchingForMissing}
|
||||
@@ -127,7 +124,7 @@ class CalendarPage extends Component {
|
||||
|
||||
<PageToolbarSection alignContent={align.RIGHT}>
|
||||
<PageToolbarButton
|
||||
label={translate('Options')}
|
||||
label="Options"
|
||||
iconName={icons.POSTER}
|
||||
onPress={this.onOptionsPress}
|
||||
/>
|
||||
@@ -143,31 +140,26 @@ class CalendarPage extends Component {
|
||||
</PageToolbarSection>
|
||||
</PageToolbar>
|
||||
|
||||
<PageContentBody
|
||||
<PageContentBodyConnector
|
||||
className={styles.calendarPageBody}
|
||||
innerClassName={styles.calendarInnerPageBody}
|
||||
>
|
||||
{
|
||||
movieIsFetching && !movieIsPopulated &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
{
|
||||
movieError &&
|
||||
<div className={styles.errorMessage}>
|
||||
{getErrorMessage(movieError, 'Failed to load movies from API')}
|
||||
{getErrorMessage(movieError, 'Failed to load movie from API')}
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!movieError && movieIsPopulated && hasMovie &&
|
||||
!movieError &&
|
||||
<Measure
|
||||
whitelist={['width']}
|
||||
onMeasure={this.onMeasure}
|
||||
>
|
||||
{
|
||||
isMeasured ?
|
||||
<CalendarConnector
|
||||
<PageComponent
|
||||
useCurrentPage={useCurrentPage}
|
||||
/> :
|
||||
<div />
|
||||
@@ -175,16 +167,11 @@ class CalendarPage extends Component {
|
||||
</Measure>
|
||||
}
|
||||
|
||||
{
|
||||
!movieError && movieIsPopulated && !hasMovie &&
|
||||
<NoMovie />
|
||||
}
|
||||
|
||||
{
|
||||
hasMovie && !movieError &&
|
||||
<LegendConnector />
|
||||
}
|
||||
</PageContentBody>
|
||||
</PageContentBodyConnector>
|
||||
|
||||
<CalendarLinkModal
|
||||
isOpen={isCalendarLinkModalOpen}
|
||||
@@ -205,8 +192,6 @@ CalendarPage.propTypes = {
|
||||
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
hasMovie: PropTypes.bool.isRequired,
|
||||
movieError: PropTypes.object,
|
||||
movieIsFetching: PropTypes.bool.isRequired,
|
||||
movieIsPopulated: PropTypes.bool.isRequired,
|
||||
missingMovieIds: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
isRssSyncExecuting: PropTypes.bool.isRequired,
|
||||
isSearchingForMissing: PropTypes.bool.isRequired,
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import moment from 'moment';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import { searchMissing, setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
import createMovieCountSelector from 'Store/Selectors/createMovieCountSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import moment from 'moment';
|
||||
import { isCommandExecuting } from 'Utilities/Command';
|
||||
import isBefore from 'Utilities/Date/isBefore';
|
||||
import * as commandNames from 'Commands/commandNames';
|
||||
import withCurrentPage from 'Components/withCurrentPage';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import { searchMissing, setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions';
|
||||
import createMovieCountSelector from 'Store/Selectors/createMovieCountSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import CalendarPage from './CalendarPage';
|
||||
|
||||
function createMissingMovieIdsSelector() {
|
||||
@@ -79,8 +79,6 @@ function createMapStateToProps() {
|
||||
colorImpairedMode: uiSettings.enableColorImpairedMode,
|
||||
hasMovie: !!movieCount.count,
|
||||
movieError: movieCount.error,
|
||||
movieIsFetching: movieCount.isFetching,
|
||||
movieIsPopulated: movieCount.isPopulated,
|
||||
missingMovieIds,
|
||||
isRssSyncExecuting,
|
||||
isSearchingForMissing
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import classNames from 'classnames';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as calendarViews from 'Calendar/calendarViews';
|
||||
import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector';
|
||||
import styles from './CalendarDay.css';
|
||||
|
||||
@@ -22,9 +22,7 @@ function createCalendarEventsConnector() {
|
||||
(state) => state.calendar.items,
|
||||
(date, items) => {
|
||||
const filtered = _.filter(items, (item) => {
|
||||
return (item.inCinemas && moment(date).isSame(moment(item.inCinemas), 'day')) ||
|
||||
(item.physicalRelease && moment(date).isSame(moment(item.physicalRelease), 'day')) ||
|
||||
(item.digitalRelease && moment(date).isSame(moment(item.digitalRelease), 'day'));
|
||||
return moment(date).isSame(moment(item.inCinemas), 'day') || moment(date).isSame(moment(item.physicalRelease), 'day');
|
||||
});
|
||||
|
||||
return sort(filtered);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import classNames from 'classnames';
|
||||
import moment from 'moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import * as calendarViews from 'Calendar/calendarViews';
|
||||
import classNames from 'classnames';
|
||||
import isToday from 'Utilities/Date/isToday';
|
||||
import * as calendarViews from 'Calendar/calendarViews';
|
||||
import CalendarDayConnector from './CalendarDayConnector';
|
||||
import styles from './CalendarDays.css';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user