diff --git a/.editorconfig b/.editorconfig index ba00f5fd8..1b41b9009 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,7 +5,7 @@ root = true # NOTE: Requires **VS2019 16.3** or later # Stylecop.ruleset -# Description: Rules for Radarr +# Description: Rules for Prowlarr # Code files [*.cs] diff --git a/.gitattributes b/.gitattributes index b4206acbb..bf91795fb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,7 +3,7 @@ # Explicitly set bash scripts to have unix endings *.sh text eol=lf -macOS/Radarr text eol=lf +macOS/Prowlarr text eol=lf # Custom for Visual Studio *.cs diff=csharp diff --git a/.gitchangelog.rc b/.gitchangelog.rc index 863287d9e..aee317954 100644 --- a/.gitchangelog.rc +++ b/.gitchangelog.rc @@ -142,7 +142,7 @@ body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip ## ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/-- -Changed-orange.svg?style=flat-square) \4') | ## ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/-- -Fixed-red.svg?style=flat-square) \4') | ## ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/-- -Updated-blue.svg?style=flat-square) \4') | -## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Radarr/Radarr/issues/\1)') | +## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | ## SetIfEmpty("No commit message.") | ucfirst | final_dot) ## Available constructs are those listed in ``body_process`` doc. @@ -151,7 +151,7 @@ subject_process = (strip | ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) \4') | ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) \4') | ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) \4') | - ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Radarr/Radarr/issues/\1)') | + ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | SetIfEmpty("No commit message.") | ucfirst | final_dot) diff --git a/.gitchangelog.rc.release b/.gitchangelog.rc.release index 56c23fc62..7e0071f74 100644 --- a/.gitchangelog.rc.release +++ b/.gitchangelog.rc.release @@ -142,7 +142,7 @@ body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip ## ReSub(r'^([cC]hang(ed?)?)(\s?:?\s)(.*)$', r'![Changed](https://img.shields.io/badge/-- -Changed-orange.svg?style=flat-square) \4') | ## ReSub(r'^([fF]ix(ed?)?)(\s?:?\s)(.*)$', r'![Fixed](https://img.shields.io/badge/-- -Fixed-red.svg?style=flat-square) \4') | ## ReSub(r'^([uU]pdat(ed?)?)(\s?:?\s)(.*)$', r'![Updated](https://img.shields.io/badge/-- -Updated-blue.svg?style=flat-square) \4') | -## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Radarr/Radarr/issues/\1)') | +## ReSub(r'#(\d{3,4})', r'[#\1](https://github.com/Prowlarr/Prowlarr/issues/\1)') | ## SetIfEmpty("No commit message.") | ucfirst | final_dot) ## Available constructs are those listed in ``body_process`` doc. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index b7dd208ec..8391d8cd0 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -2,7 +2,7 @@ github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username -open_collective: radarr +open_collective: prowlarr ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel custom: # Replace with a single custom sponsorship URL diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 7ef95fc9a..81f2a2761 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,17 +1,17 @@ **Description:** -**Radarr Version:** +**Prowlarr Version:** **Mono Version:** diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 613ed29f9..e034ec0f3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -28,7 +28,7 @@ If applicable, add screenshots to help explain your problem. - OS: [e.g. Windows] - Mono Version: [e.g. Mono 5.8] (Only needed under Linux and Mac, found under System -> Status) - Browser and Version [e.g. chrome, safari] (Only needed for UI issues) - - Radarr Version [e.g. 3.0.0.2956] + - Prowlarr Version [e.g. 3.0.0.2956] **Debug Logs** Turn on debug logs under Settings -> General and wait for the bug to occur again. **Upload the full log file here (or another site and link it). Issues will be closed, if they do not include this!** diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 38407eb5a..5d07027b5 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -4,5 +4,5 @@ contact_links: url: https://discord.gg/r5wJPt9 about: Chat with users and devs on support and setup related topics. - name: Support via Reddit - url: https://reddit.com/r/radarr + url: https://reddit.com/r/prowlarr about: Discuss and search thru support topics. diff --git a/.github/stale.yml b/.github/stale.yml index 39fd82876..69feb7130 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -15,7 +15,7 @@ exemptLabels: staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > - This issue has been automatically marked as stale because it has not had recent activity. Please verify that this is still an issue with the latest version of Radarr and report back. Otherwise this issue will be closed. + This issue has been automatically marked as stale because it has not had recent activity. Please verify that this is still an issue with the latest version of Prowlarr and report back. Otherwise this issue will be closed. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false only: issues diff --git a/.github/support.yml b/.github/support.yml index a7ac6752c..c1aa953d7 100644 --- a/.github/support.yml +++ b/.github/support.yml @@ -6,7 +6,7 @@ supportLabel: support # to a support page, or set to `false` to disable supportComment: > We use the issue tracker exclusively for bug reports and feature requests. - However, this issue appears to be a support request. Please hop over onto our [Discord](https://discord.gg/r5wJPt9) or [Subreddit](https://reddit.com/r/radarr) + However, this issue appears to be a support request. Please hop over onto our [Discord](https://discord.gg/r5wJPt9) or [Subreddit](https://reddit.com/r/prowlarr) # Whether to close issues marked as support requests close: true # Whether to lock issues marked as support requests diff --git a/.gitignore b/.gitignore index eacdd16c7..abccf45c9 100644 --- a/.gitignore +++ b/.gitignore @@ -105,7 +105,7 @@ App_Data/*.ldf _NCrunch_* _TeamCity* -# Radarr +# Prowlarr config.xml nzbdrone.log*txt UpdateLogs/ @@ -171,8 +171,8 @@ packages.config.md5sum **/.idea/**/tasks.xml **/.idea/shelf/* **/.idea/dictionaries -**/.idea/.idea.Radarr.Posix -**/.idea/.idea.Radarr.Windows +**/.idea/.idea.Prowlarr.Posix +**/.idea/.idea.Prowlarr.Windows # Sensitive or high-churn files **/.idea/**/dataSources/ diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index e8727da57..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,1096 +0,0 @@ -# Changelog - -## (unreleased) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Tags support to NetImport (Lists) ([#3127](https://github.com/Radarr/Radarr/issues/3127)) [Ricardo Amaral] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Improved templates for h264 & h265 custom formats ([#3432](https://github.com/Radarr/Radarr/issues/3432)) [RhinoRhys] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Logo-256.png to a transparent version so it looks better in Android notifications. ([#3479](https://github.com/Radarr/Radarr/issues/3479)) [jwildman16] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Radarr_Download_Id and Radarr_Download_Client to the environment ([#3276](https://github.com/Radarr/Radarr/issues/3276)) [Logan] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Allow CheckForFinishedDownloadInterval to be set from the UI ([#3233](https://github.com/Radarr/Radarr/issues/3233)) [Steven Crouchman] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Added support for Gotify notifications ([#3474](https://github.com/Radarr/Radarr/issues/3474)) [stephanrenggli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Remote poster and fanart references to Kodi metadata file ([#2837](https://github.com/Radarr/Radarr/issues/2837)) ([#3302](https://github.com/Radarr/Radarr/issues/3302)) [RobinQ124274] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Support Krypton Kodi Unique Ids ([#3388](https://github.com/Radarr/Radarr/issues/3388)) [Qstick] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Adjust Max Slider Value for Qualities ([#3393](https://github.com/Radarr/Radarr/issues/3393)) [Qstick] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md ([#3409](https://github.com/Radarr/Radarr/issues/3409)) [hotio] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Nzb Validation and Nzbget/SAB URLBase ([#3380](https://github.com/Radarr/Radarr/issues/3380)) [Qstick] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) docker link in README. [hotio] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Solve ambiguous naming ([#3417](https://github.com/Radarr/Radarr/issues/3417)) [Viserius] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Copy to clipboard not working with calendar feed ([#3495](https://github.com/Radarr/Radarr/issues/3495)) [Michael Poutre] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Edition Tags Not Showing in UI ([#3389](https://github.com/Radarr/Radarr/issues/3389)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Support new feed url format IPTorrents ([#573](https://github.com/Radarr/Radarr/issues/573)) ([#3390](https://github.com/Radarr/Radarr/issues/3390)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaCovers Race condition which leads to fanart not being downloaded. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Cannot Add ITA or ITALIAN custom format ([#3385](https://github.com/Radarr/Radarr/issues/3385)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) OsInfo for real this time. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error in unicode cleanup code removing most non-latin characters instead of just invalid ones. ([#3383](https://github.com/Radarr/Radarr/issues/3383)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Forced Subs not parsed by SubtitleLanguageRegex ([#3384](https://github.com/Radarr/Radarr/issues/3384)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) OsInfo being renamed to PlatformInfo. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Word Boundary on Edition ([#3382](https://github.com/Radarr/Radarr/issues/3382)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Mis-classification of releases as being Czech ([#3378](https://github.com/Radarr/Radarr/issues/3378)) [Václav Slavík] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Match MBluray releases ([#3358](https://github.com/Radarr/Radarr/issues/3358)) [Pieter Janssens] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Mono bug causing memory leakage when http connections use gzip compression. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Build errors due to dotnet library. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Emby library update ([#3318](https://github.com/Radarr/Radarr/issues/3318)) [hatharry] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Prevent NullRef in CustomScript on Grab for Indexer ([#3323](https://github.com/Radarr/Radarr/issues/3323)) [tobsen987] - - -## v0.2.0.1293 (2019-01-10) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Use APIKey & APIUser for authenticating to PassThePopcorn. ([#3264](https://github.com/Radarr/Radarr/issues/3264)) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Support for forcedUP status ([#3277](https://github.com/Radarr/Radarr/issues/3277)) [Swizzy] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) rTorrent - Don't start download automatically ([#3222](https://github.com/Radarr/Radarr/issues/3222)) [lps-rocks] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Remove Pre, postbot, xpost suffixes from release groups ([#3220](https://github.com/Radarr/Radarr/issues/3220)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Secure URLs for Links and Services ([#3219](https://github.com/Radarr/Radarr/issues/3219)) [Qstick] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hopefully fixed sqlite errors when finding by title. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Another IDisposable leak when lazy loading properties. [Taloth Saldono] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaCoverService tests and stupidly forgetting to open the database connection for logging. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaCovers resizing potentially leaking memory when concurrently executing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Stream leakage inside CurlHttpDispatcher. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Apparently Microsoft thinks that you should cast to IDisposable first. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Invalid SQLite cache size. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Resource leakage inside HttpClient. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Typo that could probably lead to an infinite loop. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Resource leakage inside ManagedHttpDispatcher. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Leaking of objects when logging something to the database. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) DataMapper potentially leaking stuff when being disposed. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) DataMapper not being disposed, leading to resource leakage. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Memory leak due to unmanaged Bitmaps leaking. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Unable to parse movies from 1800s. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) OSX Packages not getting correct version info. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) npm start not working with node 10. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hopefully fixed issue where a null downloadId or title would cause no downloads to be tracked. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Bump default version to prevent update running from source ([#3199](https://github.com/Radarr/Radarr/issues/3199)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaInfo Unit Test Failing due to AudioAdditionalFeatures ([#3221](https://github.com/Radarr/Radarr/issues/3221)) [Qstick] - - -## v0.2.0.1216 (2018-11-07) - -### **New features** -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) 64bit mediainfo.dll to 32bit to resolve issue: https://github.com/Radarr/Radarr/issues/3138. [geogolem] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Refactor MediaInfo tokens (fixes old tokens adds new stuff) ([#3058](https://github.com/Radarr/Radarr/issues/3058)) [Ricardo Amaral] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Don't hide custom formats behind advanced settings when editing quality. [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Upped rate at which we scan the download client. Should reduce cpu and ram usage as well as decrease pressure on download clients. [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Improve model and UI handling for lists. Should finally fix root folder errors. ([#3133](https://github.com/Radarr/Radarr/issues/3133)) [Ricardo Amaral] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Don't return unmapped folders on rootfolder API call. Massively improves loading time. ([#3116](https://github.com/Radarr/Radarr/issues/3116)) [Justin Kromlinger] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Support for Homebrew-installed mono ([#3090](https://github.com/Radarr/Radarr/issues/3090)) [Jeff Byrnes] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) mk3d file format ([#2795](https://github.com/Radarr/Radarr/issues/2795)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) "Add Paused" option to Deluge and Transmission ([#3038](https://github.com/Radarr/Radarr/issues/3038)) [cookandy] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) All-around small improvements ([#3032](https://github.com/Radarr/Radarr/issues/3032)) [Ricardo Amaral] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Czech Language ([#2948](https://github.com/Radarr/Radarr/issues/2948)) [halali] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Fallback to Bitrate_Nominal for MediaInfo ([#2886](https://github.com/Radarr/Radarr/issues/2886)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) All new custom formats 9000! (Rescan old files, delete formats, polish UI, etc. See discord for full changes): [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Upgrade MediaInfo to 17.10 (Windows/macOS) [Mark McDowall] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) The ability to set the number of threads (NOT SUPPORTED!) to use for tasks using THREAD_LIMIT environment variable. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Adds unmonitored filter option in index and editor ([#2888](https://github.com/Radarr/Radarr/issues/2888)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Monitor Toggle on Movies Editor Page ([#2887](https://github.com/Radarr/Radarr/issues/2887)) [Qstick] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) "importing an episode" to "importing a movie file" ([#2829](https://github.com/Radarr/Radarr/issues/2829)) [Travis Boss] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Fallback to 'VideoCodec' if 'VideoFormat' is unavailable ([#3142](https://github.com/Radarr/Radarr/issues/3142)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Read video 'BitRate_Nominal' if 'BitRate' is empty ([#3144](https://github.com/Radarr/Radarr/issues/3144)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) UpdateMovieQualityService Tests. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Ignore "special drives" from System » Disk Space ([#3050](https://github.com/Radarr/Radarr/issues/3050)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Tweak style of movie path template on "add movies" screen ([#3108](https://github.com/Radarr/Radarr/issues/3108)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Unable to update custom formats for releases with bad Source Titles. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Do not search movie if unmonitored ([#3131](https://github.com/Radarr/Radarr/issues/3131)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Quality badges not being shown on bulk import. ([#3121](https://github.com/Radarr/Radarr/issues/3121)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Trim filename from Kodi movie path before sending library scan request. ([#3097](https://github.com/Radarr/Radarr/issues/3097)) [Lawrence] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hopefully fixed bulk import not showing files. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MPEG-2 remuxes being detected as "Raw-HD" quality. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Allow directory to be parsed similar to past implementation ([#3057](https://github.com/Radarr/Radarr/issues/3057)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Class names on the 'add movies screen' ([#3047](https://github.com/Radarr/Radarr/issues/3047)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Use proper cursor for text and linked labels ([#3041](https://github.com/Radarr/Radarr/issues/3041)) [Ricardo Amaral] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Donate button requiring two clicks to actually work. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Templates for custom format using wrong modifiers. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Profiles always failing validation. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) ImdbIds not being padded with zeroes, which messes up matching. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Issue with custom formats when profile was saved with non existing formats. Also you now don't have to refresh your browser for them to appear / disappear. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Migration would add double underscores for format tags without modifiers. Also fixed Radarr misparsing those tags and added migration to correct this. [Leonardo Galli] -- [WIP] Additions to custom formats, such as rescanning old files. ([#2949](https://github.com/Radarr/Radarr/issues/2949)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Unnecessary housekeeping commands consuming a lot of memory. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Annoying [renamemoviesfolder] Completed popup for no reason. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Concurrent manual imports silently failing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Files that cannot be parsed, kill bulk import. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Absolutely Required Format Tag modifier being ignored when multiple modifiers were present. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when valid movie file id is around, but movie file is not loaded. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movies not being unmonitored when using clean library and lists. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Also scan media info when file is being imported (i.e. not an existing file) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Invalid qualities messing up the release module and other stuff. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Languages not showing up correctly. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Null exception due to resharper refactoring. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) No media info causing an error when importing files. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Saving IndexerSettings into DB which confuses the datamapper. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Not using correct info for determining state! [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Ability to add custom formats, working similar to qualities. ([#2669](https://github.com/Radarr/Radarr/issues/2669)) [Leonardo Galli] -- Create reaction.yml. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) .vtt files treated as subtitles ([#2885](https://github.com/Radarr/Radarr/issues/2885)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Debug log Series reference in QualityAllowedByProfile spec ([#2899](https://github.com/Radarr/Radarr/issues/2899)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Multiple UI Fixes and Additions ([#2894](https://github.com/Radarr/Radarr/issues/2894)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Multiline in table view on two lines ([#2870](https://github.com/Radarr/Radarr/issues/2870)) [hotio] - - -## v0.2.0.1120 (2018-05-27) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) AHD_Internal and G_Scene indexer flags. Also linked a wiki page with more information about indexer flags. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) indexer flags to the list of environmental variable for customs scripts (on grab) ([#2801](https://github.com/Radarr/Radarr/issues/2801)) [bobbintb] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) issue templates. [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) AwesomeHD failing on an empty imdbid. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Rare timing issue on first-use causing duplicate naming config ([#2790](https://github.com/Radarr/Radarr/issues/2790)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Qbittorrent state and eta fixes ([#2789](https://github.com/Radarr/Radarr/issues/2789)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Purge alt titles on movie delete ([#2796](https://github.com/Radarr/Radarr/issues/2796)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Don’t allow profiles in use by lists to be deleted ([#2797](https://github.com/Radarr/Radarr/issues/2797)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Throwing error when indexer doesn't support a category. Now only warns the user. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Broken Newznab testing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Omgwtfnzbs API categories (UHD, Full BR and Other) ([#2764](https://github.com/Radarr/Radarr/issues/2764)) [jusher00] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Indexers that do not support movie search should give better error messages. Radarr now also complains if an indexer does not support certain categories. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) RSS Feeds with no description failing to be added. [Leonardo Galli] - - -## v0.2.0.1067 (2018-04-17) - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Radarr not loading with an invalid sort key. [Leonardo Galli] - - -## v0.2.0.1066 (2018-04-16) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) More logging for strange PTP errors. Please report them immediately when you see them. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Setting for Colon Replacement Format ([#2711](https://github.com/Radarr/Radarr/issues/2711)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Enable Download Client Priorities ([#2699](https://github.com/Radarr/Radarr/issues/2699)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Radarr now stores cookies for PTP beyond restarts. Should limit active sessions correctly. ([#2643](https://github.com/Radarr/Radarr/issues/2643)) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Setting for absolute maximum size for a release ([#2662](https://github.com/Radarr/Radarr/issues/2662)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) A Huge Cleanup of old Series Code. (Let's pray nothing breaks :P) ([#2589](https://github.com/Radarr/Radarr/issues/2589)) [Qstick] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) stale.yml. [AeonLucid] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Register as Radarr to avoid issues with Sonarr ([#2715](https://github.com/Radarr/Radarr/issues/2715)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Handling of unknown status types in DownloadStation and Import from torrent Download Station should move since DS maintains an internal copy for seeding. ([#2420](https://github.com/Radarr/Radarr/issues/2420)) [Marcelo Castagna] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Misc Extra File Improvements (This changes mapping of backdrop images to Fanart instead of Banner) ([#2642](https://github.com/Radarr/Radarr/issues/2642)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Multiple Calendar Issues, Other UI Fixes ([#2685](https://github.com/Radarr/Radarr/issues/2685)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Cutoff Unmet Sorting by Downloaded Quality not working. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Add form param before submitting request ([#2674](https://github.com/Radarr/Radarr/issues/2674)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Don't add category when removing torrent from qBittorrent ([#2661](https://github.com/Radarr/Radarr/issues/2661)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) underscore to host part of URI regex ([#2633](https://github.com/Radarr/Radarr/issues/2633)) [mueslo] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) ICS malformed in a lot of cases. Also events are now all day. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Set category when adding torrent to qBittorrent ([#2649](https://github.com/Radarr/Radarr/issues/2649)) [themagicbullet] -- Create support.yml. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Incorrect Kodi nfo date format ([#2605](https://github.com/Radarr/Radarr/issues/2605)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Sort by Downloaded not working. [Leonardo Galli] - - -## v0.2.0.995 (2018-03-04) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Copy & Paste now triggers search ([#2587](https://github.com/Radarr/Radarr/issues/2587)) [Paul Kozlovitch] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) console logging in case NLog fails to initialize. [Taloth Saldono] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Changes in http redirect logic causing failed grabs and >25% cpu usage. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) http->https redirects do not use the tls1.2 curl fallback. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Dates before 1970 causing an exception. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Browser not updating on Movie File Imported. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movies not getting unmonitored when folder gets deleted ([#2588](https://github.com/Radarr/Radarr/issues/2588)) [Simon Chapman] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) NLog causing a crash under mono 5.10. [Leonardo Galli] -- Revert "Fixed: Updated NLog to 4.5 RC6 to handle mono 5.10" [Leonardo Galli] -- Revert "Fixed: Messed up merge from Cherry pick" [Leonardo Galli] -- Revert "Fixed: Appveyor build." [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Appveyor build. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Messed up merge from Cherry pick. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Updated NLog to 4.5 RC6 to handle mono 5.10. [Leonardo Galli] -- Revert "Fixed: NLog causing a crash under mono 5.10" [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Pin cake and addin versions. [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Temp Workaround for Appveyor Cake Issue. [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) NLog causing a crash under mono 5.10. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Poster sliding issues ([#2570](https://github.com/Radarr/Radarr/issues/2570)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Multiple History Issues ([#2571](https://github.com/Radarr/Radarr/issues/2571)) [Qstick] - - -## v0.2.0.980 (2018-02-21) - -### **New features** -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Metadata links are now better readable. Also fixed links in the poster view. ([#2562](https://github.com/Radarr/Radarr/issues/2562)) [thezoggy] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Handle ctrl-c more gracefully. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Device names for Join notifications ([#2544](https://github.com/Radarr/Radarr/issues/2544)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Same File Size MediaFile Specification ([#2532](https://github.com/Radarr/Radarr/issues/2532)) [Qstick] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) NLog to version 4.4.12. Should fix [#2218](https://github.com/Radarr/Radarr/issues/2218) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Importing extra files from downloaded movies and generate metadata such as .nfo ([#2506](https://github.com/Radarr/Radarr/issues/2506)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Quotes around alternative titles ([#2522](https://github.com/Radarr/Radarr/issues/2522)) [Qstick] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Backup improvements from Sonarr ([#2513](https://github.com/Radarr/Radarr/issues/2513)) [Qstick] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) NzbDrone references in FirewallAdapter.cs ([#2504](https://github.com/Radarr/Radarr/issues/2504)) [Qstick] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Another Delete modal is fixed. ([#2560](https://github.com/Radarr/Radarr/issues/2560)) [thezoggy] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Messed up movie deletion modal ([#2552](https://github.com/Radarr/Radarr/issues/2552)) [thezoggy] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Remove sorting on Monitor/Profile columns to prevent unexpected results until sorting can properly be handled. Quick Fix for [#2540](https://github.com/Radarr/Radarr/issues/2540) ([#2553](https://github.com/Radarr/Radarr/issues/2553)) [thezoggy] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) OSX app has bundle name of Sonarr ([#2555](https://github.com/Radarr/Radarr/issues/2555)) [thezoggy] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Alt Titles from TMDB not getting added when mappings server throws 404. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Unable to execute custom scripts if IMDB ID is null ([#2543](https://github.com/Radarr/Radarr/issues/2543)) [Qstick] -- Cleanup TV related code in API ([#2530](https://github.com/Radarr/Radarr/issues/2530)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Omgwtfnbs parsing being too greedy. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Help icon not centered ([#2531](https://github.com/Radarr/Radarr/issues/2531)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Radarr Changes every file due to timezones ([#2533](https://github.com/Radarr/Radarr/issues/2533)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Filters not working. Fuck you backbone. [Leonardo Galli] -- Cleanup Series Code from UI ([#2525](https://github.com/Radarr/Radarr/issues/2525)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Apostrophe getting replaced by an empty string causing no search results. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Integration Unit Tests ([#2500](https://github.com/Radarr/Radarr/issues/2500)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) XSS vulnerability in the navbar search. ([#2505](https://github.com/Radarr/Radarr/issues/2505)) [Scott] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) StartNzbDroneService.cs unit test ([#2499](https://github.com/Radarr/Radarr/issues/2499)) [Qstick] -- SelectAll and deselectAll MovieEditor buttons. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) build problem on windows. [geogolem] -- Revert "Fixed: Removed hebrew ISO, since english movies are still in english. ([#1922](https://github.com/Radarr/Radarr/issues/1922))" [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error with deluge when it doesn’t report a Hash. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Logging error when accessing mount point. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Invalid runtime from CP causing issues importing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Typo in TMDB Settings. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hopefully fixed errors with Delay Profiles. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when importing files and old folder doesn’t exist. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Zooqle torrents not getting added, since their torrent file is messed up. [Leonardo Galli] - - -## v0.2.0.935 (2018-02-06) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Include total space with root folders. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Manual Import now adds year after movie title for filtering. This should help finding movies such as IT. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Option to require indexer flags per indexer. (e.g. only download freeleech torrents from a private tracker) ([#2460](https://github.com/Radarr/Radarr/issues/2460)) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Files downloaded with different quality than grabbed will get rejected. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) TMDbSettings.cs to allow pipe for or for genre ids ([#2389](https://github.com/Radarr/Radarr/issues/2389)) [crhammock] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Dynamic paths cleanup old folders now! [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) No Physical Release Date causing exception when setting last write time. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movies not getting unmonitored when folder gets deleted. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Rare case of null quality causing issues with manual import. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Manual Import not automatically choosing right movie. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Rare case of RequiredIndexerFlags failing with old Newznab indexers. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Folder name getting messed up when adding movies via a list. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when adding an already excluded movie to the exclusion list. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Last commit still not compiling (whoops squared) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Last commit not compiling (whoops) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Clean Library being to agressive when lists are having failures. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when nno quality was associated with a movie file. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Allowing in use Profiles to be Deleted. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when Movie has no imdbid when searching Rargb. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Rargb failing when imdbid is not found. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) {Original Filename} not allowed in Movie Filename. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Look for changes to package.json before using old build cache ([#2445](https://github.com/Radarr/Radarr/issues/2445)) [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) HistoryDetailsLayoutTemplate.hbs ([#2361](https://github.com/Radarr/Radarr/issues/2361)) [Pieter Janssens] - - -## v0.2.0.910 (2017-12-13) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Separate naming tags for AudioLanguage and SubtitleLanguage ([#2261](https://github.com/Radarr/Radarr/issues/2261)) (Fixes [#2257](https://github.com/Radarr/Radarr/issues/2257)) [fhscholl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Include APFS disks in disk space calculation. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Upgrade MediaInfo to 17.10 (Windows/macOS) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Support for VF2 french tag. ([#2291](https://github.com/Radarr/Radarr/issues/2291)) (Fixes [#2290](https://github.com/Radarr/Radarr/issues/2290)) [kriegalex] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Customize Slack Channel ([#2308](https://github.com/Radarr/Radarr/issues/2308)) (Fixes [#2298](https://github.com/Radarr/Radarr/issues/2298)) [grokdesigns] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) SceneName to MovieFile API output ([#2250](https://github.com/Radarr/Radarr/issues/2250)) (Fixes [#2245](https://github.com/Radarr/Radarr/issues/2245)) [fhscholl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Functionality to XBMC and Plex to update indivdual titles. Also: Notification Cleanup ([#2240](https://github.com/Radarr/Radarr/issues/2240)) [fhscholl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) FolderPath to the Movie Webhook ([#2230](https://github.com/Radarr/Radarr/issues/2230)) [adnanklink] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Download_Id to On Download/On Upgrade ([#2229](https://github.com/Radarr/Radarr/issues/2229)) [adnanklink] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Movie_Quality to onGrab ([#2221](https://github.com/Radarr/Radarr/issues/2221)) (Fixes [#1833](https://github.com/Radarr/Radarr/issues/1833)) [fhscholl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Webhook Improvements ([#2220](https://github.com/Radarr/Radarr/issues/2220)) (Fixes [#1751](https://github.com/Radarr/Radarr/issues/1751)) [fhscholl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Message about adblockers preventing the log table from loading ([#2213](https://github.com/Radarr/Radarr/issues/2213)) (Fixes [#2209](https://github.com/Radarr/Radarr/issues/2209)) [James White] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Sabnzbd Update test cases and rename to MovieCategory ([#2212](https://github.com/Radarr/Radarr/issues/2212)) [James White] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Nzbget Rename TvCategory references to MovieCategory ([#2211](https://github.com/Radarr/Radarr/issues/2211)) [James White] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) default port of qBittorrent download client config ([#2187](https://github.com/Radarr/Radarr/issues/2187)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Initial state for torrents added to qBittorrent ([#2176](https://github.com/Radarr/Radarr/issues/2176)) [James White] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Adjust ambiguous date options ([#2165](https://github.com/Radarr/Radarr/issues/2165)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) a default name for Radarr.ics ([#2163](https://github.com/Radarr/Radarr/issues/2163)) [James White] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaCover endpoint. [Taloth Saldono] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Don't handle content requests in IndexHtmlMapper. [Mark McDowall] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movies parsed from lists with no year and only title getting added mutliple times. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Security Vulnerabilities allowing authentication to be bypassed (discovered by Kyle Neideck) [Taloth Saldono] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movie Editor Path screwed up. Might also fix some other movie editor issues. (Fixes [#2170](https://github.com/Radarr/Radarr/issues/2170)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Tags disappearing (Fixes [#2204](https://github.com/Radarr/Radarr/issues/2204)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) moment.js deprecated zone and add functions (Fixes [#2232](https://github.com/Radarr/Radarr/issues/2232)) (Fixes [#2231](https://github.com/Radarr/Radarr/issues/2231)) ([#2264](https://github.com/Radarr/Radarr/issues/2264)) [Fish2] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) CPU locking at a 100% in certain instances. ([#2258](https://github.com/Radarr/Radarr/issues/2258)) (Fixes [#2218](https://github.com/Radarr/Radarr/issues/2218)) [Mike] -- Revert "Fixed: moment.js deprecated zone and Added: and lossless compression of images ([#2232](https://github.com/Radarr/Radarr/issues/2232)) (Fixes [#2231](https://github.com/Radarr/Radarr/issues/2231))" [Fish2] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) moment.js deprecated zone and Added: and lossless compression of images ([#2232](https://github.com/Radarr/Radarr/issues/2232)) (Fixes [#2231](https://github.com/Radarr/Radarr/issues/2231)) [Fish2] -- Fixes [#2218](https://github.com/Radarr/Radarr/issues/2218). ([#2254](https://github.com/Radarr/Radarr/issues/2254)) [Mike] -- Minor error message tweak ([#1778](https://github.com/Radarr/Radarr/issues/1778)) [Oliver Rivett-Carnac] -- UTorrent initial state feature ([#2192](https://github.com/Radarr/Radarr/issues/2192)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) IsUpgrade and related deleted file paths for CustomScript ([#2205](https://github.com/Radarr/Radarr/issues/2205)) [fhscholl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) typo on margin-bottom ([#2182](https://github.com/Radarr/Radarr/issues/2182)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Manual Import. Fixes [#2160](https://github.com/Radarr/Radarr/issues/2160) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Remove unit on zero values ([#2178](https://github.com/Radarr/Radarr/issues/2178)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Jackett apikey cleaned from log again. ([#2177](https://github.com/Radarr/Radarr/issues/2177)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Manual Movie Page Filtering. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaInfo not getting read when quality isn't Bluray, Web-dl or HDTV. Fixes [#1465](https://github.com/Radarr/Radarr/issues/1465). Fixes [#1572](https://github.com/Radarr/Radarr/issues/1572). [Leonardo Galli] - - -## v0.2.0.870 (2017-10-09) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) new codec HEVC with ID=5 for HDBits ([#2146](https://github.com/Radarr/Radarr/issues/2146)) [Wyall] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Option to omit year from indexer searches when searching by title. Also added option to force a movie search by title instead of imdb id. Fixes [#1912](https://github.com/Radarr/Radarr/issues/1912) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Last round of optimisation. Large libraries should load around 2x faster again compared to the last version. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Improved load times of very large libraries again (around x5) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Movie files are now eager loaded. This should speed up the loading process a lot as well as RSS Sync and other tasks. It should also prevent some other bugs. [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Alignment and buttons position of Trakt Auth ([#2153](https://github.com/Radarr/Radarr/issues/2153)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) SUBBED in release name not recognized as hardcoded subs. Fixes [#1520](https://github.com/Radarr/Radarr/issues/1520) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) 1080i not correctly recognized as 1080p. Fixes [#1622](https://github.com/Radarr/Radarr/issues/1622) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Releases with UHD not getting correct resolution label. Fixes [#2134](https://github.com/Radarr/Radarr/issues/2134) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) WebDL gets marked as Remux. Fixes [#1954](https://github.com/Radarr/Radarr/issues/1954) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Parsing of TSRip and HDTSRip. Fixes [#1998](https://github.com/Radarr/Radarr/issues/1998) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) unclosed tag on BulkImportView ([#2110](https://github.com/Radarr/Radarr/issues/2110)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Change to correct provider of search results ([#2113](https://github.com/Radarr/Radarr/issues/2113)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Icon not being hidden on Discover New Movies button in X-Small breakpoint ([#2114](https://github.com/Radarr/Radarr/issues/2114)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Font folder case fix ([#2066](https://github.com/Radarr/Radarr/issues/2066)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Add space in confirmation message ([#2101](https://github.com/Radarr/Radarr/issues/2101)) [Adam Dangoor] -- Create LICENSE. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Alternative Titles appearing multiple times. Duplicate alt titles will be deleted. Fixes [#2040](https://github.com/Radarr/Radarr/issues/2040) [Leonardo Galli] - - -## v0.2.0.852 (2017-09-10) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) WOFF2 fonts for better performance in supported browsers ([#1994](https://github.com/Radarr/Radarr/issues/1994)) [James White] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Tweak NavbarLayoutTemplate.hbs ([#1996](https://github.com/Radarr/Radarr/issues/1996)) [James White] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Scripts should be included before closing body tag ([#1995](https://github.com/Radarr/Radarr/issues/1995)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Allow toolbar buttons to be full width on x-small and small breakpoints ([#1972](https://github.com/Radarr/Radarr/issues/1972)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Alt titles with less than 4 votes being used. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Cleanup of unused alt titles. [Leonardo Galli] - - -## v0.2.0.846 (2017-08-27) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Ability to force download movies that could not be mapped correctly. This also shares these mappings with other users, so everyone can profit :) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Display breakpoint name in browser window in debug mode ([#1968](https://github.com/Radarr/Radarr/issues/1968)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Ability to delete multiple movies at once via the movie editor. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Deprecation warning about Drone Factory to front end ([#1938](https://github.com/Radarr/Radarr/issues/1938)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Package-lock.json for npm 5 ([#1939](https://github.com/Radarr/Radarr/issues/1939)) [James White] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) FontAwesome to 4.7.0 ([#1928](https://github.com/Radarr/Radarr/issues/1928)) [James White] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Hebrew language ([#1909](https://github.com/Radarr/Radarr/issues/1909)) [Rotem] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Run tests through powershell. ([#1903](https://github.com/Radarr/Radarr/issues/1903)) [Mike] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Alternative Titles are now also pulled from mappings.radarr.video. [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Alternative Titles were reworked greatly. This should speed up RSS Sync massively, especially for large libraries (up to 4x). [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Refresh movie failing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Refresh movie failing for most movies. (Fixes [#2007](https://github.com/Radarr/Radarr/issues/2007)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) A few issues with the new alternative titles feature. ([#2008](https://github.com/Radarr/Radarr/issues/2008)) (Fixes [#1919](https://github.com/Radarr/Radarr/issues/1919), [#1927](https://github.com/Radarr/Radarr/issues/1927) and [#1917](https://github.com/Radarr/Radarr/issues/1917)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) A lot of small ui errors (e.g. More not showing) (Revert of [#1959](https://github.com/Radarr/Radarr/issues/1959)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Adjust Sonarr references to Radarr ([#1977](https://github.com/Radarr/Radarr/issues/1977)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Rename movie not working ([#1970](https://github.com/Radarr/Radarr/issues/1970)) (Fixes [#1908](https://github.com/Radarr/Radarr/issues/1908)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error with CP Import when no info is present. Fixes [#1792](https://github.com/Radarr/Radarr/issues/1792) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movie files & folders will actually get deleted now ([#1966](https://github.com/Radarr/Radarr/issues/1966)) (Fixes [#694](https://github.com/Radarr/Radarr/issues/694)) [Tom] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Bulk UI cleanup, fixes and consistency improvements ([#1959](https://github.com/Radarr/Radarr/issues/1959)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Parser error when using `(year) name` folder ([#1956](https://github.com/Radarr/Radarr/issues/1956)) (Fixes [#1951](https://github.com/Radarr/Radarr/issues/1951)) [MangaValk] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Missing icon preventing detailed explanation validation errors explanations from appearing. ([#1944](https://github.com/Radarr/Radarr/issues/1944)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Mask-icon and other resources when UrlBase is in use ([#1933](https://github.com/Radarr/Radarr/issues/1933)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Slack/Mattermost notifications improvements from Sonarr ([#1930](https://github.com/Radarr/Radarr/issues/1930)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) fontawesome path (Icons disappearing) ([#1929](https://github.com/Radarr/Radarr/issues/1929)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Charset and meta in index.html and login.html ([#1926](https://github.com/Radarr/Radarr/issues/1926)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Removed hebrew ISO, since english movies are still in english. ([#1922](https://github.com/Radarr/Radarr/issues/1922)) [Rotem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Adjust column sizes relative to size of dropdown values ([#1923](https://github.com/Radarr/Radarr/issues/1923)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Additional jshint warnings ([#1921](https://github.com/Radarr/Radarr/issues/1921)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Minor issues on MoreInfoViewTemplate.hbs ([#1916](https://github.com/Radarr/Radarr/issues/1916)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) gulp jshint warnings ([#1873](https://github.com/Radarr/Radarr/issues/1873)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Replace GitHub wiki references to Radarr's wiki URL ([#1914](https://github.com/Radarr/Radarr/issues/1914)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hanging form-group div ([#1911](https://github.com/Radarr/Radarr/issues/1911)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Migration failing and thus making Radarr unable to start. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Task name of PreDB Sync task ([#1875](https://github.com/Radarr/Radarr/issues/1875)) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Check that Quality Profile is not in use before deleting it. [Qstick] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Category not setting with qBitTorrent 3.3.14 and other api errors. (upstream from Sonarr) [James White] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Non-Freeleech torrents showing as freeleech for AHD. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Older movies (released more than 30 days ago) are now not refreshed as often anymore (every 30 days) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) (Hopefully) Bug where movie file was not correctly linked to movie. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) No API Key required with SignalR connections. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Guard agains null reference exception with newznab capabilities. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Update Info.plist to avoid conflict with Sonarr ([#1783](https://github.com/Radarr/Radarr/issues/1783)) [Marc Runkel] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Relax SingleInstancePolicy when using a custom data directory Fixes [#1765](https://github.com/Radarr/Radarr/issues/1765) ([#1782](https://github.com/Radarr/Radarr/issues/1782)) [Richard Schwab] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Lists are fetched much more efficiently. (Up to 40x loading time improvement with large lists!) [Leonardo Galli] -- Revert "Fixed: Support for Mono 5.x with the newer BoringTLS provider." [Taloth Saldono] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Support for Mono 5.x with the newer BoringTLS provider. [Taloth Saldono] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Old Plex ValidationFailure message ([#1770](https://github.com/Radarr/Radarr/issues/1770)) [Sandro Stikić] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) BDRemux not recognized as such and BDRips without resolution recognized as DVD. Fixes [#1755](https://github.com/Radarr/Radarr/issues/1755) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) A as part of an acronym being removed from clean title. Fixes [#1747](https://github.com/Radarr/Radarr/issues/1747) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Folder in List settings appearing blank in some browsers. Fixes [#1711](https://github.com/Radarr/Radarr/issues/1711) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Minimum Seeders not saving for Torznab indexer. Fixes [#1736](https://github.com/Radarr/Radarr/issues/1736) [Leonardo Galli] - - -## v0.2.0.778 (2017-06-20) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Radarr API url now points to new v2 version. [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Name of Radarr Lists. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) More detailed descriptions why a movie was not able to be mapped. ([#1696](https://github.com/Radarr/Radarr/issues/1696)) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Options to make parsing more lenient. (Adds support for some german and french releasegroups) ([#1692](https://github.com/Radarr/Radarr/issues/1692)) [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Bootstrap Tags Input ([#1674](https://github.com/Radarr/Radarr/issues/1674)) [Mitchell Cash] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Include css files in minification ([#1672](https://github.com/Radarr/Radarr/issues/1672)) [Mitchell Cash] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Upgrade to Bootstrap 3.3.7 ([#1673](https://github.com/Radarr/Radarr/issues/1673)) [Mitchell Cash] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Allow minimum seeders to be set on a per indexer basis. Pulled from Sonarr Upstream ([#1624](https://github.com/Radarr/Radarr/issues/1624)) [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Remove redundant IE meta tag as we use http header instead ([#1655](https://github.com/Radarr/Radarr/issues/1655)) [Mitchell Cash] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Use cleancss for minification ([#1654](https://github.com/Radarr/Radarr/issues/1654)) [Mitchell Cash] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Ability to see TMDB and lists going through the Radarr API on the discovery page. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Search 5 alternative titles as well. This should help with french as well as movies with very different titles. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) [Radarr] tag for Twitter Notifications ([#1558](https://github.com/Radarr/Radarr/issues/1558)) [Jason Costomiris] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Custom Class for Radarr API requests. Also implements new error handling present on staging server. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) HDBits Category, Codec, and Medium Filtering Capability ([#1458](https://github.com/Radarr/Radarr/issues/1458)) [randellhodges] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) radarr api url. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) TaskManager.cs. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) LogEntries token again :) [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) migration. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Redirect calls missing URL Base ([#1668](https://github.com/Radarr/Radarr/issues/1668)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Twitter oAuth callback URL ([#1669](https://github.com/Radarr/Radarr/issues/1669)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Error when processing manual import decisions ([#1670](https://github.com/Radarr/Radarr/issues/1670)) [Mitchell Cash] -- Create README.md. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) license. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Urls missing from multiple indexers after latest nightly update. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Follow 301 redirects when fetching torrents ([#1653](https://github.com/Radarr/Radarr/issues/1653)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Ensure an API Key is set when starting Radarr ([#1652](https://github.com/Radarr/Radarr/issues/1652)) [Mitchell Cash] -- Minimum availability is now working similarely to profile when adding a movie. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Forgot to include some js files in the last commit. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error when we get invalid datetime from our api. [Leonardo Galli] -- Lossless compression of images saved 92KB ([#1620](https://github.com/Radarr/Radarr/issues/1620)) [Fish2] -- Mostly fixes UI glitches for list settings. [Leonardo Galli] -- Refresh IsDuplicate in bulk import when the tmdbId changes ([#1570](https://github.com/Radarr/Radarr/issues/1570)) [Sentir101] -- Encourage Torznab use with Jackett ([#1559](https://github.com/Radarr/Radarr/issues/1559)) [flightlevel] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) PTP indexer being disabled if no results are found for a movie. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) basic naming settings. [Leonardo Galli] -- Discovery of upcoming movies points to our server now. [Leonardo Galli] -- Most likely fixed [#745](https://github.com/Radarr/Radarr/issues/745) now. [Mike] -- Chmod osx file as executable. ([#1539](https://github.com/Radarr/Radarr/issues/1539)) [Mike] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) IMDB URL to notifications ([#1531](https://github.com/Radarr/Radarr/issues/1531)) [tsubus] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) design calendar css bug ([#1527](https://github.com/Radarr/Radarr/issues/1527)) [Levi Wilcox] -- Correct Program Name ([#1524](https://github.com/Radarr/Radarr/issues/1524)) [Luke Anderson] -- Correct Program Name ([#1523](https://github.com/Radarr/Radarr/issues/1523)) [Luke Anderson] -- Osx updater now updates plist file to point to the correct executable binary. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Using our own logentries token now. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) osx updater failing. [Leonardo Galli] - - -## v0.2.0.696 (2017-05-12) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) TaskManager.cs. [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) test. [Leonardo Galli] -- Movies with same name but different year being downloaded regardlessly is now fixed! [Leonardo Galli] - - -## v0.2.0.692 (2017-05-11) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) ability to discover new movies based on upcoming blurays as well as popular movies (borrowed from steven lu :)) [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Kodi icon, fixes [#1464](https://github.com/Radarr/Radarr/issues/1464) ([#1492](https://github.com/Radarr/Radarr/issues/1492)) [hotio] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) initial migration. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) trailer links to the discovery page. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) discovery tab based on tmdb recommendations based on your existing movies. ([#1450](https://github.com/Radarr/Radarr/issues/1450)) [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) default page size to 250. Should help with safari timeouts. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) multiple new editions such as FanEdit, Anniversary and 2in1. [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) design issue when deleting css bug ([#1480](https://github.com/Radarr/Radarr/issues/1480)) Fixes [#1475](https://github.com/Radarr/Radarr/issues/1475) [Levi Wilcox] -- 10 Movies are now shown on discover as well as search results. [Leonardo Galli] -- Hotfix for when ignored movies would appear again after clicking on show more. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) appveyor build. [Leonardo Galli] -- Completely overhauled how import exclusions work. [Leonardo Galli] -- Hopefully more logging to catch errors better. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) A small bug fix for items loading as undefined in organize modal. Movie titles should now show up correctly. ([#1424](https://github.com/Radarr/Radarr/issues/1424)) [PatrickGHanna] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error when language is present in title, but has dots instead of spaces. For example The.Danish.Girl.2015. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Final in titles parsing as an edition. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Radarr not importing torrents in Vuze if the torrent already finished seeding and was stopped ([#1471](https://github.com/Radarr/Radarr/issues/1471)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Incorrect imports with Vuze when torrent contains a single file. ([#1470](https://github.com/Radarr/Radarr/issues/1470)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Sonarr UI Authentication cookie should be placed on path (UrlBase) instead of domain alone. Fixes #[#1451](https://github.com/Radarr/Radarr/issues/1451) [Mitchell Cash] -- Use Post for tmdbids request, to avoid too long URIs. [Leonardo Galli] -- Tidy up layout of buttons on the Add Movies page for mobile/tablet ([#1454](https://github.com/Radarr/Radarr/issues/1454)) [David Pooley] -- Rename Sonarr to Radarr for OSX App. [morberg] -- Minor text fixes. [Leonardo Galli] -- Enable automatic renaming, according to naming scheme, of movie folder after creation of the movie. ([#1349](https://github.com/Radarr/Radarr/issues/1349)) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for error when clicking Rescan Drone Folder. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for error when trying to manually import. [Leonardo Galli] - - -## v0.2.0.654 (2017-04-18) - -### **New features** -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) smtp.google.com to smtp.gmail.com ([#1410](https://github.com/Radarr/Radarr/issues/1410)) [Donald Webster] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) debug movie title to include Year. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Series reference to Movies, should fix [#1399](https://github.com/Radarr/Radarr/issues/1399) ([#1402](https://github.com/Radarr/Radarr/issues/1402)) [hotio] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) test for fix in last commit. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) branch. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) packages.sh some more. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) package.sh script. [Leonardo Galli] - -### **Fixes** -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) PTP_Approved turning into HDBits Internal. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) ptp tests. [Leonardo Galli] -- AHD, PTP and HDB support the new indexer flags too now! Indexer flags can be preferred over other releases. [Leonardo Galli] -- Movies with Umlauts are now correctly matched and have correct CleanTitles. [Leonardo Galli] -- Minor Text fixes. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error when MinimumAvailability was Announced and Delay was negative. [Leonardo Galli] -- Disable PreDB sync for now. [Leonardo Galli] -- Stats are now sent to our server instead of Sonarr's :) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for sql error. Did not think everything through exactly. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) when MovieTitle is the empty string (should not occur, but what evs) [Leonardo Galli] -- Fixes Movie Size not showing correctly. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) an issue where movies which were labelled with an alternative title could not be found. [Leonardo Galli] -- Indexer flags implementation. ([#1377](https://github.com/Radarr/Radarr/issues/1377)) Will be further finalized over the next few weeks with Freelech, preferring of certain flags, etc. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) default runtime when runtime info of tmdb says 0. [Leonardo Galli] -- Fixes an issue where the semicolon and space afterwards was replaced. [Leonardo Galli] -- Final tweak for package.sh. [Leonardo Galli] -- This should finally fix all packaging stuff. [Leonardo Galli] -- Test fixes. [Leonardo Galli] -- More test debugging. [Leonardo Galli] -- Remote Test debugging yey! [Leonardo Galli] -- Remove unecessary test. [Leonardo Galli] -- Using NUnit.Runners so that teamcity build works. [Leonardo Galli] -- Turn installer back on. [Leonardo Galli] -- Disabled installer being picked up, causes error with update api. [Leonardo Galli] -- Now artifacts get pushed even if tests fail. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) package script for Teamcity. [Leonardo Galli] -- Log if ParsedMovieInfo is NULL. [Leonardo Galli] -- Catching predb.me errors hopefully. [Leonardo Galli] - - -## v0.2.0.596 (2017-04-10) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) nzbdrone.iss. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) appveyor.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) build-appveyor.cake. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) appveyor.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) appveyor.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) nzbdrone.iss. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) build-appveyor.cake. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) build-appveyor.cake. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) appveyor.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) build-appveyor.cake. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) appveyor.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) nzbdrone.iss. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) nzbdrone.iss. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) "Additional Parameters Field" for Trakt RSS Feed ([#1308](https://github.com/Radarr/Radarr/issues/1308)) [rmangahas-coupa] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) movie search ([#1212](https://github.com/Radarr/Radarr/issues/1212)) [thejacer87] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Devin Buhl] - -### **Fixes** -- Just getting Appveyor to build. [Leonardo Galli] -- Installer should be built too now. [Leonardo Galli] -- Text fixes and got pending releases finally fully working. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) searching for movie after it is added from a list. [Leonardo Galli] -- Specific Subtitle tags (such as nlsub) can now be whitelisted and will be downloaded. [Leonardo Galli] -- Allow Hardcoded subs to be downloaded still. [Leonardo Galli] -- Catching HTTP Errors when adding movies from a list. [Leonardo Galli] -- SABnzbd 2.0 API compatibility ([#1339](https://github.com/Radarr/Radarr/issues/1339)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Zero length file causes MediaInfo hanging in 100% cpu load. ([#1340](https://github.com/Radarr/Radarr/issues/1340)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Newznab default capabilities erroneously cached if indexer is unavailable. ([#1341](https://github.com/Radarr/Radarr/issues/1341)) [Mitchell Cash] -- Cleanup on mapping logic. Movies with up to 4500 parts are now supported! [Rusk85] -- Released icon is back. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) spelling mistake. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) an error when searching for movies with no imdbid. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) DownloadStation api client for DSM 5.x. ([#1259](https://github.com/Radarr/Radarr/issues/1259)) [Marcelo Castagna] -- Should fix covers not being local. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error when downloading a movie. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) only one movie appearing when list does not give us a tmdbid. [Leonardo Galli] -- This should fix all imdbid problems with indexers. [Leonardo Galli] -- Revert "Move up IMDB logic in ParsingService, should help with the mismatched movies" [Devin Buhl] -- Move up IMDB logic in ParsingService, should help with the mismatched movies. [Devin Buhl] -- Clean up jsHint warnings ([#1225](https://github.com/Radarr/Radarr/issues/1225)) [Zach] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) pending release service, HDBits, also the release deduper. Clean up housekeeping ([#1211](https://github.com/Radarr/Radarr/issues/1211)) [Devin Buhl] -- Patch/onedr0p 3 16 17 ([#1200](https://github.com/Radarr/Radarr/issues/1200)) [Devin Buhl] -- Revert "Small changes to list sync ([#1179](https://github.com/Radarr/Radarr/issues/1179))" [Devin Buhl] -- Small changes to list sync ([#1179](https://github.com/Radarr/Radarr/issues/1179)) [Devin Buhl] -- Patch/onedr0p 3 14 17 ([#1171](https://github.com/Radarr/Radarr/issues/1171)) [Devin Buhl] -- Maybe fix PTP? Don't have an account, so cannot test. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for editing quality of movie files. [Leonardo Galli] -- Patch/onedr0p 3 13 17 ([#1166](https://github.com/Radarr/Radarr/issues/1166)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue where 1080p Telesyncs get tagged as 1080p Blurays. [Leonardo Galli] - - -## v0.2.0.535 (2017-03-12) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) blacklist to work with movies ([#1089](https://github.com/Radarr/Radarr/issues/1089)) [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) error to include Radarr instead of Sonarr ([#1069](https://github.com/Radarr/Radarr/issues/1069)) [flightlevel] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) wiki link for sorting and renaming ([#1045](https://github.com/Radarr/Radarr/issues/1045)) [aptalca] - -### **Fixes** -- Grammar check HelpText for CouchPotato lists ([#1142](https://github.com/Radarr/Radarr/issues/1142)) [James White] -- Preliminary Fix for downloaded error in Wanted section. [Leonardo Galli] -- Fixes banners when searching for new movies. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue where searching for new movies is not possible. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) helptext for Jackett API key ([#1121](https://github.com/Radarr/Radarr/issues/1121)) [Mathew Giljum] -- Better method to obtain the folderName. [geogolem] -- Keep the current page the same after clicking Save. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Parsing headers that have a trailing semi-colon ([#1117](https://github.com/Radarr/Radarr/issues/1117)) [Mitchell Cash] -- PreDB Integration. Update Library is advisable. [Leonardo Galli] -- QOL changes to PTP logic ([#1114](https://github.com/Radarr/Radarr/issues/1114)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for VS for Mac. [Leonardo Galli] -- Ammend to previous commit. [Leonardo Galli] -- Hopefully fix all issues with unlinked movie files. [Leonardo Galli] -- This needs to match with the property forclient mode. [geogolem] -- CP list hotfix. [Devin Buhl] -- Incorrect check for imdbId prefix. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) regression for missing libgdiplus ([#1073](https://github.com/Radarr/Radarr/issues/1073)) [SWu] -- Refactor so that filteringExpressions are constructed in one place less code duplication, easier to manage moving forward. [geogolem] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) filters were added, but they werent being handled via the API. [geogolem] -- Allow larger trakt lists than 500. [geogolem] -- Restructeured readme and added a new logo asset ([#1088](https://github.com/Radarr/Radarr/issues/1088)) [Matthew Treadwell] -- Onedr0p/3 8 17 ([#1087](https://github.com/Radarr/Radarr/issues/1087)) [Devin Buhl] -- Ensure drone factory runs on its specificed interval ([#1067](https://github.com/Radarr/Radarr/issues/1067)) [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) hotio's nightly docker image. ([#1084](https://github.com/Radarr/Radarr/issues/1084)) [Donald Webster] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Installation, Docker and Setup Guide to new Install section and add Feathub and Wiki to Support ([#1083](https://github.com/Radarr/Radarr/issues/1083)) [Donald Webster] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) the parser for movies with A. [Leonardo Galli] -- Loads only request movie first into full collection. Should fix things. ([#1046](https://github.com/Radarr/Radarr/issues/1046)) [Leonardo Galli] -- Addressing jshint warnings ([#1050](https://github.com/Radarr/Radarr/issues/1050)) [Bill Szeliga] -- Correct DownloadDescisionMaker to use ImdbId, and update the ui a little. ([#1068](https://github.com/Radarr/Radarr/issues/1068)) [Devin Buhl] -- Deluge 1.3.14 API support due to changed json-rpc checks. [Devin Buhl] -- Reverting a change made yesterday regarding sorting the change fixed sorting titles of newly added movies without a refresh however, people have noticed it broke sorting of "In Cinemas" column in general. i commented out the change; but also added a special case in the comment, that would fix the case in question, without breaking the others; however, more investigating is needed because there is an issue with sorting newly added movies in general and the fix this reverts was never good enough anyway. [geogolem] -- Oops -- this was a fix from the last merge - sorry. [geogolem] -- URLEncode the string for searching ([#1055](https://github.com/Radarr/Radarr/issues/1055)) [Mihai Blaga] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) client mode fetching.. only setPageSize when necessary. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error with weirdly formatted audioChannelPositions on MediaInfo. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) a couple typos ([#1049](https://github.com/Radarr/Radarr/issues/1049)) [Greg Fitzgerald] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) tests. [Devin Buhl] -- Patch/onedr0p ([#1048](https://github.com/Radarr/Radarr/issues/1048)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) all tests and even added some new ones :) ([#835](https://github.com/Radarr/Radarr/issues/835)) [Leonardo Galli] -- Fixes issue where quality settings wont save due to no pagesize. [Leonardo Galli] -- Fixes sorting after adding movies. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) most paging issues on first load. [Leonardo Galli] -- /movies without pagesize or page gives back the old format. [Leonardo Galli] -- This seems to make it more stable. [geogolem] -- Im not too sure why this fixes the problem but now the filterState is respected when returning from another page. [geogolem] -- Use href instead of hostname+port. [geogolem] -- Improve RSS parsing for movies without year. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) ReplaceGermanUmlauts method. [Devin Buhl] - - -## v0.2.0.453 (2017-03-05) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) new TestCase for Parser and fixed spelling error. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) FindByAlternativeTitle in MovieRepo. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) debug messages to check quality. [Leonardo Galli] -- Needed to pass the filterType, received the filterType and handle the filterType. [geogolem] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) more filters to the movie editor ([#905](https://github.com/Radarr/Radarr/issues/905)) [geogolem] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) parsing french movies ([#899](https://github.com/Radarr/Radarr/issues/899)) [Devin Buhl] - -### **Fixes** -- Try to add year to release titles that have no year (foriegn release groups) ([#1028](https://github.com/Radarr/Radarr/issues/1028)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Delay profiles are no longer hidden under advanced settings ([#1019](https://github.com/Radarr/Radarr/issues/1019)) [Mitchell Cash] -- Revert "Added FindByAlternativeTitle in MovieRepo." [Devin Buhl] -- Use http request builder (aided by onedrop) [geogolem] -- Improve indexer health check messages ([#1015](https://github.com/Radarr/Radarr/issues/1015)) [Mitchell Cash] -- Clean RSS feed before detecting type ([#1014](https://github.com/Radarr/Radarr/issues/1014)) [Mitchell Cash] -- Store titleSlug in tags for exclusions and always use TMDBID. [geogolem] -- Also use TMDBID on list sync. [geogolem] -- Always check exclusions with tmdbid. [geogolem] -- An updated radarrAPI has been deployed --> this commit makes trakt authentication ready to be merged to the develop branch. [geogolem] -- Fully functional traktAuthentication using api.couchpota.to with comments for when updated RadarrAPI is deployed. [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error with null dates. [Devin Buhl] -- Patch/more updates ([#1009](https://github.com/Radarr/Radarr/issues/1009)) [Devin Buhl] -- Revert.. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) "wrong" quality being detected. Scan will be slower though. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for wrong qualities showing up. Will be slower to load though. [Leonardo Galli] -- Patch/onedr0p 3 4 2017 ([#1006](https://github.com/Radarr/Radarr/issues/1006)) [Devin Buhl] -- Respect the page when initializing the layout. [geogolem] -- Patch/onedr0p updates ([#998](https://github.com/Radarr/Radarr/issues/998)) [Devin Buhl] -- The movie was not being printed correctly, and i believe this was also causing movies to be added when they shouldnt have been... [geogolem] -- Clean up the fetching on loading of MovieEditor and MovieIndex once and for all. [geogolem] -- I dont know why i was doing this inside the for loop... It did not scale well ! fixed. [geogolem] -- Use clone so that we only detect empty collection when collectio is empty.. not when current filter is empty but collectionis not. [geogolem] -- I believe these are old code that is not needed since pagination.. [geogolem] -- Default Wanted and Cutoff to be 50 movies per page, added filtering options to Cutoff and a Search all ([#984](https://github.com/Radarr/Radarr/issues/984)) [Devin Buhl] -- Empty string case should not be only for the contains case. [geogolem] -- Reset filters on save.. [geogolem] -- Possible fix for Custom script ([#973](https://github.com/Radarr/Radarr/issues/973)) [Devin Buhl] -- Hotfix when importing movie ([#971](https://github.com/Radarr/Radarr/issues/971)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) infinite loop. Added default destination test when adding client ([#968](https://github.com/Radarr/Radarr/issues/968)) [Marcelo Castagna] -- Date added in Movie List & Possible Fix for Importing Movies. ([#969](https://github.com/Radarr/Radarr/issues/969)) [Devin Buhl] -- Ensure collection is synced before opening movieDetails. [Tim Turner] -- Revert some changes -- use FullCollection (maybe just for now) [geogolem] -- Just show imdbid or tmdbid for now in exclusions. [geogolem] -- MovieIndexPage Stability + MovieEditor fix ([#925](https://github.com/Radarr/Radarr/issues/925)) [geogolem] -- Patch/galileo fixes ([#951](https://github.com/Radarr/Radarr/issues/951)) [Devin Buhl] -- Patch/updates onedr0p ([#946](https://github.com/Radarr/Radarr/issues/946)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) problem with TMDb list when Year is null, Revert using UrlPathEncode on newznab requests ([#937](https://github.com/Radarr/Radarr/issues/937)) [Devin Buhl] -- Expose more information to the Webhook notification ([#935](https://github.com/Radarr/Radarr/issues/935)) [Ross Valler] -- Fix/implement Webhook notifications ([#901](https://github.com/Radarr/Radarr/issues/901)) [Ross Valler] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) remux 1080p and 2160p as qualities ([#900](https://github.com/Radarr/Radarr/issues/900)) [Devin Buhl] -- NZBGet delete:scan treated as failure ([#898](https://github.com/Radarr/Radarr/issues/898)) [Mitchell Cash] -- Small changes. [Devin Buhl] -- Hotfix. [Devin Buhl] -- List sync with removal ([#656](https://github.com/Radarr/Radarr/issues/656)) [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) the footer to show correct information and refresh when FullCollection changes ([#893](https://github.com/Radarr/Radarr/issues/893)) [geogolem] -- Increase fullCollection page size, update Refresh Library command. [Tim Turner] -- Patch/updates ([#887](https://github.com/Radarr/Radarr/issues/887)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) poster placeholder height on small screens ([#883](https://github.com/Radarr/Radarr/issues/883)) [hotio] -- Small UI fixes ([#882](https://github.com/Radarr/Radarr/issues/882)) [hotio] -- Me = idiot. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) an issue where an unloaded movie could case linking to fail. [Leonardo Galli] -- Maybe fix issue with imported files not being linked to the movie? [Leonardo Galli] -- Search is now fixed too. [Leonardo Galli] -- Should fix most issues with paging. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) first steps of paging to movie editor. [Leonardo Galli] -- HDBits prefer/require internal release ([#584](https://github.com/Radarr/Radarr/issues/584)) ([#881](https://github.com/Radarr/Radarr/issues/881)) [Devin Buhl] -- Ignore Deleted Movies ([#755](https://github.com/Radarr/Radarr/issues/755)) ([#879](https://github.com/Radarr/Radarr/issues/879)) [Devin Buhl] -- First fixes for Movie Editor. Testing to see if this approach could work. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) missing showing downloaded instead. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue where details page wont load. [Leonardo Galli] -- Paging for movies :) ([#861](https://github.com/Radarr/Radarr/issues/861)) [Leonardo Galli] -- Bug fixes ([#874](https://github.com/Radarr/Radarr/issues/874)) [Devin Buhl] -- The Search All Missing button ([#860](https://github.com/Radarr/Radarr/issues/860)) [geogolem] -- Cleanup min availability ([#846](https://github.com/Radarr/Radarr/issues/846)) [geogolem] -- Some minor cleanup + changed filter on wanted/missing ([#845](https://github.com/Radarr/Radarr/issues/845)) [geogolem] -- Min availability ([#816](https://github.com/Radarr/Radarr/issues/816)) [geogolem] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) NZB Station for Synology ([#841](https://github.com/Radarr/Radarr/issues/841)) [Devin Buhl] -- Patch/filter trakt ([#838](https://github.com/Radarr/Radarr/issues/838)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) language parsing of movies with language in movie name. [Leonardo Galli] - - -## v0.2.0.375 (2017-02-22) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) .travis.yml. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) notification logos ([#804](https://github.com/Radarr/Radarr/issues/804)) [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) PULL_REQUEST_TEMPLATE.md. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) dl-clients ([#732](https://github.com/Radarr/Radarr/issues/732)) [Devin Buhl] -- NetImport - Do not allow TV Series / Mini-Series (works with IMDb) [#699](https://github.com/Radarr/Radarr/issues/699) ([#727](https://github.com/Radarr/Radarr/issues/727)) [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Devin Buhl] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) sort options to match UI ([#707](https://github.com/Radarr/Radarr/issues/707)) [zductiv] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) test for ! [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) parser tests. [Leonardo Galli] - -### **Fixes** -- Patch/bulk import tests ([#833](https://github.com/Radarr/Radarr/issues/833)) [Tim Turner] -- Patch/bulk import qol ([#785](https://github.com/Radarr/Radarr/issues/785)) [Tim Turner] -- URL Encode for newznab query strings, closes [#818](https://github.com/Radarr/Radarr/issues/818) ([#819](https://github.com/Radarr/Radarr/issues/819)) [Mihai Blaga] -- Rename Sonarr to Radarr in DownloadStation client ([#812](https://github.com/Radarr/Radarr/issues/812)) [Mitchell Cash] -- Fixes error message for MovieExistsValidator to state the movie doesn't exist ([#723](https://github.com/Radarr/Radarr/issues/723)) ([#808](https://github.com/Radarr/Radarr/issues/808)) [Ryan Matthews] -- Set PROWL application to Radarr ([#770](https://github.com/Radarr/Radarr/issues/770)) ([#807](https://github.com/Radarr/Radarr/issues/807)) [Ryan Matthews] -- TMDb Lists should be working now :) ([#775](https://github.com/Radarr/Radarr/issues/775)) [Devin Buhl] -- Roll back some code on Net Import ([#772](https://github.com/Radarr/Radarr/issues/772)) [Devin Buhl] -- Check to see if output path is right when DownloadClient.Test is invoked ([#768](https://github.com/Radarr/Radarr/issues/768)) [Marcelo Castagna] -- TMDb Filtering Options: Rating, Min Votes, Min Vote Ave, Original Language, TMDb Genre Ids (CSV), ([#765](https://github.com/Radarr/Radarr/issues/765)) [Devin Buhl] -- Small consistancy updates to PTP and AwesomeHD ([#758](https://github.com/Radarr/Radarr/issues/758)) [Devin Buhl] -- Patch/onedr0p ([#757](https://github.com/Radarr/Radarr/issues/757)) [Devin Buhl] -- Handle download data diskstation ([#744](https://github.com/Radarr/Radarr/issues/744)) [Marcelo Castagna] -- When refreshing movie, refresh Files tab. [Tim Turner] -- Feature/Add TMDb Functionality ([#739](https://github.com/Radarr/Radarr/issues/739)) [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) downloaded quality column to movie editor ([#738](https://github.com/Radarr/Radarr/issues/738)) [zductiv] -- Clean up Trakt a little ([#735](https://github.com/Radarr/Radarr/issues/735)) [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Synology Download Station ([#725](https://github.com/Radarr/Radarr/issues/725)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) pending release table. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Hardcoded .DKSubs. ([#726](https://github.com/Radarr/Radarr/issues/726)) [Devin Buhl] -- Patch/re add ghost migrations ([#724](https://github.com/Radarr/Radarr/issues/724)) [Devin Buhl] -- Patch/onedr0p ([#716](https://github.com/Radarr/Radarr/issues/716)) [Devin Buhl] -- Increase timeout when waiting for rTorrent to finish adding torrent ([#721](https://github.com/Radarr/Radarr/issues/721)) [Mitchell Cash] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) RescanMovie command for single movie. [Tim Turner] -- Hopefully fixes a lot of null reference bugs in BulkImport. [Leonardo Galli] -- Should fix blacklist items disappearing. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) manual import for when downloaded movies are in a folder. [Leonardo Galli] -- Search all missing movie works - missing tab only ([#710](https://github.com/Radarr/Radarr/issues/710)) [zductiv] -- Limit TMDb requests when importing via IMDBid ([#703](https://github.com/Radarr/Radarr/issues/703)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) parsing with lower bluray qualities. [Leonardo Galli] -- Fixes issue with movies with same name but different years being downloaded. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) a few parser issues. Also added some tests. [Leonardo Galli] -- Cutoff tab actually working now. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) trakt links for movies (like sonarr for shows) ([#690](https://github.com/Radarr/Radarr/issues/690)) [geogolem] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Sorting In Wanted and Cutoff ([#693](https://github.com/Radarr/Radarr/issues/693)) [Devin Buhl] -- Pass at seeing if this works on linux now ([#692](https://github.com/Radarr/Radarr/issues/692)) [Devin Buhl] -- Small UI changes ([#691](https://github.com/Radarr/Radarr/issues/691)) [zductiv] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) required flag for PTP ([#688](https://github.com/Radarr/Radarr/issues/688)) [Devin Buhl] -- Wanted & Missing ([#687](https://github.com/Radarr/Radarr/issues/687)) [Devin Buhl] -- * Make Missing/Wanted Work again ([#686](https://github.com/Radarr/Radarr/issues/686)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MovieMissingModule failed while processing [MovieDownloadedEvent] [Devin Buhl] -- UI Enhancements for Manual Import ([#681](https://github.com/Radarr/Radarr/issues/681)) [Tim Turner] -- May be fix loading view? Idk. [Leonardo Galli] -- Display loading view when changing page size. [Tim Turner] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) ordering in PTP, should prefer GP releases ([#667](https://github.com/Radarr/Radarr/issues/667)) [Devin Buhl] -- Patch/onedr0p updates ([#664](https://github.com/Radarr/Radarr/issues/664)) [Devin Buhl] -- Make Movie Title and Status sortable on Wanted tab ([#662](https://github.com/Radarr/Radarr/issues/662)) [schumi2004] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) paging breaking in bulk import. [Leonardo Galli] -- Bulk Import. ([#583](https://github.com/Radarr/Radarr/issues/583)) [Leonardo Galli] - - -## v0.2.0.299 (2017-02-07) - -### **New features** -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) notif list warning when importing from a list ([#648](https://github.com/Radarr/Radarr/issues/648)) [Devin Buhl] - -### **Fixes** -- Wait 5 seconds before getting the next 35 movies from TMDb using X-RateLimit-Remaining ([#647](https://github.com/Radarr/Radarr/issues/647)) [Devin Buhl] -- Correct the Kickass migration ([#649](https://github.com/Radarr/Radarr/issues/649)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) movies not showing up in Queue when downloading ([#640](https://github.com/Radarr/Radarr/issues/640)) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Movie link in history tab ([#637](https://github.com/Radarr/Radarr/issues/637)) [Devin Buhl] -- Clean up download clients to use radarr as label, fix hoduken, and blackhole. ([#635](https://github.com/Radarr/Radarr/issues/635)) [Devin Buhl] -- Use Movie Name-TmdbId for slug, update toUrlSlug ([#629](https://github.com/Radarr/Radarr/issues/629)) [Devin Buhl] -- Removed Wombles and Kickass, updated torrentpotato and torznab ([#625](https://github.com/Radarr/Radarr/issues/625)) [Devin Buhl] -- Various ui text fixes ([#620](https://github.com/Radarr/Radarr/issues/620)) [Abzie] -- Delay Profile: Fix for when preferred words is null. ([#618](https://github.com/Radarr/Radarr/issues/618)) [vertigo235] - - -## v0.2.0.288 (2017-02-05) - -### **New features** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) 'Case Insensitive.' to preferred tags info to help-inline. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) more options to trakt, popular movies, upcoming, anticipated etc.. [Devin Buhl] - -### **Fixes** -- Preferredcount -> preferredCount. [vertigo235] -- Delay Profile: Require preferred word to skip delay. [vertigo235] -- Delay Profile: Delay for at least 1 preferred word. [vertigo235] -- Delay Profile: Upgradable Check Fix. [vertigo235] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) ical ics file ([#603](https://github.com/Radarr/Radarr/issues/603)) [schumi2004] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue where quality weight was mapped wrongly. Fixes [#597](https://github.com/Radarr/Radarr/issues/597) [Leonardo Galli] -- Runtime error fix. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) runtime issues. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) glaringly obvious mistake that caused RSS Sync to fail. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) warning for docker users when switching branch. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) plain "ES" audioProfile. ([#569](https://github.com/Radarr/Radarr/issues/569)) [Chris Allen] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) delay specification when delay is not set to zero. [Leonardo Galli] -- Use shorter format Profile string. ([#561](https://github.com/Radarr/Radarr/issues/561)) [Chris Allen] -- Use movieFile instead of episodeFile. ([#560](https://github.com/Radarr/Radarr/issues/560)) [Chris Allen] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) expanded DTS audio codecs to FileNameBuilder and fix up Atmos TrueHD audioCodec string. ([#559](https://github.com/Radarr/Radarr/issues/559)) [Chris Allen] -- Don't display mapped movies in import list. [Tim Turner] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Delete modal when adding movie. [Tim Turner] -- Delete files now works. Fixes [#127](https://github.com/Radarr/Radarr/issues/127) [Leonardo Galli] -- First pass regarding delete. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) error for movies with less than 4 characters. Fixes [#507](https://github.com/Radarr/Radarr/issues/507) [Leonardo Galli] - - -## v0.2.0.267 (2017-01-30) - -### **New features** -- Updates to ptp, and using caching for cookie. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) the regex in Parser, Add workprint and telesync, change R5 to regional allow for R[0-9]{1}, changed the weights. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) weights. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) new qualities, added new qualities to profile class. Left to do: write migration, and tests. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Fetch List button style. [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) options for watched, and watchlist, and customlist to trakt. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) HDBits to work with Radarr. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) taskscheduler when config is saved with netimportsynccommand. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Synology Indexer For Movies ([#486](https://github.com/Radarr/Radarr/issues/486)) [vertigo235] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) option to specify preferred words in quality profile. ([#462](https://github.com/Radarr/Radarr/issues/462)) [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) GeneralViewTemplate.hbs. [Jordan] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) lang in UI to what profile / lang they choose when they add a movie. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) JoinProxy.cs. [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Plex Movie Sections. [vertigo235] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) slack for movies. [vertigo235] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) to favicon section, according to ([#416](https://github.com/Radarr/Radarr/issues/416)) [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) default sort order ([#429](https://github.com/Radarr/Radarr/issues/429)) [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ico files. [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) UI logos. [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) localstorage key prefixes. [Tim Turner] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Forms Auth Cookie. Fixes [#285](https://github.com/Radarr/Radarr/issues/285) [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Files tab when movie renamed. [Tim Turner] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Rename Preview to support folder renaming. [Tim Turner] -- Net Import UI Updates. [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) trakt user list importing. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) easy to use List Selection for manual import use later. The place where this resides will change. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Base URL. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) couchpotato, and added a test. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) MovieModule. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) ISSUE_TEMPLATE.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) sizing information in settings tab. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) height of posters to accomodate additional labels. [Tim Turner] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) SkyHookProxy.cs. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) Test Files for AddPaused to NZBGET. [vertigo235] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Upgraded SQLite binares for macOS. [Keivan] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Upgraded SQLite binaries for Windows (3.16.0) [Keivan Beigi] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) website and donation links. [Leonardo Galli] -- ![Changed](https://img.shields.io/badge/--%20-Changed-orange.svg?style=flat-square) Scheduled Refresh Series to Refresh Movie. Fixes [#301](https://github.com/Radarr/Radarr/issues/301) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) movie studio to movie details page ([#262](https://github.com/Radarr/Radarr/issues/262)) [Vlad Ilies] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) NewznabRequestGenerator.cs. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) trailer link to movie links ([#255](https://github.com/Radarr/Radarr/issues/255)) ([#282](https://github.com/Radarr/Radarr/issues/282)) [Vlad Ilies] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) HttpNetImporterBase. Still needs work to correctly handle failures. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) some abstraction for settings. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Qualties to Settings. [Devin Buhl] -- Updates and compile-able. [Devin Buhl] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [Leonardo Galli] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) .gitignore and remove Thumbs.db files ([#276](https://github.com/Radarr/Radarr/issues/276)) [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md ([#271](https://github.com/Radarr/Radarr/issues/271)) [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [hotio] -- ![Updated](https://img.shields.io/badge/--%20-Updated-blue.svg?style=flat-square) README.md. [hotio] -- Updates. [Devin Buhl] - -### **Fixes** -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) importfromlist abck. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) the filter modes on the movie list xD. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issues with different languages than english when adding alternative titles. [Leonardo Galli] -- Use username, password and passkey for passthepopcorn. [Devin Buhl] -- Migration migraine-tion. [Devin Buhl] -- Ensure qualities don't overflow profile card. [Tim Turner] -- Migration. [Devin Buhl] -- Migration. [Devin Buhl] -- Make DVDR not unlimited. [Devin Buhl] -- Set Drone Factory Interval default to 0 ([#515](https://github.com/Radarr/Radarr/issues/515)) [Tim Turner] -- Make year nullable for trakt. [Devin Buhl] -- Make year nullable, and rmember the profileid. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Proper port validation for download clients and connections. [Mark McDowall] -- Make NetImport sync interval work (needs some testing) [Devin Buhl] -- Allow Duplicate Preferred Words ([#484](https://github.com/Radarr/Radarr/issues/484)) [vertigo235] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for movies without an imdbid. Fixes 176. [Leonardo Galli] -- Quality of an existing movie file can now be edited. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) recognition of 4k Movies upon import. [Leonardo Galli] -- This should hopefully fix the error that decisions were not ordered correctly and therefore just the first release was grabbed. [Leonardo Galli] -- Remove confusing warning about file not being loaded. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) movie year to NotificationService ([#496](https://github.com/Radarr/Radarr/issues/496)) [Tim Turner] -- Revert "Merge branch 'rename-existing-folder' into develop" [Tim Turner] -- Revert "Add movie year to NotificationService ([#489](https://github.com/Radarr/Radarr/issues/489))" [Tim Turner] -- Revert "Ensure the movie isn't delete when the folder isn't renamed ([#491](https://github.com/Radarr/Radarr/issues/491))" [Tim Turner] -- Ensure the movie isn't delete when the folder isn't renamed ([#491](https://github.com/Radarr/Radarr/issues/491)) [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) movie year to NotificationService ([#489](https://github.com/Radarr/Radarr/issues/489)) [Tim Turner] -- Kodi Update Fix: OldFiles -> OldMovieFiles ([#483](https://github.com/Radarr/Radarr/issues/483)) [vertigo235] -- More Notification Updates ([#482](https://github.com/Radarr/Radarr/issues/482)) [vertigo235] -- Moviefile, what movie file? ([#466](https://github.com/Radarr/Radarr/issues/466)) [vertigo235] -- Remove mofilefile id for now ([#464](https://github.com/Radarr/Radarr/issues/464)) [vertigo235] -- Download Movie Quality & Formatting. [vertigo235] -- Custom Script Fix: Parse movie not episode. [vertigo235] -- Fixes issue [#447](https://github.com/Radarr/Radarr/issues/447) (Notification Icon for Join) [hotio] -- Only use internal for RSS Sync. [Devin Buhl] -- Include only internal for AHD. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) new rss-sync threshold. [schumi2004] -- "fixed" error message. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) link to Activity -> History Tab ([#408](https://github.com/Radarr/Radarr/issues/408)) [Tim Turner] -- Allow renaming of movies that don't have an "Edition" ([#432](https://github.com/Radarr/Radarr/issues/432)) [Tim Turner] -- [#292](https://github.com/Radarr/Radarr/issues/292) - Allow longer threshold for RSS Sync ([#428](https://github.com/Radarr/Radarr/issues/428)) [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) year to search ([#425](https://github.com/Radarr/Radarr/issues/425)) [Devin Buhl] -- Initial Notification Updates and Support ([#401](https://github.com/Radarr/Radarr/issues/401)) [vertigo235] -- Fixes an issue where movies with (year) at the beginning were recognized with a title of "(" [Leonardo Galli] -- Blind fix to support seperator in movie tags. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue with certain audio streams. Should fix [#404](https://github.com/Radarr/Radarr/issues/404) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) {Tags} to renaming options. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) when libgdiplus isn't present. [Leonardo Galli] -- Proper ico and favicon. [hotio] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue where monitored movies were still downloaded. Fixes [#326](https://github.com/Radarr/Radarr/issues/326) [Leonardo Galli] -- Fixes issue when multiple audio channels are present. Fixes [#315](https://github.com/Radarr/Radarr/issues/315) Fixes [#294](https://github.com/Radarr/Radarr/issues/294) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) duplicate key prefixing. [Tim Turner] -- Prefix localstorage keys with "Radarr" [Tim Turner] -- Optimized logo ([#375](https://github.com/Radarr/Radarr/issues/375)) [hotio] -- Set update interval to 30 minutes if on nightly. [Leonardo Galli] -- Prefix Keys with "Radarr" [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) more filter options to movie list. [Devin Buhl] -- Search selected button in wanted tab works. [Vlad Ilies] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) [#228](https://github.com/Radarr/Radarr/issues/228) - Fix Drone Factory interval input not saving. [Tim Turner] -- Remove old folder and all contents. [Tim Turner] -- Movie reference properly updates UI now. [Tim Turner] -- Be more proper about Ensuring the folder exists. [Tim Turner] -- Undo unecessary changes. [Tim Turner] -- Move folder on rename; event doesn't fire yet. [Tim Turner] -- Only show "Display Existing Movies" toggle after selecting a folder. [Tim Turner] -- Clean up settings UI. [Tim Turner] -- Manual Import works now! [Leonardo Galli] -- Only wanted is default for CP. [Devin Buhl] -- Manual importing almost done. Needs fixing for mapping movies. [Leonardo Galli] -- Nullable all the fields.. [Devin Buhl] -- Rephrase wording. [Devin Buhl] -- Monitored to false for movies already downloaded on CP. [Devin Buhl] -- Allow null value for seed time. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) basic ui of manual import. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) importing for StevenLu. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) StevenLu to csproj. [Devin Buhl] -- First pass at ui for manually importing from lists. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) import from http://movies.stevenlu.com/ [Devin Buhl] -- Movies can now be added monitored or unmonitored. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Ability to set RootFolderPath for Net Import List. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) netimport search and add NetImportSyncCommand. [Leonardo Galli] -- Remove duplicate code. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) movies being clobbered when a new list is sent thru. [Devin Buhl] -- Implement NetImportSearchService. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) urlBase option to CP settings. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) media info parsing of multiple audio channels. Fixes [#315](https://github.com/Radarr/Radarr/issues/315) Fixes [#294](https://github.com/Radarr/Radarr/issues/294) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) styling. Fixed definitions not being returned. [Leonardo Galli] -- Rethought about where certain things are stored. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) stuff regarding the ordering of Fields. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) migration to include ConfigContract and EnableAuto. Also fixed redirects on lists. [Leonardo Galli] -- Second UI Pass, Testing now works and other little things. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) up presets. [Leonardo Galli] -- Make presets work for RSS Import :) [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) CP list class. [Leonardo Galli] -- Migration migrainetion. [Devin Buhl] -- Couchpotato API classes. [Devin Buhl] -- WIP UI Update for adding lists. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Corruped Media Cover Images. [Leonardo Galli] -- Should fix 4K releases not getting parsed. [Leonardo Galli] -- Adds 'Movie Title, The' filename option ([#359](https://github.com/Radarr/Radarr/issues/359)) [Krystian Charubin] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue when movie file is null. [Leonardo Galli] -- Should fix upgrading of existing movie files. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) tests for 4K quality. [Leonardo Galli] -- Hopefully a fix for corrupt media covers. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) blacklist being ignored by download decision maker. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) helptext to nzbget "add paused" settings. ([#363](https://github.com/Radarr/Radarr/issues/363)) [vertigo235] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) year to quick search results. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) issue with reimporting on movie fresh ([#357](https://github.com/Radarr/Radarr/issues/357)) [Tim Turner] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) MediaCoversUpdatedEvent broadcast. [Tim Turner] -- Bug fix for 15 movie wanted tab ([#348](https://github.com/Radarr/Radarr/issues/348)) [Vlad Ilies] -- Blacklisting works now. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) pushover priority values. [vertigo235] -- Hopefully fix issue when importing. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) download status to poster view. [Tim Turner] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) IMDb ID to file naming. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) build. [Vlad Ilies] -- Basic implementation of the wanted tab (#31) [Vlad Ilies] -- Revert DownloadedMovieScanCommand to DownloadedEpisodesScanCommand. [Devin Buhl] -- Turn off scene mapping task [#329](https://github.com/Radarr/Radarr/issues/329), update TaskManager to use 'DownloadedMovieScanCommand' [Devin Buhl] -- Revert "Sonarr/sqlite updates" [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) "Add Paused" option for NZBGET downloader. [vertigo235] -- Upgraded System.Data.SQLite to 1.0.104.0. [Keivan Beigi] -- Revert "Upgraded System.Data.SQLite to 1.0.104.0" [Keivan Beigi] -- Remove series references. [Leonardo Galli] -- Hopefully fix download ordering. [Leonardo Galli] -- Maybe this will solve the error. [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Issue when adding some movies. [Devin Buhl] -- Hopefully fix RSSSync. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) publish date [#239](https://github.com/Radarr/Radarr/issues/239) [Devin Buhl] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Issue #91 - "Search All Missing" wording. [Aenima99x] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Support for changing file date to either cinema or physical release. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for movies with . in title when importing them. Fixes [#268](https://github.com/Radarr/Radarr/issues/268) [Leonardo Galli] -- Remove - as replacement for : [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) only one movie showing. Fix more button not showing up. [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) Audiochannels just being added together. [Leonardo Galli] -- Clean up rename preview & organize. [Tim Turner] -- Disambiguate Movie from Episode Renaming. [Tim Turner] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for hardcoded subs regex. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) Calendar Tab back. Fixes #32. [Leonardo Galli] -- Removed duplicate PublishDate. [Devin Buhl] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) support section to README ([#281](https://github.com/Radarr/Radarr/issues/281)) [hotio] -- First pass at hiding existing movies upon import. [Tim Turner] -- 95% done with hiding existing movies. [Tim Turner] -- Basis of UI Update. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) base for netimport api. Still nothing on the UI side. [Leonardo Galli] -- Imdbid parsing works now from url. [Leonardo Galli] -- Big Abstraction for IMDBWatchlist -> RSSImport (With a test) [Leonardo Galli] -- Whoops, only parse title once. [Devin Buhl] -- Reworked README ([#280](https://github.com/Radarr/Radarr/issues/280)) [hotio] -- Move Travis builds to container-based infrastructure ([#273](https://github.com/Radarr/Radarr/issues/273)) [Mitchell Cash] -- Adding only original title is now allowed. Fixes [#272](https://github.com/Radarr/Radarr/issues/272) [Leonardo Galli] -- ![Fixed](https://img.shields.io/badge/--%20-Fixed-red.svg?style=flat-square) for special characters when searching with title in Newznab. Fixes #97. [Leonardo Galli] -- ![New](https://img.shields.io/badge/--%20-New-brightgreen.svg?style=flat-square) {Original Title} to FileNameBuilder. Fixes [#103](https://github.com/Radarr/Radarr/issues/103) [Leonardo Galli] -- Release Group should now be available for renamer to use. [Leonardo Galli] -- Cleanup README. [Mitchell Cash] -- Few changes. [Devin Buhl] -- Initial autoimporter commit. [Devin Buhl] - - diff --git a/CLA.md b/CLA.md index 05ce7890d..74780f123 100644 --- a/CLA.md +++ b/CLA.md @@ -1,6 +1,6 @@ -# Radarr Individual Contributor License Agreement # +# Prowlarr Individual Contributor License Agreement # -Thank you for your interest in contributing to Radarr ("We" or "Us"). +Thank you for your interest in contributing to Prowlarr ("We" or "Us"). This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please complete the form below. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us. ## 1. Definitions ## diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0001a48c..d1de226b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # How to Contribute # -We're always looking for people to help make Radarr even better, there are a number of ways to contribute. +We're always looking for people to help make Prowlarr even better, there are a number of ways to contribute. ## Documentation ## Setup guides, FAQ, the more information we have on the wiki the better. @@ -10,15 +10,15 @@ Setup guides, FAQ, the more information we have on the wiki the better. See the readme for information on setting up your development environment. ### Contributing Code ### -- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Radarr/Radarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first) -- Rebase from Radarr's develop branch, don't merge +- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Prowlarr/Prowlarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first) +- Rebase from Prowlarr's develop branch, don't merge - Make meaningful commits, or squash them - Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements - Reach out to us on the discord if you have any questions - Add tests (unit/integration) - Commit with *nix line endings for consistency (We checkout Windows and commit *nix) - One feature/bug fix per pull request to keep things clean and easy to understand -- Use 4 spaces instead of tabs, this is the default for VS 2012 and WebStorm (to my knowledge) +- Use 4 spaces instead of tabs, this is the default for VS 2019 and WebStorm (to my knowledge) ### Pull Requesting ### - Only make pull requests to develop, never master, if you make a PR to master we'll comment on it and close it diff --git a/README.md b/README.md index f98603c96..a128cb686 100644 --- a/README.md +++ b/README.md @@ -1,149 +1 @@ -# Radarr - -[![Build Status](https://dev.azure.com/Radarr/Radarr/_apis/build/status/Radarr.Radarr?branchName=develop)](https://dev.azure.com/Radarr/Radarr/_build/latest?definitionId=1&branchName=develop) -[![Translated](https://translate.servarr.com/widgets/radarr/-/radarr/svg-badge.svg)](https://translate.servarr.com/engage/radarr/?utm_source=widget) -[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/radarr.svg)](https://github.com/Radarr/Radarr/wiki/Docker) -![Github Downloads](https://img.shields.io/github/downloads/Radarr/Radarr/total.svg) -[![Backers on Open Collective](https://opencollective.com/Radarr/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Radarr/sponsors/badge.svg)](#sponsors) - -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. - -## Getting Started - -[![Installation](https://img.shields.io/badge/wiki-installation-brightgreen.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/wiki/Installation) -[![Docker](https://img.shields.io/badge/wiki-docker-1488C6.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/wiki/Docker) -[![Setup Guide](https://img.shields.io/badge/wiki-setup_guide-orange.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/wiki/Setup-Guide) -[![FAQ](https://img.shields.io/badge/wiki-FAQ-BF55EC.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/wiki/FAQ) - - -If you are using Docker please ensure your Docker paths are setup correctly using [this guide to facilitate](https://old.reddit.com/r/usenet/wiki/docker) hardlinks and minimize permissions issues. - -* [Install Radarr for your desired OS](https://github.com/Radarr/Radarr/wiki/Installation) *or* use [Docker](https://github.com/Radarr/Radarr/wiki/Docker) -* *For Linux users*, run `radarr` and *optionally* have [Radarr start automatically](https://github.com/Radarr/Radarr/wiki/Autostart-on-Linux) -* Connect to the UI through or in your web browser -* See the [Setup Guide](https://github.com/Radarr/Radarr/wiki/Setup-Guide) for further configuration - -## Downloads -Please note that v0.2 will only have critical bugs resolved as of August 2020. Any additional development or features will be soley in V3. - -Each push to the "develop" branch creates a build on "nightly" release channel (release channel is the "branch" within radarr's settings), once we push a build to Github it will show up on "develop" release channel. - - -| Release Channel Type | Branch: develop (stable) (v0.2) | Branch: nightly (semi-unstable) (v3.0) | -|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Binary Releases | [![GitHub Releases](https://img.shields.io/badge/downloads-releases-brightgreen.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/releases) | [![Azure Build](https://img.shields.io/badge/downloads-Windows_X64-green.svg?maxAge=60&style=flat-square)](https://radarr.servarr.com/v1/update/nightly/updatefile?os=windows&runtime=netcore&arch=x64)
[![Azure Build](https://img.shields.io/badge/downloads-Linux_X64-green.svg?maxAge=60&style=flat-square)](https://radarr.servarr.com/v1/update/nightly/updatefile?os=linux&runtime=netcore&arch=x64)
[![Azure Build](https://img.shields.io/badge/downloads-Linux_ARM64-green.svg?maxAge=60&style=flat-square)](https://radarr.servarr.com/v1/update/nightly/updatefile?os=linux&runtime=netcore&arch=arm64) [![Azure Build](https://img.shields.io/badge/downloads-Linux_ARM-green.svg?maxAge=60&style=flat-square)](https://radarr.servarr.com/v1/update/nightly/updatefile?os=linux&runtime=netcore&arch=arm)
[![Azure Build](https://img.shields.io/badge/downloads-macOS-green.svg?maxAge=60&style=flat-square)](https://radarr.servarr.com/v1/update/nightly/updatefile?os=osx&runtime=netcore&arch=x64) -| Docker - lsio | [![Docker release](https://img.shields.io/badge/linuxserver-radarr:latest-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://hub.docker.com/r/linuxserver/radarr) | [![Docker nightly](https://img.shields.io/badge/linuxserver-radarr:nightly-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://hub.docker.com/r/linuxserver/radarr) | -| Docker - hotio | [![Docker release](https://img.shields.io/badge/hotio-radarr:latest-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://hub.docker.com/r/hotio/radarr) | [![Docker nightly](https://img.shields.io/badge/hotio-radarr:nightly-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://hub.docker.com/r/hotio/radarr) | - -## Support - -[![Discord](https://img.shields.io/badge/discord-chat-r5wJPt9.svg?maxAge=60&style=flat-square)](https://discord.gg/r5wJPt9) -[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60&style=flat-square)](https://www.reddit.com/r/radarr) -[![GitHub](https://img.shields.io/badge/github-issues-red.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/issues) -[![GitHub Wiki](https://img.shields.io/badge/github-wiki-181717.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/wiki) - -## Status - -[![GitHub issues](https://img.shields.io/github/issues/radarr/radarr.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/issues) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/radarr/radarr.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/pulls) -[![GNU GPL v3](https://img.shields.io/badge/license-GNU%20GPL%20v3-blue.svg?maxAge=60&style=flat-square)](http://www.gnu.org/licenses/gpl.html) -[![Copyright 2010-2020](https://img.shields.io/badge/copyright-2020-blue.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr) -[![Github Releases](https://img.shields.io/github/downloads/Radarr/Radarr/total.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/releases/) -[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/radarr.svg?maxAge=60&style=flat-square)](https://hub.docker.com/r/linuxserver/radarr/) -[![Changelog](https://img.shields.io/github/commit-activity/w/radarr/radarr.svg?style=flat-square)](/CHANGELOG.md#unreleased) - -### [Site and API Status](https://status.radarr.video) - -Radarr is currently undergoing rapid development and pull requests are actively added into the repository. - -## Features - -### Current Features - -* Adding new movies with lots of information, such as trailers, ratings, etc. -* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. -* Can watch for better quality of the movies you have and do an automatic upgrade. *eg. from DVD to Blu-Ray* -* Automatic failed download handling will try another release if one fails -* Manual search so you can pick any release or to see why a release was not downloaded automatically -* Full integration with SABnzbd and NZBGet -* Automatically searching for releases as well as RSS Sync -* Automatically importing downloaded movies -* Recognizing Special Editions, Director's Cut, etc. -* Identifying releases with hardcoded subs -* All indexers supported by Sonarr also supported -* New PassThePopcorn Indexer -* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming) -* New TorrentPotato Indexer -* Torznab Indexer now supports Movies (Works well with [Jackett](https://github.com/Jackett/Jackett)) -* Scanning PreDB to know when a new release is available -* Importing movies from various online sources, such as IMDb Watchlists or Trakt (v3) (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114)) -* Full integration with Kodi, Plex (notification, library update) -* And a new beautiful UI (v3) -* Importing Metadata such as trailers or subtitles -* Adding metadata such as posters and information for Kodi and others to use -* Advanced customization for profiles, such that Radarr will always download the copy you want - -#### [Feature Requests](https://github.com/Radarr/Radarr/issues/new?assignees=&labels=feature+request&template=feature_request.md&title=) - -## Configuring the Development Environment - -### Requirements - -* [Visual Studio Community 2019](https://www.visualstudio.com/vs/community/) or [Rider](http://www.jetbrains.com/rider/) -* [Git](https://git-scm.com/downloads) -* [Node.js](https://nodejs.org/en/download/) -* [Yarn](https://yarnpkg.com/) - -### Setup - -* 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)) -* 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. - -> **Notice** -> Gulp must be running at all times while you are working with Radarr client source files. - -### Build - -* To build run `sh build.sh` - -**Note:** Windows users must have bash available to do this. If you installed git, you should have a git bash utility that works. - -### 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. -* Make sure `NzbDrone.Console` is set as the startup project -* Run `build.sh` before running, or build in VS - -## Supporters - -This project would not be possible without the support by these amazing folks. [**Become a sponsor or backer**](https://opencollective.com/radarr) to help us out! - -### Sponsors - -[![Sponsors](https://opencollective.com/radarr/tiers/sponsor.svg)](https://opencollective.com/radarr/order/3851) - -### Flexible Sponsors - -[![Flexible Sponsors](https://opencollective.com/radarr/tiers/flexible-sponsor.svg?avatarHeight=54)](https://opencollective.com/radarr/order/3856) - -### Backers - -[![Backers](https://opencollective.com/radarr/tiers/backer.svg?avatarHeight=48)](https://opencollective.com/radarr/order/3850) - -### JetBrains - -Thank you to [JetBrains JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools - -* [ReSharper ReSharper](http://www.jetbrains.com/resharper/) -* [WebStorm WebStorm](http://www.jetbrains.com/webstorm/) -* [Rider Rider](http://www.jetbrains.com/rider/) -* [dotTrace dotTrace](http://www.jetbrains.com/dottrace/) - -## License - -* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html) -* Copyright 2010-2020 +# Prowlarr \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1c3647ab8..807cfeeeb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -80,7 +80,7 @@ stages: inputs: version: $(dotnetVersion) - bash: ./build.sh --backend - displayName: Build Radarr Backend + displayName: Build Prowlarr Backend - bash: | find ${OUTPUTFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \; find ${OUTPUTFOLDER} -depth -empty -type d -exec rm -r "{}" \; @@ -148,7 +148,7 @@ stages: path: $(yarnCacheFolder) displayName: Cache Yarn packages - bash: ./build.sh --frontend - displayName: Build Radarr Frontend + displayName: Build Prowlarr Frontend env: FORCE_COLOR: 0 YARN_CACHE_FOLDER: $(yarnCacheFolder) @@ -184,8 +184,8 @@ stages: - bash: ./build.sh --packages displayName: Create Packages - bash: | - setup/inno/ISCC.exe setup/radarr.iss //DFramework=netcoreapp3.1 - cp setup/output/Radarr.*windows.netcoreapp3.1.exe ${BUILD_ARTIFACTSTAGINGDIRECTORY}/Radarr.${BUILDNAME}.windows-core-x64-installer.exe + setup/inno/ISCC.exe setup/prowlarr.iss //DFramework=netcoreapp3.1 + cp setup/output/Prowlarr.*windows.netcoreapp3.1.exe ${BUILD_ARTIFACTSTAGINGDIRECTORY}/Prowlarr.${BUILDNAME}.windows-core-x64-installer.exe displayName: Create .NET Core Windows installer - publish: $(Build.ArtifactStagingDirectory) artifact: 'WindowsInstaller' @@ -218,27 +218,27 @@ stages: - bash: ./build.sh --packages displayName: Create Packages - bash: | - find . -name "Radarr" -exec chmod a+x {} \; - find . -name "Radarr.Update" -exec chmod a+x {} \; + find . -name "Prowlarr" -exec chmod a+x {} \; + find . -name "Prowlarr.Update" -exec chmod a+x {} \; displayName: Set executable bits - task: ArchiveFiles@2 displayName: Create Windows Core zip inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x64.zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).windows-core-x64.zip' archiveType: 'zip' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/windows/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create MacOS Core app inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-x64.zip' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-app-core-x64.zip' archiveType: 'zip' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/macos-app/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create MacOS Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-x64.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).osx-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -246,7 +246,7 @@ stages: - task: ArchiveFiles@2 displayName: Create Linux Mono tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -254,7 +254,7 @@ stages: - task: ArchiveFiles@2 displayName: Create Linux Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x64.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -262,7 +262,7 @@ stages: - task: ArchiveFiles@2 displayName: Create Linux Musl Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-x64.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-musl-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -270,7 +270,7 @@ stages: - task: ArchiveFiles@2 displayName: Create ARM32 Linux Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-core-arm.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -278,7 +278,7 @@ stages: - task: ArchiveFiles@2 displayName: Create ARM64 Linux Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm64.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-core-arm64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -286,7 +286,7 @@ stages: - task: ArchiveFiles@2 displayName: Create ARM64 Linux Musl Core tar inputs: - archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm64.tar.gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).linux-musl-core-arm64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false @@ -298,8 +298,8 @@ stages: echo "Uploading source maps to sentry" curl -sL https://sentry.io/get-cli/ | bash RELEASENAME="${RADARRVERSION}-${BUILD_SOURCEBRANCHNAME}" - sentry-cli releases new --finalize -p radarr -p radarr-ui -p radarr-update "${RELEASENAME}" - sentry-cli releases -p radarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite + sentry-cli releases new --finalize -p prowlarr -p prowlarr-ui -p prowlarr-update "${RELEASENAME}" + sentry-cli releases -p prowlarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite sentry-cli releases set-commits --auto "${RELEASENAME}" if [[ ${BUILD_SOURCEBRANCH} == "refs/heads/develop" ]]; then sentry-cli releases deploys "${RELEASENAME}" new -e nightly @@ -359,7 +359,7 @@ stages: osName: 'Linux' testName: 'LinuxCore' imageName: 'ubuntu-18.04' - pattern: 'Radarr.**.linux-core-x64.tar.gz' + pattern: 'Prowlarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) @@ -394,7 +394,7 @@ stages: echo "##vso[task.setvariable variable=PATH;]$MONOPREFIX/bin:$PATH" displayName: Set Mono Version condition: and(succeeded(), eq(variables['osName'], 'Mac')) - - bash: find ${TESTSFOLDER} -name "Radarr.Test.Dummy" -exec chmod a+x {} \; + - bash: find ${TESTSFOLDER} -name "Prowlarr.Test.Dummy" -exec chmod a+x {} \; displayName: Make Test Dummy Executable condition: and(succeeded(), ne(variables['osName'], 'Windows')) - bash: | @@ -453,7 +453,7 @@ stages: buildType: 'current' artifactName: $(artifactName) targetPath: $(testsFolder) - - bash: find ${TESTSFOLDER} -name "Radarr.Test.Dummy" -exec chmod a+x {} \; + - bash: find ${TESTSFOLDER} -name "Prowlarr.Test.Dummy" -exec chmod a+x {} \; displayName: Make Test Dummy Executable condition: and(succeeded(), ne(variables['osName'], 'Windows')) - bash: | @@ -497,17 +497,17 @@ stages: osName: 'Mac' testName: 'MacCore' imageName: 'macos-10.14' - pattern: 'Radarr.**.osx-core-x64.tar.gz' + pattern: 'Prowlarr.**.osx-core-x64.tar.gz' WindowsCore: osName: 'Windows' testName: 'WindowsCore' imageName: 'windows-2019' - pattern: 'Radarr.**.windows-core-x64.zip' + pattern: 'Prowlarr.**.windows-core-x64.zip' LinuxCore: osName: 'Linux' testName: 'LinuxCore' imageName: 'ubuntu-18.04' - pattern: 'Radarr.**.linux-core-x64.tar.gz' + pattern: 'Prowlarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) @@ -546,7 +546,7 @@ stages: displayName: Extract Package - bash: | mkdir -p ./bin/ - cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Radarr/. ./bin/ + cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Prowlarr/. ./bin/ displayName: Move Package Contents - bash: | chmod a+x ${TESTSFOLDER}/test.sh @@ -570,22 +570,22 @@ stages: testName: 'Mono 5.20' artifactName: LinuxTests containerImage: servarr/testimages:mono-5.20 - pattern: 'Radarr.**.linux.tar.gz' + pattern: 'Prowlarr.**.linux.tar.gz' mono610: testName: 'Mono 6.10' artifactName: LinuxTests containerImage: servarr/testimages:mono-6.10 - pattern: 'Radarr.**.linux.tar.gz' + pattern: 'Prowlarr.**.linux.tar.gz' mono612: testName: 'Mono 6.12' artifactName: LinuxTests containerImage: servarr/testimages:mono-6.12 - pattern: 'Radarr.**.linux.tar.gz' + pattern: 'Prowlarr.**.linux.tar.gz' alpine: testName: 'Musl Net Core' artifactName: LinuxMuslCoreTests containerImage: servarr/testimages:alpine - pattern: 'Radarr.**.linux-musl-core-x64.tar.gz' + pattern: 'Prowlarr.**.linux-musl-core-x64.tar.gz' pool: vmImage: 'ubuntu-18.04' @@ -619,7 +619,7 @@ stages: displayName: Extract Package - bash: | mkdir -p ./bin/ - cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Radarr/. ./bin/ + cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Prowlarr/. ./bin/ displayName: Move Package Contents - bash: | chmod a+x ${TESTSFOLDER}/test.sh @@ -644,17 +644,17 @@ stages: Linux: osName: 'Linux' imageName: 'ubuntu-18.04' - pattern: 'Radarr.**.linux-core-x64.tar.gz' + pattern: 'Prowlarr.**.linux-core-x64.tar.gz' failBuild: true Mac: osName: 'Mac' imageName: 'macos-10.14' - pattern: 'Radarr.**.osx-core-x64.tar.gz' + pattern: 'Prowlarr.**.osx-core-x64.tar.gz' failBuild: true Windows: osName: 'Windows' imageName: 'windows-2019' - pattern: 'Radarr.**.windows-core-x64.zip' + pattern: 'Prowlarr.**.windows-core-x64.zip' failBuild: true pool: @@ -686,7 +686,7 @@ stages: displayName: Extract Package - bash: | mkdir -p ./bin/ - cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Radarr/. ./bin/ + cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Prowlarr/. ./bin/ displayName: Move Package Contents - bash: | chmod a+x ${TESTSFOLDER}/test.sh @@ -759,7 +759,7 @@ stages: path: $(yarnCacheFolder) displayName: Cache Yarn packages - bash: ./build.sh --lint - displayName: Lint Radarr Frontend + displayName: Lint Prowlarr Frontend env: FORCE_COLOR: 0 YARN_CACHE_FOLDER: $(yarnCacheFolder) @@ -776,7 +776,7 @@ stages: SONAR_SCANNER_OPTS: '' inputs: SonarCloud: 'SonarCloud' - organization: 'radarr' + organization: 'prowlarr' scannerMode: 'CLI' configMode: 'manual' cliProjectKey: 'Radarr_Radarr.UI' @@ -809,14 +809,14 @@ stages: condition: eq(variables['System.PullRequest.IsFork'], 'False') inputs: SonarCloud: 'SonarCloud' - organization: 'radarr' + organization: 'prowlarr' scannerMode: 'MSBuild' projectKey: 'Radarr_Radarr' - projectName: 'Radarr' + projectName: 'Prowlarr' projectVersion: '$(radarrVersion)' extraProperties: | sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/** - sonar.coverage.exclusions=**/Radarr.Api.V3/**/*,**/NzbDrone.Api/**/*,**/MonoTorrent/**/*,**/Marr.Data/**/* + sonar.coverage.exclusions=**/Prowlarr.Api.V1/**/*,**/NzbDrone.Api/**/*,**/MonoTorrent/**/*,**/Marr.Data/**/* sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml - bash: | diff --git a/build.sh b/build.sh index 41634231a..329e66707 100755 --- a/build.sh +++ b/build.sh @@ -21,7 +21,7 @@ UpdateVersionNumber() echo "Updating Version Info" sed -i'' -e "s/[0-9.*]\+<\/AssemblyVersion>/$RADARRVERSION<\/AssemblyVersion>/g" src/Directory.Build.props sed -i'' -e "s/[\$()A-Za-z-]\+<\/AssemblyConfiguration>/${BUILD_SOURCEBRANCHNAME}<\/AssemblyConfiguration>/g" src/Directory.Build.props - sed -i'' -e "s/10.0.0.0<\/string>/$RADARRVERSION<\/string>/g" macOS/Radarr.app/Contents/Info.plist + sed -i'' -e "s/10.0.0.0<\/string>/$RADARRVERSION<\/string>/g" macOS/Prowlarr.app/Contents/Info.plist fi } @@ -47,7 +47,7 @@ Build() rm -rf $outputFolder rm -rf $testPackageFolder - slnFile=src/Radarr.sln + slnFile=src/Prowlarr.sln if [ $os = "windows" ]; then platform=Windows @@ -91,7 +91,7 @@ PackageFiles() rm -rf $folder mkdir -p $folder cp -r $outputFolder/$framework/$runtime/publish/* $folder - cp -r $outputFolder/Radarr.Update/$framework/$runtime/publish $folder/Radarr.Update + cp -r $outputFolder/Prowlarr.Update/$framework/$runtime/publish $folder/Prowlarr.Update cp -r $outputFolder/UI $folder echo "Adding LICENSE" @@ -105,7 +105,7 @@ PackageLinux() ProgressStart "Creating $runtime Package for $framework" - local folder=$artifactsFolder/$runtime/$framework/Radarr + local folder=$artifactsFolder/$runtime/$framework/Prowlarr PackageFiles "$folder" "$framework" "$runtime" @@ -113,14 +113,14 @@ PackageLinux() rm -f $folder/ServiceUninstall.* rm -f $folder/ServiceInstall.* - echo "Removing Radarr.Windows" - rm $folder/Radarr.Windows.* + echo "Removing Prowlarr.Windows" + rm $folder/Prowlarr.Windows.* - echo "Adding Radarr.Mono to UpdatePackage" - cp $folder/Radarr.Mono.* $folder/Radarr.Update + echo "Adding Prowlarr.Mono to UpdatePackage" + cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update if [ "$framework" = "netcoreapp3.1" ]; then - cp $folder/Mono.Posix.NETStandard.* $folder/Radarr.Update - cp $folder/libMonoPosixHelper.* $folder/Radarr.Update + cp $folder/Mono.Posix.NETStandard.* $folder/Prowlarr.Update + cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update fi ProgressEnd "Creating $runtime Package for $framework" @@ -132,27 +132,27 @@ PackageMacOS() ProgressStart "Creating MacOS Package for $framework" - local folder=$artifactsFolder/macos/$framework/Radarr + local folder=$artifactsFolder/macos/$framework/Prowlarr PackageFiles "$folder" "$framework" "osx-x64" if [ "$framework" = "net462" ]; then echo "Adding Startup script" - cp macOS/Radarr $folder + cp macOS/Prowlarr $folder fi echo "Removing Service helpers" rm -f $folder/ServiceUninstall.* rm -f $folder/ServiceInstall.* - echo "Removing Radarr.Windows" - rm $folder/Radarr.Windows.* + echo "Removing Prowlarr.Windows" + rm $folder/Prowlarr.Windows.* - echo "Adding Radarr.Mono to UpdatePackage" - cp $folder/Radarr.Mono.* $folder/Radarr.Update + echo "Adding Prowlarr.Mono to UpdatePackage" + cp $folder/Prowlarr.Mono.* $folder/Prowlarr.Update if [ "$framework" = "netcoreapp3.1" ]; then - cp $folder/Mono.Posix.NETStandard.* $folder/Radarr.Update - cp $folder/libMonoPosixHelper.* $folder/Radarr.Update + cp $folder/Mono.Posix.NETStandard.* $folder/Prowlarr.Update + cp $folder/libMonoPosixHelper.* $folder/Prowlarr.Update fi ProgressEnd 'Creating MacOS Package' @@ -168,14 +168,14 @@ PackageMacOSApp() rm -rf $folder mkdir -p $folder - cp -r macOS/Radarr.app $folder - mkdir -p $folder/Radarr.app/Contents/MacOS + cp -r macOS/Prowlarr.app $folder + mkdir -p $folder/Prowlarr.app/Contents/MacOS echo "Copying Binaries" - cp -r $artifactsFolder/macos/$framework/Radarr/* $folder/Radarr.app/Contents/MacOS + cp -r $artifactsFolder/macos/$framework/Prowlarr/* $folder/Prowlarr.app/Contents/MacOS echo "Removing Update Folder" - rm -r $folder/Radarr.app/Contents/MacOS/Radarr.Update + rm -r $folder/Prowlarr.app/Contents/MacOS/Prowlarr.Update ProgressEnd 'Creating macOS App Package' } @@ -186,17 +186,17 @@ PackageWindows() ProgressStart "Creating Windows Package for $framework" - local folder=$artifactsFolder/windows/$framework/Radarr + local folder=$artifactsFolder/windows/$framework/Prowlarr PackageFiles "$folder" "$framework" "win-x64" - echo "Removing Radarr.Mono" - rm -f $folder/Radarr.Mono.* + echo "Removing Prowlarr.Mono" + rm -f $folder/Prowlarr.Mono.* rm -f $folder/Mono.Posix.NETStandard.* rm -f $folder/libMonoPosixHelper.* - echo "Adding Radarr.Windows to UpdatePackage" - cp $folder/Radarr.Windows.* $folder/Radarr.Update + echo "Adding Prowlarr.Windows to UpdatePackage" + cp $folder/Prowlarr.Windows.* $folder/Prowlarr.Update ProgressEnd 'Creating Windows Package' } diff --git a/changelog.tpl b/changelog.tpl deleted file mode 100644 index 24e32051d..000000000 --- a/changelog.tpl +++ /dev/null @@ -1,14 +0,0 @@ -# Changelog - -{{#versions}} -## {{{label}}} - -{{#sections}} -### {{{label}}} -{{#commits}} -- {{{subject}}} [{{{author}}}] -{{/commits}} - -{{/sections}} - -{{/versions}} diff --git a/changelog_release.tpl b/changelog_release.tpl deleted file mode 100644 index f4eb2c1ba..000000000 --- a/changelog_release.tpl +++ /dev/null @@ -1,15 +0,0 @@ -**To receive further Pre-Release updates, please change the branch to develop. (Settings -> General (Show Advanced Settings) -> Updates -> Branch)** - -{{#versions}} - -{{#sections}} -{{{label}}} -{{#commits}} -- {{{subject}}} [{{{author}}}] -{{/commits}} - -{{/sections}} - -{{/versions}} - -**Note**: The OSX version does not automatically launch the browser. You have to go to http://localhost:7878 by yourself in a browser of your choice. diff --git a/create_test_cases.py b/create_test_cases.py deleted file mode 100644 index 5d1879ea1..000000000 --- a/create_test_cases.py +++ /dev/null @@ -1,44 +0,0 @@ -input1 = """Prometheus.Special.Edition.Fan Edit.2012..BRRip.x264.AAC-m2g -Star Wars Episode IV - A New Hope (Despecialized) 1999.mkv -Prometheus.(Special.Edition.Remastered).2012.[Bluray-1080p].mkv -Prometheus Extended 2012 -Prometheus Extended Directors Cut Fan Edit 2012 -Prometheus Director's Cut 2012 -Prometheus Directors Cut 2012 -Prometheus.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf -2001 A Space Odyssey Director's Cut (1968).mkv -2001: A Space Odyssey (Extended Directors Cut FanEdit) Bluray 1080p 1968 -A Fake Movie 2035 Directors 2012.mkv -Blade Runner Director's Cut 2049.mkv -Prometheus 50th Anniversary Edition 2012.mkv -Movie 2in1 2012.mkv -Movie IMAX 2012.mkv""" - -output1 = """Special.Edition.Fan Edit BRRip.x264.AAC-m2g -Despecialized mkv -Special.Edition.Remastered Bluray-1080p].mkv -Extended mkv -Extended Directors Cut Fan Edit mkv -Director's Cut mkv -Directors Cut mkv -Extended.Theatrical.Version.IMAX asdf -Director's Cut mkv -Extended Directors Cut FanEdit mkv -Directors mkv -Director's Cut mkv -50th Anniversary Edition mkv -2in1 mkv -IMAX mkv""" - -inputs = input1.split("\n") -outputs = output1.split("\n") -real_o = [] -for output in outputs: - real_o.append(output.split(" ")[0].replace(".", " ").strip()) - -count = 0 - -for inp in inputs: - o = real_o[count] - print "[TestCase(\"{0}\", \"{1}\")]".format(inp, o) - count += 1 diff --git a/frontend/src/Activity/History/Details/HistoryDetails.js b/frontend/src/Activity/History/Details/HistoryDetails.js index 82d8dc799..de8b9192e 100644 --- a/frontend/src/Activity/History/Details/HistoryDetails.js +++ b/frontend/src/Activity/History/Details/HistoryDetails.js @@ -176,7 +176,7 @@ function HistoryDetails(props) { reasonMessage = 'File was deleted by via UI'; break; case 'MissingFromDisk': - reasonMessage = 'Radarr was unable to find the file on disk so it was removed'; + reasonMessage = 'Prowlarr was unable to find the file on disk so it was removed'; break; case 'Upgrade': reasonMessage = 'File was deleted to import an upgrade'; diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js index 8156dc869..b387915b5 100644 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovie.js @@ -159,7 +159,7 @@ class AddNewMovie extends Component { {translate('YouCanAlsoSearch')}
- + {translate('CantFindMovie')}
diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js index 252d30058..37f22ed18 100644 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieConnector.js @@ -4,7 +4,6 @@ import { connect } from 'react-redux'; import { createSelector } from 'reselect'; import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions'; import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions'; import parseUrl from 'Utilities/String/parseUrl'; import AddNewMovie from './AddNewMovie'; @@ -28,8 +27,7 @@ function createMapStateToProps() { const mapDispatchToProps = { lookupMovie, clearAddMovie, - fetchRootFolders, - fetchImportExclusions + fetchRootFolders }; class AddNewMovieConnector extends Component { @@ -45,7 +43,6 @@ class AddNewMovieConnector extends Component { componentDidMount() { this.props.fetchRootFolders(); - this.props.fetchImportExclusions(); } componentWillUnmount() { @@ -101,8 +98,7 @@ AddNewMovieConnector.propTypes = { term: PropTypes.string, lookupMovie: PropTypes.func.isRequired, clearAddMovie: PropTypes.func.isRequired, - fetchRootFolders: PropTypes.func.isRequired, - fetchImportExclusions: PropTypes.func.isRequired + fetchRootFolders: PropTypes.func.isRequired }; export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector); diff --git a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js index 44692a785..3302a7bdb 100644 --- a/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js +++ b/frontend/src/AddMovie/AddNewMovie/AddNewMovieSearchResult.js @@ -6,7 +6,6 @@ import Label from 'Components/Label'; import Link from 'Components/Link/Link'; import Tooltip from 'Components/Tooltip/Tooltip'; import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props'; -import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks'; import MoviePoster from 'Movie/MoviePoster'; import translate from 'Utilities/String/translate'; import AddNewMovieModal from './AddNewMovieModal'; @@ -52,8 +51,6 @@ class AddNewMovieSearchResult extends Component { render() { const { tmdbId, - imdbId, - youTubeTrailerId, title, titleSlug, year, @@ -163,13 +160,6 @@ class AddNewMovieSearchResult extends Component {
} - tooltip={ - - } canFlip={true} kind={kinds.INVERSE} position={tooltipPositions.BOTTOM} diff --git a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js index 373af76fb..f874cec87 100644 --- a/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js +++ b/frontend/src/AddMovie/ImportMovie/SelectFolder/ImportMovieSelectFolderConnector.js @@ -48,7 +48,7 @@ class ImportMovieSelectFolderConnector extends Component { const newRootFolders = _.differenceBy(items, prevProps.items, (item) => item.id); if (newRootFolders.length === 1) { - this.props.push(`${window.Radarr.urlBase}/add/import/${newRootFolders[0].id}`); + this.props.push(`${window.Prowlarr.urlBase}/add/import/${newRootFolders[0].id}`); } } } diff --git a/frontend/src/App/App.js b/frontend/src/App/App.js index 80ecbcbd4..ae1e4f31b 100644 --- a/frontend/src/App/App.js +++ b/frontend/src/App/App.js @@ -8,7 +8,7 @@ import AppRoutes from './AppRoutes'; function App({ store, history }) { return ( - + diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js index 0cea72088..4db8a940a 100644 --- a/frontend/src/App/AppRoutes.js +++ b/frontend/src/App/AppRoutes.js @@ -6,22 +6,12 @@ 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 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 ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector'; import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector'; -import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector'; -import MetadataSettings from 'Settings/Metadata/MetadataSettings'; import NotificationSettings from 'Settings/Notifications/NotificationSettings'; -import Profiles from 'Settings/Profiles/Profiles'; -import Quality from 'Settings/Quality/Quality'; import Settings from 'Settings/Settings'; import TagSettings from 'Settings/Tags/TagSettings'; import UISettingsConnector from 'Settings/UI/UISettingsConnector'; @@ -51,7 +41,7 @@ function AppRoutes(props) { /> { - window.Radarr.urlBase && + window.Prowlarr.urlBase && - - - - - {/* - Calendar - */} - - - {/* Activity */} @@ -125,51 +96,16 @@ function AppRoutes(props) { component={Settings} /> - - - - - - - - - - - - - - - Radarr Updated + Prowlarr Updated
- Version {version} of Radarr has been installed, in order to get the latest changes you'll need to reload Radarr. + Version {version} of Prowlarr has been installed, in order to get the latest changes you'll need to reload Prowlarr.
{ diff --git a/frontend/src/App/AppUpdatedModalContentConnector.js b/frontend/src/App/AppUpdatedModalContentConnector.js index 325a1aa95..81e43cf19 100644 --- a/frontend/src/App/AppUpdatedModalContentConnector.js +++ b/frontend/src/App/AppUpdatedModalContentConnector.js @@ -33,7 +33,7 @@ function createMapDispatchToProps(dispatch, props) { }, onSeeChangesPress() { - window.location = `${window.Radarr.urlBase}/system/updates`; + window.location = `${window.Prowlarr.urlBase}/system/updates`; } }; } diff --git a/frontend/src/Calendar/Agenda/Agenda.css b/frontend/src/Calendar/Agenda/Agenda.css deleted file mode 100644 index 0304d9db5..000000000 --- a/frontend/src/Calendar/Agenda/Agenda.css +++ /dev/null @@ -1,3 +0,0 @@ -.agenda { - margin-top: 10px; -} diff --git a/frontend/src/Calendar/Agenda/Agenda.js b/frontend/src/Calendar/Agenda/Agenda.js deleted file mode 100644 index 40c179ac4..000000000 --- a/frontend/src/Calendar/Agenda/Agenda.js +++ /dev/null @@ -1,69 +0,0 @@ -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React from 'react'; -import AgendaEventConnector from './AgendaEventConnector'; -import styles from './Agenda.css'; - -function Agenda(props) { - const { - items, - start, - end - } = props; - - const startDateParsed = Date.parse(start); - const endDateParsed = Date.parse(end); - - items.forEach((item) => { - const cinemaDateParsed = Date.parse(item.inCinemas); - const digitalDateParsed = Date.parse(item.digitalRelease); - const physicalDateParsed = Date.parse(item.physicalRelease); - const dates = []; - - if (cinemaDateParsed > 0 && cinemaDateParsed >= startDateParsed && cinemaDateParsed <= endDateParsed) { - dates.push(cinemaDateParsed); - } - if (digitalDateParsed > 0 && digitalDateParsed >= startDateParsed && digitalDateParsed <= endDateParsed) { - dates.push(digitalDateParsed); - } - if (physicalDateParsed > 0 && physicalDateParsed >= startDateParsed && physicalDateParsed <= endDateParsed) { - dates.push(physicalDateParsed); - } - - item.sortDate = Math.min(...dates); - item.cinemaDateParsed = cinemaDateParsed; - item.digitalDateParsed = digitalDateParsed; - item.physicalDateParsed = physicalDateParsed; - }); - - items.sort((a, b) => ((a.sortDate > b.sortDate) ? 1 : -1)); - - return ( -
- { - items.map((item, index) => { - const momentDate = moment(item.inCinemas); - const showDate = index === 0 || - !moment(items[index - 1].inCinemas).isSame(momentDate, 'day'); - - return ( - - ); - }) - } -
- ); -} - -Agenda.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - start: PropTypes.string.isRequired, - end: PropTypes.string.isRequired -}; - -export default Agenda; diff --git a/frontend/src/Calendar/Agenda/AgendaConnector.js b/frontend/src/Calendar/Agenda/AgendaConnector.js deleted file mode 100644 index b6f238873..000000000 --- a/frontend/src/Calendar/Agenda/AgendaConnector.js +++ /dev/null @@ -1,14 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import Agenda from './Agenda'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - (calendar) => { - return calendar; - } - ); -} - -export default connect(createMapStateToProps)(Agenda); diff --git a/frontend/src/Calendar/Agenda/AgendaEvent.css b/frontend/src/Calendar/Agenda/AgendaEvent.css deleted file mode 100644 index 7c1e6c182..000000000 --- a/frontend/src/Calendar/Agenda/AgendaEvent.css +++ /dev/null @@ -1,96 +0,0 @@ -.event { - display: flex; - overflow-x: hidden; - padding: 5px; - border-bottom: 1px solid $borderColor; - font-size: $defaultFontSize; - - &:hover { - background-color: $tableRowHoverBackgroundColor; - } -} - -.link { - composes: link from '~Calendar/Events/CalendarEvent.css'; -} - -.eventWrapper { - display: flex; - flex: 1 0 1px; - overflow-x: hidden; - padding-left: 6px; - border-left-width: 4px; - border-left-style: solid; -} - -.date { - flex: 0 0 250px; - font-weight: bold; -} - -.time { - flex: 0 0 120px; - margin-right: 10px; - border: none !important; -} - -.movieTitle, -.genres { - @add-mixin truncate; - - flex: 0 1 300px; - margin-right: 10px; -} - -.statusIcon { - margin-left: 3px; -} - -/* - * Status - */ - -.downloaded { - composes: downloaded from '~Calendar/Events/CalendarEvent.css'; -} - -.downloading { - composes: downloading from '~Calendar/Events/CalendarEvent.css'; -} - -.unmonitored { - composes: unmonitored from '~Calendar/Events/CalendarEvent.css'; -} - -.missing { - composes: missing from '~Calendar/Events/CalendarEvent.css'; -} - -.unreleased { - composes: unreleased from '~Calendar/Events/CalendarEvent.css'; -} - -@media only screen and (max-width: $breakpointSmall) { - .event { - flex-direction: column; - } - - .eventWrapper { - display: block; - flex: 0 0 auto; - } - - .date { - margin-left: 10px; - } - - .date, - .time, - .movieTitle { - flex: 0 0 100%; - } -} - -.dateIcon { - width: 25px; -} diff --git a/frontend/src/Calendar/Agenda/AgendaEvent.js b/frontend/src/Calendar/Agenda/AgendaEvent.js deleted file mode 100644 index e6cc532bf..000000000 --- a/frontend/src/Calendar/Agenda/AgendaEvent.js +++ /dev/null @@ -1,193 +0,0 @@ -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 getStatusStyle from 'Calendar/getStatusStyle'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './AgendaEvent.css'; - -class AgendaEvent extends Component { - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isDetailsModalOpen: false - }; - } - - // - // Listeners - - onPress = () => { - this.setState({ isDetailsModalOpen: true }); - } - - onDetailsModalClose = () => { - this.setState({ isDetailsModalOpen: false }); - } - - // - // Render - - render() { - const { - movieFile, - title, - titleSlug, - genres, - isAvailable, - inCinemas, - digitalRelease, - physicalRelease, - monitored, - hasFile, - grabbed, - queueItem, - showDate, - showMovieInformation, - showCutoffUnmetIcon, - longDateFormat, - colorImpairedMode, - cinemaDateParsed, - digitalDateParsed, - physicalDateParsed, - sortDate - } = this.props; - - let startTime = null; - let releaseIcon = null; - - if (physicalDateParsed === sortDate) { - startTime = physicalRelease; - releaseIcon = icons.DISC; - } - - if (digitalDateParsed === sortDate) { - startTime = digitalRelease; - releaseIcon = icons.MOVIE_FILE; - } - - if (cinemaDateParsed === sortDate) { - startTime = inCinemas; - releaseIcon = icons.IN_CINEMAS; - } - - startTime = moment(startTime); - const downloading = !!(queueItem || grabbed); - const isMonitored = monitored; - const statusStyle = getStatusStyle(hasFile, downloading, isAvailable, isMonitored); - const joinedGenres = genres.slice(0, 2).join(', '); - const link = `/movie/${titleSlug}`; - - return ( -
- -
- -
- -
- {(showDate) ? startTime.format(longDateFormat) : null} -
- -
-
- {title} -
- - { - showMovieInformation && -
- {joinedGenres} -
- } - - { - !!queueItem && - - - - } - - { - !queueItem && grabbed && - - } - - { - showCutoffUnmetIcon && - !!movieFile && - movieFile.qualityCutoffNotMet && - - } -
- -
- ); - } -} - -AgendaEvent.propTypes = { - id: PropTypes.number.isRequired, - movieFile: PropTypes.object, - title: PropTypes.string.isRequired, - titleSlug: PropTypes.string.isRequired, - genres: PropTypes.arrayOf(PropTypes.string).isRequired, - isAvailable: PropTypes.bool.isRequired, - inCinemas: PropTypes.string, - digitalRelease: PropTypes.string, - physicalRelease: PropTypes.string, - monitored: PropTypes.bool.isRequired, - hasFile: PropTypes.bool.isRequired, - grabbed: PropTypes.bool, - queueItem: PropTypes.object, - showDate: PropTypes.bool.isRequired, - showMovieInformation: PropTypes.bool.isRequired, - showCutoffUnmetIcon: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - colorImpairedMode: PropTypes.bool.isRequired, - cinemaDateParsed: PropTypes.number, - digitalDateParsed: PropTypes.number, - physicalDateParsed: PropTypes.number, - sortDate: PropTypes.number -}; - -AgendaEvent.defaultProps = { - genres: [] -}; - -export default AgendaEvent; diff --git a/frontend/src/Calendar/Agenda/AgendaEventConnector.js b/frontend/src/Calendar/Agenda/AgendaEventConnector.js deleted file mode 100644 index ea653364a..000000000 --- a/frontend/src/Calendar/Agenda/AgendaEventConnector.js +++ /dev/null @@ -1,30 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieFileSelector from 'Store/Selectors/createMovieFileSelector'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import AgendaEvent from './AgendaEvent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.options, - createMovieSelector(), - createMovieFileSelector(), - createQueueItemSelector(), - createUISettingsSelector(), - (calendarOptions, movie, movieFile, queueItem, uiSettings) => { - return { - movie, - movieFile, - queueItem, - ...calendarOptions, - timeFormat: uiSettings.timeFormat, - longDateFormat: uiSettings.longDateFormat, - colorImpairedMode: uiSettings.enableColorImpairedMode - }; - } - ); -} - -export default connect(createMapStateToProps)(AgendaEvent); diff --git a/frontend/src/Calendar/Calendar.css b/frontend/src/Calendar/Calendar.css deleted file mode 100644 index 37e6ff618..000000000 --- a/frontend/src/Calendar/Calendar.css +++ /dev/null @@ -1,8 +0,0 @@ -.calendar { - flex-grow: 1; - width: 100%; -} - -.calendarContent { - width: 100%; -} diff --git a/frontend/src/Calendar/Calendar.js b/frontend/src/Calendar/Calendar.js deleted file mode 100644 index fec208a00..000000000 --- a/frontend/src/Calendar/Calendar.js +++ /dev/null @@ -1,67 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import translate from 'Utilities/String/translate'; -import AgendaConnector from './Agenda/AgendaConnector'; -import * as calendarViews from './calendarViews'; -import CalendarDaysConnector from './Day/CalendarDaysConnector'; -import DaysOfWeekConnector from './Day/DaysOfWeekConnector'; -import CalendarHeaderConnector from './Header/CalendarHeaderConnector'; -import styles from './Calendar.css'; - -class Calendar extends Component { - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - view - } = this.props; - - return ( -
- { - isFetching && !isPopulated && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadTheCalendar')} -
- } - - { - !error && isPopulated && view === calendarViews.AGENDA && -
- - -
- } - - { - !error && isPopulated && view !== calendarViews.AGENDA && -
- - - -
- } -
- ); - } -} - -Calendar.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - view: PropTypes.string.isRequired -}; - -export default Calendar; diff --git a/frontend/src/Calendar/CalendarConnector.js b/frontend/src/Calendar/CalendarConnector.js deleted file mode 100644 index 535d94fe8..000000000 --- a/frontend/src/Calendar/CalendarConnector.js +++ /dev/null @@ -1,195 +0,0 @@ -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 hasDifferentItems from 'Utilities/Object/hasDifferentItems'; -import selectUniqueIds from 'Utilities/Object/selectUniqueIds'; -import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; -import Calendar from './Calendar'; - -const UPDATE_DELAY = 3600000; // 1 hour - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - (state) => state.settings.ui.item.firstDayOfWeek, - createCommandExecutingSelector(commandNames.REFRESH_MOVIE), - (calendar, firstDayOfWeek, isRefreshingMovie) => { - return { - ...calendar, - isRefreshingMovie, - firstDayOfWeek - }; - } - ); -} - -const mapDispatchToProps = { - ...calendarActions, - fetchMovieFiles, - clearMovieFiles, - fetchQueueDetails, - clearQueueDetails -}; - -class CalendarConnector extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.updateTimeoutId = null; - } - - componentDidMount() { - const { - useCurrentPage, - fetchCalendar, - gotoCalendarToday - } = this.props; - - registerPagePopulator(this.repopulate); - - if (useCurrentPage) { - fetchCalendar(); - } else { - gotoCalendarToday(); - } - - this.scheduleUpdate(); - } - - componentDidUpdate(prevProps) { - const { - items, - time, - view, - isRefreshingMovie, - firstDayOfWeek - } = this.props; - - if (hasDifferentItems(prevProps.items, items)) { - const movieFileIds = selectUniqueIds(items, 'movieFileId'); - - if (movieFileIds.length) { - this.props.fetchMovieFiles({ movieFileIds }); - } - - if (items.length) { - this.props.fetchQueueDetails(); - } - } - - if (prevProps.time !== time) { - this.scheduleUpdate(); - } - - if (prevProps.firstDayOfWeek !== firstDayOfWeek) { - this.props.fetchCalendar({ time, view }); - } - - if (prevProps.isRefreshingMovie && !isRefreshingMovie) { - this.props.fetchCalendar({ time, view }); - } - } - - componentWillUnmount() { - unregisterPagePopulator(this.repopulate); - this.props.clearCalendar(); - this.props.clearQueueDetails(); - this.props.clearMovieFiles(); - this.clearUpdateTimeout(); - } - - // - // Control - - repopulate = () => { - const { - time, - view - } = this.props; - - this.props.fetchQueueDetails({ time, view }); - this.props.fetchCalendar({ time, view }); - } - - scheduleUpdate = () => { - this.clearUpdateTimeout(); - - this.updateTimeoutId = setTimeout(this.updateCalendar, UPDATE_DELAY); - } - - clearUpdateTimeout = () => { - if (this.updateTimeoutId) { - clearTimeout(this.updateTimeoutId); - } - } - - updateCalendar = () => { - this.props.gotoCalendarToday(); - this.scheduleUpdate(); - } - - // - // Listeners - - onCalendarViewChange = (view) => { - this.props.setCalendarView({ view }); - } - - onTodayPress = () => { - this.props.gotoCalendarToday(); - } - - onPreviousPress = () => { - this.props.gotoCalendarPreviousRange(); - } - - onNextPress = () => { - this.props.gotoCalendarNextRange(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -CalendarConnector.propTypes = { - useCurrentPage: PropTypes.bool.isRequired, - time: PropTypes.string, - view: PropTypes.string.isRequired, - firstDayOfWeek: PropTypes.number.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - isRefreshingMovie: PropTypes.bool.isRequired, - setCalendarView: PropTypes.func.isRequired, - gotoCalendarToday: PropTypes.func.isRequired, - gotoCalendarPreviousRange: PropTypes.func.isRequired, - gotoCalendarNextRange: PropTypes.func.isRequired, - clearCalendar: PropTypes.func.isRequired, - fetchCalendar: PropTypes.func.isRequired, - fetchMovieFiles: PropTypes.func.isRequired, - clearMovieFiles: PropTypes.func.isRequired, - fetchQueueDetails: PropTypes.func.isRequired, - clearQueueDetails: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(CalendarConnector); diff --git a/frontend/src/Calendar/CalendarPage.css b/frontend/src/Calendar/CalendarPage.css deleted file mode 100644 index b6839c467..000000000 --- a/frontend/src/Calendar/CalendarPage.css +++ /dev/null @@ -1,20 +0,0 @@ -.calendarPageBody { - composes: contentBody from '~Components/Page/PageContentBody.css'; - - display: flex; -} - -.calendarInnerPageBody { - composes: innerContentBody from '~Components/Page/PageContentBody.css'; - - display: flex; - flex-direction: column; - flex-grow: 1; - width: 100%; -} - -.errorMessage { - margin-top: 20px; - text-align: center; - font-size: 20px; -} diff --git a/frontend/src/Calendar/CalendarPage.js b/frontend/src/Calendar/CalendarPage.js deleted file mode 100644 index c569a6532..000000000 --- a/frontend/src/Calendar/CalendarPage.js +++ /dev/null @@ -1,220 +0,0 @@ -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 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 { align, icons } from 'Helpers/Props'; -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 styles from './CalendarPage.css'; - -const MINIMUM_DAY_WIDTH = 120; - -class CalendarPage extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isCalendarLinkModalOpen: false, - isOptionsModalOpen: false, - width: 0 - }; - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.setState({ width }); - const days = Math.max(3, Math.min(7, Math.floor(width / MINIMUM_DAY_WIDTH))); - - this.props.onDaysCountChange(days); - } - - onGetCalendarLinkPress = () => { - this.setState({ isCalendarLinkModalOpen: true }); - } - - onGetCalendarLinkModalClose = () => { - this.setState({ isCalendarLinkModalOpen: false }); - } - - onOptionsPress = () => { - this.setState({ isOptionsModalOpen: true }); - } - - onOptionsModalClose = () => { - this.setState({ isOptionsModalOpen: false }); - } - - onSearchMissingPress = () => { - const { - missingMovieIds, - onSearchMissingPress - } = this.props; - - onSearchMissingPress(missingMovieIds); - } - - // - // Render - - render() { - const { - selectedFilterKey, - filters, - hasMovie, - movieError, - movieIsFetching, - movieIsPopulated, - missingMovieIds, - isRssSyncExecuting, - isSearchingForMissing, - useCurrentPage, - onRssSyncPress, - onFilterSelect - } = this.props; - - const { - isCalendarLinkModalOpen, - isOptionsModalOpen - } = this.state; - - const isMeasured = this.state.width > 0; - - return ( - - - - - - - - - - - - - - - - - - - - - { - movieIsFetching && !movieIsPopulated && - - } - - { - movieError && -
- {getErrorMessage(movieError, 'Failed to load movies from API')} -
- } - - { - !movieError && movieIsPopulated && hasMovie && - - { - isMeasured ? - : -
- } - - } - - { - !movieError && movieIsPopulated && !hasMovie && - - } - - { - hasMovie && !movieError && - - } - - - - - - - ); - } -} - -CalendarPage.propTypes = { - selectedFilterKey: PropTypes.string.isRequired, - 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, - useCurrentPage: PropTypes.bool.isRequired, - onSearchMissingPress: PropTypes.func.isRequired, - onDaysCountChange: PropTypes.func.isRequired, - onRssSyncPress: PropTypes.func.isRequired, - onFilterSelect: PropTypes.func.isRequired -}; - -export default CalendarPage; diff --git a/frontend/src/Calendar/CalendarPageConnector.js b/frontend/src/Calendar/CalendarPageConnector.js deleted file mode 100644 index d9ea208d2..000000000 --- a/frontend/src/Calendar/CalendarPageConnector.js +++ /dev/null @@ -1,116 +0,0 @@ -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 { isCommandExecuting } from 'Utilities/Command'; -import isBefore from 'Utilities/Date/isBefore'; -import CalendarPage from './CalendarPage'; - -function createMissingMovieIdsSelector() { - return createSelector( - (state) => state.calendar.start, - (state) => state.calendar.end, - (state) => state.calendar.items, - (state) => state.queue.details.items, - (start, end, movies, queueDetails) => { - return movies.reduce((acc, movie) => { - const inCinemas = movie.inCinemas; - - if ( - !movie.movieFileId && - moment(inCinemas).isAfter(start) && - moment(inCinemas).isBefore(end) && - isBefore(movie.inCinemas) && - !queueDetails.some((details) => details.movieId === movie.id) - ) { - acc.push(movie.id); - } - - return acc; - }, []); - } - ); -} - -function createIsSearchingSelector() { - return createSelector( - (state) => state.calendar.searchMissingCommandId, - createCommandsSelector(), - (searchMissingCommandId, commands) => { - if (searchMissingCommandId == null) { - return false; - } - - return isCommandExecuting(commands.find((command) => { - return command.id === searchMissingCommandId; - })); - } - ); -} - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.selectedFilterKey, - (state) => state.calendar.filters, - createMovieCountSelector(), - createUISettingsSelector(), - createMissingMovieIdsSelector(), - createCommandExecutingSelector(commandNames.RSS_SYNC), - createIsSearchingSelector(), - ( - selectedFilterKey, - filters, - movieCount, - uiSettings, - missingMovieIds, - isRssSyncExecuting, - isSearchingForMissing - ) => { - return { - selectedFilterKey, - filters, - colorImpairedMode: uiSettings.enableColorImpairedMode, - hasMovie: !!movieCount.count, - movieError: movieCount.error, - movieIsFetching: movieCount.isFetching, - movieIsPopulated: movieCount.isPopulated, - missingMovieIds, - isRssSyncExecuting, - isSearchingForMissing - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onRssSyncPress() { - dispatch(executeCommand({ - name: commandNames.RSS_SYNC - })); - }, - - onSearchMissingPress(movieIds) { - dispatch(searchMissing({ movieIds })); - }, - - onDaysCountChange(dayCount) { - dispatch(setCalendarDaysCount({ dayCount })); - }, - - onFilterSelect(selectedFilterKey) { - dispatch(setCalendarFilter({ selectedFilterKey })); - } - }; -} - -export default withCurrentPage( - connect(createMapStateToProps, createMapDispatchToProps)(CalendarPage) -); diff --git a/frontend/src/Calendar/Day/CalendarDay.css b/frontend/src/Calendar/Day/CalendarDay.css deleted file mode 100644 index 79eb67ae7..000000000 --- a/frontend/src/Calendar/Day/CalendarDay.css +++ /dev/null @@ -1,25 +0,0 @@ -.day { - flex: 1 0 14.28%; - overflow: hidden; - min-height: 70px; - border-bottom: 1px solid $calendarBorderColor; - border-left: 1px solid $calendarBorderColor; -} - -.isSingleDay { - width: 100%; -} - -.dayOfMonth { - padding-right: 5px; - border-bottom: 1px solid $calendarBorderColor; - text-align: right; -} - -.isToday { - background-color: $calendarTodayBackgroundColor; -} - -.isDifferentMonth { - color: $disabledColor; -} diff --git a/frontend/src/Calendar/Day/CalendarDay.js b/frontend/src/Calendar/Day/CalendarDay.js deleted file mode 100644 index 685846766..000000000 --- a/frontend/src/Calendar/Day/CalendarDay.js +++ /dev/null @@ -1,64 +0,0 @@ -import classNames from 'classnames'; -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React from 'react'; -import * as calendarViews from 'Calendar/calendarViews'; -import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector'; -import styles from './CalendarDay.css'; - -function CalendarDay(props) { - const { - date, - time, - isTodaysDate, - events, - view, - onEventModalOpenToggle - } = props; - - return ( -
- { - view === calendarViews.MONTH && -
- {moment(date).date()} -
- } -
- { - events.map((event) => { - return ( - - ); - }) - } -
-
- ); -} - -CalendarDay.propTypes = { - date: PropTypes.string.isRequired, - time: PropTypes.string.isRequired, - isTodaysDate: PropTypes.bool.isRequired, - events: PropTypes.arrayOf(PropTypes.object).isRequired, - view: PropTypes.string.isRequired, - onEventModalOpenToggle: PropTypes.func.isRequired -}; - -export default CalendarDay; diff --git a/frontend/src/Calendar/Day/CalendarDayConnector.js b/frontend/src/Calendar/Day/CalendarDayConnector.js deleted file mode 100644 index 33fa1baa4..000000000 --- a/frontend/src/Calendar/Day/CalendarDayConnector.js +++ /dev/null @@ -1,67 +0,0 @@ -import _ from 'lodash'; -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import CalendarDay from './CalendarDay'; - -function sort(items) { - return _.sortBy(items, (item) => { - if (item.isGroup) { - return moment(item.events[0].inCinemas).unix(); - } - - return moment(item.inCinemas).unix(); - }); -} - -function createCalendarEventsConnector() { - return createSelector( - (state, { date }) => date, - (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 sort(filtered); - } - ); -} - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - createCalendarEventsConnector(), - (calendar, events) => { - return { - time: calendar.time, - view: calendar.view, - events - }; - } - ); -} - -class CalendarDayConnector extends Component { - - // - // Render - - render() { - return ( - - ); - } -} - -CalendarDayConnector.propTypes = { - date: PropTypes.string.isRequired -}; - -export default connect(createMapStateToProps)(CalendarDayConnector); diff --git a/frontend/src/Calendar/Day/CalendarDays.css b/frontend/src/Calendar/Day/CalendarDays.css deleted file mode 100644 index b6dd2100c..000000000 --- a/frontend/src/Calendar/Day/CalendarDays.css +++ /dev/null @@ -1,14 +0,0 @@ -.days { - display: flex; - border-right: 1px solid $calendarBorderColor; -} - -.day, -.week, -.forecast { - flex-wrap: nowrap; -} - -.month { - flex-wrap: wrap; -} diff --git a/frontend/src/Calendar/Day/CalendarDays.js b/frontend/src/Calendar/Day/CalendarDays.js deleted file mode 100644 index 0f2fc1fc5..000000000 --- a/frontend/src/Calendar/Day/CalendarDays.js +++ /dev/null @@ -1,164 +0,0 @@ -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 isToday from 'Utilities/Date/isToday'; -import CalendarDayConnector from './CalendarDayConnector'; -import styles from './CalendarDays.css'; - -class CalendarDays extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._touchStart = null; - - this.state = { - todaysDate: moment().startOf('day').toISOString(), - isEventModalOpen: false - }; - - this.updateTimeoutId = null; - } - - // Lifecycle - - componentDidMount() { - const view = this.props.view; - - if (view === calendarViews.MONTH) { - this.scheduleUpdate(); - } - - window.addEventListener('touchstart', this.onTouchStart); - window.addEventListener('touchend', this.onTouchEnd); - window.addEventListener('touchcancel', this.onTouchCancel); - window.addEventListener('touchmove', this.onTouchMove); - } - - componentWillUnmount() { - this.clearUpdateTimeout(); - - window.removeEventListener('touchstart', this.onTouchStart); - window.removeEventListener('touchend', this.onTouchEnd); - window.removeEventListener('touchcancel', this.onTouchCancel); - window.removeEventListener('touchmove', this.onTouchMove); - } - - // - // Control - - scheduleUpdate = () => { - this.clearUpdateTimeout(); - const todaysDate = moment().startOf('day'); - const diff = moment().diff(todaysDate.clone().add(1, 'day')); - - this.setState({ todaysDate: todaysDate.toISOString() }); - - this.updateTimeoutId = setTimeout(this.scheduleUpdate, diff); - } - - clearUpdateTimeout = () => { - if (this.updateTimeoutId) { - clearTimeout(this.updateTimeoutId); - } - } - - // - // Listeners - - onEventModalOpenToggle = (isEventModalOpen) => { - this.setState({ isEventModalOpen }); - } - - onTouchStart = (event) => { - const touches = event.touches; - const touchStart = touches[0].pageX; - - if (touches.length !== 1) { - return; - } - - if ( - touchStart < 50 || - this.props.isSidebarVisible || - this.state.isEventModalOpen - ) { - return; - } - - this._touchStart = touchStart; - } - - onTouchEnd = (event) => { - const touches = event.changedTouches; - const currentTouch = touches[0].pageX; - - if (!this._touchStart) { - return; - } - - if (currentTouch > this._touchStart && currentTouch - this._touchStart > 100) { - this.props.onNavigatePrevious(); - } else if (currentTouch < this._touchStart && this._touchStart - currentTouch > 100) { - this.props.onNavigateNext(); - } - - this._touchStart = null; - } - - onTouchCancel = (event) => { - this._touchStart = null; - } - - onTouchMove = (event) => { - if (!this._touchStart) { - return; - } - } - - // - // Render - - render() { - const { - dates, - view - } = this.props; - - return ( -
- { - dates.map((date) => { - return ( - - ); - }) - } -
- ); - } -} - -CalendarDays.propTypes = { - dates: PropTypes.arrayOf(PropTypes.string).isRequired, - view: PropTypes.string.isRequired, - isSidebarVisible: PropTypes.bool.isRequired, - onNavigatePrevious: PropTypes.func.isRequired, - onNavigateNext: PropTypes.func.isRequired -}; - -export default CalendarDays; diff --git a/frontend/src/Calendar/Day/CalendarDaysConnector.js b/frontend/src/Calendar/Day/CalendarDaysConnector.js deleted file mode 100644 index 0acce70b9..000000000 --- a/frontend/src/Calendar/Day/CalendarDaysConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { gotoCalendarNextRange, gotoCalendarPreviousRange } from 'Store/Actions/calendarActions'; -import CalendarDays from './CalendarDays'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - (state) => state.app.isSidebarVisible, - (calendar, isSidebarVisible) => { - return { - dates: calendar.dates, - view: calendar.view, - isSidebarVisible - }; - } - ); -} - -const mapDispatchToProps = { - onNavigatePrevious: gotoCalendarPreviousRange, - onNavigateNext: gotoCalendarNextRange -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(CalendarDays); diff --git a/frontend/src/Calendar/Day/DayOfWeek.css b/frontend/src/Calendar/Day/DayOfWeek.css deleted file mode 100644 index 8c3552e55..000000000 --- a/frontend/src/Calendar/Day/DayOfWeek.css +++ /dev/null @@ -1,13 +0,0 @@ -.dayOfWeek { - flex: 1 0 14.28%; - background-color: #e4eaec; - text-align: center; -} - -.isSingleDay { - width: 100%; -} - -.isToday { - background-color: $calendarTodayBackgroundColor; -} diff --git a/frontend/src/Calendar/Day/DayOfWeek.js b/frontend/src/Calendar/Day/DayOfWeek.js deleted file mode 100644 index 39e40fce8..000000000 --- a/frontend/src/Calendar/Day/DayOfWeek.js +++ /dev/null @@ -1,56 +0,0 @@ -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 getRelativeDate from 'Utilities/Date/getRelativeDate'; -import styles from './DayOfWeek.css'; - -class DayOfWeek extends Component { - - // - // Render - - render() { - const { - date, - view, - isTodaysDate, - calendarWeekColumnHeader, - shortDateFormat, - showRelativeDates - } = this.props; - - const highlightToday = view !== calendarViews.MONTH && isTodaysDate; - const momentDate = moment(date); - let formatedDate = momentDate.format('dddd'); - - if (view === calendarViews.WEEK) { - formatedDate = momentDate.format(calendarWeekColumnHeader); - } else if (view === calendarViews.FORECAST) { - formatedDate = getRelativeDate(date, shortDateFormat, showRelativeDates); - } - - return ( -
- {formatedDate} -
- ); - } -} - -DayOfWeek.propTypes = { - date: PropTypes.string.isRequired, - view: PropTypes.string.isRequired, - isTodaysDate: PropTypes.bool.isRequired, - calendarWeekColumnHeader: PropTypes.string.isRequired, - shortDateFormat: PropTypes.string.isRequired, - showRelativeDates: PropTypes.bool.isRequired -}; - -export default DayOfWeek; diff --git a/frontend/src/Calendar/Day/DaysOfWeek.css b/frontend/src/Calendar/Day/DaysOfWeek.css deleted file mode 100644 index 518664633..000000000 --- a/frontend/src/Calendar/Day/DaysOfWeek.css +++ /dev/null @@ -1,4 +0,0 @@ -.daysOfWeek { - display: flex; - margin-top: 10px; -} diff --git a/frontend/src/Calendar/Day/DaysOfWeek.js b/frontend/src/Calendar/Day/DaysOfWeek.js deleted file mode 100644 index add392730..000000000 --- a/frontend/src/Calendar/Day/DaysOfWeek.js +++ /dev/null @@ -1,97 +0,0 @@ -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import * as calendarViews from 'Calendar/calendarViews'; -import DayOfWeek from './DayOfWeek'; -import styles from './DaysOfWeek.css'; - -class DaysOfWeek extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - todaysDate: moment().startOf('day').toISOString() - }; - - this.updateTimeoutId = null; - } - - // Lifecycle - - componentDidMount() { - const view = this.props.view; - - if (view !== calendarViews.AGENDA || view !== calendarViews.MONTH) { - this.scheduleUpdate(); - } - } - - componentWillUnmount() { - this.clearUpdateTimeout(); - } - - // - // Control - - scheduleUpdate = () => { - this.clearUpdateTimeout(); - const todaysDate = moment().startOf('day'); - const diff = todaysDate.clone().add(1, 'day').diff(moment()); - - this.setState({ - todaysDate: todaysDate.toISOString() - }); - - this.updateTimeoutId = setTimeout(this.scheduleUpdate, diff); - } - - clearUpdateTimeout = () => { - if (this.updateTimeoutId) { - clearTimeout(this.updateTimeoutId); - } - } - - // - // Render - - render() { - const { - dates, - view, - ...otherProps - } = this.props; - - if (view === calendarViews.AGENDA) { - return null; - } - - return ( -
- { - dates.map((date) => { - return ( - - ); - }) - } -
- ); - } -} - -DaysOfWeek.propTypes = { - dates: PropTypes.arrayOf(PropTypes.string), - view: PropTypes.string.isRequired -}; - -export default DaysOfWeek; diff --git a/frontend/src/Calendar/Day/DaysOfWeekConnector.js b/frontend/src/Calendar/Day/DaysOfWeekConnector.js deleted file mode 100644 index 7f5cdef19..000000000 --- a/frontend/src/Calendar/Day/DaysOfWeekConnector.js +++ /dev/null @@ -1,22 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import DaysOfWeek from './DaysOfWeek'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - createUISettingsSelector(), - (calendar, UiSettings) => { - return { - dates: calendar.dates.slice(0, 7), - view: calendar.view, - calendarWeekColumnHeader: UiSettings.calendarWeekColumnHeader, - shortDateFormat: UiSettings.shortDateFormat, - showRelativeDates: UiSettings.showRelativeDates - }; - } - ); -} - -export default connect(createMapStateToProps)(DaysOfWeek); diff --git a/frontend/src/Calendar/Events/CalendarEvent.css b/frontend/src/Calendar/Events/CalendarEvent.css deleted file mode 100644 index 1e962f17c..000000000 --- a/frontend/src/Calendar/Events/CalendarEvent.css +++ /dev/null @@ -1,98 +0,0 @@ -.event { - overflow-x: hidden; - margin: 4px 2px; - padding: 5px; - border-bottom: 1px solid $borderColor; - border-left: 4px solid $borderColor; - font-size: 12px; - - &:global(.colorImpaired) { - border-left-width: 5px; - } -} - -.link { - composes: link from '~Components/Link/Link.css'; - - display: block; - color: $defaultColor; - - &:hover { - color: $defaultColor; - text-decoration: none; - } -} - -.info, -.movieInfo { - display: flex; -} - -.movieInfo { - color: $calendarTextDim; -} - -.movieTitle, -.genres { - @add-mixin truncate; - flex: 1 0 1px; - margin-right: 10px; -} - -.movieTitle { - color: #3a3f51; - font-size: $defaultFontSize; -} - -.statusIcon { - margin-left: 3px; -} - -/* - * Status - */ - -.downloaded { - border-left-color: $successColor !important; - - &:global(.colorImpaired) { - border-left-color: color($successColor, saturation(+15%)) !important; - } -} - -.downloading { - border-left-color: $purple !important; -} - -.unmonitored { - border-left-color: $gray !important; - - &:global(.colorImpaired) { - background: repeating-linear-gradient(45deg, $colorImpairedGradientDark, $colorImpairedGradientDark 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); - } -} - -.onAir { - border-left-color: $warningColor !important; - - &:global(.colorImpaired) { - background: repeating-linear-gradient(90deg, $colorImpairedGradientDark, $colorImpairedGradientDark 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); - } -} - -.missing { - border-left-color: $dangerColor !important; - - &:global(.colorImpaired) { - border-left-color: color($dangerColor saturation(+15%)) !important; - background: repeating-linear-gradient(90deg, $colorImpairedGradientDark, $colorImpairedGradientDark 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); - } -} - -.unreleased { - border-left-color: $primaryColor !important; - - &:global(.colorImpaired) { - background: repeating-linear-gradient(90deg, $colorImpairedGradientDark, $colorImpairedGradientDark 5px, $colorImpairedGradient 5px, $colorImpairedGradient 10px); - } -} diff --git a/frontend/src/Calendar/Events/CalendarEvent.js b/frontend/src/Calendar/Events/CalendarEvent.js deleted file mode 100644 index 1c8a20ea1..000000000 --- a/frontend/src/Calendar/Events/CalendarEvent.js +++ /dev/null @@ -1,159 +0,0 @@ -import classNames from 'classnames'; -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import getStatusStyle from 'Calendar/getStatusStyle'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import CalendarEventQueueDetails from './CalendarEventQueueDetails'; -import styles from './CalendarEvent.css'; - -class CalendarEvent extends Component { - - // - // Render - - render() { - const { - movieFile, - isAvailable, - inCinemas, - physicalRelease, - digitalRelease, - title, - titleSlug, - genres, - monitored, - certification, - hasFile, - grabbed, - queueItem, - showMovieInformation, - showCutoffUnmetIcon, - colorImpairedMode, - date - } = this.props; - - const isDownloading = !!(queueItem || grabbed); - const isMonitored = monitored; - const statusStyle = getStatusStyle(hasFile, isDownloading, isAvailable, isMonitored); - const joinedGenres = genres.slice(0, 2).join(', '); - const link = `/movie/${titleSlug}`; - const eventType = []; - - if (moment(date).isSame(moment(inCinemas), 'day')) { - eventType.push('Cinemas'); - } - - if (moment(date).isSame(moment(physicalRelease), 'day')) { - eventType.push('Physical'); - } - - if (moment(date).isSame(moment(digitalRelease), 'day')) { - eventType.push('Digital'); - } - - return ( -
- -
-
- {title} -
- - { - !!queueItem && - - - - } - - { - !queueItem && grabbed && - - } - - { - showCutoffUnmetIcon && - !!movieFile && - movieFile.qualityCutoffNotMet && - - } -
- - { - showMovieInformation && -
-
- {joinedGenres} -
-
- } - - { - showMovieInformation && -
-
- {eventType.join(', ')} -
-
- {certification} -
-
- } - - -
- ); - } -} - -CalendarEvent.propTypes = { - id: PropTypes.number.isRequired, - genres: PropTypes.arrayOf(PropTypes.string).isRequired, - movieFile: PropTypes.object, - title: PropTypes.string.isRequired, - titleSlug: PropTypes.string.isRequired, - isAvailable: PropTypes.bool.isRequired, - inCinemas: PropTypes.string, - physicalRelease: PropTypes.string, - digitalRelease: PropTypes.string, - monitored: PropTypes.bool.isRequired, - certification: PropTypes.string, - hasFile: PropTypes.bool.isRequired, - grabbed: PropTypes.bool, - queueItem: PropTypes.object, - showMovieInformation: PropTypes.bool.isRequired, - showCutoffUnmetIcon: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - colorImpairedMode: PropTypes.bool.isRequired, - date: PropTypes.string.isRequired -}; - -CalendarEvent.defaultProps = { - genres: [] -}; - -export default CalendarEvent; diff --git a/frontend/src/Calendar/Events/CalendarEventConnector.js b/frontend/src/Calendar/Events/CalendarEventConnector.js deleted file mode 100644 index 0a38db775..000000000 --- a/frontend/src/Calendar/Events/CalendarEventConnector.js +++ /dev/null @@ -1,26 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import createQueueItemSelector from 'Store/Selectors/createQueueItemSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import CalendarEvent from './CalendarEvent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.options, - createMovieSelector(), - createQueueItemSelector(), - createUISettingsSelector(), - (calendarOptions, movie, queueItem, uiSettings) => { - return { - movie, - queueItem, - ...calendarOptions, - timeFormat: uiSettings.timeFormat, - colorImpairedMode: uiSettings.enableColorImpairedMode - }; - } - ); -} - -export default connect(createMapStateToProps)(CalendarEvent); diff --git a/frontend/src/Calendar/Events/CalendarEventQueueDetails.js b/frontend/src/Calendar/Events/CalendarEventQueueDetails.js deleted file mode 100644 index 7284a89e1..000000000 --- a/frontend/src/Calendar/Events/CalendarEventQueueDetails.js +++ /dev/null @@ -1,57 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import QueueDetails from 'Activity/Queue/QueueDetails'; -import CircularProgressBar from 'Components/CircularProgressBar'; -import colors from 'Styles/Variables/colors'; -import translate from 'Utilities/String/translate'; - -function CalendarEventQueueDetails(props) { - const { - title, - size, - sizeleft, - estimatedCompletionTime, - status, - trackedDownloadState, - trackedDownloadStatus, - errorMessage - } = props; - - const progress = size ? (100 - sizeleft / size * 100) : 0; - - return ( - - -
- } - /> - ); -} - -CalendarEventQueueDetails.propTypes = { - title: PropTypes.string.isRequired, - size: PropTypes.number.isRequired, - sizeleft: PropTypes.number.isRequired, - estimatedCompletionTime: PropTypes.string, - status: PropTypes.string.isRequired, - trackedDownloadState: PropTypes.string.isRequired, - trackedDownloadStatus: PropTypes.string.isRequired, - errorMessage: PropTypes.string -}; - -export default CalendarEventQueueDetails; diff --git a/frontend/src/Calendar/Header/CalendarHeader.css b/frontend/src/Calendar/Header/CalendarHeader.css deleted file mode 100644 index 4b6915406..000000000 --- a/frontend/src/Calendar/Header/CalendarHeader.css +++ /dev/null @@ -1,53 +0,0 @@ -.header { - display: flex; -} - -.navigationButtons { - flex: 1 1 33%; - text-align: left; -} - -.todayButton { - composes: button from '~Components/Link/Button.css'; - - margin-left: 5px; -} - -.titleDesktop, -.titleMobile { - text-align: center; - font-size: 18px; -} - -.titleMobile { - margin-bottom: 5px; -} - -.viewButtonsContainer { - display: flex; - justify-content: flex-end; - flex: 1 1 33%; -} - -.viewMenu { - composes: menu from '~Components/Menu/Menu.css'; - - line-height: 31px; -} - -.loading { - composes: loading from '~Components/Loading/LoadingIndicator.css'; - - margin-top: 5px; - margin-right: 10px; -} - -@media only screen and (max-width: $breakpointSmall) { - .navigationButtons { - flex: 1 0 50%; - } - - .viewButtonsContainer { - flex: 0 0 100px; - } -} diff --git a/frontend/src/Calendar/Header/CalendarHeader.js b/frontend/src/Calendar/Header/CalendarHeader.js deleted file mode 100644 index 95497c7f0..000000000 --- a/frontend/src/Calendar/Header/CalendarHeader.js +++ /dev/null @@ -1,268 +0,0 @@ -import moment from 'moment'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import * as calendarViews from 'Calendar/calendarViews'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Menu from 'Components/Menu/Menu'; -import MenuButton from 'Components/Menu/MenuButton'; -import MenuContent from 'Components/Menu/MenuContent'; -import ViewMenuItem from 'Components/Menu/ViewMenuItem'; -import { align, icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import CalendarHeaderViewButton from './CalendarHeaderViewButton'; -import styles from './CalendarHeader.css'; - -function getTitle(time, start, end, view, longDateFormat) { - const timeMoment = moment(time); - const startMoment = moment(start); - const endMoment = moment(end); - - if (view === 'day') { - return timeMoment.format(longDateFormat); - } else if (view === 'month') { - return timeMoment.format('MMMM YYYY'); - } else if (view === 'agenda') { - return `Agenda: ${startMoment.format('MMM D')} - ${endMoment.format('MMM D')}`; - } - - let startFormat = 'MMM D YYYY'; - let endFormat = 'MMM D YYYY'; - - if (startMoment.isSame(endMoment, 'month')) { - startFormat = 'MMM D'; - endFormat = 'D YYYY'; - } else if (startMoment.isSame(endMoment, 'year')) { - startFormat = 'MMM D'; - endFormat = 'MMM D YYYY'; - } - - return `${startMoment.format(startFormat)} \u2014 ${endMoment.format(endFormat)}`; -} - -// TODO Convert to a stateful Component so we can track view internally when changed - -class CalendarHeader extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - view: props.view - }; - } - - componentDidUpdate(prevProps) { - const view = this.props.view; - - if (prevProps.view !== view) { - this.setState({ view }); - } - } - - // - // Listeners - - onViewChange = (view) => { - this.setState({ view }, () => { - this.props.onViewChange(view); - }); - } - - // - // Render - - render() { - const { - isFetching, - time, - start, - end, - longDateFormat, - isSmallScreen, - collapseViewButtons, - onTodayPress, - onPreviousPress, - onNextPress - } = this.props; - - const view = this.state.view; - - const title = getTitle(time, start, end, view, longDateFormat); - - return ( -
- { - isSmallScreen && -
- {title} -
- } - -
-
- - - - - -
- - { - !isSmallScreen && -
- {title} -
- } - -
- { - isFetching && - - } - - { - collapseViewButtons ? - - - - - - - { - isSmallScreen ? - null : - - Month - - } - - - Week - - - - Forecast - - - - {translate('Day')} - - - - {translate('Agenda')} - - - : - -
- - - - - - - - - -
- } -
-
-
- ); - } -} - -CalendarHeader.propTypes = { - isFetching: PropTypes.bool.isRequired, - time: PropTypes.string.isRequired, - start: PropTypes.string.isRequired, - end: PropTypes.string.isRequired, - view: PropTypes.oneOf(calendarViews.all).isRequired, - isSmallScreen: PropTypes.bool.isRequired, - collapseViewButtons: PropTypes.bool.isRequired, - longDateFormat: PropTypes.string.isRequired, - onViewChange: PropTypes.func.isRequired, - onTodayPress: PropTypes.func.isRequired, - onPreviousPress: PropTypes.func.isRequired, - onNextPress: PropTypes.func.isRequired -}; - -export default CalendarHeader; diff --git a/frontend/src/Calendar/Header/CalendarHeaderConnector.js b/frontend/src/Calendar/Header/CalendarHeaderConnector.js deleted file mode 100644 index ba3941eab..000000000 --- a/frontend/src/Calendar/Header/CalendarHeaderConnector.js +++ /dev/null @@ -1,81 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { gotoCalendarNextRange, gotoCalendarPreviousRange, gotoCalendarToday, setCalendarView } from 'Store/Actions/calendarActions'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import CalendarHeader from './CalendarHeader'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar, - createDimensionsSelector(), - createUISettingsSelector(), - (calendar, dimensions, uiSettings) => { - return { - isFetching: calendar.isFetching, - view: calendar.view, - time: calendar.time, - start: calendar.start, - end: calendar.end, - isSmallScreen: dimensions.isSmallScreen, - collapseViewButtons: dimensions.isLargeScreen, - longDateFormat: uiSettings.longDateFormat - }; - } - ); -} - -const mapDispatchToProps = { - setCalendarView, - gotoCalendarToday, - gotoCalendarPreviousRange, - gotoCalendarNextRange -}; - -class CalendarHeaderConnector extends Component { - - // - // Listeners - - onViewChange = (view) => { - this.props.setCalendarView({ view }); - } - - onTodayPress = () => { - this.props.gotoCalendarToday(); - } - - onPreviousPress = () => { - this.props.gotoCalendarPreviousRange(); - } - - onNextPress = () => { - this.props.gotoCalendarNextRange(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -CalendarHeaderConnector.propTypes = { - setCalendarView: PropTypes.func.isRequired, - gotoCalendarToday: PropTypes.func.isRequired, - gotoCalendarPreviousRange: PropTypes.func.isRequired, - gotoCalendarNextRange: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(CalendarHeaderConnector); diff --git a/frontend/src/Calendar/Header/CalendarHeaderViewButton.js b/frontend/src/Calendar/Header/CalendarHeaderViewButton.js deleted file mode 100644 index 808518efd..000000000 --- a/frontend/src/Calendar/Header/CalendarHeaderViewButton.js +++ /dev/null @@ -1,45 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import * as calendarViews from 'Calendar/calendarViews'; -import Button from 'Components/Link/Button'; -import titleCase from 'Utilities/String/titleCase'; -// import styles from './CalendarHeaderViewButton.css'; - -class CalendarHeaderViewButton extends Component { - - // - // Listeners - - onPress = () => { - this.props.onPress(this.props.view); - } - - // - // Render - - render() { - const { - view, - selectedView, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -CalendarHeaderViewButton.propTypes = { - view: PropTypes.oneOf(calendarViews.all).isRequired, - selectedView: PropTypes.oneOf(calendarViews.all).isRequired, - onPress: PropTypes.func.isRequired -}; - -export default CalendarHeaderViewButton; diff --git a/frontend/src/Calendar/Legend/Legend.css b/frontend/src/Calendar/Legend/Legend.css deleted file mode 100644 index 296cbd9d5..000000000 --- a/frontend/src/Calendar/Legend/Legend.css +++ /dev/null @@ -1,6 +0,0 @@ -.legend { - display: flex; - flex-wrap: wrap; - margin-top: 10px; - padding: 3px 0; -} diff --git a/frontend/src/Calendar/Legend/Legend.js b/frontend/src/Calendar/Legend/Legend.js deleted file mode 100644 index 34eff9e59..000000000 --- a/frontend/src/Calendar/Legend/Legend.js +++ /dev/null @@ -1,72 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { icons, kinds } from 'Helpers/Props'; -import LegendIconItem from './LegendIconItem'; -import LegendItem from './LegendItem'; -import styles from './Legend.css'; - -function Legend(props) { - const { - showCutoffUnmetIcon, - colorImpairedMode - } = props; - - const iconsToShow = []; - - if (showCutoffUnmetIcon) { - iconsToShow.push( - - ); - } - - return ( -
-
- - - -
- -
- - - -
- - { - iconsToShow.length > 0 && -
- {iconsToShow[0]} -
- } -
- ); -} - -Legend.propTypes = { - showCutoffUnmetIcon: PropTypes.bool.isRequired, - colorImpairedMode: PropTypes.bool.isRequired -}; - -export default Legend; diff --git a/frontend/src/Calendar/Legend/LegendConnector.js b/frontend/src/Calendar/Legend/LegendConnector.js deleted file mode 100644 index 30bbc4adb..000000000 --- a/frontend/src/Calendar/Legend/LegendConnector.js +++ /dev/null @@ -1,19 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import Legend from './Legend'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.options, - createUISettingsSelector(), - (calendarOptions, uiSettings) => { - return { - ...calendarOptions, - colorImpairedMode: uiSettings.enableColorImpairedMode - }; - } - ); -} - -export default connect(createMapStateToProps)(Legend); diff --git a/frontend/src/Calendar/Legend/LegendIconItem.css b/frontend/src/Calendar/Legend/LegendIconItem.css deleted file mode 100644 index 01db0ba5a..000000000 --- a/frontend/src/Calendar/Legend/LegendIconItem.css +++ /dev/null @@ -1,10 +0,0 @@ -.legendIconItem { - margin: 3px 0; - margin-right: 6px; - width: 150px; - cursor: default; -} - -.icon { - margin-right: 5px; -} diff --git a/frontend/src/Calendar/Legend/LegendIconItem.js b/frontend/src/Calendar/Legend/LegendIconItem.js deleted file mode 100644 index 13e106784..000000000 --- a/frontend/src/Calendar/Legend/LegendIconItem.js +++ /dev/null @@ -1,37 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import styles from './LegendIconItem.css'; - -function LegendIconItem(props) { - const { - name, - icon, - kind, - tooltip - } = props; - - return ( -
- - - {name} -
- ); -} - -LegendIconItem.propTypes = { - name: PropTypes.string.isRequired, - icon: PropTypes.object.isRequired, - kind: PropTypes.string.isRequired, - tooltip: PropTypes.string.isRequired -}; - -export default LegendIconItem; diff --git a/frontend/src/Calendar/Legend/LegendItem.css b/frontend/src/Calendar/Legend/LegendItem.css deleted file mode 100644 index ddf3e6a61..000000000 --- a/frontend/src/Calendar/Legend/LegendItem.css +++ /dev/null @@ -1,33 +0,0 @@ -.legendItem { - margin: 3px 0; - margin-right: 6px; - padding-left: 5px; - width: 150px; - border-left-width: 4px; - border-left-style: solid; - cursor: default; -} - -/* - * Status - */ - -.downloaded { - composes: downloaded from '~Calendar/Events/CalendarEvent.css'; -} - -.downloading { - composes: downloading from '~Calendar/Events/CalendarEvent.css'; -} - -.unmonitored { - composes: unmonitored from '~Calendar/Events/CalendarEvent.css'; -} - -.missing { - composes: missing from '~Calendar/Events/CalendarEvent.css'; -} - -.unreleased { - composes: unreleased from '~Calendar/Events/CalendarEvent.css'; -} diff --git a/frontend/src/Calendar/Legend/LegendItem.js b/frontend/src/Calendar/Legend/LegendItem.js deleted file mode 100644 index 5da15baba..000000000 --- a/frontend/src/Calendar/Legend/LegendItem.js +++ /dev/null @@ -1,36 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React from 'react'; -import titleCase from 'Utilities/String/titleCase'; -import styles from './LegendItem.css'; - -function LegendItem(props) { - const { - name, - status, - tooltip, - colorImpairedMode - } = props; - - return ( -
- {name ? name : titleCase(status)} -
- ); -} - -LegendItem.propTypes = { - name: PropTypes.string, - status: PropTypes.string.isRequired, - tooltip: PropTypes.string.isRequired, - colorImpairedMode: PropTypes.bool.isRequired -}; - -export default LegendItem; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModal.js b/frontend/src/Calendar/Options/CalendarOptionsModal.js deleted file mode 100644 index b68c83f30..000000000 --- a/frontend/src/Calendar/Options/CalendarOptionsModal.js +++ /dev/null @@ -1,29 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import CalendarOptionsModalContentConnector from './CalendarOptionsModalContentConnector'; - -function CalendarOptionsModal(props) { - const { - isOpen, - onModalClose - } = props; - - return ( - - - - ); -} - -CalendarOptionsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default CalendarOptionsModal; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModalContent.js b/frontend/src/Calendar/Options/CalendarOptionsModalContent.js deleted file mode 100644 index 32650184b..000000000 --- a/frontend/src/Calendar/Options/CalendarOptionsModalContent.js +++ /dev/null @@ -1,217 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -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 ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import { firstDayOfWeekOptions, timeFormatOptions, weekColumnOptions } from 'Settings/UI/UISettings'; -import translate from 'Utilities/String/translate'; - -class CalendarOptionsModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - firstDayOfWeek, - calendarWeekColumnHeader, - timeFormat, - enableColorImpairedMode - } = props; - - this.state = { - firstDayOfWeek, - calendarWeekColumnHeader, - timeFormat, - enableColorImpairedMode - }; - } - - componentDidUpdate(prevProps) { - const { - firstDayOfWeek, - calendarWeekColumnHeader, - timeFormat, - enableColorImpairedMode - } = this.props; - - if ( - prevProps.firstDayOfWeek !== firstDayOfWeek || - prevProps.calendarWeekColumnHeader !== calendarWeekColumnHeader || - prevProps.timeFormat !== timeFormat || - prevProps.enableColorImpairedMode !== enableColorImpairedMode - ) { - this.setState({ - firstDayOfWeek, - calendarWeekColumnHeader, - timeFormat, - enableColorImpairedMode - }); - } - } - - // - // Listeners - - onOptionInputChange = ({ name, value }) => { - const { - dispatchSetCalendarOption - } = this.props; - - dispatchSetCalendarOption({ [name]: value }); - } - - onGlobalInputChange = ({ name, value }) => { - const { - dispatchSaveUISettings - } = this.props; - - const setting = { [name]: value }; - - this.setState(setting, () => { - dispatchSaveUISettings(setting); - }); - } - - onLinkFocus = (event) => { - event.target.select(); - } - - // - // Render - - render() { - const { - showMovieInformation, - showCutoffUnmetIcon, - onModalClose - } = this.props; - - const { - firstDayOfWeek, - calendarWeekColumnHeader, - timeFormat, - enableColorImpairedMode - } = this.state; - - return ( - - - Calendar Options - - - -
-
- - {translate('ShowMovieInformation')} - - - - - - {translate('IconForCutoffUnmet')} - - - -
-
- -
-
- - {translate('FirstDayOfWeek')} - - - - - - {translate('WeekColumnHeader')} - - - - - - {translate('TimeFormat')} - - - - {translate('EnableColorImpairedMode')} - - - - -
-
-
- - - - -
- ); - } -} - -CalendarOptionsModalContent.propTypes = { - showMovieInformation: PropTypes.bool.isRequired, - showCutoffUnmetIcon: PropTypes.bool.isRequired, - firstDayOfWeek: PropTypes.number.isRequired, - calendarWeekColumnHeader: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - enableColorImpairedMode: PropTypes.bool.isRequired, - dispatchSetCalendarOption: PropTypes.func.isRequired, - dispatchSaveUISettings: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default CalendarOptionsModalContent; diff --git a/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js b/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js deleted file mode 100644 index 1f517b698..000000000 --- a/frontend/src/Calendar/Options/CalendarOptionsModalContentConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setCalendarOption } from 'Store/Actions/calendarActions'; -import { saveUISettings } from 'Store/Actions/settingsActions'; -import CalendarOptionsModalContent from './CalendarOptionsModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.calendar.options, - (state) => state.settings.ui.item, - (options, uiSettings) => { - return { - ...options, - ...uiSettings - }; - } - ); -} - -const mapDispatchToProps = { - dispatchSetCalendarOption: setCalendarOption, - dispatchSaveUISettings: saveUISettings -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(CalendarOptionsModalContent); diff --git a/frontend/src/Calendar/calendarViews.js b/frontend/src/Calendar/calendarViews.js deleted file mode 100644 index 929958b66..000000000 --- a/frontend/src/Calendar/calendarViews.js +++ /dev/null @@ -1,7 +0,0 @@ -export const DAY = 'day'; -export const WEEK = 'week'; -export const MONTH = 'month'; -export const FORECAST = 'forecast'; -export const AGENDA = 'agenda'; - -export const all = [DAY, WEEK, MONTH, FORECAST, AGENDA]; diff --git a/frontend/src/Calendar/getStatusStyle.js b/frontend/src/Calendar/getStatusStyle.js deleted file mode 100644 index 043fba273..000000000 --- a/frontend/src/Calendar/getStatusStyle.js +++ /dev/null @@ -1,23 +0,0 @@ - -function getStatusStyle(hasFile, downloading, isAvailable, isMonitored) { - - if (hasFile) { - return 'downloaded'; - } - - if (downloading) { - return 'downloading'; - } - - if (!isMonitored) { - return 'unmonitored'; - } - - if (isAvailable && !hasFile) { - return 'missing'; - } - - return 'unreleased'; -} - -export default getStatusStyle; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModal.js b/frontend/src/Calendar/iCal/CalendarLinkModal.js deleted file mode 100644 index 8cc487c16..000000000 --- a/frontend/src/Calendar/iCal/CalendarLinkModal.js +++ /dev/null @@ -1,29 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import CalendarLinkModalContentConnector from './CalendarLinkModalContentConnector'; - -function CalendarLinkModal(props) { - const { - isOpen, - onModalClose - } = props; - - return ( - - - - ); -} - -CalendarLinkModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default CalendarLinkModal; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModalContent.js b/frontend/src/Calendar/iCal/CalendarLinkModalContent.js deleted file mode 100644 index f4fa69226..000000000 --- a/frontend/src/Calendar/iCal/CalendarLinkModalContent.js +++ /dev/null @@ -1,203 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Form from 'Components/Form/Form'; -import FormGroup from 'Components/Form/FormGroup'; -import FormInputButton from 'Components/Form/FormInputButton'; -import FormInputGroup from 'Components/Form/FormInputGroup'; -import FormLabel from 'Components/Form/FormLabel'; -import Icon from 'Components/Icon'; -import Button from 'Components/Link/Button'; -import ClipboardButton from 'Components/Link/ClipboardButton'; -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 { icons, inputTypes, kinds, sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function getUrls(state) { - const { - unmonitored, - asAllDay, - tags - } = state; - - let icalUrl = `${window.location.host}${window.Radarr.urlBase}/feed/calendar/Radarr.ics?`; - - if (unmonitored) { - icalUrl += 'unmonitored=true&'; - } - - if (asAllDay) { - icalUrl += 'asAllDay=true&'; - } - - if (tags.length) { - icalUrl += `tags=${tags.toString()}&`; - } - - icalUrl += `apikey=${window.Radarr.apiKey}`; - - const iCalHttpUrl = `${window.location.protocol}//${icalUrl}`; - const iCalWebCalUrl = `webcal://${icalUrl}`; - - return { - iCalHttpUrl, - iCalWebCalUrl - }; -} - -class CalendarLinkModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const defaultState = { - unmonitored: false, - asAllDay: false, - tags: [] - }; - - const urls = getUrls(defaultState); - - this.state = { - ...defaultState, - ...urls - }; - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - const state = { - ...this.state, - [name]: value - }; - - const urls = getUrls(state); - - this.setState({ - [name]: value, - ...urls - }); - } - - onLinkFocus = (event) => { - event.target.select(); - } - - // - // Render - - render() { - const { - onModalClose - } = this.props; - - const { - unmonitored, - asAllDay, - tags, - iCalHttpUrl, - iCalWebCalUrl - } = this.state; - - return ( - - - Radarr Calendar Feed - - - -
- - {translate('IncludeUnmonitored')} - - - - - - {translate('ShowAsAllDayEvents')} - - - - - - {translate('Tags')} - - - - - - {translate('ICalFeed')} - - , - - - - - ]} - onChange={this.onInputChange} - onFocus={this.onLinkFocus} - /> - -
-
- - - - -
- ); - } -} - -CalendarLinkModalContent.propTypes = { - tagList: PropTypes.arrayOf(PropTypes.object).isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default CalendarLinkModalContent; diff --git a/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js b/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js deleted file mode 100644 index e10c5c3f9..000000000 --- a/frontend/src/Calendar/iCal/CalendarLinkModalContentConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createTagsSelector from 'Store/Selectors/createTagsSelector'; -import CalendarLinkModalContent from './CalendarLinkModalContent'; - -function createMapStateToProps() { - return createSelector( - createTagsSelector(), - (tagList) => { - return { - tagList - }; - } - ); -} - -export default connect(createMapStateToProps)(CalendarLinkModalContent); diff --git a/frontend/src/Components/Error/ErrorBoundaryError.js b/frontend/src/Components/Error/ErrorBoundaryError.js index 05cf8165a..28327e1ba 100644 --- a/frontend/src/Components/Error/ErrorBoundaryError.js +++ b/frontend/src/Components/Error/ErrorBoundaryError.js @@ -21,7 +21,7 @@ function ErrorBoundaryError(props) {
diff --git a/frontend/src/Components/FileBrowser/FileBrowserModalContent.js b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js index 75aae2891..a6a45592e 100644 --- a/frontend/src/Components/FileBrowser/FileBrowserModalContent.js +++ b/frontend/src/Components/FileBrowser/FileBrowserModalContent.js @@ -129,7 +129,7 @@ class FileBrowserModalContent extends Component { className={styles.mappedDrivesWarning} kind={kinds.WARNING} > - Mapped network drives are not available when running as a Windows Service, see the FAQ for more information. + Mapped network drives are not available when running as a Windows Service, see the FAQ for more information. } diff --git a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js index b0ea07c6f..9cc6d0360 100644 --- a/frontend/src/Components/Filter/Builder/FilterBuilderRow.js +++ b/frontend/src/Components/Filter/Builder/FilterBuilderRow.js @@ -6,7 +6,6 @@ import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Prop import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue'; import DateFilterBuilderRowValue from './DateFilterBuilderRowValue'; import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector'; -import ImportListFilterBuilderRowValueConnector from './ImportListFilterBuilderRowValueConnector'; import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector'; import MovieStatusFilterBuilderRowValue from './MovieStatusFilterBuilderRowValue'; import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue'; @@ -75,9 +74,6 @@ function getRowValueConnector(selectedFilterBuilderProp) { case filterBuilderValueTypes.TAG: return TagFilterBuilderRowValueConnector; - case filterBuilderValueTypes.IMPORTLIST: - return ImportListFilterBuilderRowValueConnector; - default: return FilterBuilderRowValueConnector; } diff --git a/frontend/src/Components/Filter/Builder/ImportListFilterBuilderRowValueConnector.js b/frontend/src/Components/Filter/Builder/ImportListFilterBuilderRowValueConnector.js deleted file mode 100644 index c617c2c3e..000000000 --- a/frontend/src/Components/Filter/Builder/ImportListFilterBuilderRowValueConnector.js +++ /dev/null @@ -1,27 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createImportListSelector from 'Store/Selectors/createImportListSelector'; -import FilterBuilderRowValue from './FilterBuilderRowValue'; - -function createMapStateToProps() { - return createSelector( - createImportListSelector(), - (importLists) => { - return { - tagList: importLists.map((importList) => { - const { - id, - name - } = importList; - - return { - id, - name - }; - }) - }; - } - ); -} - -export default connect(createMapStateToProps)(FilterBuilderRowValue); diff --git a/frontend/src/Components/Link/Link.js b/frontend/src/Components/Link/Link.js index 86f8b17a6..1ad8fabf6 100644 --- a/frontend/src/Components/Link/Link.js +++ b/frontend/src/Components/Link/Link.js @@ -47,13 +47,13 @@ class Link extends Component { el = 'a'; linkProps.href = to; linkProps.target = target || '_self'; - } else if (to.startsWith(`${window.Radarr.urlBase}/`)) { + } else if (to.startsWith(`${window.Prowlarr.urlBase}/`)) { el = RouterLink; linkProps.to = to; linkProps.target = target; } else { el = RouterLink; - linkProps.to = `${window.Radarr.urlBase}/${to.replace(/^\//, '')}`; + linkProps.to = `${window.Prowlarr.urlBase}/${to.replace(/^\//, '')}`; linkProps.target = target; } } diff --git a/frontend/src/Components/Loading/LoadingMessage.js b/frontend/src/Components/Loading/LoadingMessage.js index 3c9d7a738..1cb52b0aa 100644 --- a/frontend/src/Components/Loading/LoadingMessage.js +++ b/frontend/src/Components/Loading/LoadingMessage.js @@ -4,7 +4,7 @@ import styles from './LoadingMessage.css'; const messages = [ 'Downloading more RAM', 'Now in Technicolor', - 'Previously on Radarr...', + 'Previously on Prowlarr...', 'Bleep Bloop.', 'Locating the required gigapixels to render...', 'Spinning up the hamster wheel...', diff --git a/frontend/src/Components/NotFound.js b/frontend/src/Components/NotFound.js index cd424ce09..d924c55f2 100644 --- a/frontend/src/Components/NotFound.js +++ b/frontend/src/Components/NotFound.js @@ -14,7 +14,7 @@ function NotFound({ message }) {
diff --git a/frontend/src/Components/Page/ErrorPage.js b/frontend/src/Components/Page/ErrorPage.js index 4f01a8a0f..ae9df30de 100644 --- a/frontend/src/Components/Page/ErrorPage.js +++ b/frontend/src/Components/Page/ErrorPage.js @@ -16,7 +16,7 @@ function ErrorPage(props) { systemStatusError } = props; - let errorMessage = 'Failed to load Radarr'; + let errorMessage = 'Failed to load Prowlarr'; if (!isLocalStorageSupported) { errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.'; diff --git a/frontend/src/Components/Page/Header/MovieSearchInputConnector.js b/frontend/src/Components/Page/Header/MovieSearchInputConnector.js index f470394c4..d0cb96e1a 100644 --- a/frontend/src/Components/Page/Header/MovieSearchInputConnector.js +++ b/frontend/src/Components/Page/Header/MovieSearchInputConnector.js @@ -59,11 +59,11 @@ function createMapStateToProps() { function createMapDispatchToProps(dispatch, props) { return { onGoToMovie(titleSlug) { - dispatch(push(`${window.Radarr.urlBase}/movie/${titleSlug}`)); + dispatch(push(`${window.Prowlarr.urlBase}/movie/${titleSlug}`)); }, onGoToAddNewMovie(query) { - dispatch(push(`${window.Radarr.urlBase}/add/new?term=${encodeURIComponent(query)}`)); + dispatch(push(`${window.Prowlarr.urlBase}/add/new?term=${encodeURIComponent(query)}`)); } }; } diff --git a/frontend/src/Components/Page/Header/PageHeader.js b/frontend/src/Components/Page/Header/PageHeader.js index 5d40ce323..0054d99b5 100644 --- a/frontend/src/Components/Page/Header/PageHeader.js +++ b/frontend/src/Components/Page/Header/PageHeader.js @@ -53,10 +53,10 @@ class PageHeader extends Component { return (
- +
@@ -75,14 +75,14 @@ class PageHeader extends Component { state.customFilters.isPopulated, (state) => state.tags.isPopulated, (state) => state.settings.ui.isPopulated, - (state) => state.settings.qualityProfiles.isPopulated, (state) => state.settings.languages.isPopulated, (state) => state.settings.indexerFlags.isPopulated, - (state) => state.settings.importLists.isPopulated, (state) => state.system.status.isPopulated, ( customFiltersIsPopulated, tagsIsPopulated, uiSettingsIsPopulated, - qualityProfilesIsPopulated, languagesIsPopulated, indexerFlagsIsPopulated, - importListsIsPopulated, systemStatusIsPopulated ) => { return ( customFiltersIsPopulated && tagsIsPopulated && uiSettingsIsPopulated && - qualityProfilesIsPopulated && languagesIsPopulated && indexerFlagsIsPopulated && - importListsIsPopulated && systemStatusIsPopulated ); } @@ -78,29 +71,23 @@ const selectErrors = createSelector( (state) => state.customFilters.error, (state) => state.tags.error, (state) => state.settings.ui.error, - (state) => state.settings.qualityProfiles.error, (state) => state.settings.languages.error, (state) => state.settings.indexerFlags.error, - (state) => state.settings.importLists.error, (state) => state.system.status.error, ( customFiltersError, tagsError, uiSettingsError, - qualityProfilesError, languagesError, indexerFlagsError, - importListsError, systemStatusError ) => { const hasError = !!( customFiltersError || tagsError || uiSettingsError || - qualityProfilesError || languagesError || indexerFlagsError || - importListsError || systemStatusError ); @@ -109,10 +96,8 @@ const selectErrors = createSelector( customFiltersError, tagsError, uiSettingsError, - qualityProfilesError, languagesError, indexerFlagsError, - importListsError, systemStatusError }; } @@ -145,27 +130,18 @@ function createMapStateToProps() { function createMapDispatchToProps(dispatch, props) { return { - dispatchFetchMovies() { - dispatch(fetchMovies()); - }, dispatchFetchCustomFilters() { dispatch(fetchCustomFilters()); }, dispatchFetchTags() { dispatch(fetchTags()); }, - dispatchFetchQualityProfiles() { - dispatch(fetchQualityProfiles()); - }, dispatchFetchLanguages() { dispatch(fetchLanguages()); }, dispatchFetchIndexerFlags() { dispatch(fetchIndexerFlags()); }, - dispatchFetchImportLists() { - dispatch(fetchImportLists()); - }, dispatchFetchUISettings() { dispatch(fetchUISettings()); }, @@ -196,13 +172,10 @@ class PageConnector extends Component { componentDidMount() { if (!this.props.isPopulated) { - this.props.dispatchFetchMovies(); this.props.dispatchFetchCustomFilters(); this.props.dispatchFetchTags(); - this.props.dispatchFetchQualityProfiles(); this.props.dispatchFetchLanguages(); this.props.dispatchFetchIndexerFlags(); - this.props.dispatchFetchImportLists(); this.props.dispatchFetchUISettings(); this.props.dispatchFetchStatus(); } @@ -222,12 +195,9 @@ class PageConnector extends Component { const { isPopulated, hasError, - dispatchFetchMovies, dispatchFetchTags, - dispatchFetchQualityProfiles, dispatchFetchLanguages, dispatchFetchIndexerFlags, - dispatchFetchImportLists, dispatchFetchUISettings, dispatchFetchStatus, ...otherProps @@ -261,13 +231,10 @@ PageConnector.propTypes = { isPopulated: PropTypes.bool.isRequired, hasError: PropTypes.bool.isRequired, isSidebarVisible: PropTypes.bool.isRequired, - dispatchFetchMovies: PropTypes.func.isRequired, dispatchFetchCustomFilters: PropTypes.func.isRequired, dispatchFetchTags: PropTypes.func.isRequired, - dispatchFetchQualityProfiles: PropTypes.func.isRequired, dispatchFetchLanguages: PropTypes.func.isRequired, dispatchFetchIndexerFlags: PropTypes.func.isRequired, - dispatchFetchImportLists: PropTypes.func.isRequired, dispatchFetchUISettings: PropTypes.func.isRequired, dispatchFetchStatus: PropTypes.func.isRequired, onSidebarVisibleChange: PropTypes.func.isRequired diff --git a/frontend/src/Components/Page/PageContent.js b/frontend/src/Components/Page/PageContent.js index 62d5b5d13..d21304991 100644 --- a/frontend/src/Components/Page/PageContent.js +++ b/frontend/src/Components/Page/PageContent.js @@ -14,7 +14,7 @@ function PageContent(props) { return ( - +
{children}
diff --git a/frontend/src/Components/Page/Sidebar/PageSidebar.js b/frontend/src/Components/Page/Sidebar/PageSidebar.js index 0006fa0db..d38f77a5c 100644 --- a/frontend/src/Components/Page/Sidebar/PageSidebar.js +++ b/frontend/src/Components/Page/Sidebar/PageSidebar.js @@ -21,7 +21,7 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth); const links = [ { iconName: icons.MOVIE_CONTINUING, - title: translate('Movies'), + title: 'Indexers', to: '/', alias: '/movies', children: [ @@ -32,23 +32,13 @@ const links = [ { title: translate('Import'), to: '/add/import' - }, - { - title: translate('Discover'), - to: '/add/discover' } ] }, - { - iconName: icons.CALENDAR, - title: translate('Calendar'), - to: '/calendar' - }, - { iconName: icons.ACTIVITY, - title: translate('Activity'), + title: 'Search', to: '/activity/queue', children: [ { @@ -72,42 +62,14 @@ const links = [ title: translate('Settings'), to: '/settings', children: [ - { - title: translate('MediaManagement'), - to: '/settings/mediamanagement' - }, - { - title: translate('Profiles'), - to: '/settings/profiles' - }, - { - title: translate('Quality'), - to: '/settings/quality' - }, - { - title: translate('CustomFormats'), - to: '/settings/customformats' - }, { title: translate('Indexers'), to: '/settings/indexers' }, - { - title: translate('DownloadClients'), - to: '/settings/downloadclients' - }, - { - title: translate('Lists'), - to: '/settings/importlists' - }, { title: translate('Connect'), to: '/settings/connect' }, - { - title: translate('Metadata'), - to: '/settings/metadata' - }, { title: translate('Tags'), to: '/settings/tags' @@ -415,7 +377,7 @@ class PageSidebar extends Component { transform } = this.state; - const urlBase = window.Radarr.urlBase; + const urlBase = window.Prowlarr.urlBase; const pathname = urlBase ? location.pathname.substr(urlBase.length) || '/' : location.pathname; const activeParent = getActiveParent(pathname); diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index 90be9795e..74b005460 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -59,7 +59,7 @@ function Logger(minimumLogLevel) { } Logger.prototype.cleanse = function(message) { - const apikey = new RegExp(`access_token=${window.Radarr.apiKey}`, 'g'); + const apikey = new RegExp(`access_token=${window.Prowlarr.apiKey}`, 'g'); return message.replace(apikey, 'access_token=(removed)'); }; @@ -99,11 +99,11 @@ class SignalRConnector extends Component { componentDidMount() { console.log('[signalR] starting'); - const url = `${window.Radarr.urlBase}/signalr/messages`; + const url = `${window.Prowlarr.urlBase}/signalr/messages`; this.connection = new signalR.HubConnectionBuilder() .configureLogging(new Logger(signalR.LogLevel.Information)) - .withUrl(`${url}?access_token=${window.Radarr.apiKey}`) + .withUrl(`${url}?access_token=${window.Prowlarr.apiKey}`) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: (retryContext) => { if (retryContext.elapsedMilliseconds > 180000) { diff --git a/frontend/src/DiscoverMovie/AddNewDiscoverMovieModal.js b/frontend/src/DiscoverMovie/AddNewDiscoverMovieModal.js deleted file mode 100644 index 87bb2bb50..000000000 --- a/frontend/src/DiscoverMovie/AddNewDiscoverMovieModal.js +++ /dev/null @@ -1,31 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import AddNewDiscoverMovieModalContentConnector from './AddNewDiscoverMovieModalContentConnector'; - -function AddNewDiscoverMovieModal(props) { - const { - isOpen, - onModalClose, - ...otherProps - } = props; - - return ( - - - - ); -} - -AddNewDiscoverMovieModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddNewDiscoverMovieModal; diff --git a/frontend/src/DiscoverMovie/AddNewDiscoverMovieModalContentConnector.js b/frontend/src/DiscoverMovie/AddNewDiscoverMovieModalContentConnector.js deleted file mode 100644 index dd3987aec..000000000 --- a/frontend/src/DiscoverMovie/AddNewDiscoverMovieModalContentConnector.js +++ /dev/null @@ -1,105 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import AddNewMovieModalContent from 'AddMovie/AddNewMovie/AddNewMovieModalContent'; -import { addMovie, setAddMovieDefault } from 'Store/Actions/discoverMovieActions'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; -import selectSettings from 'Store/Selectors/selectSettings'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie, - createDimensionsSelector(), - createSystemStatusSelector(), - (discoverMovieState, dimensions, systemStatus) => { - const { - isAdding, - addError, - defaults - } = discoverMovieState; - - const { - settings, - validationErrors, - validationWarnings - } = selectSettings(defaults, {}, addError); - - return { - isAdding, - addError, - isSmallScreen: dimensions.isSmallScreen, - validationErrors, - validationWarnings, - isWindows: systemStatus.isWindows, - ...settings - }; - } - ); -} - -const mapDispatchToProps = { - setAddMovieDefault, - addMovie -}; - -class AddNewDiscoverMovieModalContentConnector extends Component { - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setAddMovieDefault({ [name]: value }); - } - - onAddMoviePress = (searchForMovie) => { - const { - tmdbId, - rootFolderPath, - monitor, - qualityProfileId, - minimumAvailability, - tags - } = this.props; - - this.props.addMovie({ - tmdbId, - rootFolderPath: rootFolderPath.value, - monitor: monitor.value, - qualityProfileId: qualityProfileId.value, - minimumAvailability: minimumAvailability.value, - tags: tags.value, - searchForMovie - }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -AddNewDiscoverMovieModalContentConnector.propTypes = { - tmdbId: PropTypes.number.isRequired, - rootFolderPath: PropTypes.object, - monitor: PropTypes.object.isRequired, - qualityProfileId: PropTypes.object, - minimumAvailability: PropTypes.object.isRequired, - tags: PropTypes.object.isRequired, - onModalClose: PropTypes.func.isRequired, - setAddMovieDefault: PropTypes.func.isRequired, - addMovie: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddNewDiscoverMovieModalContentConnector); diff --git a/frontend/src/DiscoverMovie/DiscoverMovie.js b/frontend/src/DiscoverMovie/DiscoverMovie.js deleted file mode 100644 index 9ec0ccc5d..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovie.js +++ /dev/null @@ -1,464 +0,0 @@ -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 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 DiscoverMovieFilterMenu from './Menus/DiscoverMovieFilterMenu'; -import DiscoverMovieSortMenu from './Menus/DiscoverMovieSortMenu'; -import DiscoverMovieViewMenu from './Menus/DiscoverMovieViewMenu'; -import NoDiscoverMovie from './NoDiscoverMovie'; -import DiscoverMovieOverviewsConnector from './Overview/DiscoverMovieOverviewsConnector'; -import DiscoverMovieOverviewOptionsModal from './Overview/Options/DiscoverMovieOverviewOptionsModal'; -import DiscoverMoviePostersConnector from './Posters/DiscoverMoviePostersConnector'; -import DiscoverMoviePosterOptionsModal from './Posters/Options/DiscoverMoviePosterOptionsModal'; -import DiscoverMovieTableConnector from './Table/DiscoverMovieTableConnector'; -import DiscoverMovieTableOptionsConnector from './Table/DiscoverMovieTableOptionsConnector'; - -function getViewComponent(view) { - if (view === 'posters') { - return DiscoverMoviePostersConnector; - } - - if (view === 'overview') { - return DiscoverMovieOverviewsConnector; - } - - return DiscoverMovieTableConnector; -} - -class DiscoverMovie extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - scroller: null, - jumpBarItems: { order: [] }, - jumpToCharacter: null, - isPosterOptionsModalOpen: false, - isOverviewOptionsModalOpen: false, - isConfirmSearchModalOpen: false, - searchType: null, - allSelected: false, - allUnselected: false, - lastToggled: null, - selectedState: {} - }; - } - - componentDidMount() { - this.setJumpBarItems(); - this.setSelectedState(); - } - - componentDidUpdate(prevProps) { - const { - items, - sortKey, - sortDirection - } = this.props; - - if (sortKey !== prevProps.sortKey || - sortDirection !== prevProps.sortDirection || - hasDifferentItemsOrOrder(prevProps.items, items) - ) { - this.setJumpBarItems(); - this.setSelectedState(); - } - - if (this.state.jumpToCharacter != null) { - this.setState({ jumpToCharacter: null }); - } - } - - // - // Control - - setScrollerRef = (ref) => { - 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, - sortKey, - sortDirection - } = this.props; - - // Reset if not sorting by sortTitle - if (sortKey !== 'sortTitle') { - this.setState({ jumpBarItems: { order: [] } }); - return; - } - - const characters = _.reduce(items, (acc, item) => { - let char = item.sortTitle.charAt(0); - - if (!isNaN(char)) { - char = '#'; - } - - if (char in acc) { - acc[char] = acc[char] + 1; - } else { - acc[char] = 1; - } - - return acc; - }, {}); - - const order = Object.keys(characters).sort(); - - // Reverse if sorting descending - if (sortDirection === sortDirections.DESCENDING) { - order.reverse(); - } - - const jumpBarItems = { - characters, - order - }; - - this.setState({ jumpBarItems }); - } - - // - // Listeners - - onPosterOptionsPress = () => { - this.setState({ isPosterOptionsModalOpen: true }); - } - - onPosterOptionsModalClose = () => { - this.setState({ isPosterOptionsModalOpen: false }); - } - - onOverviewOptionsPress = () => { - this.setState({ isOverviewOptionsModalOpen: true }); - } - - onOverviewOptionsModalClose = () => { - this.setState({ isOverviewOptionsModalOpen: false }); - } - - onJumpBarItemPress = (jumpToCharacter) => { - this.setState({ jumpToCharacter }); - } - - onSelectAllChange = ({ value }) => { - this.setState(selectAll(this.state.selectedState, value)); - } - - onSelectAllPress = () => { - this.onSelectAllChange({ value: !this.state.allSelected }); - } - - onImportListSyncPress = () => { - this.props.onImportListSyncPress(); - } - - onSelectedChange = ({ id, value, shiftKey = false }) => { - this.setState((state) => { - return toggleSelected(state, this.props.items, id, value, shiftKey, 'tmdbId'); - }); - } - - onAddMoviesPress = ({ addOptions }) => { - this.props.onAddMoviesPress({ ids: this.getSelectedIds(), addOptions }); - } - - onExcludeMoviesPress = () => { - this.props.onExcludeMoviesPress({ ids: this.getSelectedIds() }); - } - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - totalItems, - items, - columns, - selectedFilterKey, - filters, - customFilters, - sortKey, - sortDirection, - view, - onSortSelect, - onFilterSelect, - onViewSelect, - onScroll, - onAddMoviesPress, - isSyncingLists, - ...otherProps - } = this.props; - - const { - scroller, - jumpBarItems, - jumpToCharacter, - isPosterOptionsModalOpen, - isOverviewOptionsModalOpen, - selectedState, - allSelected, - allUnselected - } = this.state; - - const selectedMovieIds = this.getSelectedIds(); - - const ViewComponent = getViewComponent(view); - const isLoaded = !!(!error && isPopulated && items.length && scroller); - const hasNoMovie = !totalItems; - - return ( - - - - - - - - - { - view === 'table' ? - - - : - null - } - - { - view === 'posters' ? - : - null - } - - { - view === 'overview' ? - : - null - } - - { - (view === 'posters' || view === 'overview') && - - } - - - - - - - - - -
- - { - isFetching && !isPopulated && - - } - - { - !isFetching && !!error && -
- {translate('UnableToLoadMovies')} -
- } - - { - isLoaded && -
- -
- } - - { - !error && isPopulated && !items.length && - - } -
- - { - isLoaded && !!jumpBarItems.order.length && - - } -
- - { - isLoaded && - - } - - - - -
- ); - } -} - -DiscoverMovie.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - totalItems: PropTypes.number.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - filters: PropTypes.arrayOf(PropTypes.object).isRequired, - customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - sortDirection: PropTypes.oneOf(sortDirections.all), - view: PropTypes.string.isRequired, - isSyncingLists: PropTypes.bool.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - onSortSelect: PropTypes.func.isRequired, - onFilterSelect: PropTypes.func.isRequired, - onViewSelect: PropTypes.func.isRequired, - onScroll: PropTypes.func.isRequired, - onAddMoviesPress: PropTypes.func.isRequired, - onExcludeMoviesPress: PropTypes.func.isRequired, - onImportListSyncPress: PropTypes.func.isRequired -}; - -export default DiscoverMovie; diff --git a/frontend/src/DiscoverMovie/DiscoverMovieConnector.js b/frontend/src/DiscoverMovie/DiscoverMovieConnector.js deleted file mode 100644 index 0d78d9945..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieConnector.js +++ /dev/null @@ -1,155 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import * as commandNames from 'Commands/commandNames'; -import withScrollPosition from 'Components/withScrollPosition'; -import { executeCommand } from 'Store/Actions/commandActions'; -import { addImportExclusions, addMovies, clearAddMovie, fetchDiscoverMovies, setListMovieFilter, setListMovieSort, setListMovieTableOption, setListMovieView } from 'Store/Actions/discoverMovieActions'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions'; -import scrollPositions from 'Store/scrollPositions'; -import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createDiscoverMovieClientSideCollectionItemsSelector from 'Store/Selectors/createDiscoverMovieClientSideCollectionItemsSelector'; -import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; -import DiscoverMovie from './DiscoverMovie'; - -function createMapStateToProps() { - return createSelector( - createDiscoverMovieClientSideCollectionItemsSelector('discoverMovie'), - createCommandExecutingSelector(commandNames.IMPORT_LIST_SYNC), - createDimensionsSelector(), - ( - movies, - isSyncingLists, - dimensionsState - ) => { - return { - ...movies, - isSyncingLists, - isSmallScreen: dimensionsState.isSmallScreen - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - dispatchFetchRootFolders() { - dispatch(fetchRootFolders()); - }, - - dispatchFetchImportExclusions() { - dispatch(fetchImportExclusions()); - }, - - dispatchClearListMovie() { - dispatch(clearAddMovie()); - }, - - dispatchFetchListMovies() { - dispatch(fetchDiscoverMovies()); - }, - - onTableOptionChange(payload) { - dispatch(setListMovieTableOption(payload)); - }, - - onSortSelect(sortKey) { - dispatch(setListMovieSort({ sortKey })); - }, - - onFilterSelect(selectedFilterKey) { - dispatch(setListMovieFilter({ selectedFilterKey })); - }, - - dispatchSetListMovieView(view) { - dispatch(setListMovieView({ view })); - }, - - dispatchAddMovies(ids, addOptions) { - dispatch(addMovies({ ids, addOptions })); - }, - - dispatchAddImportExclusions(exclusions) { - dispatch(addImportExclusions(exclusions)); - }, - - onImportListSyncPress() { - dispatch(executeCommand({ - name: commandNames.IMPORT_LIST_SYNC - })); - } - }; -} - -class DiscoverMovieConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - registerPagePopulator(this.repopulate); - this.props.dispatchFetchRootFolders(); - this.props.dispatchFetchImportExclusions(); - this.props.dispatchFetchListMovies(); - } - - componentWillUnmount() { - this.props.dispatchClearListMovie(); - unregisterPagePopulator(this.repopulate); - } - - // - // Listeners - - onViewSelect = (view) => { - this.props.dispatchSetListMovieView(view); - } - - onScroll = ({ scrollTop }) => { - scrollPositions.discoverMovie = scrollTop; - } - - onAddMoviesPress = ({ ids, addOptions }) => { - this.props.dispatchAddMovies(ids, addOptions); - } - - onExcludeMoviesPress =({ ids }) => { - this.props.dispatchAddImportExclusions({ ids }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DiscoverMovieConnector.propTypes = { - isSmallScreen: PropTypes.bool.isRequired, - view: PropTypes.string.isRequired, - dispatchFetchImportExclusions: PropTypes.func.isRequired, - dispatchFetchRootFolders: PropTypes.func.isRequired, - dispatchFetchListMovies: PropTypes.func.isRequired, - dispatchClearListMovie: PropTypes.func.isRequired, - dispatchSetListMovieView: PropTypes.func.isRequired, - dispatchAddMovies: PropTypes.func.isRequired, - dispatchAddImportExclusions: PropTypes.func.isRequired -}; - -export default withScrollPosition( - connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieConnector), - 'discoverMovie' -); diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFilterModalConnector.js b/frontend/src/DiscoverMovie/DiscoverMovieFilterModalConnector.js deleted file mode 100644 index bfac00b84..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFilterModalConnector.js +++ /dev/null @@ -1,24 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import FilterModal from 'Components/Filter/FilterModal'; -import { setListMovieFilter } from 'Store/Actions/discoverMovieActions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie.items, - (state) => state.discoverMovie.filterBuilderProps, - (sectionItems, filterBuilderProps) => { - return { - sectionItems, - filterBuilderProps, - customFilterType: 'discoverMovie' - }; - } - ); -} - -const mapDispatchToProps = { - dispatchSetFilter: setListMovieFilter -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(FilterModal); diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFooter.css b/frontend/src/DiscoverMovie/DiscoverMovieFooter.css deleted file mode 100644 index c9cf4ce4c..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFooter.css +++ /dev/null @@ -1,56 +0,0 @@ -.inputContainer { - margin-right: 20px; - min-width: 150px; -} - -.buttonContainer { - display: flex; - justify-content: flex-end; - flex-grow: 1; -} - -.buttonContainerContent { - flex-grow: 0; -} - -.buttons { - display: flex; - justify-content: flex-end; - flex-grow: 1; -} - -.addSelectedButton { - composes: button from '~Components/Link/SpinnerButton.css'; - - margin-right: 10px; - height: 35px; -} - -.excludeSelectedButton { - composes: button from '~Components/Link/SpinnerButton.css'; - - margin-left: 25px; - height: 35px; -} - -@media only screen and (max-width: $breakpointSmall) { - .inputContainer { - margin-right: 0; - } - - .buttonContainer { - justify-content: flex-start; - } - - .buttonContainerContent { - flex-grow: 1; - } - - .buttons { - justify-content: space-between; - } - - .selectedMovieLabel { - text-align: left; - } -} diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFooter.js b/frontend/src/DiscoverMovie/DiscoverMovieFooter.js deleted file mode 100644 index fc3c9eb26..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFooter.js +++ /dev/null @@ -1,277 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import AvailabilitySelectInput from 'Components/Form/AvailabilitySelectInput'; -import CheckInput from 'Components/Form/CheckInput'; -import QualityProfileSelectInputConnector from 'Components/Form/QualityProfileSelectInputConnector'; -import RootFolderSelectInputConnector from 'Components/Form/RootFolderSelectInputConnector'; -import SelectInput from 'Components/Form/SelectInput'; -import SpinnerButton from 'Components/Link/SpinnerButton'; -import PageContentFooter from 'Components/Page/PageContentFooter'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import DiscoverMovieFooterLabel from './DiscoverMovieFooterLabel'; -import ExcludeMovieModal from './Exclusion/ExcludeMovieModal'; -import styles from './DiscoverMovieFooter.css'; - -class DiscoverMovieFooter extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - const { - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - defaultRootFolderPath, - defaultSearchForMovie - } = props; - - this.state = { - monitor: defaultMonitor, - qualityProfileId: defaultQualityProfileId, - minimumAvailability: defaultMinimumAvailability, - rootFolderPath: defaultRootFolderPath, - searchForMovie: defaultSearchForMovie, - isExcludeMovieModalOpen: false, - destinationRootFolder: null - }; - } - - componentDidUpdate(prevProps) { - const { - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - defaultRootFolderPath, - defaultSearchForMovie - } = this.props; - - const { - monitor, - qualityProfileId, - minimumAvailability, - rootFolderPath, - searchForMovie - } = this.state; - - const newState = {}; - - if (monitor !== defaultMonitor) { - newState.monitor = defaultMonitor; - } - - if (qualityProfileId !== defaultQualityProfileId) { - newState.qualityProfileId = defaultQualityProfileId; - } - - if (minimumAvailability !== defaultMinimumAvailability) { - newState.minimumAvailability = defaultMinimumAvailability; - } - - if (rootFolderPath !== defaultRootFolderPath) { - newState.rootFolderPath = defaultRootFolderPath; - } - - if (searchForMovie !== defaultSearchForMovie) { - newState.searchForMovie = defaultSearchForMovie; - } - - if (!_.isEmpty(newState)) { - this.setState(newState); - } - } - - // - // Listeners - - onExcludeSelectedPress = () => { - this.setState({ isExcludeMovieModalOpen: true }); - } - - onExcludeMovieModalClose = () => { - this.setState({ isExcludeMovieModalOpen: false }); - } - - onAddMoviesPress = () => { - const { - monitor, - qualityProfileId, - minimumAvailability, - rootFolderPath, - searchForMovie - } = this.state; - - const addOptions = { - monitor, - qualityProfileId, - minimumAvailability, - rootFolderPath, - searchForMovie - }; - - this.props.onAddMoviesPress({ addOptions }); - } - - // - // Render - - render() { - const { - selectedIds, - selectedCount, - isAdding, - isExcluding, - onInputChange - } = this.props; - - const { - monitor, - qualityProfileId, - minimumAvailability, - rootFolderPath, - searchForMovie, - isExcludeMovieModalOpen - } = this.state; - - const monitoredOptions = [ - { key: true, value: 'Monitored' }, - { key: false, value: 'Unmonitored' } - ]; - - return ( - -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
-
- - -
-
- - {translate('AddMovies')} - - - - {translate('AddExclusion')} - -
-
-
-
- - -
- ); - } -} - -DiscoverMovieFooter.propTypes = { - selectedIds: PropTypes.arrayOf(PropTypes.number).isRequired, - selectedCount: PropTypes.number.isRequired, - isAdding: PropTypes.bool.isRequired, - isExcluding: PropTypes.bool.isRequired, - defaultMonitor: PropTypes.string.isRequired, - defaultQualityProfileId: PropTypes.number, - defaultMinimumAvailability: PropTypes.string, - defaultRootFolderPath: PropTypes.string, - defaultSearchForMovie: PropTypes.bool, - onInputChange: PropTypes.func.isRequired, - onAddMoviesPress: PropTypes.func.isRequired, - onExcludeMoviesPress: PropTypes.func.isRequired -}; - -export default DiscoverMovieFooter; diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFooterConnector.js b/frontend/src/DiscoverMovie/DiscoverMovieFooterConnector.js deleted file mode 100644 index 6562f893f..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFooterConnector.js +++ /dev/null @@ -1,74 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setAddMovieDefault } from 'Store/Actions/discoverMovieActions'; -import DiscoverMovieFooter from './DiscoverMovieFooter'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie, - (state) => state.settings.importExclusions, - (state, { selectedIds }) => selectedIds, - (discoverMovie, importExclusions, selectedIds) => { - const { - monitor: defaultMonitor, - qualityProfileId: defaultQualityProfileId, - minimumAvailability: defaultMinimumAvailability, - rootFolderPath: defaultRootFolderPath, - searchForMovie: defaultSearchForMovie - } = discoverMovie.defaults; - - const { - isAdding - } = discoverMovie; - - const { - isSaving - } = importExclusions; - - return { - selectedCount: selectedIds.length, - isAdding, - isExcluding: isSaving, - defaultMonitor, - defaultQualityProfileId, - defaultMinimumAvailability, - defaultRootFolderPath, - defaultSearchForMovie - }; - } - ); -} - -const mapDispatchToProps = { - setAddMovieDefault -}; - -class DiscoverMovieFooterConnector extends Component { - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setAddMovieDefault({ [name]: value }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -DiscoverMovieFooterConnector.propTypes = { - setAddMovieDefault: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(DiscoverMovieFooterConnector); diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.css b/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.css deleted file mode 100644 index 9b4b40be6..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.css +++ /dev/null @@ -1,8 +0,0 @@ -.label { - margin-bottom: 3px; - font-weight: bold; -} - -.savingIcon { - margin-left: 8px; -} diff --git a/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.js b/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.js deleted file mode 100644 index c03d2cafc..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieFooterLabel.js +++ /dev/null @@ -1,40 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import SpinnerIcon from 'Components/SpinnerIcon'; -import { icons } from 'Helpers/Props'; -import styles from './DiscoverMovieFooterLabel.css'; - -function DiscoverMovieFooterLabel(props) { - const { - className, - label, - isSaving - } = props; - - return ( -
- {label} - - { - isSaving && - - } -
- ); -} - -DiscoverMovieFooterLabel.propTypes = { - className: PropTypes.string.isRequired, - label: PropTypes.string.isRequired, - isSaving: PropTypes.bool.isRequired -}; - -DiscoverMovieFooterLabel.defaultProps = { - className: styles.label -}; - -export default DiscoverMovieFooterLabel; diff --git a/frontend/src/DiscoverMovie/DiscoverMovieItemConnector.js b/frontend/src/DiscoverMovie/DiscoverMovieItemConnector.js deleted file mode 100644 index bee5235df..000000000 --- a/frontend/src/DiscoverMovie/DiscoverMovieItemConnector.js +++ /dev/null @@ -1,60 +0,0 @@ -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'; - -function createMapStateToProps() { - return createSelector( - createDiscoverMovieSelector(), - ( - movie - ) => { - - // If a movie is deleted this selector may fire before the parent - // selecors, which will result in an undefined movie, if that happens - // we want to return early here and again in the render function to avoid - // trying to show a movie that has no information available. - - if (!movie) { - return {}; - } - - return { - ...movie - }; - } - ); -} - -class DiscoverMovieItemConnector extends Component { - - // - // Render - - render() { - const { - tmdbId, - component: ItemComponent, - ...otherProps - } = this.props; - - if (!tmdbId) { - return null; - } - - return ( - - ); - } -} - -DiscoverMovieItemConnector.propTypes = { - tmdbId: PropTypes.number, - component: PropTypes.elementType.isRequired -}; - -export default connect(createMapStateToProps)(DiscoverMovieItemConnector); diff --git a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModal.js b/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModal.js deleted file mode 100644 index 02ab50972..000000000 --- a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModal.js +++ /dev/null @@ -1,33 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import ExcludeMovieModalContentConnector from './ExcludeMovieModalContentConnector'; - -function ExcludeMovieModal(props) { - const { - isOpen, - onModalClose, - ...otherProps - } = props; - - return ( - - - - ); -} - -ExcludeMovieModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ExcludeMovieModal; diff --git a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.css b/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.css deleted file mode 100644 index dbfef0871..000000000 --- a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.css +++ /dev/null @@ -1,12 +0,0 @@ -.pathContainer { - margin-bottom: 20px; -} - -.pathIcon { - margin-right: 8px; -} - -.deleteFilesMessage { - margin-top: 20px; - color: $dangerColor; -} diff --git a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.js b/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.js deleted file mode 100644 index 4eb4577b1..000000000 --- a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContent.js +++ /dev/null @@ -1,70 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Button from 'Components/Link/Button'; -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 translate from 'Utilities/String/translate'; -import styles from './ExcludeMovieModalContent.css'; - -class ExcludeMovieModalContent extends Component { - - // - // Listeners - - onExcludeMovieConfirmed = () => { - this.props.onExcludePress(); - } - - // - // Render - - render() { - const { - tmdbId, - title, - onModalClose - } = this.props; - - return ( - - - Exclude - {title} ({tmdbId}) - - - -
- Exclude {title}? This will prevent Radarr from adding automatically via list sync. -
- -
- - - - - - -
- ); - } -} - -ExcludeMovieModalContent.propTypes = { - tmdbId: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - onExcludePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default ExcludeMovieModalContent; diff --git a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContentConnector.js b/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContentConnector.js deleted file mode 100644 index 84c314b5a..000000000 --- a/frontend/src/DiscoverMovie/Exclusion/ExcludeMovieModalContentConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { addImportExclusions } from 'Store/Actions/discoverMovieActions'; -import ExcludeMovieModalContent from './ExcludeMovieModalContent'; - -const mapDispatchToProps = { - addImportExclusions -}; - -class ExcludeMovieModalContentConnector extends Component { - - // - // Listeners - - onExcludePress = () => { - this.props.addImportExclusions({ ids: [this.props.tmdbId] }); - - this.props.onModalClose(true); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ExcludeMovieModalContentConnector.propTypes = { - tmdbId: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - onModalClose: PropTypes.func.isRequired, - addImportExclusions: PropTypes.func.isRequired -}; - -export default connect(undefined, mapDispatchToProps)(ExcludeMovieModalContentConnector); diff --git a/frontend/src/DiscoverMovie/Menus/DiscoverMovieFilterMenu.js b/frontend/src/DiscoverMovie/Menus/DiscoverMovieFilterMenu.js deleted file mode 100644 index 717443050..000000000 --- a/frontend/src/DiscoverMovie/Menus/DiscoverMovieFilterMenu.js +++ /dev/null @@ -1,41 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FilterMenu from 'Components/Menu/FilterMenu'; -import DiscoverMovieFilterModalConnector from 'DiscoverMovie/DiscoverMovieFilterModalConnector'; -import { align } from 'Helpers/Props'; - -function DiscoverMovieFilterMenu(props) { - const { - selectedFilterKey, - filters, - customFilters, - isDisabled, - onFilterSelect - } = props; - - return ( - - ); -} - -DiscoverMovieFilterMenu.propTypes = { - selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - filters: PropTypes.arrayOf(PropTypes.object).isRequired, - customFilters: PropTypes.arrayOf(PropTypes.object).isRequired, - isDisabled: PropTypes.bool.isRequired, - onFilterSelect: PropTypes.func.isRequired -}; - -DiscoverMovieFilterMenu.defaultProps = { - showCustomFilters: false -}; - -export default DiscoverMovieFilterMenu; diff --git a/frontend/src/DiscoverMovie/Menus/DiscoverMovieSortMenu.js b/frontend/src/DiscoverMovie/Menus/DiscoverMovieSortMenu.js deleted file mode 100644 index 691c645b7..000000000 --- a/frontend/src/DiscoverMovie/Menus/DiscoverMovieSortMenu.js +++ /dev/null @@ -1,114 +0,0 @@ -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'; - -function DiscoverMovieSortMenu(props) { - const { - sortKey, - sortDirection, - isDisabled, - onSortSelect - } = props; - - return ( - - - - Status - - - - Title - - - - Studio - - - - In Cinemas - - - - Physical Release - - - - Digital Release - - - - Runtime - - - - Rating - - - - Certification - - - - ); -} - -DiscoverMovieSortMenu.propTypes = { - sortKey: PropTypes.string, - sortDirection: PropTypes.oneOf(sortDirections.all), - isDisabled: PropTypes.bool.isRequired, - onSortSelect: PropTypes.func.isRequired -}; - -export default DiscoverMovieSortMenu; diff --git a/frontend/src/DiscoverMovie/Menus/DiscoverMovieViewMenu.js b/frontend/src/DiscoverMovie/Menus/DiscoverMovieViewMenu.js deleted file mode 100644 index 6ad076bdc..000000000 --- a/frontend/src/DiscoverMovie/Menus/DiscoverMovieViewMenu.js +++ /dev/null @@ -1,55 +0,0 @@ -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'; - -function DiscoverMovieViewMenu(props) { - const { - view, - isDisabled, - onViewSelect - } = props; - - return ( - - - - Table - - - - Posters - - - - Overview - - - - ); -} - -DiscoverMovieViewMenu.propTypes = { - view: PropTypes.string.isRequired, - isDisabled: PropTypes.bool.isRequired, - onViewSelect: PropTypes.func.isRequired -}; - -export default DiscoverMovieViewMenu; diff --git a/frontend/src/DiscoverMovie/NoDiscoverMovie.css b/frontend/src/DiscoverMovie/NoDiscoverMovie.css deleted file mode 100644 index 38a01f391..000000000 --- a/frontend/src/DiscoverMovie/NoDiscoverMovie.css +++ /dev/null @@ -1,11 +0,0 @@ -.message { - margin-top: 10px; - margin-bottom: 30px; - text-align: center; - font-size: 20px; -} - -.buttonContainer { - margin-top: 20px; - text-align: center; -} diff --git a/frontend/src/DiscoverMovie/NoDiscoverMovie.js b/frontend/src/DiscoverMovie/NoDiscoverMovie.js deleted file mode 100644 index a967b867e..000000000 --- a/frontend/src/DiscoverMovie/NoDiscoverMovie.js +++ /dev/null @@ -1,61 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Button from 'Components/Link/Button'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './NoDiscoverMovie.css'; - -function NoDiscoverMovie(props) { - const { totalItems } = props; - - if (totalItems > 0) { - return ( -
-
- {translate('AllMoviesHiddenDueToFilter')} -
-
- ); - } - - return ( -
-
- No list items or recommendations found, to get started you'll want to add a new movie, import some existing ones, or add a list. -
- -
- -
- -
- -
- -
- -
-
- ); -} - -NoDiscoverMovie.propTypes = { - totalItems: PropTypes.number.isRequired -}; - -export default NoDiscoverMovie; diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.css b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.css deleted file mode 100644 index b0e503eb4..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.css +++ /dev/null @@ -1,100 +0,0 @@ -$hoverScale: 1.05; - -.content { - display: flex; - flex-grow: 1; -} - -.poster { - position: relative; -} - -.editorSelect { - position: absolute; - top: 0; - left: 5px; - z-index: 3; -} - -.posterContainer { - position: relative; -} - -.link { - composes: link from '~Components/Link/Link.css'; - - display: block; - color: $defaultColor; - - &:hover { - color: $defaultColor; - text-decoration: none; - } -} - -.alreadyExistsIcon { - margin-left: 10px; - color: #37bc9b; - pointer-events: all; -} - -.exclusionIcon { - margin-left: 10px; - color: $dangerColor; - pointer-events: all; -} - -.info { - display: flex; - flex: 1 0 1px; - flex-direction: column; - overflow: hidden; - padding-left: 10px; -} - -.titleRow { - display: flex; - justify-content: space-between; - flex: 0 0 auto; - margin-bottom: 5px; - line-height: 32px; -} - -.lists { - display: flex; - margin-bottom: 5px; -} - -.title { - @add-mixin truncate; - composes: link; - - flex: 1 0 1px; - font-weight: 300; - font-size: 30px; - line-height: 1; -} - -.actions { - white-space: nowrap; -} - -.details { - display: flex; - justify-content: space-between; - flex: 1 0 auto; -} - -.overview { - composes: link; - - flex: 0 1 1000px; - overflow: hidden; - min-height: 0; -} - -@media only screen and (max-width: $breakpointSmall) { - .overview { - display: none; - } -} diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.js deleted file mode 100644 index d9d13bf73..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverview.js +++ /dev/null @@ -1,294 +0,0 @@ -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 ImportListListConnector from 'Components/ImportListListConnector'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import Link from 'Components/Link/Link'; -import Popover from 'Components/Tooltip/Popover'; -import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal'; -import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal'; -import { icons, kinds } from 'Helpers/Props'; -import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks'; -import MoviePoster from 'Movie/MoviePoster'; -import dimensions from 'Styles/Variables/dimensions'; -import fonts from 'Styles/Variables/fonts'; -import translate from 'Utilities/String/translate'; -import DiscoverMovieOverviewInfo from './DiscoverMovieOverviewInfo'; -import styles from './DiscoverMovieOverview.css'; - -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); -const defaultFontSize = parseInt(fonts.defaultFontSize); -const lineHeight = parseFloat(fonts.lineHeight); - -// Hardcoded height beased on line-height of 32 + bottom margin of 10. 19 + 5 for List Row -// Less side-effecty than using react-measure. -const titleRowHeight = 66; - -function getContentHeight(rowHeight, isSmallScreen) { - const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding; - - return rowHeight - padding; -} - -class DiscoverMovieOverview extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isNewAddMovieModalOpen: false, - isExcludeMovieModalOpen: false - }; - } - - // - // Listeners - - onPress = () => { - this.setState({ isNewAddMovieModalOpen: true }); - } - - onAddMovieModalClose = () => { - 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, - folder, - year, - overview, - images, - lists, - posterWidth, - posterHeight, - rowHeight, - isSmallScreen, - isExisting, - isExcluded, - isRecommendation, - isSelected, - overviewOptions, - ...otherProps - } = this.props; - - const { - isNewAddMovieModalOpen, - isExcludeMovieModalOpen - } = this.state; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onPress }; - - const contentHeight = getContentHeight(rowHeight, isSmallScreen); - const overviewHeight = contentHeight - titleRowHeight; - - return ( -
-
-
-
-
- -
- - -
-
- -
-
- - {title} - - { - isExisting ? - : null - } - { - isExcluded && - - } - - -
- - - } - title={translate('Links')} - body={ - - } - /> - - - -
-
- -
- { - isRecommendation ? - : - null - } - - -
- -
-
- -
- - - -
-
-
- - - - -
- ); - } -} - -DiscoverMovieOverview.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, - status: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - rowHeight: PropTypes.number.isRequired, - overviewOptions: PropTypes.object.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - isExisting: PropTypes.bool.isRequired, - isExcluded: PropTypes.bool.isRequired, - isRecommendation: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - lists: PropTypes.arrayOf(PropTypes.number).isRequired, - onSelectedChange: PropTypes.func.isRequired -}; - -DiscoverMovieOverview.defaultProps = { - lists: [] -}; - -export default DiscoverMovieOverview; diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewConnector.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewConnector.js deleted file mode 100644 index 3b4ee0acf..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import DiscoverMovieOverview from './DiscoverMovieOverview'; - -function createMapStateToProps() { - return createSelector( - createDimensionsSelector(), - (dimensions) => { - return { - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(DiscoverMovieOverview); diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.css b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.css deleted file mode 100644 index 5dc53762f..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.css +++ /dev/null @@ -1,12 +0,0 @@ -.infos { - display: flex; - flex: 0 0 250px; - flex-direction: column; - margin-left: 10px; -} - -@media only screen and (max-width: $breakpointSmall) { - .infos { - margin-left: 0; - } -} diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.js deleted file mode 100644 index ca728f2e4..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfo.js +++ /dev/null @@ -1,147 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { icons } from 'Helpers/Props'; -import dimensions from 'Styles/Variables/dimensions'; -import DiscoverMovieOverviewInfoRow from './DiscoverMovieOverviewInfoRow'; -import styles from './DiscoverMovieOverviewInfo.css'; - -const infoRowHeight = parseInt(dimensions.movieIndexOverviewInfoRowHeight); - -const rows = [ - { - name: 'year', - showProp: 'showYear', - valueProp: 'year' - }, - { - name: 'genres', - showProp: 'showGenres', - valueProp: 'genres' - }, - { - name: 'ratings', - showProp: 'showRatings', - valueProp: 'ratings' - }, - { - name: 'certification', - showProp: 'showCertification', - valueProp: 'certification' - }, - { - name: 'studio', - showProp: 'showStudio', - valueProp: 'studio' - } -]; - -function isVisible(row, props) { - const { - name, - showProp, - valueProp - } = row; - - if (props[valueProp] == null) { - return false; - } - - return props[showProp] || props.sortKey === name; -} - -function getInfoRowProps(row, props) { - const { name } = row; - - if (name === 'year') { - return { - title: 'Year', - iconName: icons.CALENDAR, - label: props.year - }; - } - - if (name === 'genres') { - return { - title: 'Genres', - iconName: icons.GENRE, - label: props.genres.slice(0, 2).join(', ') - }; - } - - if (name === 'ratings') { - return { - title: 'Ratings', - iconName: icons.HEART, - label: `${props.ratings.value * 10}%` - }; - } - - if (name === 'certification') { - return { - title: 'Certification', - iconName: icons.FILM, - label: props.certification - }; - } - - if (name === 'studio') { - return { - title: 'Studio', - iconName: icons.STUDIO, - label: props.studio - }; - } -} - -function DiscoverMovieOverviewInfo(props) { - const { - height - } = props; - - let shownRows = 1; - const maxRows = Math.floor(height / (infoRowHeight + 4)); - - return ( -
- { - rows.map((row) => { - if (!isVisible(row, props)) { - return null; - } - - if (shownRows >= maxRows) { - return null; - } - - shownRows++; - - const infoRowProps = getInfoRowProps(row, props); - - return ( - - ); - }) - } -
- ); -} - -DiscoverMovieOverviewInfo.propTypes = { - height: PropTypes.number.isRequired, - showStudio: PropTypes.bool.isRequired, - showYear: PropTypes.bool.isRequired, - showRatings: PropTypes.bool.isRequired, - showCertification: PropTypes.bool.isRequired, - showGenres: PropTypes.bool.isRequired, - studio: PropTypes.string, - year: PropTypes.number, - certification: PropTypes.string, - ratings: PropTypes.object, - genres: PropTypes.arrayOf(PropTypes.string).isRequired, - sortKey: PropTypes.string.isRequired -}; - -export default DiscoverMovieOverviewInfo; diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.css b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.css deleted file mode 100644 index ea94e2ef6..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.css +++ /dev/null @@ -1,10 +0,0 @@ -.infoRow { - flex: 0 0 $movieIndexOverviewInfoRowHeight; - margin: 2px 0; -} - -.icon { - margin-right: 5px; - width: 25px !important; - text-align: center; -} diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.js deleted file mode 100644 index df97de1b2..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewInfoRow.js +++ /dev/null @@ -1,35 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import styles from './DiscoverMovieOverviewInfoRow.css'; - -function DiscoverMovieOverviewInfoRow(props) { - const { - title, - iconName, - label - } = props; - - return ( -
- - - {label} -
- ); -} - -DiscoverMovieOverviewInfoRow.propTypes = { - title: PropTypes.string, - iconName: PropTypes.object.isRequired, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired -}; - -export default DiscoverMovieOverviewInfoRow; diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.css b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.css deleted file mode 100644 index a0cee09ff..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.css +++ /dev/null @@ -1,15 +0,0 @@ -.grid { - flex: 1 0 auto; -} - -.container { - &:hover { - .content { - background-color: $tableRowHoverBackgroundColor; - } - } -} - -.externalLinks { - margin-right: 0.5em; -} diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.js deleted file mode 100644 index cde82441e..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviews.js +++ /dev/null @@ -1,261 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Grid, WindowScroller } from 'react-virtualized'; -import Measure from 'Components/Measure'; -import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector'; -import dimensions from 'Styles/Variables/dimensions'; -import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; -import DiscoverMovieOverviewConnector from './DiscoverMovieOverviewConnector'; -import styles from './DiscoverMovieOverviews.css'; - -// Poster container dimensions -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); - -function calculatePosterWidth(posterSize, isSmallScreen) { - const maxiumPosterWidth = isSmallScreen ? 152 : 162; - - if (posterSize === 'large') { - return maxiumPosterWidth; - } - - if (posterSize === 'medium') { - return Math.floor(maxiumPosterWidth * 0.75); - } - - return Math.floor(maxiumPosterWidth * 0.5); -} - -function calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions) { - - const heights = [ - posterHeight, - isSmallScreen ? columnPaddingSmallScreen : columnPadding - ]; - - return heights.reduce((acc, height) => acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class DiscoverMovieOverviews extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, null, props.isSmallScreen, {}) - }; - - this._grid = null; - } - - componentDidUpdate(prevProps, prevState) { - const { - items, - sortKey, - overviewOptions, - jumpToCharacter - } = this.props; - - const { - width, - rowHeight - } = this.state; - - if (prevProps.sortKey !== sortKey || - prevProps.overviewOptions !== overviewOptions) { - this.calculateGrid(); - } - - if (this._grid && - (prevState.width !== width || - prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId'))) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - - if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) { - const index = getIndexOfFirstCharacter(items, jumpToCharacter); - - if (this._grid && index != null) { - - this._grid.scrollToCell({ - rowIndex: index, - columnIndex: 0 - }); - } - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - const { - sortKey, - overviewOptions - } = this.props; - - const posterWidth = calculatePosterWidth(overviewOptions.size, isSmallScreen); - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions); - - this.setState({ - width, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, style }) => { - const { - items, - sortKey, - overviewOptions, - showRelativeDates, - shortDateFormat, - longDateFormat, - timeFormat, - isSmallScreen, - selectedState, - onSelectedChange - } = this.props; - - const { - posterWidth, - posterHeight, - rowHeight - } = this.state; - - const movie = items[rowIndex]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - isSmallScreen, - scroller, - items, - selectedState - } = this.props; - - const { - width, - rowHeight - } = this.state; - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -DiscoverMovieOverviews.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - overviewOptions: PropTypes.object.isRequired, - jumpToCharacter: PropTypes.string, - scroller: PropTypes.instanceOf(Element).isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - selectedState: PropTypes.object.isRequired, - onSelectedChange: PropTypes.func.isRequired -}; - -export default DiscoverMovieOverviews; diff --git a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewsConnector.js b/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewsConnector.js deleted file mode 100644 index 33706cf89..000000000 --- a/frontend/src/DiscoverMovie/Overview/DiscoverMovieOverviewsConnector.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import DiscoverMovieOverviews from './DiscoverMovieOverviews'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie.overviewOptions, - createUISettingsSelector(), - createDimensionsSelector(), - (overviewOptions, uiSettings, dimensions) => { - return { - overviewOptions, - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - longDateFormat: uiSettings.longDateFormat, - timeFormat: uiSettings.timeFormat, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(DiscoverMovieOverviews); diff --git a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModal.js b/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModal.js deleted file mode 100644 index 695d27c7c..000000000 --- a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import DiscoverMovieOverviewOptionsModalContentConnector from './DiscoverMovieOverviewOptionsModalContentConnector'; - -function DiscoverMovieOverviewOptionsModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -DiscoverMovieOverviewOptionsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default DiscoverMovieOverviewOptionsModal; diff --git a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContent.js b/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContent.js deleted file mode 100644 index 2bc383416..000000000 --- a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContent.js +++ /dev/null @@ -1,239 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -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 ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -const posterSizeOptions = [ - { key: 'small', value: 'Small' }, - { key: 'medium', value: 'Medium' }, - { key: 'large', value: 'Large' } -]; - -class DiscoverMovieOverviewOptionsModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - size: props.size, - showStudio: props.showStudio, - showCertification: props.showCertification, - showRatings: props.showRatings, - showYear: props.showYear, - showGenres: props.showGenres, - includeRecommendations: props.includeRecommendations - }; - } - - componentDidUpdate(prevProps) { - const { - size, - showStudio, - showYear, - showRatings, - showCertification, - showGenres, - includeRecommendations - } = this.props; - - const state = {}; - - if (size !== prevProps.size) { - state.size = size; - } - - if (showStudio !== prevProps.showStudio) { - state.showStudio = showStudio; - } - - if (showYear !== prevProps.showYear) { - state.showYear = showYear; - } - - if (showRatings !== prevProps.showRatings) { - state.showRatings = showRatings; - } - - if (showCertification !== prevProps.showCertification) { - state.showCertification = showCertification; - } - - if (showGenres !== prevProps.showGenres) { - state.showGenres = showGenres; - } - - if (includeRecommendations !== prevProps.includeRecommendations) { - state.includeRecommendations = includeRecommendations; - } - - if (!_.isEmpty(state)) { - this.setState(state); - } - } - - // - // Listeners - - onChangeOverviewOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangeOverviewOption({ [name]: value }); - }); - } - - onChangeOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangeOption({ - [name]: value - }); - }); - } - - // - // Render - - render() { - const { - onModalClose - } = this.props; - - const { - size, - showStudio, - showCertification, - showRatings, - showYear, - showGenres, - includeRecommendations - } = this.state; - - return ( - - - Overview Options - - - -
- - {translate('IncludeRadarrRecommendations')} - - - - - {translate('PosterSize')} - - - - - - {translate('ShowGenres')} - - - - - - {translate('ShowStudio')} - - - - - - {translate('ShowYear')} - - - - - - {translate('ShowRatings')} - - - - - - {translate('ShowCertification')} - - - -
-
- - - - -
- ); - } -} - -DiscoverMovieOverviewOptionsModalContent.propTypes = { - size: PropTypes.string.isRequired, - showStudio: PropTypes.bool.isRequired, - showYear: PropTypes.bool.isRequired, - showRatings: PropTypes.bool.isRequired, - showCertification: PropTypes.bool.isRequired, - showGenres: PropTypes.bool.isRequired, - includeRecommendations: PropTypes.bool.isRequired, - onChangeOverviewOption: PropTypes.func.isRequired, - onChangeOption: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default DiscoverMovieOverviewOptionsModalContent; diff --git a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContentConnector.js b/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContentConnector.js deleted file mode 100644 index 366a091ef..000000000 --- a/frontend/src/DiscoverMovie/Overview/Options/DiscoverMovieOverviewOptionsModalContentConnector.js +++ /dev/null @@ -1,29 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setListMovieOption, setListMovieOverviewOption } from 'Store/Actions/discoverMovieActions'; -import DiscoverMovieOverviewOptionsModalContent from './DiscoverMovieOverviewOptionsModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie, - (discoverMovie) => { - return { - ...discoverMovie.options, - ...discoverMovie.overviewOptions - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onChangeOverviewOption(payload) { - dispatch(setListMovieOverviewOption(payload)); - }, - onChangeOption(payload) { - dispatch(setListMovieOption(payload)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieOverviewOptionsModalContent); diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.css b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.css deleted file mode 100644 index 9f3b92170..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.css +++ /dev/null @@ -1,103 +0,0 @@ -$hoverScale: 1.05; - -.content { - transition: all 200ms ease-in; - - &:hover { - z-index: 2; - box-shadow: 0 0 12px $black; - transition: all 200ms ease-in; - - .controls { - opacity: 0.9; - transition: opacity 200ms linear 150ms; - } - } -} - -.posterContainer { - position: relative; -} - -.link { - composes: link from '~Components/Link/Link.css'; - - position: relative; - display: block; - background-color: $defaultColor; -} - -.externalLinks { - margin-right: 0.5em; - margin-left: 0.5em; -} - -.overlayTitle { - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - padding: 5px; - width: 100%; - height: 100%; - color: $offWhite; - text-align: center; - font-size: 20px; -} - -.title { - @add-mixin truncate; - - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} - -.excluded { - 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; -} - -.controls { - position: absolute; - bottom: 10px; - left: 10px; - z-index: 3; - border-radius: 4px; - background-color: #707070; - color: $white; - font-size: $smallFontSize; - opacity: 0; - transition: opacity 0; -} - -.editorSelect { - position: absolute; - top: 10px; - left: 10px; - z-index: 3; -} - -.action { - composes: button from '~Components/Link/IconButton.css'; - - &:hover { - color: $radarrYellow; - } -} - -@media only screen and (max-width: $breakpointSmall) { - .container { - padding: 5px; - } -} diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.js b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.js deleted file mode 100644 index 012d3660a..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePoster.js +++ /dev/null @@ -1,245 +0,0 @@ -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 translate from 'Utilities/String/translate'; -import DiscoverMoviePosterInfo from './DiscoverMoviePosterInfo'; -import styles from './DiscoverMoviePoster.css'; - -class DiscoverMoviePoster extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - hasPosterError: false, - isNewAddMovieModalOpen: false, - isExcludeMovieModalOpen: false - }; - } - - // - // Listeners - - onPress = () => { - this.setState({ isNewAddMovieModalOpen: true }); - } - - onAddMovieModalClose = () => { - this.setState({ isNewAddMovieModalOpen: false }); - } - - onExcludeMoviePress = () => { - this.setState({ isExcludeMovieModalOpen: true }); - } - - onExcludeMovieModalClose = () => { - this.setState({ isExcludeMovieModalOpen: false }); - } - - onPosterLoad = () => { - if (this.state.hasPosterError) { - this.setState({ hasPosterError: false }); - } - } - - onPosterLoadError = () => { - if (!this.state.hasPosterError) { - this.setState({ hasPosterError: true }); - } - } - - onChange = ({ value, shiftKey }) => { - const { - tmdbId, - onSelectedChange - } = this.props; - - onSelectedChange({ id: tmdbId, value, shiftKey }); - } - - // - // Render - - render() { - const { - tmdbId, - imdbId, - youTubeTrailerId, - title, - year, - overview, - folder, - images, - posterWidth, - posterHeight, - showTitle, - isExisting, - isExcluded, - isSelected, - showRelativeDates, - shortDateFormat, - timeFormat, - ...otherProps - } = this.props; - - const { - hasPosterError, - isNewAddMovieModalOpen, - isExcludeMovieModalOpen - } = this.state; - - const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onPress }; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - return ( -
-
- { -
- -
- } - - - - { - isExcluded && -
- } - - - - - { - hasPosterError && -
- {title} -
- } - -
- - { - showTitle && -
- {title} -
- } - - - - - - -
- ); - } -} - -DiscoverMoviePoster.propTypes = { - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string, - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - overview: PropTypes.string.isRequired, - folder: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - showTitle: PropTypes.bool.isRequired, - 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 -}; - -export default DiscoverMoviePoster; diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterConnector.js b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterConnector.js deleted file mode 100644 index 312468dd6..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import DiscoverMoviePoster from './DiscoverMoviePoster'; - -function createMapStateToProps() { - return createSelector( - createDimensionsSelector(), - ( dimensions) => { - return { - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(DiscoverMoviePoster); diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.css b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.css deleted file mode 100644 index aab27d827..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.css +++ /dev/null @@ -1,5 +0,0 @@ -.info { - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.js b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.js deleted file mode 100644 index 334aa71ea..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosterInfo.js +++ /dev/null @@ -1,139 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import HeartRating from 'Components/HeartRating'; -import { getMovieStatusDetails } from 'Movie/MovieStatus'; -import formatRuntime from 'Utilities/Date/formatRuntime'; -import getRelativeDate from 'Utilities/Date/getRelativeDate'; -import styles from './DiscoverMoviePosterInfo.css'; - -function DiscoverMoviePosterInfo(props) { - const { - status, - studio, - inCinemas, - digitalRelease, - physicalRelease, - certification, - runtime, - ratings, - sortKey, - showRelativeDates, - shortDateFormat, - timeFormat - } = props; - - if (sortKey === 'status' && status) { - return ( -
- {getMovieStatusDetails(status).title} -
- ); - } - - if (sortKey === 'studio' && studio) { - return ( -
- {studio} -
- ); - } - - if (sortKey === 'inCinemas' && inCinemas) { - const inCinemasDate = getRelativeDate( - inCinemas, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {`In Cinemas ${inCinemasDate}`} -
- ); - } - - if (sortKey === 'digitalRelease' && digitalRelease) { - const digitalReleaseDate = getRelativeDate( - digitalRelease, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {`Digital ${digitalReleaseDate}`} -
- ); - } - - if (sortKey === 'physicalRelease' && physicalRelease) { - const physicalReleaseDate = getRelativeDate( - physicalRelease, - shortDateFormat, - showRelativeDates, - { - timeFormat, - timeForToday: false - } - ); - - return ( -
- {`Released ${physicalReleaseDate}`} -
- ); - } - - if (sortKey === 'certification' && certification) { - return ( -
- {certification} -
- ); - } - - if (sortKey === 'runtime' && runtime) { - return ( -
- {formatRuntime(runtime)} -
- ); - } - - if (sortKey === 'ratings' && ratings) { - return ( -
- -
- ); - } - - return null; -} - -DiscoverMoviePosterInfo.propTypes = { - status: PropTypes.string, - studio: PropTypes.string, - inCinemas: PropTypes.string, - certification: PropTypes.string, - digitalRelease: PropTypes.string, - physicalRelease: PropTypes.string, - runtime: PropTypes.number, - ratings: PropTypes.object, - sortKey: PropTypes.string.isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired -}; - -export default DiscoverMoviePosterInfo; diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.css b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.css deleted file mode 100644 index 9c6520fb5..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.css +++ /dev/null @@ -1,3 +0,0 @@ -.grid { - flex: 1 0 auto; -} diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.js b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.js deleted file mode 100644 index 138612a38..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePosters.js +++ /dev/null @@ -1,306 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Grid, WindowScroller } from 'react-virtualized'; -import Measure from 'Components/Measure'; -import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector'; -import dimensions from 'Styles/Variables/dimensions'; -import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; -import DiscoverMoviePosterConnector from './DiscoverMoviePosterConnector'; -import styles from './DiscoverMoviePosters.css'; - -// Poster container dimensions -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); -const progressBarHeight = parseInt(dimensions.progressBarSmallHeight); -const detailedProgressBarHeight = parseInt(dimensions.progressBarMediumHeight); - -const additionalColumnCount = { - small: 3, - medium: 2, - large: 1 -}; - -function calculateColumnWidth(width, posterSize, isSmallScreen) { - const maxiumColumnWidth = isSmallScreen ? 172 : 182; - const columns = Math.floor(width / maxiumColumnWidth); - const remainder = width % maxiumColumnWidth; - - if (remainder === 0 && posterSize === 'large') { - return maxiumColumnWidth; - } - - return Math.floor(width / (columns + additionalColumnCount[posterSize])); -} - -function calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions) { - const { - detailedProgressBar, - showTitle - } = posterOptions; - - const nextAiringHeight = 19; - - const heights = [ - posterHeight, - detailedProgressBar ? detailedProgressBarHeight : progressBarHeight, - nextAiringHeight, - isSmallScreen ? columnPaddingSmallScreen : columnPadding - ]; - - if (showTitle) { - heights.push(19); - } - - switch (sortKey) { - case 'studio': - default: - // No need to add a height of 0 - } - - return heights.reduce((acc, height) => acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class DiscoverMoviePosters extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnWidth: 182, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, null, props.isSmallScreen, {}) - }; - - this._isInitialized = false; - this._grid = null; - this._padding = props.isSmallScreen ? columnPaddingSmallScreen : columnPadding; - } - - componentDidUpdate(prevProps, prevState) { - const { - items, - sortKey, - posterOptions, - jumpToCharacter, - isSmallScreen, - selectedState - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - if (prevProps.sortKey !== sortKey || - prevProps.posterOptions !== posterOptions) { - this.calculateGrid(width, isSmallScreen); - } - - if (this._grid && - (prevState.width !== width || - prevState.columnWidth !== columnWidth || - prevState.columnCount !== columnCount || - prevState.rowHeight !== rowHeight || - prevProps.selectedState !== selectedState || - hasDifferentItemsOrOrder(prevProps.items, items, 'tmdbId'))) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - - if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) { - const index = getIndexOfFirstCharacter(items, jumpToCharacter); - - if (this._grid && index != null) { - const row = Math.floor(index / columnCount); - - this._grid.scrollToCell({ - rowIndex: row, - columnIndex: 0 - }); - } - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - const { - sortKey, - posterOptions - } = this.props; - - const columnWidth = calculateColumnWidth(width, posterOptions.size, isSmallScreen); - const columnCount = Math.max(Math.floor(width / columnWidth), 1); - const posterWidth = columnWidth - this._padding * 2; - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, posterOptions); - - this.setState({ - width, - columnWidth, - columnCount, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, columnIndex, style }) => { - const { - items, - sortKey, - posterOptions, - showRelativeDates, - shortDateFormat, - timeFormat, - selectedState, - onSelectedChange - } = this.props; - - const { - posterWidth, - posterHeight, - columnCount - } = this.state; - - const { - showTitle - } = posterOptions; - - const movieIdx = rowIndex * columnCount + columnIndex; - const movie = items[movieIdx]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - isSmallScreen, - scroller, - items, - selectedState - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - const rowCount = Math.ceil(items.length / columnCount); - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -DiscoverMoviePosters.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - sortKey: PropTypes.string, - posterOptions: PropTypes.object.isRequired, - jumpToCharacter: PropTypes.string, - scroller: PropTypes.instanceOf(Element).isRequired, - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - timeFormat: PropTypes.string.isRequired, - selectedState: PropTypes.object.isRequired, - onSelectedChange: PropTypes.func.isRequired -}; - -export default DiscoverMoviePosters; diff --git a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePostersConnector.js b/frontend/src/DiscoverMovie/Posters/DiscoverMoviePostersConnector.js deleted file mode 100644 index 3ca8bacec..000000000 --- a/frontend/src/DiscoverMovie/Posters/DiscoverMoviePostersConnector.js +++ /dev/null @@ -1,24 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import DiscoverMoviePosters from './DiscoverMoviePosters'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie.posterOptions, - createUISettingsSelector(), - createDimensionsSelector(), - (posterOptions, uiSettings, dimensions) => { - return { - posterOptions, - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - timeFormat: uiSettings.timeFormat, - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(DiscoverMoviePosters); diff --git a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModal.js b/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModal.js deleted file mode 100644 index 0e926edbb..000000000 --- a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import DiscoverMoviePosterOptionsModalContentConnector from './DiscoverMoviePosterOptionsModalContentConnector'; - -function DiscoverMoviePosterOptionsModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -DiscoverMoviePosterOptionsModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default DiscoverMoviePosterOptionsModal; diff --git a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContent.js b/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContent.js deleted file mode 100644 index c15b5ebb7..000000000 --- a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContent.js +++ /dev/null @@ -1,165 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -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 ModalContent from 'Components/Modal/ModalContent'; -import ModalFooter from 'Components/Modal/ModalFooter'; -import ModalHeader from 'Components/Modal/ModalHeader'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -const posterSizeOptions = [ - { key: 'small', value: 'Small' }, - { key: 'medium', value: 'Medium' }, - { key: 'large', value: 'Large' } -]; - -class DiscoverMoviePosterOptionsModalContent extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - size: props.size, - showTitle: props.showTitle, - includeRecommendations: props.includeRecommendations - }; - } - - componentDidUpdate(prevProps) { - const { - size, - showTitle, - includeRecommendations - } = this.props; - - const state = {}; - - if (size !== prevProps.size) { - state.size = size; - } - - if (showTitle !== prevProps.showTitle) { - state.showTitle = showTitle; - } - - if (includeRecommendations !== prevProps.includeRecommendations) { - state.includeRecommendations = includeRecommendations; - } - - if (!_.isEmpty(state)) { - this.setState(state); - } - } - - // - // Listeners - - onChangePosterOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangePosterOption({ [name]: value }); - }); - } - - onChangeOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangeOption({ - [name]: value - }); - }); - } - - // - // Render - - render() { - const { - onModalClose - } = this.props; - - const { - size, - showTitle, - includeRecommendations - } = this.state; - - return ( - - - Poster Options - - - -
- - {translate('IncludeRadarrRecommendations')} - - - - - - {translate('PosterSize')} - - - - - - {translate('ShowTitle')} - - - -
-
- - - - -
- ); - } -} - -DiscoverMoviePosterOptionsModalContent.propTypes = { - size: PropTypes.string.isRequired, - showTitle: PropTypes.bool.isRequired, - includeRecommendations: PropTypes.bool.isRequired, - onChangePosterOption: PropTypes.func.isRequired, - onChangeOption: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default DiscoverMoviePosterOptionsModalContent; diff --git a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContentConnector.js b/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContentConnector.js deleted file mode 100644 index 0ff0b3845..000000000 --- a/frontend/src/DiscoverMovie/Posters/Options/DiscoverMoviePosterOptionsModalContentConnector.js +++ /dev/null @@ -1,29 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setListMovieOption, setListMoviePosterOption } from 'Store/Actions/discoverMovieActions'; -import DiscoverMoviePosterOptionsModalContent from './DiscoverMoviePosterOptionsModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie, - (discoverMovie) => { - return { - ...discoverMovie.options, - ...discoverMovie.posterOptions - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onChangePosterOption(payload) { - dispatch(setListMoviePosterOption(payload)); - }, - onChangeOption(payload) { - dispatch(setListMovieOption(payload)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMoviePosterOptionsModalContent); diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieActionsCell.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieActionsCell.js deleted file mode 100644 index dfb41a424..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieActionsCell.js +++ /dev/null @@ -1,54 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell'; - -class DiscoverMovieActionsCell extends Component { - - // - // Render - - render() { - const { - id, - ...otherProps - } = this.props; - - return ( - - {/* - - */} - - {/* - - */} - - ); - } -} - -DiscoverMovieActionsCell.propTypes = { - id: PropTypes.number.isRequired -}; - -export default DiscoverMovieActionsCell; diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.css b/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.css deleted file mode 100644 index d3a880fca..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.css +++ /dev/null @@ -1,58 +0,0 @@ -.status { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 0 30px; -} - -.collection, -.sortTitle { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 4 0 110px; -} - -.studio { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 2 0 90px; -} - -.inCinemas, -.physicalRelease, -.digitalRelease, -.genres { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 0 180px; -} - -.ratings, -.runtime { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 0 90px; -} - -.lists { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 1 0 110px; -} - -.certification { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 0 115px; -} - -.isRecommendation { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 0 50px; -} - -.actions { - composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css'; - - flex: 0 1 90px; -} diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.js deleted file mode 100644 index 024fd35c6..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeader.js +++ /dev/null @@ -1,140 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Icon from 'Components/Icon'; -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 DiscoverMovieTableOptionsConnector from './DiscoverMovieTableOptionsConnector'; -import styles from './DiscoverMovieHeader.css'; - -class DiscoverMovieHeader extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isTableOptionsModalOpen: false - }; - } - - // - // Listeners - - onTableOptionsPress = () => { - this.setState({ isTableOptionsModalOpen: true }); - } - - onTableOptionsModalClose = () => { - this.setState({ isTableOptionsModalOpen: false }); - } - - // - // Render - - render() { - const { - columns, - onTableOptionChange, - allSelected, - allUnselected, - onSelectAllChange, - ...otherProps - } = this.props; - - return ( - - - - { - columns.map((column) => { - const { - name, - label, - isSortable, - isVisible - } = column; - - if (!isVisible) { - return null; - } - - if (name === 'actions') { - return ( - - - - ); - } - - if (name === 'isRecommendation') { - return ( - - - - ); - } - - return ( - - {label} - - ); - }) - } - - - - ); - } -} - -DiscoverMovieHeader.propTypes = { - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - onTableOptionChange: PropTypes.func.isRequired, - allSelected: PropTypes.bool.isRequired, - allUnselected: PropTypes.bool.isRequired, - onSelectAllChange: PropTypes.func.isRequired -}; - -export default DiscoverMovieHeader; diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeaderConnector.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieHeaderConnector.js deleted file mode 100644 index 422e67cff..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieHeaderConnector.js +++ /dev/null @@ -1,13 +0,0 @@ -import { connect } from 'react-redux'; -import { setListMovieTableOption } from 'Store/Actions/discoverMovieActions'; -import DiscoverMovieHeader from './DiscoverMovieHeader'; - -function createMapDispatchToProps(dispatch, props) { - return { - onTableOptionChange(payload) { - dispatch(setListMovieTableOption(payload)); - } - }; -} - -export default connect(undefined, createMapDispatchToProps)(DiscoverMovieHeader); diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.css b/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.css deleted file mode 100644 index 48c9c6825..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.css +++ /dev/null @@ -1,88 +0,0 @@ -.cell { - composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css'; - - display: flex; - align-items: center; -} - -.status { - composes: cell; - - flex: 0 0 30px; -} - -.alreadyExistsIcon { - width: 20px !important; - color: #37bc9b; - pointer-events: all; -} - -.exclusionIcon { - width: 20px !important; - color: $dangerColor; - pointer-events: all; -} - -.collection, -.sortTitle { - composes: cell; - - flex: 4 0 110px; -} - -.studio { - composes: cell; - - flex: 2 0 90px; -} - -.inCinemas, -.physicalRelease, -.digitalRelease, -.genres { - composes: cell; - - flex: 0 0 180px; -} - -.certification { - composes: cell; - - flex: 0 0 115px; -} - -.ratings, -.runtime { - composes: cell; - - flex: 0 0 90px; -} - -.lists { - composes: cell; - - flex: 1 0 110px; -} - -.isRecommendation { - composes: cell; - - flex: 0 0 50px; -} - -.actions { - composes: cell; - - flex: 0 1 90px; - min-width: 60px; -} - -.checkInput { - composes: input from '~Components/Form/CheckInput.css'; - - margin-top: 0; -} - -.externalLinks { - margin-right: 0.5em; -} diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.js deleted file mode 100644 index a9d468d66..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieRow.js +++ /dev/null @@ -1,393 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import HeartRating from 'Components/HeartRating'; -import Icon from 'Components/Icon'; -import ImportListListConnector from 'Components/ImportListListConnector'; -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 formatRuntime from 'Utilities/Date/formatRuntime'; -import translate from 'Utilities/String/translate'; -import ListMovieStatusCell from './ListMovieStatusCell'; -import styles from './DiscoverMovieRow.css'; - -class DiscoverMovieRow extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isNewAddMovieModalOpen: false, - isExcludeMovieModalOpen: false - }; - } - - // - // Listeners - - onAddMoviePress = () => { - this.setState({ isNewAddMovieModalOpen: true }); - } - - onAddMovieModalClose = () => { - this.setState({ isNewAddMovieModalOpen: false }); - } - - onExcludeMoviePress = () => { - this.setState({ isExcludeMovieModalOpen: true }); - } - - onExcludeMovieModalClose = () => { - this.setState({ isExcludeMovieModalOpen: false }); - } - - // - // Render - - render() { - const { - status, - tmdbId, - imdbId, - youTubeTrailerId, - title, - studio, - inCinemas, - physicalRelease, - digitalRelease, - runtime, - year, - overview, - folder, - images, - genres, - ratings, - certification, - collection, - columns, - isExisting, - isExcluded, - isRecommendation, - isSelected, - lists, - onSelectedChange - } = this.props; - - const { - isNewAddMovieModalOpen, - isExcludeMovieModalOpen - } = this.state; - - const linkProps = isExisting ? { to: `/movie/${tmdbId}` } : { onPress: this.onAddMoviePress }; - - return ( - <> - - - { - columns.map((column) => { - const { - name, - isVisible - } = column; - - if (!isVisible) { - return null; - } - - if (name === 'status') { - return ( - - ); - } - - if (name === 'sortTitle') { - return ( - - - {title} - - - { - isExisting ? - : null - } - - { - isExcluded ? - : null - } - - ); - } - - if (name === 'collection') { - return ( - - {collection ? collection.name : null } - - ); - } - - if (name === 'studio') { - return ( - - {studio} - - ); - } - - if (name === 'inCinemas') { - return ( - - ); - } - - if (name === 'physicalRelease') { - return ( - - ); - } - - if (name === 'digitalRelease') { - return ( - - ); - } - - if (name === 'runtime') { - return ( - - {formatRuntime(runtime)} - - ); - } - - if (name === 'genres') { - const joinedGenres = genres.join(', '); - - return ( - - - {joinedGenres} - - - ); - } - - if (name === 'ratings') { - return ( - - - - ); - } - - if (name === 'certification') { - return ( - - {certification} - - ); - } - - if (name === 'lists') { - return ( - - - - ); - } - - if (name === 'isRecommendation') { - return ( - - { - isRecommendation ? - : - null - } - - ); - } - - if (name === 'actions') { - return ( - - - - } - title={translate('Links')} - body={ - - } - /> - - - - - ); - } - - return null; - }) - } - - - - - - ); - } -} - -DiscoverMovieRow.propTypes = { - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string, - status: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - year: PropTypes.number.isRequired, - overview: PropTypes.string.isRequired, - folder: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - studio: PropTypes.string, - inCinemas: PropTypes.string, - physicalRelease: PropTypes.string, - digitalRelease: PropTypes.string, - runtime: PropTypes.number, - genres: PropTypes.arrayOf(PropTypes.string).isRequired, - ratings: PropTypes.object.isRequired, - certification: PropTypes.string, - collection: PropTypes.object, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - isExisting: PropTypes.bool.isRequired, - isExcluded: PropTypes.bool.isRequired, - isSelected: PropTypes.bool, - isRecommendation: PropTypes.bool.isRequired, - lists: PropTypes.arrayOf(PropTypes.number).isRequired, - onSelectedChange: PropTypes.func.isRequired -}; - -DiscoverMovieRow.defaultProps = { - genres: [], - lists: [] -}; - -export default DiscoverMovieRow; diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieRowConnector.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieRowConnector.js deleted file mode 100644 index 5d54eafc5..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieRowConnector.js +++ /dev/null @@ -1,17 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import DiscoverMovieRow from './DiscoverMovieRow'; - -function createMapStateToProps() { - return createSelector( - createDimensionsSelector(), - (dimensions) => { - return { - isSmallScreen: dimensions.isSmallScreen - }; - } - ); -} - -export default connect(createMapStateToProps)(DiscoverMovieRow); diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.css b/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.css deleted file mode 100644 index 23ab127b5..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.css +++ /dev/null @@ -1,5 +0,0 @@ -.tableContainer { - composes: tableContainer from '~Components/Table/VirtualTable.css'; - - flex: 1 0 auto; -} diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.js deleted file mode 100644 index 6b2e64421..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieTable.js +++ /dev/null @@ -1,135 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import VirtualTable from 'Components/Table/VirtualTable'; -import VirtualTableRow from 'Components/Table/VirtualTableRow'; -import DiscoverMovieItemConnector from 'DiscoverMovie/DiscoverMovieItemConnector'; -import { sortDirections } from 'Helpers/Props'; -import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter'; -import DiscoverMovieHeaderConnector from './DiscoverMovieHeaderConnector'; -import DiscoverMovieRowConnector from './DiscoverMovieRowConnector'; -import styles from './DiscoverMovieTable.css'; - -class DiscoverMovieTable extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - scrollIndex: null - }; - } - - componentDidUpdate(prevProps) { - const { - items, - jumpToCharacter - } = this.props; - - if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) { - - const scrollIndex = getIndexOfFirstCharacter(items, jumpToCharacter); - - if (scrollIndex != null) { - this.setState({ scrollIndex }); - } - } else if (jumpToCharacter == null && prevProps.jumpToCharacter != null) { - this.setState({ scrollIndex: null }); - } - } - - // - // Control - - rowRenderer = ({ key, rowIndex, style }) => { - const { - items, - columns, - selectedState, - onSelectedChange - } = this.props; - - const movie = items[rowIndex]; - - return ( - - - - ); - } - - // - // Render - - render() { - const { - items, - columns, - sortKey, - sortDirection, - isSmallScreen, - onSortPress, - scroller, - allSelected, - allUnselected, - onSelectAllChange, - selectedState - } = this.props; - - return ( - - } - selectedState={selectedState} - columns={columns} - /> - ); - } -} - -DiscoverMovieTable.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - columns: PropTypes.arrayOf(PropTypes.object).isRequired, - 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 -}; - -export default DiscoverMovieTable; diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableConnector.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieTableConnector.js deleted file mode 100644 index b6b57b2bf..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableConnector.js +++ /dev/null @@ -1,27 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setListMovieSort } from 'Store/Actions/discoverMovieActions'; -import DiscoverMovieTable from './DiscoverMovieTable'; - -function createMapStateToProps() { - return createSelector( - (state) => state.app.dimensions, - (state) => state.discoverMovie.columns, - (dimensions, columns) => { - return { - isSmallScreen: dimensions.isSmallScreen, - columns - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onSortPress(sortKey) { - dispatch(setListMovieSort({ sortKey })); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieTable); diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptions.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptions.js deleted file mode 100644 index 183c4e188..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptions.js +++ /dev/null @@ -1,74 +0,0 @@ -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 } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -class DiscoverMovieTableOptions extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - includeRecommendations: props.includeRecommendations - }; - } - - componentDidUpdate(prevProps) { - const { includeRecommendations } = this.props; - - if (includeRecommendations !== prevProps.includeRecommendations) { - this.setState({ - includeRecommendations - }); - } - } - - // - // Listeners - - onChangeOption = ({ name, value }) => { - this.setState({ - [name]: value - }, () => { - this.props.onChangeOption({ - [name]: value - }); - }); - } - - // - // Render - - render() { - const { - includeRecommendations - } = this.state; - - return ( - - {translate('IncludeRadarrRecommendations')} - - - - ); - } -} - -DiscoverMovieTableOptions.propTypes = { - includeRecommendations: PropTypes.bool.isRequired, - onChangeOption: PropTypes.func.isRequired -}; - -export default DiscoverMovieTableOptions; diff --git a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptionsConnector.js b/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptionsConnector.js deleted file mode 100644 index 9084a7e29..000000000 --- a/frontend/src/DiscoverMovie/Table/DiscoverMovieTableOptionsConnector.js +++ /dev/null @@ -1,24 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { setListMovieOption } from 'Store/Actions/discoverMovieActions'; -import DiscoverMovieTableOptions from './DiscoverMovieTableOptions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.discoverMovie, - (discoverMovie) => { - return discoverMovie.options; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - onChangeOption(payload) { - dispatch(setListMovieOption(payload)); - } - }; -} - -export default connect(createMapStateToProps, createMapDispatchToProps)(DiscoverMovieTableOptions); - diff --git a/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.css b/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.css deleted file mode 100644 index a3e4e82f1..000000000 --- a/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.css +++ /dev/null @@ -1,3 +0,0 @@ -.statusIcon { - width: 20px !important; -} diff --git a/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.js b/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.js deleted file mode 100644 index db8241790..000000000 --- a/frontend/src/DiscoverMovie/Table/ListMovieStatusCell.js +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import VirtualTableRowCell from 'Components/Table/Cells/TableRowCell'; -import { getMovieStatusDetails } from 'Movie/MovieStatus'; -import styles from './ListMovieStatusCell.css'; - -function ListMovieStatusCell(props) { - const { - className, - status, - component: Component, - ...otherProps - } = props; - - const statusDetails = getMovieStatusDetails(status); - - return ( - - - - - ); -} - -ListMovieStatusCell.propTypes = { - className: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - component: PropTypes.elementType -}; - -ListMovieStatusCell.defaultProps = { - className: styles.status, - component: VirtualTableRowCell -}; - -export default ListMovieStatusCell; diff --git a/frontend/src/Movie/Delete/DeleteMovieModalContent.js b/frontend/src/Movie/Delete/DeleteMovieModalContent.js index f4eec2b8a..7153e6d4e 100644 --- a/frontend/src/Movie/Delete/DeleteMovieModalContent.js +++ b/frontend/src/Movie/Delete/DeleteMovieModalContent.js @@ -124,7 +124,7 @@ class DeleteMovieModalContent extends Component { type={inputTypes.CHECK} name="addImportExclusion" value={addImportExclusion} - helpText="Prevent movie from being added to Radarr by lists" + helpText="Prevent movie from being added to Prowlarr by lists" kind={kinds.DANGER} onChange={this.onAddImportExclusionChange} /> diff --git a/frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js b/frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js index 6cb7dd8b8..be9dd10ee 100644 --- a/frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js +++ b/frontend/src/Movie/Delete/DeleteMovieModalContentConnector.js @@ -36,7 +36,7 @@ class DeleteMovieModalContentConnector extends Component { this.props.onModalClose(true); if (this.props.nextMovieRelativePath) { - this.props.push(window.Radarr.urlBase + this.props.nextMovieRelativePath); + this.props.push(window.Prowlarr.urlBase + this.props.nextMovieRelativePath); } } diff --git a/frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js b/frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js deleted file mode 100644 index 90b409b31..000000000 --- a/frontend/src/Movie/Details/Credits/Cast/MovieCastPoster.js +++ /dev/null @@ -1,159 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import { icons } from 'Helpers/Props'; -import MovieHeadshot from 'Movie/MovieHeadshot'; -import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector'; -import translate from 'Utilities/String/translate'; -import styles from '../MovieCreditPoster.css'; - -class MovieCastPoster extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - hasPosterError: false, - isEditImportListModalOpen: false - }; - } - - // - // Listeners - - onEditImportListPress = () => { - this.setState({ isEditImportListModalOpen: true }); - } - - onAddImportListPress = () => { - this.props.onImportListSelect(); - this.setState({ isEditImportListModalOpen: true }); - } - - onEditImportListModalClose = () => { - this.setState({ isEditImportListModalOpen: false }); - } - - onPosterLoad = () => { - if (this.state.hasPosterError) { - this.setState({ hasPosterError: false }); - } - } - - onPosterLoadError = () => { - if (!this.state.hasPosterError) { - this.setState({ hasPosterError: true }); - } - } - - // - // Render - - render() { - const { - personName, - character, - images, - posterWidth, - posterHeight, - importListId - } = this.props; - - const { - hasPosterError - } = this.state; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - const contentStyle = { - width: `${posterWidth}px` - }; - - return ( -
-
- - -
- - - { - hasPosterError && -
- {personName} -
- } -
-
- -
- {personName} -
-
- {character} -
- - -
- ); - } -} - -MovieCastPoster.propTypes = { - tmdbId: PropTypes.number.isRequired, - personName: PropTypes.string.isRequired, - character: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - importListId: PropTypes.number.isRequired, - onImportListSelect: PropTypes.func.isRequired -}; - -MovieCastPoster.defaultProps = { - importListId: 0 -}; - -export default MovieCastPoster; diff --git a/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js b/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js deleted file mode 100644 index 091d1fad8..000000000 --- a/frontend/src/Movie/Details/Credits/Cast/MovieCastPostersConnector.js +++ /dev/null @@ -1,60 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import MovieCreditPosters from '../MovieCreditPosters'; -import MovieCastPoster from './MovieCastPoster'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieCredits.items, - (credits) => { - const cast = _.reduce(credits, (acc, credit) => { - if (credit.type === 'cast') { - acc.push(credit); - } - - return acc; - }, []); - - return { - items: cast - }; - } - ); -} - -const mapDispatchToProps = { - fetchRootFolders -}; - -class MovieCastPostersConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchRootFolders(); - } - - // - // Render - - render() { - - return ( - - ); - } -} - -MovieCastPostersConnector.propTypes = { - fetchRootFolders: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieCastPostersConnector); diff --git a/frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js deleted file mode 100644 index 70ce32984..000000000 --- a/frontend/src/Movie/Details/Credits/Crew/MovieCrewPoster.js +++ /dev/null @@ -1,159 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Label from 'Components/Label'; -import IconButton from 'Components/Link/IconButton'; -import { icons } from 'Helpers/Props'; -import MovieHeadshot from 'Movie/MovieHeadshot'; -import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector'; -import translate from 'Utilities/String/translate'; -import styles from '../MovieCreditPoster.css'; - -class MovieCrewPoster extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - hasPosterError: false, - isEditImportListModalOpen: false - }; - } - - // - // Listeners - - onEditImportListPress = () => { - this.setState({ isEditImportListModalOpen: true }); - } - - onAddImportListPress = () => { - this.props.onImportListSelect(); - this.setState({ isEditImportListModalOpen: true }); - } - - onEditImportListModalClose = () => { - this.setState({ isEditImportListModalOpen: false }); - } - - onPosterLoad = () => { - if (this.state.hasPosterError) { - this.setState({ hasPosterError: false }); - } - } - - onPosterLoadError = () => { - if (!this.state.hasPosterError) { - this.setState({ hasPosterError: true }); - } - } - - // - // Render - - render() { - const { - personName, - job, - images, - posterWidth, - posterHeight, - importListId - } = this.props; - - const { - hasPosterError - } = this.state; - - const elementStyle = { - width: `${posterWidth}px`, - height: `${posterHeight}px` - }; - - const contentStyle = { - width: `${posterWidth}px` - }; - - return ( -
-
- - -
- - - { - hasPosterError && -
- {personName} -
- } -
-
- -
- {personName} -
-
- {job} -
- - -
- ); - } -} - -MovieCrewPoster.propTypes = { - tmdbId: PropTypes.number.isRequired, - personName: PropTypes.string.isRequired, - job: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - posterWidth: PropTypes.number.isRequired, - posterHeight: PropTypes.number.isRequired, - importListId: PropTypes.number.isRequired, - onImportListSelect: PropTypes.func.isRequired -}; - -MovieCrewPoster.defaultProps = { - importListId: 0 -}; - -export default MovieCrewPoster; diff --git a/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js b/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js deleted file mode 100644 index 419fe6835..000000000 --- a/frontend/src/Movie/Details/Credits/Crew/MovieCrewPostersConnector.js +++ /dev/null @@ -1,60 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import MovieCreditPosters from '../MovieCreditPosters'; -import MovieCrewPoster from './MovieCrewPoster'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movieCredits.items, - (credits) => { - const crew = _.reduce(credits, (acc, credit) => { - if (credit.type === 'crew') { - acc.push(credit); - } - - return acc; - }, []); - - return { - items: crew - }; - } - ); -} - -const mapDispatchToProps = { - fetchRootFolders -}; - -class MovieCrewPostersConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchRootFolders(); - } - - // - // Render - - render() { - - return ( - - ); - } -} - -MovieCrewPostersConnector.propTypes = { - fetchRootFolders: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieCrewPostersConnector); diff --git a/frontend/src/Movie/Details/Credits/MovieCreditPoster.css b/frontend/src/Movie/Details/Credits/MovieCreditPoster.css deleted file mode 100644 index 3c0d27827..000000000 --- a/frontend/src/Movie/Details/Credits/MovieCreditPoster.css +++ /dev/null @@ -1,76 +0,0 @@ -$hoverScale: 1.05; - -.content { - transition: all 200ms ease-in; - - &:hover { - z-index: 2; - box-shadow: 0 0 12px $black; - transition: all 200ms ease-in; - - .controls { - opacity: 0.9; - transition: opacity 200ms linear 150ms; - } - } -} - -.posterContainer { - position: relative; -} - -.poster { - position: relative; - display: block; - background-color: $defaultColor; -} - -.overlayTitle { - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; - padding: 5px; - width: 100%; - height: 100%; - color: $offWhite; - text-align: center; - font-size: 20px; -} - -.title { - @add-mixin truncate; - - background-color: #fafbfc; - text-align: center; - font-size: $smallFontSize; -} - -.controls { - position: absolute; - bottom: 10px; - left: 10px; - z-index: 3; - border-radius: 4px; - background-color: #707070; - color: $white; - font-size: $smallFontSize; - opacity: 0; - transition: opacity 0; -} - -.action { - composes: button from '~Components/Link/IconButton.css'; - - &:hover { - color: $radarrYellow; - } -} - -@media only screen and (max-width: $breakpointSmall) { - .container { - padding: 5px; - } -} diff --git a/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js b/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js deleted file mode 100644 index e58741666..000000000 --- a/frontend/src/Movie/Details/Credits/MovieCreditPosterConnector.js +++ /dev/null @@ -1,58 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { selectImportListSchema, setImportListFieldValue, setImportListValue } from 'Store/Actions/settingsActions'; -import createMovieCreditListSelector from 'Store/Selectors/createMovieCreditListSelector'; - -function createMapStateToProps() { - return createMovieCreditListSelector(); -} - -const mapDispatchToProps = { - selectImportListSchema, - setImportListFieldValue, - setImportListValue -}; - -class MovieCreditPosterConnector extends Component { - - // - // Listeners - - onImportListSelect = () => { - this.props.selectImportListSchema({ implementation: 'TMDbPersonImport', presetName: undefined }); - this.props.setImportListFieldValue({ name: 'personId', value: this.props.tmdbId.toString() }); - this.props.setImportListValue({ name: 'name', value: `${this.props.personName} - ${this.props.tmdbId}` }); - } - - // - // Render - - render() { - const { - tmdbId, - component: ItemComponent, - personName - } = this.props; - - return ( - - ); - } -} - -MovieCreditPosterConnector.propTypes = { - tmdbId: PropTypes.number.isRequired, - personName: PropTypes.string.isRequired, - component: PropTypes.elementType.isRequired, - selectImportListSchema: PropTypes.func.isRequired, - setImportListFieldValue: PropTypes.func.isRequired, - setImportListValue: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieCreditPosterConnector); diff --git a/frontend/src/Movie/Details/Credits/MovieCreditPosters.css b/frontend/src/Movie/Details/Credits/MovieCreditPosters.css deleted file mode 100644 index d80f951a0..000000000 --- a/frontend/src/Movie/Details/Credits/MovieCreditPosters.css +++ /dev/null @@ -1,7 +0,0 @@ -.grid { - flex: 1 0 auto; -} - -.container { - padding: 10px; -} diff --git a/frontend/src/Movie/Details/Credits/MovieCreditPosters.js b/frontend/src/Movie/Details/Credits/MovieCreditPosters.js deleted file mode 100644 index cd2f40735..000000000 --- a/frontend/src/Movie/Details/Credits/MovieCreditPosters.js +++ /dev/null @@ -1,232 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Grid, WindowScroller } from 'react-virtualized'; -import Measure from 'Components/Measure'; -import dimensions from 'Styles/Variables/dimensions'; -import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder'; -import MovieCreditPosterConnector from './MovieCreditPosterConnector'; -import styles from './MovieCreditPosters.css'; - -// Poster container dimensions -const columnPadding = parseInt(dimensions.movieIndexColumnPadding); -const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen); - -const additionalColumnCount = { - small: 3, - medium: 2, - large: 1 -}; - -function calculateColumnWidth(width, posterSize, isSmallScreen) { - const maxiumColumnWidth = isSmallScreen ? 172 : 182; - const columns = Math.floor(width / maxiumColumnWidth); - const remainder = width % maxiumColumnWidth; - - if (remainder === 0 && posterSize === 'large') { - return maxiumColumnWidth; - } - - return Math.floor(width / (columns + additionalColumnCount[posterSize])); -} - -function calculateRowHeight(posterHeight, isSmallScreen) { - const titleHeight = 19; - const characterHeight = 19; - - const heights = [ - posterHeight, - titleHeight, - characterHeight, - isSmallScreen ? columnPaddingSmallScreen : columnPadding - ]; - - return heights.reduce((acc, height) => acc + height, 0); -} - -function calculatePosterHeight(posterWidth) { - return Math.ceil((250 / 170) * posterWidth); -} - -class MovieCreditPosters extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - width: 0, - columnWidth: 182, - columnCount: 1, - posterWidth: 162, - posterHeight: 238, - rowHeight: calculateRowHeight(238, props.isSmallScreen) - }; - - this._isInitialized = false; - this._grid = null; - } - - componentDidUpdate(prevProps, prevState) { - const { - items - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - if (this._grid && - (prevState.width !== width || - prevState.columnWidth !== columnWidth || - prevState.columnCount !== columnCount || - prevState.rowHeight !== rowHeight || - hasDifferentItemsOrOrder(prevProps.items, items))) { - // recomputeGridSize also forces Grid to discard its cache of rendered cells - this._grid.recomputeGridSize(); - } - } - - // - // Control - - setGridRef = (ref) => { - this._grid = ref; - } - - calculateGrid = (width = this.state.width, isSmallScreen) => { - - const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding; - const columnWidth = calculateColumnWidth(width, 'small', isSmallScreen); - const columnCount = Math.max(Math.floor(width / columnWidth), 1); - const posterWidth = columnWidth - padding; - const posterHeight = calculatePosterHeight(posterWidth); - const rowHeight = calculateRowHeight(posterHeight, isSmallScreen); - - this.setState({ - width, - columnWidth, - columnCount, - posterWidth, - posterHeight, - rowHeight - }); - } - - cellRenderer = ({ key, rowIndex, columnIndex, style }) => { - const { - items, - itemComponent - } = this.props; - - const { - posterWidth, - posterHeight, - columnCount - } = this.state; - - const movieIdx = rowIndex * columnCount + columnIndex; - const movie = items[movieIdx]; - - if (!movie) { - return null; - } - - return ( -
- -
- ); - } - - // - // Listeners - - onMeasure = ({ width }) => { - this.calculateGrid(width, this.props.isSmallScreen); - } - - // - // Render - - render() { - const { - items - } = this.props; - - const { - width, - columnWidth, - columnCount, - rowHeight - } = this.state; - - const rowCount = Math.ceil(items.length / columnCount); - - return ( - - - {({ height, registerChild, onChildScroll, scrollTop }) => { - if (!height) { - return
; - } - - return ( -
- -
- ); - } - } - - - ); - } -} - -MovieCreditPosters.propTypes = { - items: PropTypes.arrayOf(PropTypes.object).isRequired, - itemComponent: PropTypes.elementType.isRequired, - isSmallScreen: PropTypes.bool.isRequired -}; - -export default MovieCreditPosters; diff --git a/frontend/src/Movie/Details/MovieAlternateTitles.css b/frontend/src/Movie/Details/MovieAlternateTitles.css deleted file mode 100644 index 1af1ae68b..000000000 --- a/frontend/src/Movie/Details/MovieAlternateTitles.css +++ /dev/null @@ -1,3 +0,0 @@ -.alternateTitle { - white-space: nowrap; -} diff --git a/frontend/src/Movie/Details/MovieAlternateTitles.js b/frontend/src/Movie/Details/MovieAlternateTitles.js deleted file mode 100644 index 5b0fdaeaa..000000000 --- a/frontend/src/Movie/Details/MovieAlternateTitles.js +++ /dev/null @@ -1,28 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import styles from './MovieAlternateTitles.css'; - -function MovieAlternateTitles({ alternateTitles }) { - return ( -
    - { - alternateTitles.filter((x, i, a) => a.indexOf(x) === i).map((alternateTitle) => { - return ( -
  • - {alternateTitle} -
  • - ); - }) - } -
- ); -} - -MovieAlternateTitles.propTypes = { - alternateTitles: PropTypes.arrayOf(PropTypes.string).isRequired -}; - -export default MovieAlternateTitles; diff --git a/frontend/src/Movie/Details/MovieDetails.css b/frontend/src/Movie/Details/MovieDetails.css deleted file mode 100644 index 5806d607f..000000000 --- a/frontend/src/Movie/Details/MovieDetails.css +++ /dev/null @@ -1,223 +0,0 @@ -.innerContentBody { - padding: 0; -} - -.header { - position: relative; - width: 100%; - height: 350px; -} - -.errorMessage { - margin-top: 20px; - text-align: center; - font-size: 20px; -} - -.backdrop { - position: absolute; - z-index: -1; - width: 100%; - height: 100%; - background-size: cover; -} - -.backdropOverlay { - position: absolute; - width: 100%; - height: 100%; - background: $black; - opacity: 0.7; -} - -.headerContent { - display: flex; - padding: 30px; - width: 100%; - height: 100%; - color: $white; -} - -.poster { - flex-shrink: 0; - margin-right: 35px; - width: 200px; - height: 294px; -} - -.info { - display: flex; - flex-direction: column; - flex-grow: 1; - overflow: hidden; -} - -.titleRow { - position: relative; - display: flex; - justify-content: space-between; - flex: 0 0 auto; -} - -.titleContainer { - display: flex; - margin-bottom: 5px; -} - -.title { - font-weight: 300; - font-size: 50px; - line-height: 60px; -} - -.toggleMonitoredContainer { - align-self: center; - margin-right: 10px; -} - -.monitorToggleButton { - composes: toggleButton from '~Components/MonitorToggleButton.css'; - - width: 40px; - - &:hover { - color: $iconButtonHoverLightColor; - } -} - -.alternateTitlesIconContainer { - align-self: flex-end; - margin-left: 20px; -} - -.filterIcon { - float: right; -} - -.movieNavigationButtons { - position: absolute; - right: 0; - white-space: nowrap; -} - -.movieNavigationButton { - composes: button from '~Components/Link/IconButton.css'; - - margin-left: 5px; - width: 30px; - color: #e1e2e3; - white-space: nowrap; - - &:hover { - color: $iconButtonHoverLightColor; - } -} - -.details { - margin-bottom: 8px; - padding-left: 7px; - font-weight: 300; - font-size: 20px; -} - -.links, -.rating, -.year, -.runtime { - margin-right: 14px; -} - -.certification { - margin-right: 15px; - padding: 0 5px; - border: 1px solid; - border-radius: 5px; -} - -.detailsLabel { - composes: label from '~Components/Label.css'; - - margin: 5px 10px 5px 0; -} - -.detailsInfoLabel { - composes: label from '~Components/InfoLabel.css'; - - margin: 5px 10px 5px 0; -} - -.path, -.sizeOnDisk, -.qualityProfileName, -.statusName, -.studio, -.collection { - font-weight: 300; - font-size: 17px; -} - -.overview { - flex: 1 0 auto; - margin-top: 8px; - padding-left: 7px; - min-height: 0; - font-size: $intermediateFontSize; -} - -.contentContainer { - padding: 20px; -} - -.tabList { - margin: 0; - padding: 0; - border-bottom: 1px solid $lightGray; -} - -.tab { - position: relative; - bottom: -1px; - display: inline-block; - padding: 6px 12px; - border: 1px solid transparent; - border-top: none; - list-style: none; - cursor: pointer; -} - -.selectedTab { - border-bottom: 4px solid $linkColor; -} - -.tabContent { - margin-top: 20px; -} - -@media only screen and (max-width: $breakpointSmall) { - .contentContainer { - padding: 20px 0; - } - - .headerContent { - padding: 15px; - } -} - -@media only screen and (max-width: $breakpointLarge) { - .poster, - .movieNavigationButtons { - display: none; - } - - .certification, - .links, - .rating, - .year, - .runtime { - margin-right: 9px; - } - - .details { - font-size: 19px; - } -} diff --git a/frontend/src/Movie/Details/MovieDetails.js b/frontend/src/Movie/Details/MovieDetails.js deleted file mode 100644 index 89c1d7ddf..000000000 --- a/frontend/src/Movie/Details/MovieDetails.js +++ /dev/null @@ -1,807 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Tab, TabList, TabPanel, Tabs } from 'react-tabs'; -import TextTruncate from 'react-text-truncate'; -import HeartRating from 'Components/HeartRating'; -import Icon from 'Components/Icon'; -import InfoLabel from 'Components/InfoLabel'; -import IconButton from 'Components/Link/IconButton'; -import Marquee from 'Components/Marquee'; -import Measure from 'Components/Measure'; -import MonitorToggleButton from 'Components/MonitorToggleButton'; -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 Popover from 'Components/Tooltip/Popover'; -import Tooltip from 'Components/Tooltip/Tooltip'; -import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props'; -import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; -import InteractiveSearchFilterMenuConnector from 'InteractiveSearch/InteractiveSearchFilterMenuConnector'; -import InteractiveSearchTable from 'InteractiveSearch/InteractiveSearchTable'; -import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; -import MovieHistoryTable from 'Movie/History/MovieHistoryTable'; -import MoviePoster from 'Movie/MoviePoster'; -import MovieFileEditorTable from 'MovieFile/Editor/MovieFileEditorTable'; -import ExtraFileTable from 'MovieFile/Extras/ExtraFileTable'; -import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector'; -import QualityProfileNameConnector from 'Settings/Profiles/Quality/QualityProfileNameConnector'; -import fonts from 'Styles/Variables/fonts'; -import * as keyCodes from 'Utilities/Constants/keyCodes'; -import formatRuntime from 'Utilities/Date/formatRuntime'; -import formatBytes from 'Utilities/Number/formatBytes'; -import translate from 'Utilities/String/translate'; -import selectAll from 'Utilities/Table/selectAll'; -import toggleSelected from 'Utilities/Table/toggleSelected'; -import MovieCollectionConnector from './../MovieCollectionConnector'; -import MovieCastPostersConnector from './Credits/Cast/MovieCastPostersConnector'; -import MovieCrewPostersConnector from './Credits/Crew/MovieCrewPostersConnector'; -import MovieDetailsLinks from './MovieDetailsLinks'; -import MovieReleaseDatesConnector from './MovieReleaseDatesConnector'; -import MovieStatusLabel from './MovieStatusLabel'; -import MovieTagsConnector from './MovieTagsConnector'; -import MovieTitlesTable from './Titles/MovieTitlesTable'; -import styles from './MovieDetails.css'; - -const defaultFontSize = parseInt(fonts.defaultFontSize); -const lineHeight = parseFloat(fonts.lineHeight); - -function getFanartUrl(images) { - const fanartImage = _.find(images, { coverType: 'fanart' }); - if (fanartImage) { - // Remove protocol - return fanartImage.url.replace(/^https?:/, ''); - } -} - -function getExpandedState(newState) { - return { - allExpanded: newState.allSelected, - allCollapsed: newState.allUnselected, - expandedState: newState.selectedState - }; -} - -class MovieDetails extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isOrganizeModalOpen: false, - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: false, - isInteractiveImportModalOpen: false, - allExpanded: false, - allCollapsed: false, - expandedState: {}, - selectedTabIndex: 0, - overviewHeight: 0, - titleWidth: 0 - }; - } - - componentDidMount() { - window.addEventListener('touchstart', this.onTouchStart); - window.addEventListener('touchend', this.onTouchEnd); - window.addEventListener('touchcancel', this.onTouchCancel); - window.addEventListener('touchmove', this.onTouchMove); - window.addEventListener('keyup', this.onKeyUp); - } - - componentWillUnmount() { - window.removeEventListener('touchstart', this.onTouchStart); - window.removeEventListener('touchend', this.onTouchEnd); - window.removeEventListener('touchcancel', this.onTouchCancel); - window.removeEventListener('touchmove', this.onTouchMove); - window.removeEventListener('keyup', this.onKeyUp); - } - - // - // Listeners - - onOrganizePress = () => { - this.setState({ isOrganizeModalOpen: true }); - } - - onOrganizeModalClose = () => { - this.setState({ isOrganizeModalOpen: false }); - } - - onManageEpisodesPress = () => { - this.setState({ isManageEpisodesOpen: true }); - } - - onInteractiveImportPress = () => { - this.setState({ isInteractiveImportModalOpen: true }); - } - - onInteractiveImportModalClose = () => { - this.setState({ isInteractiveImportModalOpen: false }); - } - - onEditMoviePress = () => { - this.setState({ isEditMovieModalOpen: true }); - } - - onEditMovieModalClose = () => { - this.setState({ isEditMovieModalOpen: false }); - } - - onDeleteMoviePress = () => { - this.setState({ - isEditMovieModalOpen: false, - isDeleteMovieModalOpen: true - }); - } - - onDeleteMovieModalClose = () => { - this.setState({ isDeleteMovieModalOpen: false }); - } - - onExpandAllPress = () => { - const { - allExpanded, - expandedState - } = this.state; - - this.setState(getExpandedState(selectAll(expandedState, !allExpanded))); - } - - onExpandPress = (seasonNumber, isExpanded) => { - this.setState((state) => { - const convertedState = { - allSelected: state.allExpanded, - allUnselected: state.allCollapsed, - selectedState: state.expandedState - }; - - const newState = toggleSelected(convertedState, [], seasonNumber, isExpanded, false); - - return getExpandedState(newState); - }); - } - - onMeasure = ({ height }) => { - this.setState({ overviewHeight: height }); - } - - onTitleMeasure = ({ width }) => { - this.setState({ titleWidth: width }); - } - - onKeyUp = (event) => { - if (event.path.length === 4) { - if (event.keyCode === keyCodes.LEFT_ARROW) { - this.props.onGoToMovie(this.props.previousMovie.titleSlug); - } - if (event.keyCode === keyCodes.RIGHT_ARROW) { - this.props.onGoToMovie(this.props.nextMovie.titleSlug); - } - } - } - - onTouchStart = (event) => { - const touches = event.touches; - const touchStart = touches[0].pageX; - const touchY = touches[0].pageY; - - // Only change when swipe is on header, we need horizontal scroll on tables - if (touchY > 470) { - return; - } - - if (touches.length !== 1) { - return; - } - - if ( - touchStart < 50 || - this.props.isSidebarVisible || - this.state.isEventModalOpen - ) { - return; - } - - this._touchStart = touchStart; - } - - onTouchEnd = (event) => { - const touches = event.changedTouches; - const currentTouch = touches[0].pageX; - - if (!this._touchStart) { - return; - } - - if (currentTouch > this._touchStart && currentTouch - this._touchStart > 100) { - this.props.onGoToMovie(this.props.previousMovie.titleSlug); - } else if (currentTouch < this._touchStart && this._touchStart - currentTouch > 100) { - this.props.onGoToMovie(this.props.nextMovie.titleSlug); - } - - this._touchStart = null; - } - - onTouchCancel = (event) => { - this._touchStart = null; - } - - onTouchMove = (event) => { - if (!this._touchStart) { - return; - } - } - - onTabSelect = (index, lastIndex) => { - this.setState({ selectedTabIndex: index }); - } - - // - // Render - - render() { - const { - id, - tmdbId, - imdbId, - title, - originalTitle, - year, - inCinemas, - physicalRelease, - digitalRelease, - runtime, - certification, - ratings, - path, - sizeOnDisk, - qualityProfileId, - monitored, - studio, - collection, - overview, - youTubeTrailerId, - isAvailable, - images, - tags, - isSaving, - isRefreshing, - isSearching, - isFetching, - isSmallScreen, - movieFilesError, - movieCreditsError, - extraFilesError, - hasMovieFiles, - previousMovie, - nextMovie, - onMonitorTogglePress, - onRefreshPress, - onSearchPress, - queueDetails, - movieRuntimeFormat - } = this.props; - - const { - isOrganizeModalOpen, - isEditMovieModalOpen, - isDeleteMovieModalOpen, - isInteractiveImportModalOpen, - overviewHeight, - titleWidth, - selectedTabIndex - } = this.state; - - const marqueeWidth = isSmallScreen ? titleWidth : (titleWidth - 150); - - return ( - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- -
- - -
- -
-
-
- -
- -
- - - - -
- - - -
- - - -
-
- { - !!certification && - - {certification} - - } - - { - year > 0 && - - - } - position={tooltipPositions.BOTTOM} - /> - - } - - { - !!runtime && - - {formatRuntime(runtime, movieRuntimeFormat)} - - } - - { - !!ratings && - - - - } - - { - - - } - tooltip={ - - } - position={tooltipPositions.BOTTOM} - /> - - } - - { - !!tags.length && - - - } - tooltip={ - - } - position={tooltipPositions.BOTTOM} - /> - - } -
-
- -
- - - {path} - - - - - - - - - - - - { - - } - - - - - - { - formatBytes(sizeOnDisk || 0) - } - - - - { - !!collection && - -
- -
-
- } - - { - !!studio && !isSmallScreen && - - - {studio} - - - } -
- - -
- -
-
- - - - -
- { - !isFetching && movieFilesError && -
- {translate('LoadingMovieFilesFailed')} -
- } - - { - !isFetching && movieCreditsError && -
- {translate('LoadingMovieCreditsFailed')} -
- } - - { - !isFetching && extraFilesError && -
- {translate('LoadingMovieExtraFilesFailed')} -
- } - - - - - {translate('History')} - - - - {translate('Search')} - - - - {translate('Files')} - - - - {translate('Titles')} - - - - {translate('Cast')} - - - - {translate('Crew')} - - - { - selectedTabIndex === 1 && -
- -
- } - -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - - - - - - ); - } -} - -MovieDetails.propTypes = { - id: PropTypes.number.isRequired, - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - title: PropTypes.string.isRequired, - originalTitle: PropTypes.string, - year: PropTypes.number.isRequired, - runtime: PropTypes.number.isRequired, - certification: PropTypes.string, - ratings: PropTypes.object.isRequired, - path: PropTypes.string.isRequired, - sizeOnDisk: PropTypes.number.isRequired, - qualityProfileId: PropTypes.number.isRequired, - monitored: PropTypes.bool.isRequired, - status: PropTypes.string.isRequired, - studio: PropTypes.string, - collection: PropTypes.object, - youTubeTrailerId: PropTypes.string, - isAvailable: PropTypes.bool.isRequired, - inCinemas: PropTypes.string, - physicalRelease: PropTypes.string, - digitalRelease: PropTypes.string, - overview: PropTypes.string.isRequired, - images: PropTypes.arrayOf(PropTypes.object).isRequired, - alternateTitles: PropTypes.arrayOf(PropTypes.string).isRequired, - tags: PropTypes.arrayOf(PropTypes.number).isRequired, - isSaving: PropTypes.bool.isRequired, - isRefreshing: PropTypes.bool.isRequired, - isSearching: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - isSidebarVisible: PropTypes.bool.isRequired, - movieFilesError: PropTypes.object, - movieCreditsError: PropTypes.object, - extraFilesError: PropTypes.object, - hasMovieFiles: PropTypes.bool.isRequired, - previousMovie: PropTypes.object.isRequired, - nextMovie: PropTypes.object.isRequired, - onMonitorTogglePress: PropTypes.func.isRequired, - onRefreshPress: PropTypes.func.isRequired, - onSearchPress: PropTypes.func.isRequired, - onGoToMovie: PropTypes.func.isRequired, - queueDetails: PropTypes.object, - movieRuntimeFormat: PropTypes.string.isRequired -}; - -MovieDetails.defaultProps = { - tags: [], - isSaving: false, - sizeOnDisk: 0 -}; - -export default MovieDetails; diff --git a/frontend/src/Movie/Details/MovieDetailsConnector.js b/frontend/src/Movie/Details/MovieDetailsConnector.js deleted file mode 100644 index 2ab6b9167..000000000 --- a/frontend/src/Movie/Details/MovieDetailsConnector.js +++ /dev/null @@ -1,370 +0,0 @@ -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 * as commandNames from 'Commands/commandNames'; -import { executeCommand } from 'Store/Actions/commandActions'; -import { clearExtraFiles, fetchExtraFiles } from 'Store/Actions/extraFileActions'; -import { toggleMovieMonitored } from 'Store/Actions/movieActions'; -import { clearMovieBlacklist, fetchMovieBlacklist } from 'Store/Actions/movieBlacklistActions'; -import { clearMovieCredits, fetchMovieCredits } from 'Store/Actions/movieCreditsActions'; -import { clearMovieFiles, fetchMovieFiles } from 'Store/Actions/movieFileActions'; -import { clearMovieHistory, fetchMovieHistory } from 'Store/Actions/movieHistoryActions'; -import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions'; -import { cancelFetchReleases, clearReleases } from 'Store/Actions/releaseActions'; -import { fetchImportListSchema } from 'Store/Actions/settingsActions'; -import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector'; -import createCommandsSelector from 'Store/Selectors/createCommandsSelector'; -import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector'; -import { findCommand, isCommandExecuting } from 'Utilities/Command'; -import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; -import MovieDetails from './MovieDetails'; - -const selectMovieFiles = createSelector( - (state) => state.movieFiles, - (movieFiles) => { - const { - items, - isFetching, - isPopulated, - error - } = movieFiles; - - const hasMovieFiles = !!items.length; - - const sizeOnDisk = items.map((item) => item.size).reduce((prev, curr) => prev + curr, 0); - - return { - isMovieFilesFetching: isFetching, - isMovieFilesPopulated: isPopulated, - movieFilesError: error, - hasMovieFiles, - sizeOnDisk - }; - } -); - -const selectMovieCredits = createSelector( - (state) => state.movieCredits, - (movieCredits) => { - const { - isFetching, - isPopulated, - error - } = movieCredits; - - return { - isMovieCreditsFetching: isFetching, - isMovieCreditsPopulated: isPopulated, - movieCreditsError: error - }; - } -); - -const selectExtraFiles = createSelector( - (state) => state.extraFiles, - (extraFiles) => { - const { - isFetching, - isPopulated, - error - } = extraFiles; - - return { - isExtraFilesFetching: isFetching, - isExtraFilesPopulated: isPopulated, - extraFilesError: error - }; - } -); - -function createMapStateToProps() { - return createSelector( - (state, { titleSlug }) => titleSlug, - selectMovieFiles, - selectMovieCredits, - selectExtraFiles, - createAllMoviesSelector(), - createCommandsSelector(), - createDimensionsSelector(), - (state) => state.queue.details, - (state) => state.app.isSidebarVisible, - (state) => state.settings.ui.item.movieRuntimeFormat, - (titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, queueDetails, isSidebarVisible, movieRuntimeFormat) => { - const sortedMovies = _.orderBy(allMovies, 'sortTitle'); - const movieIndex = _.findIndex(sortedMovies, { titleSlug }); - const movie = sortedMovies[movieIndex]; - - if (!movie) { - return {}; - } - - const { - isMovieFilesFetching, - isMovieFilesPopulated, - movieFilesError, - hasMovieFiles, - sizeOnDisk - } = movieFiles; - - const { - isMovieCreditsFetching, - isMovieCreditsPopulated, - movieCreditsError - } = movieCredits; - - const { - isExtraFilesFetching, - isExtraFilesPopulated, - extraFilesError - } = extraFiles; - - const previousMovie = sortedMovies[movieIndex - 1] || _.last(sortedMovies); - const nextMovie = sortedMovies[movieIndex + 1] || _.first(sortedMovies); - const isMovieRefreshing = isCommandExecuting(findCommand(commands, { name: commandNames.REFRESH_MOVIE, movieIds: [movie.id] })); - const movieRefreshingCommand = findCommand(commands, { name: commandNames.REFRESH_MOVIE }); - const allMoviesRefreshing = ( - isCommandExecuting(movieRefreshingCommand) && - !movieRefreshingCommand.body.movieId - ); - const isRefreshing = isMovieRefreshing || allMoviesRefreshing; - const isSearching = isCommandExecuting(findCommand(commands, { name: commandNames.MOVIE_SEARCH, movieIds: [movie.id] })); - const isRenamingFiles = isCommandExecuting(findCommand(commands, { name: commandNames.RENAME_FILES, movieId: movie.id })); - const isRenamingMovieCommand = findCommand(commands, { name: commandNames.RENAME_MOVIE }); - const isRenamingMovie = ( - isCommandExecuting(isRenamingMovieCommand) && - isRenamingMovieCommand.body.movieIds.indexOf(movie.id) > -1 - ); - - const isFetching = isMovieFilesFetching || isMovieCreditsFetching || isExtraFilesFetching; - const isPopulated = isMovieFilesPopulated && isMovieCreditsPopulated && isExtraFilesPopulated; - const alternateTitles = _.reduce(movie.alternateTitles, (acc, alternateTitle) => { - acc.push(alternateTitle.title); - return acc; - }, []); - - return { - ...movie, - alternateTitles, - isMovieRefreshing, - allMoviesRefreshing, - isRefreshing, - isSearching, - isRenamingFiles, - isRenamingMovie, - isFetching, - isPopulated, - movieFilesError, - movieCreditsError, - extraFilesError, - hasMovieFiles, - sizeOnDisk, - previousMovie, - nextMovie, - isSmallScreen: dimensions.isSmallScreen, - isSidebarVisible, - queueDetails, - movieRuntimeFormat - }; - } - ); -} - -function createMapDispatchToProps(dispatch, props) { - return { - dispatchFetchMovieFiles({ movieId }) { - dispatch(fetchMovieFiles({ movieId })); - }, - dispatchClearMovieFiles() { - dispatch(clearMovieFiles()); - }, - dispatchFetchMovieHistory({ movieId }) { - dispatch(fetchMovieHistory({ movieId })); - }, - dispatchClearMovieHistory() { - dispatch(clearMovieHistory()); - }, - dispatchFetchMovieCredits({ movieId }) { - dispatch(fetchMovieCredits({ movieId })); - }, - dispatchClearMovieCredits() { - dispatch(clearMovieCredits()); - }, - dispatchFetchExtraFiles({ movieId }) { - dispatch(fetchExtraFiles({ movieId })); - }, - dispatchClearExtraFiles() { - dispatch(clearExtraFiles()); - }, - dispatchClearReleases() { - dispatch(clearReleases()); - }, - dispatchCancelFetchReleases() { - dispatch(cancelFetchReleases()); - }, - dispatchFetchQueueDetails({ movieId }) { - dispatch(fetchQueueDetails({ movieId })); - }, - dispatchClearQueueDetails() { - dispatch(clearQueueDetails()); - }, - dispatchFetchImportListSchema() { - dispatch(fetchImportListSchema()); - }, - dispatchToggleMovieMonitored(payload) { - dispatch(toggleMovieMonitored(payload)); - }, - dispatchExecuteCommand(payload) { - dispatch(executeCommand(payload)); - }, - onGoToMovie(titleSlug) { - dispatch(push(`${window.Radarr.urlBase}/movie/${titleSlug}`)); - }, - dispatchFetchMovieBlacklist({ movieId }) { - dispatch(fetchMovieBlacklist({ movieId })); - }, - dispatchClearMovieBlacklist() { - dispatch(clearMovieBlacklist()); - } - }; -} - -class MovieDetailsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - registerPagePopulator(this.populate); - this.populate(); - } - - componentDidUpdate(prevProps) { - const { - id, - isMovieRefreshing, - allMoviesRefreshing, - isRenamingFiles, - isRenamingMovie - } = this.props; - - if ( - (prevProps.isMovieRefreshing && !isMovieRefreshing) || - (prevProps.allMoviesRefreshing && !allMoviesRefreshing) || - (prevProps.isRenamingFiles && !isRenamingFiles) || - (prevProps.isRenamingMovie && !isRenamingMovie) - ) { - this.populate(); - } - - // If the id has changed we need to clear the episodes/episode - // files and fetch from the server. - - if (prevProps.id !== id) { - this.unpopulate(); - this.populate(); - } - } - - componentWillUnmount() { - unregisterPagePopulator(this.populate); - this.unpopulate(); - } - - // - // Control - - populate = () => { - const movieId = this.props.id; - - this.props.dispatchFetchMovieFiles({ movieId }); - this.props.dispatchFetchMovieBlacklist({ movieId }); - this.props.dispatchFetchMovieHistory({ movieId }); - this.props.dispatchFetchExtraFiles({ movieId }); - this.props.dispatchFetchMovieCredits({ movieId }); - this.props.dispatchFetchQueueDetails({ movieId }); - this.props.dispatchFetchImportListSchema(); - } - - unpopulate = () => { - this.props.dispatchCancelFetchReleases(); - this.props.dispatchClearMovieBlacklist(); - this.props.dispatchClearMovieFiles(); - this.props.dispatchClearMovieHistory(); - this.props.dispatchClearExtraFiles(); - this.props.dispatchClearMovieCredits(); - this.props.dispatchClearQueueDetails(); - this.props.dispatchClearReleases(); - } - - // - // Listeners - - onMonitorTogglePress = (monitored) => { - this.props.dispatchToggleMovieMonitored({ - movieId: this.props.id, - monitored - }); - } - - onRefreshPress = () => { - this.props.dispatchExecuteCommand({ - name: commandNames.REFRESH_MOVIE, - movieIds: [this.props.id] - }); - } - - onSearchPress = () => { - this.props.dispatchExecuteCommand({ - name: commandNames.MOVIE_SEARCH, - movieIds: [this.props.id] - }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -MovieDetailsConnector.propTypes = { - id: PropTypes.number.isRequired, - titleSlug: PropTypes.string.isRequired, - isMovieRefreshing: PropTypes.bool.isRequired, - allMoviesRefreshing: PropTypes.bool.isRequired, - isRefreshing: PropTypes.bool.isRequired, - isRenamingFiles: PropTypes.bool.isRequired, - isRenamingMovie: PropTypes.bool.isRequired, - isSmallScreen: PropTypes.bool.isRequired, - dispatchFetchMovieFiles: PropTypes.func.isRequired, - dispatchClearMovieFiles: PropTypes.func.isRequired, - dispatchFetchMovieHistory: PropTypes.func.isRequired, - dispatchClearMovieHistory: PropTypes.func.isRequired, - dispatchFetchExtraFiles: PropTypes.func.isRequired, - dispatchClearExtraFiles: PropTypes.func.isRequired, - dispatchFetchMovieCredits: PropTypes.func.isRequired, - dispatchClearMovieCredits: PropTypes.func.isRequired, - dispatchClearReleases: PropTypes.func.isRequired, - dispatchCancelFetchReleases: PropTypes.func.isRequired, - dispatchToggleMovieMonitored: PropTypes.func.isRequired, - dispatchFetchQueueDetails: PropTypes.func.isRequired, - dispatchClearQueueDetails: PropTypes.func.isRequired, - dispatchFetchImportListSchema: PropTypes.func.isRequired, - dispatchExecuteCommand: PropTypes.func.isRequired, - dispatchFetchMovieBlacklist: PropTypes.func.isRequired, - dispatchClearMovieBlacklist: PropTypes.func.isRequired, - onGoToMovie: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, createMapDispatchToProps)(MovieDetailsConnector); diff --git a/frontend/src/Movie/Details/MovieDetailsLinks.css b/frontend/src/Movie/Details/MovieDetailsLinks.css deleted file mode 100644 index d37a082a1..000000000 --- a/frontend/src/Movie/Details/MovieDetailsLinks.css +++ /dev/null @@ -1,13 +0,0 @@ -.links { - margin: 0; -} - -.link { - white-space: nowrap; -} - -.linkLabel { - composes: label from '~Components/Label.css'; - - cursor: pointer; -} diff --git a/frontend/src/Movie/Details/MovieDetailsLinks.js b/frontend/src/Movie/Details/MovieDetailsLinks.js deleted file mode 100644 index cdeab6eec..000000000 --- a/frontend/src/Movie/Details/MovieDetailsLinks.js +++ /dev/null @@ -1,100 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import Link from 'Components/Link/Link'; -import { kinds, sizes } from 'Helpers/Props'; -import styles from './MovieDetailsLinks.css'; - -function MovieDetailsLinks(props) { - const { - tmdbId, - imdbId, - youTubeTrailerId - } = props; - - return ( -
- - - - - - - - - { - !!imdbId && - - - - } - - { - !!imdbId && - - - - } - - { - !!youTubeTrailerId && - - - - } -
- ); -} - -MovieDetailsLinks.propTypes = { - tmdbId: PropTypes.number.isRequired, - imdbId: PropTypes.string, - youTubeTrailerId: PropTypes.string -}; - -export default MovieDetailsLinks; diff --git a/frontend/src/Movie/Details/MovieDetailsPageConnector.js b/frontend/src/Movie/Details/MovieDetailsPageConnector.js deleted file mode 100644 index 7a3ba0d29..000000000 --- a/frontend/src/Movie/Details/MovieDetailsPageConnector.js +++ /dev/null @@ -1,118 +0,0 @@ -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 LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import NotFound from 'Components/NotFound'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import getErrorMessage from 'Utilities/Object/getErrorMessage'; -import translate from 'Utilities/String/translate'; -import MovieDetailsConnector from './MovieDetailsConnector'; -import styles from './MovieDetails.css'; - -function createMapStateToProps() { - return createSelector( - (state, { match }) => match, - (state) => state.movies, - (match, movies) => { - const titleSlug = match.params.titleSlug; - const { - isFetching, - isPopulated, - error, - items - } = movies; - - const movieIndex = _.findIndex(items, { titleSlug }); - - if (movieIndex > -1) { - return { - isFetching, - isPopulated, - titleSlug - }; - } - - return { - isFetching, - isPopulated, - error - }; - } - ); -} - -const mapDispatchToProps = { - push -}; - -class MovieDetailsPageConnector extends Component { - - // - // Lifecycle - - componentDidUpdate(prevProps) { - if (!this.props.titleSlug) { - this.props.push(`${window.Radarr.urlBase}/`); - return; - } - } - - // - // Render - - render() { - const { - titleSlug, - isFetching, - isPopulated, - error - } = this.props; - - if (isFetching && !isPopulated) { - return ( - - - - - - ); - } - - if (!isFetching && !!error) { - return ( -
- {getErrorMessage(error, 'Failed to load movie from API')} -
- ); - } - - if (!titleSlug) { - return ( - - ); - } - - return ( - - ); - } -} - -MovieDetailsPageConnector.propTypes = { - titleSlug: PropTypes.string, - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - match: PropTypes.shape({ params: PropTypes.shape({ titleSlug: PropTypes.string.isRequired }).isRequired }).isRequired, - push: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieDetailsPageConnector); diff --git a/frontend/src/Movie/Details/MovieReleaseDates.css b/frontend/src/Movie/Details/MovieReleaseDates.css deleted file mode 100644 index 7b50624cc..000000000 --- a/frontend/src/Movie/Details/MovieReleaseDates.css +++ /dev/null @@ -1,6 +0,0 @@ -.dateIcon { - display: inline-block; - padding-right: 10px; - width: 30px; - text-align: center; -} diff --git a/frontend/src/Movie/Details/MovieReleaseDates.js b/frontend/src/Movie/Details/MovieReleaseDates.js deleted file mode 100644 index 4679faf56..000000000 --- a/frontend/src/Movie/Details/MovieReleaseDates.js +++ /dev/null @@ -1,67 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Icon from 'Components/Icon'; -import { icons } from 'Helpers/Props'; -import getRelativeDate from 'Utilities/Date/getRelativeDate'; -import styles from './MovieReleaseDates.css'; - -function MovieReleaseDates(props) { - const { - showRelativeDates, - shortDateFormat, - timeFormat, - inCinemas, - physicalRelease, - digitalRelease - } = props; - - return ( -
- { - !!inCinemas && -
-
- -
- {getRelativeDate(inCinemas, shortDateFormat, showRelativeDates, { timeFormat, timeForToday: false })} -
- } - { - !!digitalRelease && -
-
- -
- {getRelativeDate(digitalRelease, shortDateFormat, showRelativeDates, { timeFormat, timeForToday: false })} -
- } - { - !!physicalRelease && -
-
- -
- {getRelativeDate(physicalRelease, shortDateFormat, showRelativeDates, { timeFormat, timeForToday: false })} -
- } -
- ); -} - -MovieReleaseDates.propTypes = { - showRelativeDates: PropTypes.bool.isRequired, - shortDateFormat: PropTypes.string.isRequired, - longDateFormat: PropTypes.string.isRequired, - timeFormat: PropTypes.string.isRequired, - inCinemas: PropTypes.string, - physicalRelease: PropTypes.string, - digitalRelease: PropTypes.string -}; - -export default MovieReleaseDates; diff --git a/frontend/src/Movie/Details/MovieReleaseDatesConnector.js b/frontend/src/Movie/Details/MovieReleaseDatesConnector.js deleted file mode 100644 index 9c60c374b..000000000 --- a/frontend/src/Movie/Details/MovieReleaseDatesConnector.js +++ /dev/null @@ -1,20 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; -import MovieReleaseDates from './MovieReleaseDates'; - -function createMapStateToProps() { - return createSelector( - createUISettingsSelector(), - (uiSettings) => { - return { - showRelativeDates: uiSettings.showRelativeDates, - shortDateFormat: uiSettings.shortDateFormat, - longDateFormat: uiSettings.longDateFormat, - timeFormat: uiSettings.timeFormat - }; - } - ); -} - -export default connect(createMapStateToProps, null)(MovieReleaseDates); diff --git a/frontend/src/Movie/Details/MovieStatusLabel.css b/frontend/src/Movie/Details/MovieStatusLabel.css deleted file mode 100644 index fff54bd98..000000000 --- a/frontend/src/Movie/Details/MovieStatusLabel.css +++ /dev/null @@ -1,24 +0,0 @@ -.missing { - padding-left: 2px; - border-left: 4px solid $dangerColor; -} - -.downloaded { - padding-left: 2px; - border-left: 4px solid $successColor; -} - -.notAvailable { - padding-left: 2px; - border-left: 4px solid $primaryColor; -} - -.unmonitored { - padding-left: 2px; - border-left: 4px solid $warningColor; -} - -.queue { - padding-left: 2px; - border-left: 4px solid $queueColor; -} diff --git a/frontend/src/Movie/Details/MovieStatusLabel.js b/frontend/src/Movie/Details/MovieStatusLabel.js deleted file mode 100644 index c605bb91d..000000000 --- a/frontend/src/Movie/Details/MovieStatusLabel.js +++ /dev/null @@ -1,70 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import getQueueStatusText from 'Utilities/Movie/getQueueStatusText'; -import firstCharToUpper from 'Utilities/String/firstCharToUpper'; -import translate from 'Utilities/String/translate'; -import styles from './MovieStatusLabel.css'; - -function getMovieStatus(hasFile, isMonitored, isAvailable, queueDetails = false) { - - if (queueDetails.items[0]) { - const queueStatus = queueDetails.items[0].status; - const queueState = queueDetails.items[0].trackedDownloadStatus; - const queueStatusText = getQueueStatusText(queueStatus, queueState); - - if (queueStatusText) { - return queueStatusText; - } - } - - if (hasFile) { - return 'downloaded'; - } - - if (!isMonitored) { - return 'unmonitored'; - } - - if (isAvailable && !hasFile) { - return 'missing'; - } - - return 'notAvailable'; -} - -function MovieStatusLabel(props) { - const { - hasMovieFiles, - monitored, - isAvailable, - queueDetails - } = props; - - const status = getMovieStatus(hasMovieFiles, monitored, isAvailable, queueDetails); - let statusClass = status; - - if (queueDetails.items.length) { - statusClass = 'queue'; - } - - return ( - - {translate(firstCharToUpper(status))} - - ); -} - -MovieStatusLabel.propTypes = { - hasMovieFiles: PropTypes.bool.isRequired, - monitored: PropTypes.bool.isRequired, - isAvailable: PropTypes.bool.isRequired, - queueDetails: PropTypes.object -}; - -MovieStatusLabel.defaultProps = { - title: '' -}; - -export default MovieStatusLabel; diff --git a/frontend/src/Movie/Details/MovieTags.js b/frontend/src/Movie/Details/MovieTags.js deleted file mode 100644 index 0b3e994a1..000000000 --- a/frontend/src/Movie/Details/MovieTags.js +++ /dev/null @@ -1,30 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Label from 'Components/Label'; -import { kinds, sizes } from 'Helpers/Props'; - -function MovieTags({ tags }) { - return ( -
- { - tags.map((tag) => { - return ( - - ); - }) - } -
- ); -} - -MovieTags.propTypes = { - tags: PropTypes.arrayOf(PropTypes.string).isRequired -}; - -export default MovieTags; diff --git a/frontend/src/Movie/Details/MovieTagsConnector.js b/frontend/src/Movie/Details/MovieTagsConnector.js deleted file mode 100644 index ce03ff2c2..000000000 --- a/frontend/src/Movie/Details/MovieTagsConnector.js +++ /dev/null @@ -1,30 +0,0 @@ -import _ from 'lodash'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import createMovieSelector from 'Store/Selectors/createMovieSelector'; -import createTagsSelector from 'Store/Selectors/createTagsSelector'; -import MovieTags from './MovieTags'; - -function createMapStateToProps() { - return createSelector( - createMovieSelector(), - createTagsSelector(), - (movie, tagList) => { - const tags = _.reduce(movie.tags, (acc, tag) => { - const matchingTag = _.find(tagList, { id: tag }); - - if (matchingTag) { - acc.push(matchingTag.label); - } - - return acc; - }, []); - - return { - tags - }; - } - ); -} - -export default connect(createMapStateToProps)(MovieTags); diff --git a/frontend/src/Movie/Details/Titles/MovieTitlesRow.js b/frontend/src/Movie/Details/Titles/MovieTitlesRow.js deleted file mode 100644 index ea12bbd97..000000000 --- a/frontend/src/Movie/Details/Titles/MovieTitlesRow.js +++ /dev/null @@ -1,52 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import TableRowCell from 'Components/Table/Cells/TableRowCell'; -import TableRow from 'Components/Table/TableRow'; -import MovieLanguage from 'Movie/MovieLanguage'; -import titleCase from 'Utilities/String/titleCase'; - -class MovieTitlesRow extends Component { - - // - // Render - - render() { - const { - title, - language, - sourceType - } = this.props; - - // TODO - Fix languages to all take arrays - const languages = [language]; - - return ( - - - - {title} - - - - - - - - {titleCase(sourceType)} - - - - ); - } -} - -MovieTitlesRow.propTypes = { - id: PropTypes.number.isRequired, - title: PropTypes.string.isRequired, - language: PropTypes.object.isRequired, - sourceType: PropTypes.string.isRequired -}; - -export default MovieTitlesRow; diff --git a/frontend/src/Movie/Details/Titles/MovieTitlesTable.js b/frontend/src/Movie/Details/Titles/MovieTitlesTable.js deleted file mode 100644 index 9223a7585..000000000 --- a/frontend/src/Movie/Details/Titles/MovieTitlesTable.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import MovieTitlesTableContentConnector from './MovieTitlesTableContentConnector'; - -function MovieTitlesTable(props) { - const { - ...otherProps - } = props; - - return ( - - ); -} - -MovieTitlesTable.propTypes = { -}; - -export default MovieTitlesTable; diff --git a/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.css b/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.css deleted file mode 100644 index 34be6dff1..000000000 --- a/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.blankpad { - padding-top: 10px; - padding-bottom: 10px; - padding-left: 2em; -} diff --git a/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.js b/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.js deleted file mode 100644 index f7c0c6ef1..000000000 --- a/frontend/src/Movie/Details/Titles/MovieTitlesTableContent.js +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import Table from 'Components/Table/Table'; -import TableBody from 'Components/Table/TableBody'; -import translate from 'Utilities/String/translate'; -import MovieTitlesRow from './MovieTitlesRow'; -import styles from './MovieTitlesTableContent.css'; - -const columns = [ - { - name: 'altTitle', - label: translate('AlternativeTitle'), - isVisible: true - }, - { - name: 'language', - label: translate('Language'), - isVisible: true - }, - { - name: 'sourceType', - label: translate('Type'), - isVisible: true - } -]; - -class MovieTitlesTableContent extends Component { - - // - // Render - - render() { - const { - isFetching, - isPopulated, - error, - items - } = this.props; - - const hasItems = !!items.length; - return ( -
- { - isFetching && - - } - - { - !isFetching && !!error && -
Unable to load alternative titles.
- } - - { - isPopulated && !hasItems && !error && -
No alternative titles.
- } - - { - isPopulated && hasItems && !error && - - - { - items.reverse().map((item) => { - return ( - - ); - }) - } - -
- } -
- ); - } -} - -MovieTitlesTableContent.propTypes = { - isFetching: PropTypes.bool.isRequired, - isPopulated: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default MovieTitlesTableContent; diff --git a/frontend/src/Movie/Details/Titles/MovieTitlesTableContentConnector.js b/frontend/src/Movie/Details/Titles/MovieTitlesTableContentConnector.js deleted file mode 100644 index 136a7e994..000000000 --- a/frontend/src/Movie/Details/Titles/MovieTitlesTableContentConnector.js +++ /dev/null @@ -1,44 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import MovieTitlesTableContent from './MovieTitlesTableContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.movies, - (movies) => { - return movies; - } - ); -} - -const mapDispatchToProps = { -// fetchMovies -}; - -class MovieTitlesTableContentConnector extends Component { - - // - // Render - - render() { - const movie = this.props.items.filter((obj) => { - return obj.id === this.props.movieId; - }); - - return ( - - ); - } -} - -MovieTitlesTableContentConnector.propTypes = { - movieId: PropTypes.number.isRequired, - items: PropTypes.arrayOf(PropTypes.object).isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(MovieTitlesTableContentConnector); diff --git a/frontend/src/Movie/Index/MovieIndex.js b/frontend/src/Movie/Index/MovieIndex.js index 7c1e78b52..c176eda73 100644 --- a/frontend/src/Movie/Index/MovieIndex.js +++ b/frontend/src/Movie/Index/MovieIndex.js @@ -610,7 +610,7 @@ class MovieIndex extends Component { Are you sure you want to perform mass movie search for {isMovieEditorActive && selectedMovieIds.length > 0 ? selectedMovieIds.length : this.props.items.length} movies?
- This cannot be cancelled once started without restarting Radarr. + This cannot be cancelled once started without restarting Prowlarr.
} diff --git a/frontend/src/Movie/Index/Overview/MovieIndexOverview.js b/frontend/src/Movie/Index/Overview/MovieIndexOverview.js index 2541988d5..63579c0da 100644 --- a/frontend/src/Movie/Index/Overview/MovieIndexOverview.js +++ b/frontend/src/Movie/Index/Overview/MovieIndexOverview.js @@ -9,7 +9,6 @@ import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import Popover from 'Components/Tooltip/Popover'; import { icons } from 'Helpers/Props'; import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks'; import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; import MovieIndexProgressBar from 'Movie/Index/ProgressBar/MovieIndexProgressBar'; import MoviePoster from 'Movie/MoviePoster'; @@ -199,11 +198,7 @@ class MovieIndexOverview extends Component { } title={translate('Links')} body={ - + 'place' } /> diff --git a/frontend/src/Movie/Index/Posters/MovieIndexPoster.js b/frontend/src/Movie/Index/Posters/MovieIndexPoster.js index d68e8c20a..ada3c7fd8 100644 --- a/frontend/src/Movie/Index/Posters/MovieIndexPoster.js +++ b/frontend/src/Movie/Index/Posters/MovieIndexPoster.js @@ -9,7 +9,6 @@ import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import Popover from 'Components/Tooltip/Popover'; import { icons } from 'Helpers/Props'; import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks'; import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; import MovieIndexProgressBar from 'Movie/Index/ProgressBar/MovieIndexProgressBar'; import MoviePoster from 'Movie/MoviePoster'; @@ -178,11 +177,7 @@ class MovieIndexPoster extends Component { } title={translate('Links')} body={ - + 'place' } /> diff --git a/frontend/src/Movie/Index/Table/MovieIndexRow.js b/frontend/src/Movie/Index/Table/MovieIndexRow.js index c84ae6c43..4b2d1090e 100644 --- a/frontend/src/Movie/Index/Table/MovieIndexRow.js +++ b/frontend/src/Movie/Index/Table/MovieIndexRow.js @@ -11,7 +11,6 @@ import TagListConnector from 'Components/TagListConnector'; import Tooltip from 'Components/Tooltip/Tooltip'; import { icons, kinds } from 'Helpers/Props'; import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal'; -import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks'; import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector'; import MovieFileStatusConnector from 'Movie/MovieFileStatusConnector'; import MovieTitleLink from 'Movie/MovieTitleLink'; @@ -376,13 +375,6 @@ class MovieIndexRow extends Component { size={12} /> } - tooltip={ - - } canFlip={true} kind={kinds.INVERSE} /> diff --git a/frontend/src/Movie/MovieCollection.js b/frontend/src/Movie/MovieCollection.js index 396638ec9..44136224a 100644 --- a/frontend/src/Movie/MovieCollection.js +++ b/frontend/src/Movie/MovieCollection.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import MonitorToggleButton from 'Components/MonitorToggleButton'; -import EditImportListModalConnector from 'Settings/ImportLists/ImportLists/EditImportListModalConnector'; import styles from './MovieCollection.css'; class MovieCollection extends Component { @@ -39,7 +38,6 @@ class MovieCollection extends Component { } = this.props; const monitored = collectionList !== undefined && collectionList.enabled && collectionList.enableAuto; - const importListId = collectionList ? collectionList.id : 0; return (
@@ -51,12 +49,6 @@ class MovieCollection extends Component { onPress={this.onAddImportListPress} /> {name} -
); } diff --git a/frontend/src/Movie/MovieCollectionConnector.js b/frontend/src/Movie/MovieCollectionConnector.js index 3b119d14a..fc73d619e 100644 --- a/frontend/src/Movie/MovieCollectionConnector.js +++ b/frontend/src/Movie/MovieCollectionConnector.js @@ -2,7 +2,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import { saveImportList, selectImportListSchema, setImportListFieldValue, setImportListValue } from 'Store/Actions/settingsActions'; import createMovieCollectionListSelector from 'Store/Selectors/createMovieCollectionListSelector'; import createMovieSelector from 'Store/Selectors/createMovieSelector'; import MovieCollection from './MovieCollection'; @@ -11,8 +10,7 @@ function createMapStateToProps() { return createSelector( createMovieSelector(), createMovieCollectionListSelector(), - (state) => state.settings.importLists, - (movie, collectionList, importLists) => { + (movie, collectionList) => { const { monitored, qualityProfileId, @@ -23,40 +21,19 @@ function createMapStateToProps() { collectionList, monitored, qualityProfileId, - minimumAvailability, - isSaving: importLists.isSaving + minimumAvailability }; } ); } -const mapDispatchToProps = { - selectImportListSchema, - setImportListFieldValue, - setImportListValue, - saveImportList -}; - class MovieCollectionConnector extends Component { // // Listeners onMonitorTogglePress = (monitored) => { - if (this.props.collectionList) { - this.props.setImportListValue({ name: 'enabled', value: monitored }); - this.props.setImportListValue({ name: 'enableAuto', value: monitored }); - this.props.saveImportList({ id: this.props.collectionList.id }); - } else { - this.props.selectImportListSchema({ implementation: 'TMDbCollectionImport', presetName: undefined }); - this.props.setImportListFieldValue({ name: 'collectionId', value: this.props.tmdbId.toString() }); - this.props.setImportListValue({ name: 'enabled', value: true }); - this.props.setImportListValue({ name: 'enableAuto', value: true }); - this.props.setImportListValue({ name: 'name', value: `${this.props.name} - ${this.props.tmdbId}` }); - this.props.setImportListValue({ name: 'qualityProfileId', value: this.props.qualityProfileId }); - this.props.setImportListValue({ name: 'monitored', value: this.props.monitored }); - this.props.setImportListValue({ name: 'minimumAvailability', value: this.props.minimumAvailability }); - } + } // @@ -80,11 +57,7 @@ MovieCollectionConnector.propTypes = { monitored: PropTypes.bool.isRequired, qualityProfileId: PropTypes.number.isRequired, minimumAvailability: PropTypes.string.isRequired, - isSaving: PropTypes.bool.isRequired, - selectImportListSchema: PropTypes.func.isRequired, - setImportListFieldValue: PropTypes.func.isRequired, - setImportListValue: PropTypes.func.isRequired, - saveImportList: PropTypes.func.isRequired + isSaving: PropTypes.bool.isRequired }; -export default connect(createMapStateToProps, mapDispatchToProps)(MovieCollectionConnector); +export default connect(createMapStateToProps)(MovieCollectionConnector); diff --git a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js index 21bd0ddd9..fda59c073 100644 --- a/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js +++ b/frontend/src/Settings/CustomFormats/CustomFormats/Specifications/AddSpecificationModalContent.js @@ -57,7 +57,7 @@ class AddSpecificationModalContent extends Component {
{translate('VisitGithubCustomFormatsAphrodite')} - GitHub + GitHub
diff --git a/frontend/src/Settings/General/GeneralSettings.js b/frontend/src/Settings/General/GeneralSettings.js index 3870e2754..263ddef73 100644 --- a/frontend/src/Settings/General/GeneralSettings.js +++ b/frontend/src/Settings/General/GeneralSettings.js @@ -189,7 +189,7 @@ class GeneralSettings extends Component { kind={kinds.DANGER} title={translate('RestartRadarr')} message={ - `Radarr requires a restart to apply changes, do you want to restart now? ${isWindowsService ? 'Depending which user is running the Radarr service you may need to restart Radarr as admin once before the service will start automatically.' : ''}` + `Prowlarr requires a restart to apply changes, do you want to restart now? ${isWindowsService ? 'Depending which user is running the Prowlarr service you may need to restart Prowlarr as admin once before the service will start automatically.' : ''}` } cancelLabel={translate('IllRestartLater')} confirmLabel={translate('RestartNow')} diff --git a/frontend/src/Settings/General/UpdateSettings.js b/frontend/src/Settings/General/UpdateSettings.js index 2c62dc4ae..3c5ab6891 100644 --- a/frontend/src/Settings/General/UpdateSettings.js +++ b/frontend/src/Settings/General/UpdateSettings.js @@ -55,7 +55,7 @@ function UpdateSettings(props) { type={inputTypes.TEXT} name="branch" helpText={usingExternalUpdateMechanism ? translate('BranchUpdateMechanism') : translate('BranchUpdate')} - helpLink="https://github.com/Radarr/Radarr/wiki/Release-Branches" + helpLink="https://github.com/Prowlarr/Prowlarr/wiki/Release-Branches" {...branch} onChange={onInputChange} readOnly={usingExternalUpdateMechanism} @@ -92,7 +92,7 @@ function UpdateSettings(props) { name="updateMechanism" values={updateOptions} helpText={translate('UpdateMechanismHelpText')} - helpLink="https://github.com/Radarr/Radarr/wiki/Updating" + helpLink="https://github.com/Prowlarr/Prowlarr/wiki/Updating" onChange={onInputChange} {...updateMechanism} /> diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModal.js b/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModal.js deleted file mode 100644 index 9d140de43..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditImportExclusionModalContentConnector from './EditImportExclusionModalContentConnector'; - -function EditImportExclusionModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditImportExclusionModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditImportExclusionModal; diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalConnector.js b/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalConnector.js deleted file mode 100644 index f7e6dee80..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalConnector.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import EditImportExclusionModal from './EditImportExclusionModal'; - -function mapStateToProps() { - return {}; -} - -const mapDispatchToProps = { - clearPendingChanges -}; - -class EditImportExclusionModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.clearPendingChanges({ section: 'settings.importExclusions' }); - this.props.onModalClose(); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditImportExclusionModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - clearPendingChanges: PropTypes.func.isRequired -}; - -export default connect(mapStateToProps, mapDispatchToProps)(EditImportExclusionModalConnector); diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.css b/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.css deleted file mode 100644 index 97e132552..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.css +++ /dev/null @@ -1,11 +0,0 @@ -.body { - composes: modalBody from '~Components/Modal/ModalBody.css'; - - flex: 1 1 430px; -} - -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.js b/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.js deleted file mode 100644 index 2840200a1..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContent.js +++ /dev/null @@ -1,146 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -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 SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -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 { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './EditImportExclusionModalContent.css'; - -function EditImportExclusionModalContent(props) { - const { - id, - isFetching, - error, - isSaving, - saveError, - item, - onInputChange, - onSavePress, - onModalClose, - onDeleteImportExclusionPress, - ...otherProps - } = props; - - const { - movieTitle = '', - tmdbId, - movieYear - } = item; - - return ( - - - {id ? 'Edit List Exclusion' : 'Add List Exclusion'} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewListExclusionPleaseTryAgain')} -
- } - - { - !isFetching && !error && -
- - {translate('TMDBId')} - - - - - - {translate('MovieTitle')} - - - - - - {translate('MovieYear')} - - - - -
- } -
- - - { - id && - - } - - - - - {translate('Save')} - - -
- ); -} - -EditImportExclusionModalContent.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onDeleteImportExclusionPress: PropTypes.func -}; - -export default EditImportExclusionModalContent; diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContentConnector.js b/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContentConnector.js deleted file mode 100644 index 70ea1d873..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/EditImportExclusionModalContentConnector.js +++ /dev/null @@ -1,119 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveImportExclusion, setImportExclusionValue } from 'Store/Actions/settingsActions'; -import selectSettings from 'Store/Selectors/selectSettings'; -import EditImportExclusionModalContent from './EditImportExclusionModalContent'; - -const newImportExclusion = { - movieTitle: '', - tmdbId: 0, - movieYear: 0 -}; - -function createImportExclusionSelector() { - return createSelector( - (state, { id }) => id, - (state) => state.settings.importExclusions, - (id, importExclusions) => { - const { - isFetching, - error, - isSaving, - saveError, - pendingChanges, - items - } = importExclusions; - - const mapping = id ? _.find(items, { id }) : newImportExclusion; - const settings = selectSettings(mapping, pendingChanges, saveError); - - return { - id, - isFetching, - error, - isSaving, - saveError, - item: settings.settings, - ...settings - }; - } - ); -} - -function createMapStateToProps() { - return createSelector( - createImportExclusionSelector(), - (importExclusion) => { - return { - ...importExclusion - }; - } - ); -} - -const mapDispatchToProps = { - setImportExclusionValue, - saveImportExclusion -}; - -class EditImportExclusionModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - if (!this.props.id) { - Object.keys(newImportExclusion).forEach((name) => { - this.props.setImportExclusionValue({ - name, - value: newImportExclusion[name] - }); - }); - } - } - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setImportExclusionValue({ name, value }); - } - - onSavePress = () => { - this.props.saveImportExclusion({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditImportExclusionModalContentConnector.propTypes = { - id: PropTypes.number, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setImportExclusionValue: PropTypes.func.isRequired, - saveImportExclusion: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditImportExclusionModalContentConnector); diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.css b/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.css deleted file mode 100644 index cbfea3f15..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.css +++ /dev/null @@ -1,24 +0,0 @@ -.importExclusion { - display: flex; - align-items: stretch; - margin-bottom: 10px; - height: 30px; - border-bottom: 1px solid $borderColor; - line-height: 30px; -} - -.movieTitle { - flex: 0 0 400px; -} - -.tmdbId, -.movieYear { - flex: 0 0 200px; -} - -.actions { - display: flex; - justify-content: flex-end; - flex: 1 0 auto; - padding-right: 10px; -} diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.js b/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.js deleted file mode 100644 index c3a8ea79f..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusion.js +++ /dev/null @@ -1,115 +0,0 @@ -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { icons, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditImportExclusionModalConnector from './EditImportExclusionModalConnector'; -import styles from './ImportExclusion.css'; - -class ImportExclusion extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditImportExclusionModalOpen: false, - isDeleteImportExclusionModalOpen: false - }; - } - - // - // Listeners - - onEditImportExclusionPress = () => { - this.setState({ isEditImportExclusionModalOpen: true }); - } - - onEditImportExclusionModalClose = () => { - this.setState({ isEditImportExclusionModalOpen: false }); - } - - onDeleteImportExclusionPress = () => { - this.setState({ - isEditImportExclusionModalOpen: false, - isDeleteImportExclusionModalOpen: true - }); - } - - onDeleteImportExclusionModalClose = () => { - this.setState({ isDeleteImportExclusionModalOpen: false }); - } - - onConfirmDeleteImportExclusion = () => { - this.props.onConfirmDeleteImportExclusion(this.props.id); - } - - // - // Render - - render() { - const { - id, - movieTitle, - tmdbId, - movieYear - } = this.props; - - return ( -
-
{tmdbId}
-
{movieTitle}
-
{movieYear}
- -
- - - -
- - - - -
- ); - } -} - -ImportExclusion.propTypes = { - id: PropTypes.number.isRequired, - movieTitle: PropTypes.string.isRequired, - tmdbId: PropTypes.number.isRequired, - movieYear: PropTypes.number.isRequired, - onConfirmDeleteImportExclusion: PropTypes.func.isRequired -}; - -ImportExclusion.defaultProps = { - // The drag preview will not connect the drag handle. - connectDragSource: (node) => node -}; - -export default ImportExclusion; diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.css b/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.css deleted file mode 100644 index 06720845c..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.css +++ /dev/null @@ -1,24 +0,0 @@ -.importExclusionsHeader { - display: flex; - margin-bottom: 10px; - font-weight: bold; -} - -.title { - flex: 0 0 400px; -} - -.tmdbId, -.movieYear { - flex: 0 0 200px; -} - -.addImportExclusion { - display: flex; - justify-content: flex-end; - padding-right: 10px; -} - -.addButton { - text-align: center; -} diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.js b/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.js deleted file mode 100644 index d2ec7acfd..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusions.js +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import Link from 'Components/Link/Link'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditImportExclusionModalConnector from './EditImportExclusionModalConnector'; -import ImportExclusion from './ImportExclusion'; -import styles from './ImportExclusions.css'; - -class ImportExclusions extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddImportExclusionModalOpen: false - }; - } - - // - // Listeners - - onAddImportExclusionPress = () => { - this.setState({ isAddImportExclusionModalOpen: true }); - } - - onModalClose = () => { - this.setState({ isAddImportExclusionModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - onConfirmDeleteImportExclusion, - ...otherProps - } = this.props; - - return ( -
- -
-
TMDB Id
-
Title
-
Year
-
- -
- { - items.map((item, index) => { - return ( - - ); - }) - } -
- -
- - - -
- - - -
-
- ); - } -} - -ImportExclusions.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteImportExclusion: PropTypes.func.isRequired -}; - -export default ImportExclusions; diff --git a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusionsConnector.js b/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusionsConnector.js deleted file mode 100644 index 4cf7320a8..000000000 --- a/frontend/src/Settings/ImportLists/ImportExclusions/ImportExclusionsConnector.js +++ /dev/null @@ -1,59 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { deleteImportExclusion, fetchImportExclusions } from 'Store/Actions/settingsActions'; -import ImportExclusions from './ImportExclusions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.importExclusions, - (importExclusions) => { - return { - ...importExclusions - }; - } - ); -} - -const mapDispatchToProps = { - fetchImportExclusions, - deleteImportExclusion -}; - -class ImportExclusionsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchImportExclusions(); - } - - // - // Listeners - - onConfirmDeleteImportExclusion = (id) => { - this.props.deleteImportExclusion({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportExclusionsConnector.propTypes = { - fetchImportExclusions: PropTypes.func.isRequired, - deleteImportExclusion: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportExclusionsConnector); diff --git a/frontend/src/Settings/ImportLists/ImportListSettings.js b/frontend/src/Settings/ImportLists/ImportListSettings.js deleted file mode 100644 index 62a96ecf9..000000000 --- a/frontend/src/Settings/ImportLists/ImportListSettings.js +++ /dev/null @@ -1,102 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component, Fragment } from 'react'; -import PageContent from 'Components/Page/PageContent'; -import PageContentBody from 'Components/Page/PageContentBody'; -import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton'; -import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator'; -import { icons } from 'Helpers/Props'; -import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; -import translate from 'Utilities/String/translate'; -import ImportExclusionsConnector from './ImportExclusions/ImportExclusionsConnector'; -import ImportListsConnector from './ImportLists/ImportListsConnector'; -import ImportListOptionsConnector from './Options/ImportListOptionsConnector'; - -class ImportListSettings extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this._saveCallback = null; - - this.state = { - isSaving: false, - hasPendingChanges: false - }; - } - - // - // Listeners - - onChildMounted = (saveCallback) => { - this._saveCallback = saveCallback; - } - - onChildStateChange = (payload) => { - this.setState(payload); - } - - onSavePress = () => { - if (this._saveCallback) { - this._saveCallback(); - } - } - - // Render - // - - render() { - const { - isTestingAll, - dispatchTestAllImportList - } = this.props; - - const { - isSaving, - hasPendingChanges - } = this.state; - - return ( - - - - - - - } - onSavePress={this.onSavePress} - /> - - - - - - - - - - - ); - } -} - -ImportListSettings.propTypes = { - isTestingAll: PropTypes.bool.isRequired, - dispatchTestAllImportList: PropTypes.func.isRequired -}; - -export default ImportListSettings; diff --git a/frontend/src/Settings/ImportLists/ImportListSettingsConnector.js b/frontend/src/Settings/ImportLists/ImportListSettingsConnector.js deleted file mode 100644 index 87c856d5d..000000000 --- a/frontend/src/Settings/ImportLists/ImportListSettingsConnector.js +++ /dev/null @@ -1,21 +0,0 @@ -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { testAllImportList } from 'Store/Actions/settingsActions'; -import ImportListSettings from './ImportListSettings'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.importLists.isTestingAll, - (isTestingAll) => { - return { - isTestingAll - }; - } - ); -} - -const mapDispatchToProps = { - dispatchTestAllImportList: testAllImportList -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportListSettings); diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.css b/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.css deleted file mode 100644 index 7b0f4c58e..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.css +++ /dev/null @@ -1,44 +0,0 @@ -.importList { - composes: card from '~Components/Card.css'; - - position: relative; - width: 300px; - height: 100px; -} - -.underlay { - @add-mixin cover; -} - -.overlay { - @add-mixin linkOverlay; - - padding: 10px; -} - -.name { - text-align: center; - font-weight: lighter; - font-size: 24px; -} - -.actions { - margin-top: 20px; - text-align: right; -} - -.presetsMenu { - composes: menu from '~Components/Menu/Menu.css'; - - display: inline-block; - margin: 0 5px; -} - -.presetsMenuButton { - composes: button from '~Components/Link/Button.css'; - - &::after { - margin-left: 5px; - content: '\25BE'; - } -} diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.js b/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.js deleted file mode 100644 index bf3c418d2..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListItem.js +++ /dev/null @@ -1,111 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Button from 'Components/Link/Button'; -import Link from 'Components/Link/Link'; -import Menu from 'Components/Menu/Menu'; -import MenuContent from 'Components/Menu/MenuContent'; -import { sizes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddImportListPresetMenuItem from './AddImportListPresetMenuItem'; -import styles from './AddImportListItem.css'; - -class AddImportListItem extends Component { - - // - // Listeners - - onImportListSelect = () => { - const { - implementation - } = this.props; - - this.props.onImportListSelect({ implementation }); - } - - // - // Render - - render() { - const { - implementation, - implementationName, - infoLink, - presets, - onImportListSelect - } = this.props; - - const hasPresets = !!presets && !!presets.length; - - return ( -
- - -
-
- {implementationName} -
- -
- { - hasPresets && - - - - - - - - { - presets.map((preset) => { - return ( - - ); - }) - } - - - - } - - -
-
-
- ); - } -} - -AddImportListItem.propTypes = { - implementation: PropTypes.string.isRequired, - implementationName: PropTypes.string.isRequired, - infoLink: PropTypes.string.isRequired, - presets: PropTypes.arrayOf(PropTypes.object), - onImportListSelect: PropTypes.func.isRequired -}; - -export default AddImportListItem; diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModal.js b/frontend/src/Settings/ImportLists/ImportLists/AddImportListModal.js deleted file mode 100644 index a188d6b4a..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModal.js +++ /dev/null @@ -1,25 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import AddImportListModalContentConnector from './AddImportListModalContentConnector'; - -function AddImportListModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -AddImportListModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddImportListModal; diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.css b/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.css deleted file mode 100644 index 2fa2fbe84..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.importLists { - display: flex; - justify-content: center; - flex-wrap: wrap; -} diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.js b/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.js deleted file mode 100644 index 5aa0cbb40..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContent.js +++ /dev/null @@ -1,110 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Alert from 'Components/Alert'; -import FieldSet from 'Components/FieldSet'; -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 titleCase from 'Utilities/String/titleCase'; -import translate from 'Utilities/String/translate'; -import AddImportListItem from './AddImportListItem'; -import styles from './AddImportListModalContent.css'; - -class AddImportListModalContent extends Component { - - // - // Render - - render() { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - listGroups, - onImportListSelect, - onModalClose - } = this.props; - - return ( - - - {translate('AddList')} - - - - { - isSchemaFetching && - - } - - { - !isSchemaFetching && !!schemaError && -
- {translate('UnableToAddANewListPleaseTryAgain')} -
- } - - { - isSchemaPopulated && !schemaError && -
- - -
- {translate('RadarrSupportsAnyRSSMovieListsAsWellAsTheOneStatedBelow')} -
-
- {translate('ForMoreInformationOnTheIndividualImportListsClinkOnTheInfoButtons')} -
-
- - { - Object.keys(listGroups).map((key) => { - return ( -
-
- { - listGroups[key].map((importList) => { - return ( - - ); - }) - } -
-
- ); - }) - } -
- } -
- - - -
- ); - } -} - -AddImportListModalContent.propTypes = { - isSchemaFetching: PropTypes.bool.isRequired, - isSchemaPopulated: PropTypes.bool.isRequired, - schemaError: PropTypes.object, - listGroups: PropTypes.object.isRequired, - onImportListSelect: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default AddImportListModalContent; diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContentConnector.js b/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContentConnector.js deleted file mode 100644 index 67b2f1da8..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListModalContentConnector.js +++ /dev/null @@ -1,76 +0,0 @@ -import _ from 'lodash'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchImportListSchema, selectImportListSchema } from 'Store/Actions/settingsActions'; -import AddImportListModalContent from './AddImportListModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.importLists, - (importLists) => { - const { - isSchemaFetching, - isSchemaPopulated, - schemaError, - schema - } = importLists; - - const listGroups = _.chain(schema) - .sortBy((o) => o.listOrder) - .groupBy('listType') - .value(); - - return { - isSchemaFetching, - isSchemaPopulated, - schemaError, - listGroups - }; - } - ); -} - -const mapDispatchToProps = { - fetchImportListSchema, - selectImportListSchema -}; - -class AddImportListModalContentConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchImportListSchema(); - } - - // - // Listeners - - onImportListSelect = ({ implementation, name }) => { - this.props.selectImportListSchema({ implementation, presetName: name }); - this.props.onModalClose({ importListSelected: true }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -AddImportListModalContentConnector.propTypes = { - fetchImportListSchema: PropTypes.func.isRequired, - selectImportListSchema: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(AddImportListModalContentConnector); diff --git a/frontend/src/Settings/ImportLists/ImportLists/AddImportListPresetMenuItem.js b/frontend/src/Settings/ImportLists/ImportLists/AddImportListPresetMenuItem.js deleted file mode 100644 index 477044ae0..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/AddImportListPresetMenuItem.js +++ /dev/null @@ -1,49 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import MenuItem from 'Components/Menu/MenuItem'; - -class AddImportListPresetMenuItem extends Component { - - // - // Listeners - - onPress = () => { - const { - name, - implementation - } = this.props; - - this.props.onPress({ - name, - implementation - }); - } - - // - // Render - - render() { - const { - name, - implementation, - ...otherProps - } = this.props; - - return ( - - {name} - - ); - } -} - -AddImportListPresetMenuItem.propTypes = { - name: PropTypes.string.isRequired, - implementation: PropTypes.string.isRequired, - onPress: PropTypes.func.isRequired -}; - -export default AddImportListPresetMenuItem; diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModal.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModal.js deleted file mode 100644 index 5fec8e09d..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModal.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import Modal from 'Components/Modal/Modal'; -import { sizes } from 'Helpers/Props'; -import EditImportListModalContentConnector from './EditImportListModalContentConnector'; - -function EditImportListModal({ isOpen, onModalClose, ...otherProps }) { - return ( - - - - ); -} - -EditImportListModal.propTypes = { - isOpen: PropTypes.bool.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default EditImportListModal; diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalConnector.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalConnector.js deleted file mode 100644 index b4632918b..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalConnector.js +++ /dev/null @@ -1,65 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { cancelSaveImportList, cancelTestImportList } from 'Store/Actions/settingsActions'; -import EditImportListModal from './EditImportListModal'; - -function createMapDispatchToProps(dispatch, props) { - const section = 'settings.importLists'; - - return { - dispatchClearPendingChanges() { - dispatch(clearPendingChanges({ section })); - }, - - dispatchCancelTestImportList() { - dispatch(cancelTestImportList({ section })); - }, - - dispatchCancelSaveImportList() { - dispatch(cancelSaveImportList({ section })); - } - }; -} - -class EditImportListModalConnector extends Component { - - // - // Listeners - - onModalClose = () => { - this.props.dispatchClearPendingChanges(); - this.props.dispatchCancelTestImportList(); - this.props.dispatchCancelSaveImportList(); - this.props.onModalClose(); - } - - // - // Render - - render() { - const { - dispatchClearPendingChanges, - dispatchCancelTestImportList, - dispatchCancelSaveImportList, - ...otherProps - } = this.props; - - return ( - - ); - } -} - -EditImportListModalConnector.propTypes = { - onModalClose: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired, - dispatchCancelTestImportList: PropTypes.func.isRequired, - dispatchCancelSaveImportList: PropTypes.func.isRequired -}; - -export default connect(null, createMapDispatchToProps)(EditImportListModalConnector); diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.css b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.css deleted file mode 100644 index a2b6014df..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.css +++ /dev/null @@ -1,5 +0,0 @@ -.deleteButton { - composes: button from '~Components/Link/Button.css'; - - margin-right: auto; -} diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js deleted file mode 100644 index a1c74884b..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContent.js +++ /dev/null @@ -1,254 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -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 ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup'; -import Button from 'Components/Link/Button'; -import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; -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 { inputTypes, kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import styles from './EditImportListModalContent.css'; - -function EditImportListModalContent(props) { - const { - advancedSettings, - isFetching, - error, - isSaving, - isTesting, - saveError, - item, - onInputChange, - onFieldChange, - onModalClose, - onSavePress, - onTestPress, - onDeleteImportListPress, - ...otherProps - } = props; - - const { - id, - implementationName, - name, - enabled, - enableAuto, - shouldMonitor, - minimumAvailability, - qualityProfileId, - rootFolderPath, - searchOnAdd, - tags, - fields - } = item; - - return ( - - - {`${id ? 'Edit' : 'Add'} List - ${implementationName}`} - - - - { - isFetching && - - } - - { - !isFetching && !!error && -
- {translate('UnableToAddANewListPleaseTryAgain')} -
- } - - { - !isFetching && !error && -
- - {translate('Name')} - - - - - - {translate('Enable')} - - - - - - {translate('EnableAutomaticAdd')} - - - - - - {translate('AddMoviesMonitored')} - - - - - { - shouldMonitor && - - {translate('SearchOnAdd')} - - - - } - - - {translate('MinimumAvailability')} - - - - - {translate('QualityProfile')} - - - - - - {translate('Folder')} - - - - - - {translate('RadarrTags')} - - - - - { - fields.map((field) => { - return ( - - ); - }) - } - - - } -
- - { - id && - - } - - - {translate('Test')} - - - - - - {translate('Save')} - - -
- ); -} - -EditImportListModalContent.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - isSaving: PropTypes.bool.isRequired, - isTesting: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - onInputChange: PropTypes.func.isRequired, - onFieldChange: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired, - onSavePress: PropTypes.func.isRequired, - onTestPress: PropTypes.func.isRequired, - onDeleteImportListPress: PropTypes.func -}; - -export default EditImportListModalContent; diff --git a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContentConnector.js b/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContentConnector.js deleted file mode 100644 index 3529a328f..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/EditImportListModalContentConnector.js +++ /dev/null @@ -1,88 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { saveImportList, setImportListFieldValue, setImportListValue, testImportList } from 'Store/Actions/settingsActions'; -import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; -import EditImportListModalContent from './EditImportListModalContent'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createProviderSettingsSelector('importLists'), - (advancedSettings, importList) => { - return { - advancedSettings, - ...importList - }; - } - ); -} - -const mapDispatchToProps = { - setImportListValue, - setImportListFieldValue, - saveImportList, - testImportList -}; - -class EditImportListModalContentConnector extends Component { - - // - // Lifecycle - - componentDidUpdate(prevProps, prevState) { - if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) { - this.props.onModalClose(); - } - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.setImportListValue({ name, value }); - } - - onFieldChange = ({ name, value }) => { - this.props.setImportListFieldValue({ name, value }); - } - - onSavePress = () => { - this.props.saveImportList({ id: this.props.id }); - } - - onTestPress = () => { - this.props.testImportList({ id: this.props.id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -EditImportListModalContentConnector.propTypes = { - id: PropTypes.number, - isFetching: PropTypes.bool.isRequired, - isSaving: PropTypes.bool.isRequired, - saveError: PropTypes.object, - item: PropTypes.object.isRequired, - setImportListValue: PropTypes.func.isRequired, - setImportListFieldValue: PropTypes.func.isRequired, - saveImportList: PropTypes.func.isRequired, - testImportList: PropTypes.func.isRequired, - onModalClose: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(EditImportListModalContentConnector); diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportList.css b/frontend/src/Settings/ImportLists/ImportLists/ImportList.css deleted file mode 100644 index d73c6a521..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportList.css +++ /dev/null @@ -1,19 +0,0 @@ -.importList { - composes: card from '~Components/Card.css'; - - width: 290px; -} - -.name { - @add-mixin truncate; - - margin-bottom: 20px; - font-weight: 300; - font-size: 24px; -} - -.enabled { - display: flex; - flex-wrap: wrap; - margin-top: 5px; -} diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportList.js b/frontend/src/Settings/ImportLists/ImportLists/ImportList.js deleted file mode 100644 index 3cee64e1e..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportList.js +++ /dev/null @@ -1,128 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import Label from 'Components/Label'; -import ConfirmModal from 'Components/Modal/ConfirmModal'; -import { kinds } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import EditImportListModalConnector from './EditImportListModalConnector'; -import styles from './ImportList.css'; - -class ImportList extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isEditImportListModalOpen: false, - isDeleteImportListModalOpen: false - }; - } - - // - // Listeners - - onEditImportListPress = () => { - this.setState({ isEditImportListModalOpen: true }); - } - - onEditImportListModalClose = () => { - this.setState({ isEditImportListModalOpen: false }); - } - - onDeleteImportListPress = () => { - this.setState({ - isEditImportListModalOpen: false, - isDeleteImportListModalOpen: true - }); - } - - onDeleteImportListModalClose= () => { - this.setState({ isDeleteImportListModalOpen: false }); - } - - onConfirmDeleteImportList = () => { - this.props.onConfirmDeleteImportList(this.props.id); - } - - // - // Render - - render() { - const { - id, - name, - enabled, - enableAuto - } = this.props; - - return ( - -
- {name} -
- -
- - { - enabled && - - } - - { - enableAuto && - - } - - { - !enabled && !enableAuto && - - } -
- - - - -
- ); - } -} - -ImportList.propTypes = { - id: PropTypes.number.isRequired, - name: PropTypes.string.isRequired, - enabled: PropTypes.bool.isRequired, - enableAuto: PropTypes.bool.isRequired, - onConfirmDeleteImportList: PropTypes.func.isRequired -}; - -export default ImportList; diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportLists.css b/frontend/src/Settings/ImportLists/ImportLists/ImportLists.css deleted file mode 100644 index 1b412d280..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportLists.css +++ /dev/null @@ -1,20 +0,0 @@ -.importLists { - display: flex; - flex-wrap: wrap; -} - -.addImportList { - composes: importList from '~./ImportList.css'; - - background-color: $cardAlternateBackgroundColor; - color: $gray; - text-align: center; -} - -.center { - display: inline-block; - padding: 5px 20px 0; - border: 1px solid $borderColor; - border-radius: 4px; - background-color: $white; -} diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportLists.js b/frontend/src/Settings/ImportLists/ImportLists/ImportLists.js deleted file mode 100644 index aa5791017..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportLists.js +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import Card from 'Components/Card'; -import FieldSet from 'Components/FieldSet'; -import Icon from 'Components/Icon'; -import PageSectionContent from 'Components/Page/PageSectionContent'; -import { icons } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; -import AddImportListModal from './AddImportListModal'; -import EditImportListModalConnector from './EditImportListModalConnector'; -import ImportList from './ImportList'; -import styles from './ImportLists.css'; - -class ImportLists extends Component { - - // - // Lifecycle - - constructor(props, context) { - super(props, context); - - this.state = { - isAddImportListModalOpen: false, - isEditImportListModalOpen: false - }; - } - - // - // Listeners - - onAddImportListPress = () => { - this.setState({ isAddImportListModalOpen: true }); - } - - onAddImportListModalClose = ({ importListSelected = false } = {}) => { - this.setState({ - isAddImportListModalOpen: false, - isEditImportListModalOpen: importListSelected - }); - } - - onEditImportListModalClose = () => { - this.setState({ isEditImportListModalOpen: false }); - } - - // - // Render - - render() { - const { - items, - onConfirmDeleteImportList, - ...otherProps - } = this.props; - - const { - isAddImportListModalOpen, - isEditImportListModalOpen - } = this.state; - - return ( -
- -
- { - items.map((item) => { - return ( - - ); - }) - } - - -
- -
-
-
- - - - -
-
- ); - } -} - -ImportLists.propTypes = { - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - items: PropTypes.arrayOf(PropTypes.object).isRequired, - onConfirmDeleteImportList: PropTypes.func.isRequired -}; - -export default ImportLists; diff --git a/frontend/src/Settings/ImportLists/ImportLists/ImportListsConnector.js b/frontend/src/Settings/ImportLists/ImportLists/ImportListsConnector.js deleted file mode 100644 index 67cfcdd22..000000000 --- a/frontend/src/Settings/ImportLists/ImportLists/ImportListsConnector.js +++ /dev/null @@ -1,60 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; -import { deleteImportList, fetchImportLists } from 'Store/Actions/settingsActions'; -import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; -import sortByName from 'Utilities/Array/sortByName'; -import ImportLists from './ImportLists'; - -function createMapStateToProps() { - return createSelector( - createSortedSectionSelector('settings.importLists', sortByName), - (importLists) => importLists - ); -} - -const mapDispatchToProps = { - fetchImportLists, - deleteImportList, - fetchRootFolders -}; - -class ImportListsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - this.props.fetchImportLists(); - this.props.fetchRootFolders(); - } - - // - // Listeners - - onConfirmDeleteImportList = (id) => { - this.props.deleteImportList({ id }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportListsConnector.propTypes = { - fetchImportLists: PropTypes.func.isRequired, - deleteImportList: PropTypes.func.isRequired, - fetchRootFolders: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportListsConnector); diff --git a/frontend/src/Settings/ImportLists/Options/ImportListOptions.js b/frontend/src/Settings/ImportLists/Options/ImportListOptions.js deleted file mode 100644 index 08c480b83..000000000 --- a/frontend/src/Settings/ImportLists/Options/ImportListOptions.js +++ /dev/null @@ -1,87 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import FieldSet from 'Components/FieldSet'; -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 LoadingIndicator from 'Components/Loading/LoadingIndicator'; -import { inputTypes } from 'Helpers/Props'; -import translate from 'Utilities/String/translate'; - -function ImportListOptions(props) { - const { - isFetching, - error, - settings, - hasSettings, - onInputChange - } = props; - - const cleanLibraryLevelOptions = [ - { key: 'disabled', value: 'Disabled' }, - { key: 'logOnly', value: 'Log Only' }, - { key: 'keepAndUnmonitor', value: 'Keep and Unmonitor' }, - { key: 'removeAndKeep', value: 'Remove and Keep' }, - { key: 'removeAndDelete', value: 'Remove and Delete' } - ]; - - return ( -
- { - isFetching && - - } - - { - !isFetching && error && -
- {translate('UnableToLoadListOptions')} -
- } - - { - hasSettings && !isFetching && !error && -
- - {translate('ListUpdateInterval')} - - - - - - {translate('CleanLibraryLevel')} - - - -
- } -
- ); -} - -ImportListOptions.propTypes = { - advancedSettings: PropTypes.bool.isRequired, - isFetching: PropTypes.bool.isRequired, - error: PropTypes.object, - settings: PropTypes.object.isRequired, - hasSettings: PropTypes.bool.isRequired, - onInputChange: PropTypes.func.isRequired -}; - -export default ImportListOptions; diff --git a/frontend/src/Settings/ImportLists/Options/ImportListOptionsConnector.js b/frontend/src/Settings/ImportLists/Options/ImportListOptionsConnector.js deleted file mode 100644 index fa4aaaa96..000000000 --- a/frontend/src/Settings/ImportLists/Options/ImportListOptionsConnector.js +++ /dev/null @@ -1,101 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clearPendingChanges } from 'Store/Actions/baseActions'; -import { fetchImportListOptions, saveImportListOptions, setImportListOptionsValue } from 'Store/Actions/settingsActions'; -import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector'; -import ImportListOptions from './ImportListOptions'; - -const SECTION = 'importListOptions'; - -function createMapStateToProps() { - return createSelector( - (state) => state.settings.advancedSettings, - createSettingsSectionSelector(SECTION), - (advancedSettings, sectionSettings) => { - return { - advancedSettings, - ...sectionSettings - }; - } - ); -} - -const mapDispatchToProps = { - dispatchFetchImportListOptions: fetchImportListOptions, - dispatchSetImportListOptionsValue: setImportListOptionsValue, - dispatchSaveImportListOptions: saveImportListOptions, - dispatchClearPendingChanges: clearPendingChanges -}; - -class ImportListOptionsConnector extends Component { - - // - // Lifecycle - - componentDidMount() { - const { - dispatchFetchImportListOptions, - dispatchSaveImportListOptions, - onChildMounted - } = this.props; - - dispatchFetchImportListOptions(); - onChildMounted(dispatchSaveImportListOptions); - } - - componentDidUpdate(prevProps) { - const { - hasPendingChanges, - isSaving, - onChildStateChange - } = this.props; - - if ( - prevProps.isSaving !== isSaving || - prevProps.hasPendingChanges !== hasPendingChanges - ) { - onChildStateChange({ - isSaving, - hasPendingChanges - }); - } - } - - componentWillUnmount() { - this.props.dispatchClearPendingChanges({ section: SECTION }); - } - - // - // Listeners - - onInputChange = ({ name, value }) => { - this.props.dispatchSetImportListOptionsValue({ name, value }); - } - - // - // Render - - render() { - return ( - - ); - } -} - -ImportListOptionsConnector.propTypes = { - isSaving: PropTypes.bool.isRequired, - hasPendingChanges: PropTypes.bool.isRequired, - dispatchFetchImportListOptions: PropTypes.func.isRequired, - dispatchSetImportListOptionsValue: PropTypes.func.isRequired, - dispatchSaveImportListOptions: PropTypes.func.isRequired, - dispatchClearPendingChanges: PropTypes.func.isRequired, - onChildMounted: PropTypes.func.isRequired, - onChildStateChange: PropTypes.func.isRequired -}; - -export default connect(createMapStateToProps, mapDispatchToProps)(ImportListOptionsConnector); diff --git a/frontend/src/Settings/Indexers/Options/IndexerOptions.js b/frontend/src/Settings/Indexers/Options/IndexerOptions.js index e6139bc14..47adfe959 100644 --- a/frontend/src/Settings/Indexers/Options/IndexerOptions.js +++ b/frontend/src/Settings/Indexers/Options/IndexerOptions.js @@ -85,7 +85,7 @@ function IndexerOptions(props) { type={inputTypes.CHECK} name="preferIndexerFlags" helpText={translate('PreferIndexerFlagsHelpText')} - helpLink="https://github.com/Radarr/Radarr/wiki/Indexer-Flags" + helpLink="https://github.com/Prowlarr/Prowlarr/wiki/Indexer-Flags" onChange={onInputChange} {...settings.preferIndexerFlags} /> @@ -118,7 +118,7 @@ function IndexerOptions(props) { unit="minutes" helpText={translate('HelpText')} helpTextWarning={translate('RSSSyncIntervalHelpTextWarning')} - helpLink="https://github.com/Radarr/Radarr/wiki/RSS-Sync" + helpLink="https://github.com/Prowlarr/Prowlarr/wiki/RSS-Sync" onChange={onInputChange} {...settings.rssSyncInterval} /> diff --git a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js b/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js index ad3f9290a..c8848a079 100644 --- a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js +++ b/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js @@ -36,7 +36,7 @@ function NotificationEventItems(props) {
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js index 960372346..21e8152ab 100644 --- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js +++ b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js @@ -82,7 +82,7 @@ class QualityProfileFormatItems extends Component {
{ diff --git a/frontend/src/Settings/Settings.js b/frontend/src/Settings/Settings.js index 60271c1c6..f2cf6f4de 100644 --- a/frontend/src/Settings/Settings.js +++ b/frontend/src/Settings/Settings.js @@ -14,50 +14,6 @@ function Settings() { /> - - {translate('MediaManagement')} - - -
- {translate('MediaManagementSettingsSummary')} -
- - - {translate('Profiles')} - - -
- {translate('ProfilesSettingsSummary')} -
- - - {translate('Quality')} - - -
- {translate('QualitySettingsSummary')} -
- - - {translate('CustomFormats')} - - -
- {translate('CustomFormatsSettingsSummary')} -
- - - {translate('DownloadClients')} - - -
- {translate('DownloadClientsSettingsSummary')} -
- - - {translate('Lists')} - - -
- {translate('ListsSettingsSummary')} -
- - - {translate('Metadata')} - - -
- {translate('MetadataSettingsSummary')} -
- } - - { - !!importLists.length && -
- { - importLists.map((item) => { - return ( -
- {item.name} -
- ); - }) - } -
- } @@ -191,7 +175,6 @@ TagDetailsModalContent.propTypes = { delayProfiles: PropTypes.arrayOf(PropTypes.object).isRequired, notifications: PropTypes.arrayOf(PropTypes.object).isRequired, restrictions: PropTypes.arrayOf(PropTypes.object).isRequired, - importLists: PropTypes.arrayOf(PropTypes.object).isRequired, onModalClose: PropTypes.func.isRequired, onDeleteTagPress: PropTypes.func.isRequired }; diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js b/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js index defb88635..a1e081e1a 100644 --- a/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js +++ b/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js @@ -61,28 +61,18 @@ function createMatchingRestrictionsSelector() { ); } -function createMatchingImportListsSelector() { - return createSelector( - (state, { importListIds }) => importListIds, - (state) => state.settings.importLists.items, - findMatchingItems - ); -} - function createMapStateToProps() { return createSelector( createMatchingMoviesSelector(), createMatchingDelayProfilesSelector(), createMatchingNotificationsSelector(), createMatchingRestrictionsSelector(), - createMatchingImportListsSelector(), - (movies, delayProfiles, notifications, restrictions, importLists) => { + (movies, delayProfiles, notifications, restrictions) => { return { movies, delayProfiles, notifications, - restrictions, - importLists + restrictions }; } ); diff --git a/frontend/src/Settings/Tags/TagsConnector.js b/frontend/src/Settings/Tags/TagsConnector.js index 88ffcd776..c75bc0c7b 100644 --- a/frontend/src/Settings/Tags/TagsConnector.js +++ b/frontend/src/Settings/Tags/TagsConnector.js @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; -import { fetchDelayProfiles, fetchImportLists, fetchNotifications, fetchRestrictions } from 'Store/Actions/settingsActions'; +import { fetchDelayProfiles, fetchNotifications, fetchRestrictions } from 'Store/Actions/settingsActions'; import { fetchTagDetails } from 'Store/Actions/tagActions'; import Tags from './Tags'; @@ -28,8 +28,7 @@ const mapDispatchToProps = { dispatchFetchTagDetails: fetchTagDetails, dispatchFetchDelayProfiles: fetchDelayProfiles, dispatchFetchNotifications: fetchNotifications, - dispatchFetchRestrictions: fetchRestrictions, - dispatchFetchImportLists: fetchImportLists + dispatchFetchRestrictions: fetchRestrictions }; class MetadatasConnector extends Component { @@ -42,15 +41,13 @@ class MetadatasConnector extends Component { dispatchFetchTagDetails, dispatchFetchDelayProfiles, dispatchFetchNotifications, - dispatchFetchRestrictions, - dispatchFetchImportLists + dispatchFetchRestrictions } = this.props; dispatchFetchTagDetails(); dispatchFetchDelayProfiles(); dispatchFetchNotifications(); dispatchFetchRestrictions(); - dispatchFetchImportLists(); } // @@ -69,8 +66,7 @@ MetadatasConnector.propTypes = { dispatchFetchTagDetails: PropTypes.func.isRequired, dispatchFetchDelayProfiles: PropTypes.func.isRequired, dispatchFetchNotifications: PropTypes.func.isRequired, - dispatchFetchRestrictions: PropTypes.func.isRequired, - dispatchFetchImportLists: PropTypes.func.isRequired + dispatchFetchRestrictions: PropTypes.func.isRequired }; export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector); diff --git a/frontend/src/Shared/piwikCheck.js b/frontend/src/Shared/piwikCheck.js index aadc9cec7..d81c459ed 100644 --- a/frontend/src/Shared/piwikCheck.js +++ b/frontend/src/Shared/piwikCheck.js @@ -1,4 +1,4 @@ -if (window.Radarr.analytics) { +if (window.Prowlarr.analytics) { const d = document; const g = d.createElement('script'); const s = d.getElementsByTagName('script')[0]; diff --git a/frontend/src/Store/Actions/Settings/importExclusions.js b/frontend/src/Store/Actions/Settings/importExclusions.js deleted file mode 100644 index 17812fa8f..000000000 --- a/frontend/src/Store/Actions/Settings/importExclusions.js +++ /dev/null @@ -1,71 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.importExclusions'; - -// -// Actions Types - -export const FETCH_IMPORT_EXCLUSIONS = 'settings/importExclusions/fetchImportExclusions'; -export const SAVE_IMPORT_EXCLUSION = 'settings/importExclusions/saveImportExclusion'; -export const DELETE_IMPORT_EXCLUSION = 'settings/importExclusions/deleteImportExclusion'; -export const SET_IMPORT_EXCLUSION_VALUE = 'settings/importExclusions/setImportExclusionValue'; - -// -// Action Creators - -export const fetchImportExclusions = createThunk(FETCH_IMPORT_EXCLUSIONS); - -export const saveImportExclusion = createThunk(SAVE_IMPORT_EXCLUSION); -export const deleteImportExclusion = createThunk(DELETE_IMPORT_EXCLUSION); - -export const setImportExclusionValue = createAction(SET_IMPORT_EXCLUSION_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - items: [], - isSaving: false, - saveError: null, - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_IMPORT_EXCLUSIONS]: createFetchHandler(section, '/exclusions'), - - [SAVE_IMPORT_EXCLUSION]: createSaveProviderHandler(section, '/exclusions'), - [DELETE_IMPORT_EXCLUSION]: createRemoveItemHandler(section, '/exclusions') - }, - - // - // Reducers - - reducers: { - [SET_IMPORT_EXCLUSION_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/importListOptions.js b/frontend/src/Store/Actions/Settings/importListOptions.js deleted file mode 100644 index e33c80770..000000000 --- a/frontend/src/Store/Actions/Settings/importListOptions.js +++ /dev/null @@ -1,64 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createSaveHandler from 'Store/Actions/Creators/createSaveHandler'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; - -// -// Variables - -const section = 'settings.importListOptions'; - -// -// Actions Types - -export const FETCH_IMPORT_LIST_OPTIONS = 'settings/importListOptions/fetchImportListOptions'; -export const SAVE_IMPORT_LIST_OPTIONS = 'settings/importListOptions/saveImportListOptions'; -export const SET_IMPORT_LIST_OPTIONS_VALUE = 'settings/importListOptions/setImportListOptionsValue'; - -// -// Action Creators - -export const fetchImportListOptions = createThunk(FETCH_IMPORT_LIST_OPTIONS); -export const saveImportListOptions = createThunk(SAVE_IMPORT_LIST_OPTIONS); -export const setImportListOptionsValue = createAction(SET_IMPORT_LIST_OPTIONS_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - pendingChanges: {}, - isSaving: false, - saveError: null, - item: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_IMPORT_LIST_OPTIONS]: createFetchHandler(section, '/config/importlist'), - [SAVE_IMPORT_LIST_OPTIONS]: createSaveHandler(section, '/config/importlist') - }, - - // - // Reducers - - reducers: { - [SET_IMPORT_LIST_OPTIONS_VALUE]: createSetSettingValueReducer(section) - } - -}; diff --git a/frontend/src/Store/Actions/Settings/importLists.js b/frontend/src/Store/Actions/Settings/importLists.js deleted file mode 100644 index 9f7854224..000000000 --- a/frontend/src/Store/Actions/Settings/importLists.js +++ /dev/null @@ -1,116 +0,0 @@ -import { createAction } from 'redux-actions'; -import createFetchHandler from 'Store/Actions/Creators/createFetchHandler'; -import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; -import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; -import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; -import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler'; -import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; -import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer'; -import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer'; -import { createThunk } from 'Store/thunks'; -import selectProviderSchema from 'Utilities/State/selectProviderSchema'; - -// -// Variables - -const section = 'settings.importLists'; - -// -// Actions Types - -export const FETCH_IMPORT_LISTS = 'settings/importLists/fetchImportLists'; -export const FETCH_IMPORT_LIST_SCHEMA = 'settings/importLists/fetchImportListSchema'; -export const SELECT_IMPORT_LIST_SCHEMA = 'settings/importLists/selectImportListSchema'; -export const SET_IMPORT_LIST_VALUE = 'settings/importLists/setImportListValue'; -export const SET_IMPORT_LIST_FIELD_VALUE = 'settings/importLists/setImportListFieldValue'; -export const SAVE_IMPORT_LIST = 'settings/importLists/saveImportList'; -export const CANCEL_SAVE_IMPORT_LIST = 'settings/importLists/cancelSaveImportList'; -export const DELETE_IMPORT_LIST = 'settings/importLists/deleteImportList'; -export const TEST_IMPORT_LIST = 'settings/importLists/testImportList'; -export const CANCEL_TEST_IMPORT_LIST = 'settings/importLists/cancelTestImportList'; -export const TEST_ALL_IMPORT_LIST = 'settings/importLists/testAllImportList'; - -// -// Action Creators - -export const fetchImportLists = createThunk(FETCH_IMPORT_LISTS); -export const fetchImportListSchema = createThunk(FETCH_IMPORT_LIST_SCHEMA); -export const selectImportListSchema = createAction(SELECT_IMPORT_LIST_SCHEMA); - -export const saveImportList = createThunk(SAVE_IMPORT_LIST); -export const cancelSaveImportList = createThunk(CANCEL_SAVE_IMPORT_LIST); -export const deleteImportList = createThunk(DELETE_IMPORT_LIST); -export const testImportList = createThunk(TEST_IMPORT_LIST); -export const cancelTestImportList = createThunk(CANCEL_TEST_IMPORT_LIST); -export const testAllImportList = createThunk(TEST_ALL_IMPORT_LIST); - -export const setImportListValue = createAction(SET_IMPORT_LIST_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -export const setImportListFieldValue = createAction(SET_IMPORT_LIST_FIELD_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Details - -export default { - - // - // State - - defaultState: { - isFetching: false, - isPopulated: false, - error: null, - isSchemaFetching: false, - isSchemaPopulated: false, - schemaError: null, - schema: [], - selectedSchema: {}, - isSaving: false, - saveError: null, - isTesting: false, - isTestingAll: false, - items: [], - pendingChanges: {} - }, - - // - // Action Handlers - - actionHandlers: { - [FETCH_IMPORT_LISTS]: createFetchHandler(section, '/importlist'), - [FETCH_IMPORT_LIST_SCHEMA]: createFetchSchemaHandler(section, '/importlist/schema'), - - [SAVE_IMPORT_LIST]: createSaveProviderHandler(section, '/importlist'), - [CANCEL_SAVE_IMPORT_LIST]: createCancelSaveProviderHandler(section), - [DELETE_IMPORT_LIST]: createRemoveItemHandler(section, '/importlist'), - [TEST_IMPORT_LIST]: createTestProviderHandler(section, '/importlist'), - [CANCEL_TEST_IMPORT_LIST]: createCancelTestProviderHandler(section), - [TEST_ALL_IMPORT_LIST]: createTestAllProvidersHandler(section, '/importlist') - }, - - // - // Reducers - - reducers: { - [SET_IMPORT_LIST_VALUE]: createSetSettingValueReducer(section), - [SET_IMPORT_LIST_FIELD_VALUE]: createSetProviderFieldValueReducer(section), - - [SELECT_IMPORT_LIST_SCHEMA]: (state, { payload }) => { - return selectProviderSchema(state, section, payload, (selectedSchema) => { - - return selectedSchema; - }); - } - } - -}; diff --git a/frontend/src/Store/Actions/appActions.js b/frontend/src/Store/Actions/appActions.js index 66387468c..b774e7a38 100644 --- a/frontend/src/Store/Actions/appActions.js +++ b/frontend/src/Store/Actions/appActions.js @@ -31,7 +31,7 @@ export const defaultState = { messages: { items: [] }, - version: window.Radarr.version, + version: window.Prowlarr.version, isUpdated: false, isConnected: true, isReconnecting: false, diff --git a/frontend/src/Store/Actions/calendarActions.js b/frontend/src/Store/Actions/calendarActions.js deleted file mode 100644 index 08168ab93..000000000 --- a/frontend/src/Store/Actions/calendarActions.js +++ /dev/null @@ -1,389 +0,0 @@ -import _ from 'lodash'; -import moment from 'moment'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import * as calendarViews from 'Calendar/calendarViews'; -import * as commandNames from 'Commands/commandNames'; -import { filterTypes } from 'Helpers/Props'; -import { createThunk, handleThunks } from 'Store/thunks'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import translate from 'Utilities/String/translate'; -import { set, update } from './baseActions'; -import { executeCommandHelper } from './commandActions'; -import createHandleActions from './Creators/createHandleActions'; -import createClearReducer from './Creators/Reducers/createClearReducer'; - -// -// Variables - -export const section = 'calendar'; - -const viewRanges = { - [calendarViews.DAY]: 'day', - [calendarViews.WEEK]: 'week', - [calendarViews.MONTH]: 'month', - [calendarViews.FORECAST]: 'day' -}; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - start: null, - end: null, - dates: [], - dayCount: 7, - view: window.innerWidth > 768 ? 'month' : 'day', - error: null, - items: [], - searchMissingCommandId: null, - - options: { - showMovieInformation: true, - showCutoffUnmetIcon: false - }, - - selectedFilterKey: 'monitored', - - filters: [ - { - key: 'all', - label: translate('All'), - filters: [ - { - key: 'monitored', - value: false, - type: filterTypes.EQUAL - } - ] - }, - { - key: 'monitored', - label: translate('MonitoredOnly'), - filters: [ - { - key: 'monitored', - value: true, - type: filterTypes.EQUAL - } - ] - } - - ] -}; - -export const persistState = [ - 'calendar.view', - 'calendar.selectedFilterKey', - 'calendar.options' -]; - -// -// Actions Types - -export const FETCH_CALENDAR = 'calendar/fetchCalendar'; -export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount'; -export const SET_CALENDAR_FILTER = 'calendar/setCalendarFilter'; -export const SET_CALENDAR_VIEW = 'calendar/setCalendarView'; -export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday'; -export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange'; -export const CLEAR_CALENDAR = 'calendar/clearCalendar'; -export const SET_CALENDAR_OPTION = 'calendar/setCalendarOption'; -export const SEARCH_MISSING = 'calendar/searchMissing'; -export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange'; - -// -// Helpers - -function getDays(start, end) { - const startTime = moment(start); - const endTime = moment(end); - const difference = endTime.diff(startTime, 'days'); - - // Difference is one less than the number of days we need to account for. - return _.times(difference + 1, (i) => { - return startTime.clone().add(i, 'days').toISOString(); - }); -} - -function getDates(time, view, firstDayOfWeek, dayCount) { - const weekName = firstDayOfWeek === 0 ? 'week' : 'isoWeek'; - - let start = time.clone().startOf('day'); - let end = time.clone().endOf('day'); - - if (view === calendarViews.WEEK) { - start = time.clone().startOf(weekName); - end = time.clone().endOf(weekName); - } - - if (view === calendarViews.FORECAST) { - start = time.clone().subtract(1, 'day').startOf('day'); - end = time.clone().add(dayCount - 2, 'days').endOf('day'); - } - - if (view === calendarViews.MONTH) { - start = time.clone().startOf('month').startOf(weekName); - end = time.clone().endOf('month').endOf(weekName); - } - - if (view === calendarViews.AGENDA) { - start = time.clone().subtract(1, 'day').startOf('day'); - end = time.clone().add(1, 'month').endOf('day'); - } - - return { - start: start.toISOString(), - end: end.toISOString(), - time: time.toISOString(), - dates: getDays(start, end) - }; -} - -function getPopulatableRange(startDate, endDate, view) { - switch (view) { - case calendarViews.DAY: - return { - start: moment(startDate).subtract(1, 'day').toISOString(), - end: moment(endDate).add(1, 'day').toISOString() - }; - case calendarViews.WEEK: - case calendarViews.FORECAST: - return { - start: moment(startDate).subtract(1, 'week').toISOString(), - end: moment(endDate).add(1, 'week').toISOString() - }; - default: - return { - start: startDate, - end: endDate - }; - } -} - -function isRangePopulated(start, end, state) { - const { - start: currentStart, - end: currentEnd, - view: currentView - } = state; - - if (!currentStart || !currentEnd) { - return false; - } - - const { - start: currentPopulatedStart, - end: currentPopulatedEnd - } = getPopulatableRange(currentStart, currentEnd, currentView); - - if ( - moment(start).isAfter(currentPopulatedStart) && - moment(start).isBefore(currentPopulatedEnd) - ) { - return true; - } - - return false; -} - -// -// Action Creators - -export const fetchCalendar = createThunk(FETCH_CALENDAR); -export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT); -export const setCalendarFilter = createThunk(SET_CALENDAR_FILTER); -export const setCalendarView = createThunk(SET_CALENDAR_VIEW); -export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY); -export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE); -export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE); -export const clearCalendar = createAction(CLEAR_CALENDAR); -export const setCalendarOption = createAction(SET_CALENDAR_OPTION); -export const searchMissing = createThunk(SEARCH_MISSING); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - [FETCH_CALENDAR]: function(getState, payload, dispatch) { - const state = getState(); - const calendar = state.calendar; - const unmonitored = calendar.selectedFilterKey === 'all'; - - const { - time = calendar.time, - view = calendar.view - } = payload; - - const dayCount = state.calendar.dayCount; - const dates = getDates(moment(time), view, state.settings.ui.item.firstDayOfWeek, dayCount); - const { start, end } = getPopulatableRange(dates.start, dates.end, view); - const isPrePopulated = isRangePopulated(start, end, state.calendar); - - const basesAttrs = { - section, - isFetching: true - }; - - const attrs = isPrePopulated ? - { - view, - ...basesAttrs, - ...dates - } : - basesAttrs; - - dispatch(set(attrs)); - - const promise = createAjaxRequest({ - url: '/calendar', - data: { - unmonitored, - start, - end - } - }).request; - - promise.done((data) => { - dispatch(batchActions([ - update({ section, data }), - - set({ - section, - view, - ...dates, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr - })); - }); - }, - - [SET_CALENDAR_DAYS_COUNT]: function(getState, payload, dispatch) { - if (payload.dayCount === getState().calendar.dayCount) { - return; - } - - dispatch(set({ - section, - dayCount: payload.dayCount - })); - - const state = getState(); - const { time, view } = state.calendar; - - dispatch(fetchCalendar({ time, view })); - }, - - [SET_CALENDAR_FILTER]: function(getState, payload, dispatch) { - dispatch(set({ - section, - selectedFilterKey: payload.selectedFilterKey - })); - - const state = getState(); - const { time, view } = state.calendar; - - dispatch(fetchCalendar({ time, view })); - }, - - [SET_CALENDAR_VIEW]: function(getState, payload, dispatch) { - const state = getState(); - const view = payload.view; - const time = view === calendarViews.FORECAST || calendarViews.AGENDA ? - moment() : - state.calendar.time; - - dispatch(fetchCalendar({ time, view })); - }, - - [GOTO_CALENDAR_TODAY]: function(getState, payload, dispatch) { - const state = getState(); - const view = state.calendar.view; - const time = moment(); - - dispatch(fetchCalendar({ time, view })); - }, - - [GOTO_CALENDAR_PREVIOUS_RANGE]: function(getState, payload, dispatch) { - const state = getState(); - - const { - view, - dayCount - } = state.calendar; - - const amount = view === calendarViews.FORECAST ? dayCount : 1; - const time = moment(state.calendar.time).subtract(amount, viewRanges[view]); - - dispatch(fetchCalendar({ time, view })); - }, - - [GOTO_CALENDAR_NEXT_RANGE]: function(getState, payload, dispatch) { - const state = getState(); - - const { - view, - dayCount - } = state.calendar; - - const amount = view === calendarViews.FORECAST ? dayCount : 1; - const time = moment(state.calendar.time).add(amount, viewRanges[view]); - - dispatch(fetchCalendar({ time, view })); - }, - - [SEARCH_MISSING]: function(getState, payload, dispatch) { - const { movieIds } = payload; - - const commandPayload = { - name: commandNames.MOVIE_SEARCH, - movieIds - }; - - executeCommandHelper(commandPayload, dispatch).then((data) => { - dispatch(set({ - section, - searchMissingCommandId: data.id - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [CLEAR_CALENDAR]: createClearReducer(section, { - isFetching: false, - isPopulated: false, - error: null, - items: [] - }), - - [SET_CALENDAR_OPTION]: function(state, { payload }) { - const options = state.options; - - return { - ...state, - options: { - ...options, - ...payload - } - }; - } - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/discoverMovieActions.js b/frontend/src/Store/Actions/discoverMovieActions.js deleted file mode 100644 index 524f1a486..000000000 --- a/frontend/src/Store/Actions/discoverMovieActions.js +++ /dev/null @@ -1,688 +0,0 @@ -import _ from 'lodash'; -import { createAction } from 'redux-actions'; -import { batchActions } from 'redux-batched-actions'; -import { filterBuilderTypes, filterBuilderValueTypes, filterTypes, sortDirections } from 'Helpers/Props'; -import { createThunk, handleThunks } from 'Store/thunks'; -import sortByName from 'Utilities/Array/sortByName'; -import createAjaxRequest from 'Utilities/createAjaxRequest'; -import getNewMovie from 'Utilities/Movie/getNewMovie'; -import getSectionState from 'Utilities/State/getSectionState'; -import updateSectionState from 'Utilities/State/updateSectionState'; -import translate from 'Utilities/String/translate'; -import { removeItem, set, updateItem } from './baseActions'; -import createHandleActions from './Creators/createHandleActions'; -import createClearReducer from './Creators/Reducers/createClearReducer'; -import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer'; -import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer'; -import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer'; -import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer'; -import { filterPredicates } from './movieActions'; - -// -// Variables - -export const section = 'discoverMovie'; - -// -// State - -export const defaultState = { - isFetching: false, - isPopulated: false, - error: null, - isAdding: false, - isAdded: false, - addError: null, - items: [], - sortKey: 'sortTitle', - sortDirection: sortDirections.ASCENDING, - secondarySortKey: 'sortTitle', - secondarySortDirection: sortDirections.ASCENDING, - view: 'overview', - - options: { - includeRecommendations: true - }, - - defaults: { - rootFolderPath: '', - monitor: 'true', - qualityProfileId: 0, - minimumAvailability: 'announced', - tags: [], - searchForMovie: false - }, - - posterOptions: { - size: 'large', - showTitle: false - }, - - overviewOptions: { - detailedProgressBar: false, - size: 'medium', - showStudio: true, - showRatings: true, - showYear: true, - showCertification: true, - showGenres: true - }, - - tableOptions: { - // showSearchAction: false - }, - - columns: [ - { - name: 'status', - columnLabel: translate('Status'), - isSortable: true, - isVisible: true, - isModifiable: false - }, - { - name: 'isRecommendation', - columnLabel: 'Recommedation', - isSortable: true, - isVisible: true, - isModifiable: false - }, - { - name: 'sortTitle', - label: translate('MovieTitle'), - isSortable: true, - isVisible: true, - isModifiable: false - }, - { - name: 'collection', - label: translate('Collection'), - isSortable: true, - isVisible: false - }, - { - name: 'studio', - label: translate('Studio'), - isSortable: true, - isVisible: true - }, - { - name: 'inCinemas', - label: translate('InCinemas'), - isSortable: true, - isVisible: true - }, - { - name: 'physicalRelease', - label: translate('PhysicalRelease'), - isSortable: true, - isVisible: false - }, - { - name: 'digitalRelease', - label: translate('DigitalRelease'), - isSortable: true, - isVisible: false - }, - { - name: 'runtime', - label: translate('Runtime'), - isSortable: true, - isVisible: false - }, - { - name: 'genres', - label: translate('Genres'), - isSortable: false, - isVisible: false - }, - { - name: 'ratings', - label: translate('Ratings'), - isSortable: true, - isVisible: false - }, - { - name: 'certification', - label: translate('Certification'), - isSortable: true, - isVisible: false - }, - { - name: 'lists', - label: 'Lists', - isSortable: false, - isVisible: false - }, - { - name: 'actions', - columnLabel: translate('Actions'), - isVisible: true, - isModifiable: false - } - ], - - sortPredicates: { - status: function(item) { - let result = 0; - - if (item.isExcluded) { - result += 4; - } - - if (item.status === 'announced') { - result++; - } - - if (item.status === 'inCinemas') { - result += 2; - } - - if (item.status === 'released') { - result += 3; - } - - return result; - }, - - collection: function(item) { - const { collection ={} } = item; - - return collection.name; - }, - - studio: function(item) { - const studio = item.studio; - - return studio ? studio.toLowerCase() : ''; - }, - - ratings: function(item) { - const { ratings = {} } = item; - - return ratings.value; - } - }, - - selectedFilterKey: 'newNotExcluded', - - filters: [ - { - key: 'all', - label: translate('All'), - filters: [] - }, - { - key: 'newNotExcluded', - label: 'New Non-Excluded', - filters: [ - { - key: 'isExisting', - value: false, - type: filterTypes.EQUAL - }, - { - key: 'isExcluded', - value: false, - type: filterTypes.EQUAL - } - ] - } - ], - - filterPredicates, - - filterBuilderProps: [ - { - name: 'status', - label: 'Status', - type: filterBuilderTypes.EXACT, - valueType: filterBuilderValueTypes.MOVIE_STATUS - }, - { - name: 'studio', - label: 'Studio', - type: filterBuilderTypes.ARRAY, - optionsSelector: function(items) { - const tagList = items.reduce((acc, movie) => { - acc.push({ - id: movie.studio, - name: movie.studio - }); - - return acc; - }, []); - - return tagList.sort(sortByName); - } - }, - { - name: 'collection', - label: translate('Collection'), - type: filterBuilderTypes.ARRAY, - optionsSelector: function(items) { - const collectionList = items.reduce((acc, movie) => { - if (movie.collection) { - acc.push({ - id: movie.collection.name, - name: movie.collection.name - }); - } - - return acc; - }, []); - - return collectionList.sort(sortByName); - } - }, - { - name: 'inCinemas', - label: 'In Cinemas', - type: filterBuilderTypes.DATE, - valueType: filterBuilderValueTypes.DATE - }, - { - name: 'physicalRelease', - label: 'Physical Release', - type: filterBuilderTypes.DATE, - valueType: filterBuilderValueTypes.DATE - }, - { - name: 'digitalRelease', - label: 'Digital Release', - type: filterBuilderTypes.DATE, - valueType: filterBuilderValueTypes.DATE - }, - { - name: 'runtime', - label: translate('Runtime'), - type: filterBuilderTypes.NUMBER - }, - { - name: 'genres', - label: 'Genres', - type: filterBuilderTypes.ARRAY, - optionsSelector: function(items) { - const tagList = items.reduce((acc, movie) => { - movie.genres.forEach((genre) => { - acc.push({ - id: genre, - name: genre - }); - }); - - return acc; - }, []); - - return tagList.sort(sortByName); - } - }, - { - name: 'ratings', - label: 'Rating', - type: filterBuilderTypes.NUMBER - }, - { - name: 'certification', - label: 'Certification', - type: filterBuilderTypes.EXACT - }, - { - name: 'lists', - label: 'Lists', - type: filterBuilderTypes.ARRAY, - valueType: filterBuilderValueTypes.IMPORTLIST - }, - { - name: 'isExcluded', - label: 'On Excluded List', - type: filterBuilderTypes.EXACT, - valueType: filterBuilderValueTypes.BOOL - }, - { - name: 'isExisting', - label: 'Exists in Library', - type: filterBuilderTypes.EXACT, - valueType: filterBuilderValueTypes.BOOL - }, - { - name: 'isRecommendation', - label: 'Recommended', - type: filterBuilderTypes.EXACT, - valueType: filterBuilderValueTypes.BOOL - } - ] -}; - -export const persistState = [ - 'discoverMovie.defaults', - 'discoverMovie.sortKey', - 'discoverMovie.sortDirection', - 'discoverMovie.selectedFilterKey', - 'discoverMovie.customFilters', - 'discoverMovie.view', - 'discoverMovie.columns', - 'discoverMovie.options', - 'discoverMovie.posterOptions', - 'discoverMovie.overviewOptions', - 'discoverMovie.tableOptions' -]; - -// -// Actions Types - -export const ADD_MOVIE = 'discoverMovie/addMovie'; -export const ADD_MOVIES = 'discoverMovie/addMovies'; -export const SET_ADD_MOVIE_VALUE = 'discoverMovie/setAddMovieValue'; -export const CLEAR_ADD_MOVIE = 'discoverMovie/clearAddMovie'; -export const SET_ADD_MOVIE_DEFAULT = 'discoverMovie/setAddMovieDefault'; - -export const FETCH_DISCOVER_MOVIES = 'discoverMovie/fetchDiscoverMovies'; - -export const SET_LIST_MOVIE_SORT = 'discoverMovie/setListMovieSort'; -export const SET_LIST_MOVIE_FILTER = 'discoverMovie/setListMovieFilter'; -export const SET_LIST_MOVIE_VIEW = 'discoverMovie/setListMovieView'; -export const SET_LIST_MOVIE_OPTION = 'discoverMovie/setListMovieMovieOption'; -export const SET_LIST_MOVIE_TABLE_OPTION = 'discoverMovie/setListMovieTableOption'; -export const SET_LIST_MOVIE_POSTER_OPTION = 'discoverMovie/setListMoviePosterOption'; -export const SET_LIST_MOVIE_OVERVIEW_OPTION = 'discoverMovie/setListMovieOverviewOption'; - -export const ADD_IMPORT_EXCLUSIONS = 'discoverMovie/addImportExclusions'; - -// -// Action Creators - -export const addMovie = createThunk(ADD_MOVIE); -export const addMovies = createThunk(ADD_MOVIES); -export const clearAddMovie = createAction(CLEAR_ADD_MOVIE); -export const setAddMovieDefault = createAction(SET_ADD_MOVIE_DEFAULT); - -export const fetchDiscoverMovies = createThunk(FETCH_DISCOVER_MOVIES); - -export const setListMovieSort = createAction(SET_LIST_MOVIE_SORT); -export const setListMovieFilter = createAction(SET_LIST_MOVIE_FILTER); -export const setListMovieView = createAction(SET_LIST_MOVIE_VIEW); -export const setListMovieOption = createAction(SET_LIST_MOVIE_OPTION); -export const setListMovieTableOption = createAction(SET_LIST_MOVIE_TABLE_OPTION); -export const setListMoviePosterOption = createAction(SET_LIST_MOVIE_POSTER_OPTION); -export const setListMovieOverviewOption = createAction(SET_LIST_MOVIE_OVERVIEW_OPTION); - -export const addImportExclusions = createThunk(ADD_IMPORT_EXCLUSIONS); - -export const setAddMovieValue = createAction(SET_ADD_MOVIE_VALUE, (payload) => { - return { - section, - ...payload - }; -}); - -// -// Action Handlers - -export const actionHandlers = handleThunks({ - - [FETCH_DISCOVER_MOVIES]: function(getState, payload, dispatch) { - dispatch(set({ section, isFetching: true })); - - const { - id, - ...otherPayload - } = payload; - - const includeRecommendations = getState().discoverMovie.options.includeRecommendations; - - const promise = createAjaxRequest({ - url: `/importlist/movie?includeRecommendations=${includeRecommendations}`, - data: otherPayload, - traditional: true - }).request; - - promise.done((data) => { - // set an Id so the selectors and updaters done blow up. - data = data.map((movie) => ({ ...movie, id: movie.tmdbId })); - - dispatch(batchActions([ - ...data.map((movie) => updateItem({ section, ...movie })), - - set({ - section, - isFetching: false, - isPopulated: true, - error: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isFetching: false, - isPopulated: false, - error: xhr.aborted ? null : xhr - })); - }); - }, - - [ADD_MOVIE]: function(getState, payload, dispatch) { - dispatch(set({ section, isAdding: true })); - - const tmdbId = payload.tmdbId; - const items = getState().discoverMovie.items; - const itemToUpdate = _.find(items, { tmdbId }); - - const newMovie = getNewMovie(_.cloneDeep(itemToUpdate), payload); - newMovie.id = 0; - - const promise = createAjaxRequest({ - url: '/movie', - method: 'POST', - contentType: 'application/json', - data: JSON.stringify(newMovie) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - updateItem({ section: 'movies', ...data }), - - itemToUpdate.lists.length === 0 ? removeItem({ section: 'discoverMovie', ...itemToUpdate }) : - updateItem({ section: 'discoverMovie', ...itemToUpdate, isExisting: true }), - - set({ - section, - isAdding: false, - isAdded: true, - addError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isAdding: false, - isAdded: false, - addError: xhr - })); - }); - }, - - [ADD_MOVIES]: function(getState, payload, dispatch) { - dispatch(set({ section, isAdding: true })); - - const ids = payload.ids; - const addOptions = payload.addOptions; - const items = getState().discoverMovie.items; - const addedIds = []; - - const allNewMovies = ids.reduce((acc, id) => { - const item = items.find((i) => i.id === id); - const selectedMovie = item; - - // Make sure we have a selected movie and - // the same movie hasn't been added yet. - if (selectedMovie && !acc.some((a) => a.tmdbId === selectedMovie.tmdbId)) { - if (!selectedMovie.isExisting) { - const newMovie = getNewMovie(_.cloneDeep(selectedMovie), addOptions); - newMovie.id = 0; - - addedIds.push(id); - acc.push(newMovie); - } - } - - return acc; - }, []); - - const promise = createAjaxRequest({ - url: '/movie/import', - method: 'POST', - contentType: 'application/json', - data: JSON.stringify(allNewMovies) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - set({ - section, - isAdding: false, - isAdded: true - }), - - ...data.map((movie) => updateItem({ section: 'movies', ...movie })), - - ...addedIds.map((id) => (items.find((i) => i.id === id).lists.length === 0 ? removeItem({ section, id }) : updateItem({ section, id, isExisting: true }))) - - ])); - }); - - promise.fail((xhr) => { - dispatch( - set({ - section, - isAdding: false, - isAdded: true - }) - ); - }); - }, - - [ADD_IMPORT_EXCLUSIONS]: function(getState, payload, dispatch) { - - const ids = payload.ids; - const items = getState().discoverMovie.items; - - const exclusions = ids.reduce((acc, id) => { - const item = items.find((i) => i.tmdbId === id); - - const newExclusion = { - tmdbId: id, - movieTitle: item.title, - movieYear: item.year - }; - - acc.push(newExclusion); - - return acc; - }, []); - - const promise = createAjaxRequest({ - url: '/exclusions/bulk', - method: 'POST', - data: JSON.stringify(exclusions) - }).request; - - promise.done((data) => { - dispatch(batchActions([ - ...data.map((item) => updateItem({ section: 'settings.importExclusions', ...item })), - - ...data.map((item) => updateItem({ section, id: item.tmdbId, isExcluded: true })), - - set({ - section, - isSaving: false, - saveError: null - }) - ])); - }); - - promise.fail((xhr) => { - dispatch(set({ - section, - isSaving: false, - saveError: xhr - })); - }); - } -}); - -// -// Reducers - -export const reducers = createHandleActions({ - - [SET_ADD_MOVIE_VALUE]: createSetSettingValueReducer(section), - - [SET_ADD_MOVIE_DEFAULT]: function(state, { payload }) { - const newState = getSectionState(state, section); - - newState.defaults = { - ...newState.defaults, - ...payload - }; - - return updateSectionState(state, section, newState); - }, - - [SET_LIST_MOVIE_SORT]: createSetClientSideCollectionSortReducer(section), - [SET_LIST_MOVIE_FILTER]: createSetClientSideCollectionFilterReducer(section), - - [SET_LIST_MOVIE_VIEW]: function(state, { payload }) { - return Object.assign({}, state, { view: payload.view }); - }, - - [SET_LIST_MOVIE_OPTION]: function(state, { payload }) { - const discoveryMovieOptions = state.options; - - return { - ...state, - options: { - ...discoveryMovieOptions, - ...payload - } - }; - }, - - [SET_LIST_MOVIE_TABLE_OPTION]: createSetTableOptionReducer(section), - - [SET_LIST_MOVIE_POSTER_OPTION]: function(state, { payload }) { - const posterOptions = state.posterOptions; - - return { - ...state, - posterOptions: { - ...posterOptions, - ...payload - } - }; - }, - - [SET_LIST_MOVIE_OVERVIEW_OPTION]: function(state, { payload }) { - const overviewOptions = state.overviewOptions; - - return { - ...state, - overviewOptions: { - ...overviewOptions, - ...payload - } - }; - }, - - [CLEAR_ADD_MOVIE]: createClearReducer(section, { - isFetching: false, - isPopulated: false, - error: null, - items: [] - }) - -}, defaultState, section); diff --git a/frontend/src/Store/Actions/index.js b/frontend/src/Store/Actions/index.js index 21c6123a3..3de50b558 100644 --- a/frontend/src/Store/Actions/index.js +++ b/frontend/src/Store/Actions/index.js @@ -1,11 +1,9 @@ import * as addMovie from './addMovieActions'; import * as app from './appActions'; import * as blacklist from './blacklistActions'; -import * as calendar from './calendarActions'; import * as captcha from './captchaActions'; import * as commands from './commandActions'; import * as customFilters from './customFilterActions'; -import * as discoverMovie from './discoverMovieActions'; import * as extraFiles from './extraFileActions'; import * as history from './historyActions'; import * as importMovie from './importMovieActions'; @@ -31,11 +29,9 @@ export default [ addMovie, app, blacklist, - calendar, captcha, commands, customFilters, - discoverMovie, movieFiles, extraFiles, history, diff --git a/frontend/src/Store/Actions/oAuthActions.js b/frontend/src/Store/Actions/oAuthActions.js index 94a4a655c..b6b05d05e 100644 --- a/frontend/src/Store/Actions/oAuthActions.js +++ b/frontend/src/Store/Actions/oAuthActions.js @@ -14,7 +14,7 @@ import createHandleActions from './Creators/createHandleActions'; // Variables export const section = 'oAuth'; -const callbackUrl = `${window.location.origin}${window.Radarr.urlBase}/oauth.html`; +const callbackUrl = `${window.location.origin}${window.Prowlarr.urlBase}/oauth.html`; // // State diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js index f14548f9a..3eae6ded7 100644 --- a/frontend/src/Store/Actions/settingsActions.js +++ b/frontend/src/Store/Actions/settingsActions.js @@ -7,9 +7,6 @@ import delayProfiles from './Settings/delayProfiles'; import downloadClientOptions from './Settings/downloadClientOptions'; import downloadClients from './Settings/downloadClients'; import general from './Settings/general'; -import importExclusions from './Settings/importExclusions'; -import importListOptions from './Settings/importListOptions'; -import importLists from './Settings/importLists'; import indexerFlags from './Settings/indexerFlags'; import indexerOptions from './Settings/indexerOptions'; import indexers from './Settings/indexers'; @@ -36,9 +33,6 @@ export * from './Settings/indexerFlags'; export * from './Settings/indexerOptions'; export * from './Settings/indexers'; export * from './Settings/languages'; -export * from './Settings/importExclusions'; -export * from './Settings/importListOptions'; -export * from './Settings/importLists'; export * from './Settings/mediaManagement'; export * from './Settings/metadata'; export * from './Settings/metadataOptions'; @@ -72,9 +66,6 @@ export const defaultState = { indexerOptions: indexerOptions.defaultState, indexers: indexers.defaultState, languages: languages.defaultState, - importExclusions: importExclusions.defaultState, - importListOptions: importListOptions.defaultState, - importLists: importLists.defaultState, mediaManagement: mediaManagement.defaultState, metadata: metadata.defaultState, metadataOptions: metadataOptions.defaultState, @@ -116,9 +107,6 @@ export const actionHandlers = handleThunks({ ...indexerOptions.actionHandlers, ...indexers.actionHandlers, ...languages.actionHandlers, - ...importExclusions.actionHandlers, - ...importListOptions.actionHandlers, - ...importLists.actionHandlers, ...mediaManagement.actionHandlers, ...metadata.actionHandlers, ...metadataOptions.actionHandlers, @@ -151,9 +139,6 @@ export const reducers = createHandleActions({ ...indexerOptions.reducers, ...indexers.reducers, ...languages.reducers, - ...importExclusions.reducers, - ...importListOptions.reducers, - ...importLists.reducers, ...mediaManagement.reducers, ...metadata.reducers, ...metadataOptions.reducers, diff --git a/frontend/src/Store/Middleware/createPersistState.js b/frontend/src/Store/Middleware/createPersistState.js index c7415c8ec..6576b4699 100644 --- a/frontend/src/Store/Middleware/createPersistState.js +++ b/frontend/src/Store/Middleware/createPersistState.js @@ -87,7 +87,7 @@ const config = { slicer, serialize, merge, - key: 'radarr' + key: 'prowlarr' }; export default function createPersistState() { diff --git a/frontend/src/Store/Middleware/createSentryMiddleware.js b/frontend/src/Store/Middleware/createSentryMiddleware.js index 6358a9d8e..441caa959 100644 --- a/frontend/src/Store/Middleware/createSentryMiddleware.js +++ b/frontend/src/Store/Middleware/createSentryMiddleware.js @@ -36,8 +36,8 @@ function identity(stuff) { } function stripUrlBase(frame) { - if (frame.filename && window.Radarr.urlBase) { - frame.filename = frame.filename.replace(window.Radarr.urlBase, ''); + if (frame.filename && window.Prowlarr.urlBase) { + frame.filename = frame.filename.replace(window.Prowlarr.urlBase, ''); } return frame; } @@ -74,7 +74,7 @@ export default function createSentryMiddleware() { release, userHash, isProduction - } = window.Radarr; + } = window.Prowlarr; if (!analytics) { return; diff --git a/frontend/src/Store/Selectors/createHealthCheckSelector.js b/frontend/src/Store/Selectors/createHealthCheckSelector.js index 1cb74558b..b9d03f9a4 100644 --- a/frontend/src/Store/Selectors/createHealthCheckSelector.js +++ b/frontend/src/Store/Selectors/createHealthCheckSelector.js @@ -12,7 +12,7 @@ function createHealthCheckSelector() { source: 'UI', type: 'warning', message: 'Could not connect to SignalR, UI won\'t update', - wikiUrl: 'https://github.com/Radarr/Radarr/wiki/Health-Checks#could-not-connect-to-signalr' + wikiUrl: 'https://github.com/Prowlarr/Prowlarr/wiki/Health-Checks#could-not-connect-to-signalr' }); } diff --git a/frontend/src/Store/Selectors/createImportListSelector.js b/frontend/src/Store/Selectors/createImportListSelector.js deleted file mode 100644 index 6f365aed5..000000000 --- a/frontend/src/Store/Selectors/createImportListSelector.js +++ /dev/null @@ -1,12 +0,0 @@ -import { createSelector } from 'reselect'; - -function createImportListSelector() { - return createSelector( - (state) => state.settings.importLists.items, - (lists) => { - return lists; - } - ); -} - -export default createImportListSelector; diff --git a/frontend/src/Store/Selectors/createMovieCollectionListSelector.js b/frontend/src/Store/Selectors/createMovieCollectionListSelector.js deleted file mode 100644 index 6db80a118..000000000 --- a/frontend/src/Store/Selectors/createMovieCollectionListSelector.js +++ /dev/null @@ -1,33 +0,0 @@ -import _ from 'lodash'; -import { createSelector } from 'reselect'; - -function createMovieCollectionListSelector() { - return createSelector( - (state, { tmdbId }) => tmdbId, - (state) => state.settings.importLists.items, - (tmdbId, importLists) => { - const importListIds = _.reduce(importLists, (acc, list) => { - if (list.implementation === 'TMDbCollectionImport') { - const collectionIdField = list.fields.find((field) => { - return field.name === 'collectionId'; - }); - - if (collectionIdField && parseInt(collectionIdField.value) === tmdbId) { - acc.push(list); - return acc; - } - } - - return acc; - }, []); - - if (importListIds.length === 0) { - return undefined; - } - - return importListIds[0]; - } - ); -} - -export default createMovieCollectionListSelector; diff --git a/frontend/src/Store/Selectors/createMovieCreditListSelector.js b/frontend/src/Store/Selectors/createMovieCreditListSelector.js deleted file mode 100644 index 51764b379..000000000 --- a/frontend/src/Store/Selectors/createMovieCreditListSelector.js +++ /dev/null @@ -1,37 +0,0 @@ -import _ from 'lodash'; -import { createSelector } from 'reselect'; - -function createMovieCreditListSelector() { - return createSelector( - (state, { tmdbId }) => tmdbId, - (state) => state.settings.importLists.items, - (tmdbId, importLists) => { - const importListIds = _.reduce(importLists, (acc, list) => { - if (list.implementation === 'TMDbPersonImport') { - const personIdField = list.fields.find((field) => { - return field.name === 'personId'; - }); - - if (personIdField && parseInt(personIdField.value) === tmdbId) { - acc.push(list); - return acc; - } - } - - return acc; - }, []); - - let importListId = 0; - - if (importListIds.length > 0) { - importListId = importListIds[0].id; - } - - return { - importListId - }; - } - ); -} - -export default createMovieCreditListSelector; diff --git a/frontend/src/Store/Selectors/createProfileInUseSelector.js b/frontend/src/Store/Selectors/createProfileInUseSelector.js index 7b2e4d169..e9b1c5113 100644 --- a/frontend/src/Store/Selectors/createProfileInUseSelector.js +++ b/frontend/src/Store/Selectors/createProfileInUseSelector.js @@ -6,13 +6,12 @@ function createProfileInUseSelector(profileProp) { return createSelector( (state, { id }) => id, createAllMoviesSelector(), - (state) => state.settings.importLists.items, - (id, movies, lists) => { + (id, movies) => { if (!id) { return false; } - if (_.some(movies, { [profileProp]: id }) || _.some(lists, { [profileProp]: id })) { + if (_.some(movies, { [profileProp]: id })) { return true; } diff --git a/frontend/src/System/Backup/BackupRow.js b/frontend/src/System/Backup/BackupRow.js index 2f454a4b3..1e57c2f7b 100644 --- a/frontend/src/System/Backup/BackupRow.js +++ b/frontend/src/System/Backup/BackupRow.js @@ -97,7 +97,7 @@ class BackupRow extends Component { {name} diff --git a/frontend/src/System/Backup/RestoreBackupModalContent.js b/frontend/src/System/Backup/RestoreBackupModalContent.js index bd3f90598..3c86ae0d4 100644 --- a/frontend/src/System/Backup/RestoreBackupModalContent.js +++ b/frontend/src/System/Backup/RestoreBackupModalContent.js @@ -203,7 +203,7 @@ class RestoreBackupModalContent extends Component {
- Note: Radarr will automatically restart and reload the UI during the restore process. + Note: Prowlarr will automatically restart and reload the UI during the restore process.