1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-19 16:34:34 -04:00

Compare commits

...

347 Commits

Author SHA1 Message Date
Weblate
7cc04245ec Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Jason54 <jason54700.jg@gmail.com>
Co-authored-by: Mark Martines <mark-martines@hotmail.com>
Co-authored-by: Maxence Winandy <maxence.winandy@gmail.com>
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: fordas <fordas15@gmail.com>
Co-authored-by: linkin931 <931linkin@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-03-08 11:08:04 +02:00
Mark McDowall
2caf3c6725 Fixed: Error sending Manual Interaction Required notification
(cherry picked from commit a12cdb34bc0ab78937e3c3677012bf030923aebf)
2024-03-08 08:52:48 +02:00
Bogdan
41ff9352b9 Prevent NullRef in naming when truncating a null Release Group
(cherry picked from commit 13e29bd257ccfccb09e66c940ffabeb6503c05b5)
2024-03-08 08:52:48 +02:00
Helvio Pedreschi
d7b9b2ccb2 Fixed: WebApp functionality on Apple devices
(cherry picked from commit c7dd7abf892eead7796fcc482aa2f2aabaf88712)
2024-03-08 08:52:48 +02:00
Mark McDowall
e90a50a3aa Fixed: Overly aggressive exception release group parsing
(cherry picked from commit 0183812cc58dad0e555125ddd8b33a85cbdecbf2)
2024-03-08 08:52:48 +02:00
Bogdan
a0dd26c353 Configurable URL Base setting for Kodi connections 2024-03-04 03:16:23 +02:00
Bogdan
2286055d6a Fixed: URL Base setting for Kodi connections 2024-03-03 13:48:25 +02:00
Mark McDowall
0a5a4e0a6f New: URL Base setting for Media Server connections
(cherry picked from commit 9fd193d2a82d5c2cdc0f36c1f984e4b6b68aaa8d)
2024-03-03 12:29:47 +02:00
Mark McDowall
619c38c493 Queue Manual Import commands at high priority
(cherry picked from commit 64c6a8879beb1b17122c8f6f74bf7b3cf4dd1570)
2024-03-03 12:29:45 +02:00
Louis R
0b8694c627 Fixed: Don't disable IPv6 in IPv6-only Environment
(cherry picked from commit 13af6f57796e54c3949cf340e03f020e6f8575c4)
2024-03-03 12:23:59 +02:00
Bogdan
e2793e56e9 Bump version to 5.4.2 2024-03-03 12:23:41 +02:00
nopoz
68f61da321 New: Add download directory & move completed for Deluge 2024-03-03 12:23:22 +02:00
Weblate
8edb541e21 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: GkhnGRBZ <gkhn.gurbuz@hotmail.com>
Co-authored-by: Nicolò Castagnola <nipica@outlook.it>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: fordas <fordas15@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translation: Servarr/Radarr
2024-03-03 02:34:23 +02:00
Mark McDowall
d441becc74 New: Bypass archived history for failed downloads in SABnzbd
(cherry picked from commit c99d81e79ba5e6ecec01ddd942440d8a48a1c23b)
2024-03-02 04:01:40 +02:00
Mark McDowall
a97b2ee2ed Increase migration timeout to 5 minutes
(cherry picked from commit 086d3b5afaa7680d22835ca66da2afcb6dd5865e)
2024-03-02 04:00:35 +02:00
Bogdan
e70c61e24e Update caniuse-lite 2024-02-29 02:35:06 +02:00
Bogdan
d1f96746e0 Fix RSS translation token 2024-02-29 02:26:35 +02:00
Weblate
35893697bd Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: EDUYO <eduardoestabiel@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Sadi A. Nogueira <contato@sadi.eti.br>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Xupix <colinaubert25@gmail.com>
Co-authored-by: 闫锦彪 <yanjinbiaohere@163.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-02-29 02:25:08 +02:00
Bogdan
540c150b93 Wrap external links tooltip in Movie Details with flex
Co-authored-by: ricci2511 <ricardo.christmann@protonmail.com>

Fixes #8003
2024-02-28 00:31:57 +02:00
Bogdan
48f819caee Bump version to 5.4.1 2024-02-27 02:25:03 +02:00
Bogdan
4ad7b60d9d New: Add 'cn' language code as Chinese language 2024-02-25 04:09:45 +02:00
Bogdan
7e4231fc0e Fixed: Selection of last added custom filter
Plus some translations and typos
2024-02-23 05:43:48 +02:00
bakerboy448
94287d9427 Update name for errors with metadata API 2024-02-22 01:03:08 +02:00
Servarr
8ec6b5dd4d Automated API Docs update 2024-02-21 22:05:02 +02:00
Mark McDowall
4be43c9f2b Fixed: Multi-word genres in Auto Tags
Fixed #6488

(cherry picked from commit 5c4f82999368edfedd038a0a27d323e04b81a400)
2024-02-21 20:53:34 +02:00
servarr[bot]
c388cf968b Bump node to v20.x on builder 2024-02-21 20:52:43 +02:00
Bogdan
b6b809f473 Fixed: Reprocessing custom formats for file in Manual Import 2024-02-21 20:46:16 +02:00
Bogdan
9dd31be7b3 New: Set Indexer flags in Manual Import 2024-02-21 20:46:16 +02:00
Bogdan
25ab396a2c Fixed: Notifications with only On Movie Add enabled being labeled as disabled 2024-02-21 17:05:39 +02:00
Bogdan
145cd74969 Avoid saving Indexer Flags in Last RSS Release info 2024-02-19 20:55:50 +02:00
Bogdan
b9c76d9bed Bump version to 5.4.0 2024-02-18 19:27:49 +02:00
Weblate
63f16924b1 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Chaoshuai Lü <lcs@meta.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: fordas <fordas15@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-02-17 21:35:15 +02:00
Bogdan
a91a9f7fd9 Fixed: Movie titles using default language after using movie editor 2024-02-17 09:08:56 +02:00
Bogdan
4c8e9f204e Fix movie queue status for download client unavailable 2024-02-16 03:49:23 +02:00
Bogdan
d64ee6681f Fixed: Avoid upgrades for custom formats cut-off already met 2024-02-15 02:21:21 +02:00
Bogdan
2ecc57cd31 Translations for Discover list 2024-02-15 00:34:35 +02:00
Bogdan
9620207503 Improve add/loading error notices
(cherry picked from commit dd704579df43b0dd835f8bb618c4b4412561a888)

Closes #9767
2024-02-15 00:06:28 +02:00
bakerboy448
0b090e5f39 Improve Custom Format rejection messaging
(cherry picked from commit cac97c057faa44c1656e02681cb9ba668faca488)

Closes #9747
2024-02-14 19:21:11 +02:00
Bogdan
51cb0920ed Fix translation token for DL client directory help text
Closes #9769
2024-02-14 19:15:31 +02:00
Bogdan
a90d6682d3 Update Custom Format Deletion confirmation message
Consistency with the rest of the Delete*MessageText

Closes #9766
2024-02-14 19:12:58 +02:00
Bogdan
db62eddf5a Fixed: Allow selection of Cast/Crew names
Fixed #9781
2024-02-14 19:09:19 +02:00
Weblate
ac2b2e6215 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Steve Hansen <steve@hansenconsultancy.be>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-02-14 19:09:05 +02:00
Bogdan
9581dd9764 Show download client ID as hint in select options
(cherry picked from commit c0b17d9345367ab6500b7cca6bb70c1e3b930284)
2024-02-14 02:55:47 +02:00
Bogdan
6c459c744a Improve messaging on indexer specified download client is not available
(cherry picked from commit 84e657482d37eed35f09c6dab3c2b8b5ebd5bac4)
2024-02-14 02:55:31 +02:00
abcasada
4676ecfce9 Hints for week column and short dates in UI settings
(cherry picked from commit 4558f552820b52bb1f9cd97fdabe03654ce9924a)

(cherry picked from commit f1d343218cdbd5a63abeb2eb97bba1105dc8035d)
2024-02-14 02:55:21 +02:00
Bogdan
ef92af9dd8 Fix translation for list exclusion on movie deletion 2024-02-14 02:54:06 +02:00
Qstick
b144482d68 Bump version to 5.3.6 2024-02-11 18:21:31 -06:00
Qstick
173b1d6a4c Fixed: Align DownloadClientInfo in ManualInteractionRequiredMessage with DownloadMessage
Also handle null ref exceptions when DownloadClientInfo is null in notification service
2024-02-11 17:56:35 -06:00
Servarr
5f624a147b Automated API Docs update 2024-02-10 23:10:20 -05:00
Stevie Robinson
af066da4ff New: Ignore 'Other' subfolder when scanning disk
Closes #9718

(cherry picked from commit e1c6722aad1e35a1e2371bc47f399b57e4f96f27)
2024-02-10 22:05:06 -06:00
Alex Herbig
937ebcdac3 New: Add RZeroX to release group parsing exceptions
Closes #9569
Clsoes #9719

(cherry picked from commit e2210228b34a4d98ef64965e810689d39733734e)
2024-02-10 21:54:59 -06:00
Mark McDowall
67f5199667 Fixed: Parsing Hungarian anime releases
Closes #9673

(cherry picked from commit 9ba5850fcaf0a5fb73dec7d7f8f1d8d3de0b3fb9)
2024-02-10 21:40:46 -06:00
Qstick
38cd130da5 Fixed: Remove old naming config from API responses
Closes #9741
2024-02-10 21:32:55 -06:00
Weblate
ed340be2b1 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: aghus <aghus.m@outlook.com>
Co-authored-by: bogdan-rgb <b.hmelniczky@yandex.ru>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translation: Servarr/Radarr
2024-02-11 05:12:22 +02:00
Weblate
34cfb58b39 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Hicabi Erdem <bilgi@hicabierdem.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: aghus <aghus.m@outlook.com>
Co-authored-by: bai0012 <baicongrui@gmail.com>
Co-authored-by: gr0sz <joshuatg727@gmail.com>
Co-authored-by: savin-msk <ns@a77.io>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-02-09 15:26:25 +02:00
Bogdan
3d0f22ca7c Fixed: Ignore invalid tags in CustomScript/Discord/Webhook 2024-02-09 15:17:05 +02:00
Bogdan
2510f44c25 Fixed: Refresh tags state to clear removed tags by housekeeping 2024-02-07 23:20:25 +02:00
Bogdan
c0bf75cae3 Fixed: Recommendations on Postgres 2024-02-07 18:22:45 +02:00
Mark McDowall
a63ab1ddd6 Fixed: Don't use sub folder to check for free disk space for update
(cherry picked from commit f722d49b3a9efefa65bef1b24d90be9332ca62ea)

Closes #9748
2024-02-07 08:53:37 +02:00
Mark McDowall
41cb020ff0 New: Log database engine version on startup
(cherry picked from commit 6ab1d8e16b29e98b4d2ebb68e0356f6f2d3a2c10)
2024-02-07 08:51:39 +02:00
Mark McDowall
d660309b5a Fixed: Redirecting after login
(cherry picked from commit 745b92daf4bf4b9562ffe52dad84a12a5561add5)
2024-02-07 08:51:08 +02:00
Bogdan
222c19e4b3 Fixed: Edit button for import list exclusion on mobile
Fixes #9736
2024-02-06 01:19:58 +02:00
Mark McDowall
b08981dee0 Sort movie files on movie details page
(cherry picked from commit 113b0864b8e92b7b768acc8341bdf4c9e2e1a47f)
2024-02-05 00:24:21 +02:00
Bogdan
4a9c0b2240 Bump version to 5.3.5 2024-02-04 12:54:19 +02:00
Weblate
8970b1276f Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-02-03 22:43:43 +02:00
Bogdan
e868dbf911 Fixed: Naming validation when using max token length 2024-02-03 01:38:54 +02:00
Bogdan
e38b31a220 Fix table columns order for Interactive Search 2024-02-02 23:21:19 +02:00
Bogdan
9b1dac4b57 Tests for Movie Statistics
Closes #7891
2024-02-02 22:34:14 +02:00
Bogdan
20ac0bb0e1 Avoid import loop for already imported movies
(cherry picked from commit b183743d9f0a0b15e4a9db0a9d3d2d1c238b0d9c)

Closes #9325
2024-02-02 22:34:09 +02:00
Mark McDowall
9ffa1cc2b9 Refactor select options in Manual Import
(cherry picked from commit 0685896ed8263ef6d05a933acaf584e6f4aa9f92)

Closes #9613
2024-02-02 20:45:07 +02:00
Mark McDowall
422db874f0 New: Accept ':##' on renaming tokens to allow specifying a maximum length for movie titles and release group
(cherry picked from commit 19db75b36beaa5e549d903b136dbda300f1f8562)

Closes #9713
2024-02-02 19:48:20 +02:00
Servarr
adf647f3e1 Automated API Docs update 2024-02-02 18:03:05 +02:00
Bogdan
dc81f51d40 New: Search Movies on Add for bulk manage collections
Fixes #8670
2024-02-02 17:40:08 +02:00
Mark McDowall
c9da7ee0c9 New: Use Movie Folder Format to improve unmapped folders within root folders
(cherry picked from commit 81d2b18ce1c079c2a9dc3de037c9dceea16733fd)

Closes #8065
2024-02-02 17:40:08 +02:00
Bogdan
7198aa24a6 Refactor tags in WebhookMovie 2024-02-02 17:40:08 +02:00
Weblate
35c6fef2d1 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-02-02 17:39:55 +02:00
Bogdan
deac2bdf5c New: Tags field for Notifiarr and Webhook 2024-02-02 04:22:35 +02:00
bakerboy448
8837473ed8 Improve Release Grabbing & Failure Logging
(cherry picked from commit d7aea82e45a7c5fec9e72b534fc4c9fb8654c519)

Closes #9714
2024-02-02 01:12:35 +02:00
Bogdan
4ac538682d Fix ImportFixture test 2024-02-02 00:59:30 +02:00
Weblate
0277b2b201 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translation: Servarr/Radarr
2024-02-02 00:05:02 +02:00
Stevie Robinson
e73015010e New: Send 'On Manual Interaction Required' notifications in more cases
(cherry picked from commit c5a724f14eec20acf565ac3a036944191b30cab0)

Closes #9722
2024-02-02 00:01:24 +02:00
Mark McDowall
f704ab1512 Improve messaging if release is in queue because all movies in release were not imported
Sync with upstream

(cherry picked from commit 2728bf79ca41bc372de515cb09e1034a8c006c2b)
2024-02-01 23:54:09 +02:00
Bogdan
2f1e077e0d Bind shortcut for pending changes confirmation only when it's shown 2024-01-31 19:42:51 +02:00
Bogdan
cd3397a7a1 Use movie specific translation for quality limits message 2024-01-31 19:42:36 +02:00
Mark McDowall
b3517c14de New: Show error message for pending queue items without movies
(cherry picked from commit 5ca868b4b2d34ba65ba3d40144ed889ccf55343d)

Closes #8320
2024-01-30 22:39:39 +02:00
Bogdan
2d05708fa9 Wrap external links tooltip in Movie Details 2024-01-30 22:22:57 +02:00
Havok Dan
2ca581f2b6 Translated using Weblate (Portuguese (Brazil)) [skip ci]
Currently translated at 100.0% (1700 of 1700 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
2024-01-29 23:48:52 +02:00
Magyar
8289b8978f Translated using Weblate (Hungarian) [skip ci]
Currently translated at 74.6% (1269 of 1700 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
2024-01-29 23:48:52 +02:00
Oskari Lavinto
54c1f54b13 Translated using Weblate (Finnish) [skip ci]
Currently translated at 93.8% (1596 of 1700 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
2024-01-29 23:48:51 +02:00
fordas
918fcfd86e Translated using Weblate (Spanish) [skip ci]
Currently translated at 75.1% (1278 of 1700 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
2024-01-29 23:48:18 +02:00
Crocmou
f55206537c Translated using Weblate (French) [skip ci]
Currently translated at 90.4% (1538 of 1700 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
2024-01-29 23:47:28 +02:00
Weblate
d2d9ac8b9d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-01-29 23:47:26 +02:00
Stevie Robinson
ca1a40723b Add Translations to Settings Pages
(cherry picked from commit f2c31e92ceec7c6a8daffa78f30f15ab8684bef9)
2024-01-29 23:36:09 +02:00
Bogdan
bfff736cfc Translations and some cleanup for extra files and movie editor tables 2024-01-28 14:50:57 +02:00
Bogdan
c2d28dd41b Bump version to 5.3.4 2024-01-28 09:12:02 +02:00
Servarr
0e8a1ca522 Automated API Docs update 2024-01-27 21:23:24 -06:00
Qstick
1ba7bfe585 Correctly show separator for Discovery Table view 2024-01-27 21:15:28 -06:00
Qstick
0be449033f New: Trending and Popular Movies in Discovery 2024-01-27 21:15:28 -06:00
Qstick
3b1d4460ad Fixed: Only show recommendations based on library movies 2024-01-27 21:15:28 -06:00
Bogdan
4eb4128a89 Remove BOM from download clients 2024-01-28 00:01:00 +02:00
Stevie Robinson
f90cdbb112 Translate Download Clients on the backend
(cherry picked from commit 48b12f5b00429a7cd218d23f0544641b0da62a06)

Closes #9391
2024-01-27 23:49:48 +02:00
Stevie Robinson
a8dbc97921 Fixed: Validating DownloadStation output path
(cherry picked from commit 07cbd7c8d29f2e0731f0a11c685f898f7e83b0c8)

Closes #9695
2024-01-27 18:38:44 +02:00
Bogdan
f93e136386 Use string interpolation for test string
Closes #9696
2024-01-27 18:13:37 +02:00
Bogdan
a70fa0fcfe Fix improve parsing logging 2024-01-27 17:58:43 +02:00
Stevie Robinson
c8931784a7 Translate Calendar Frontend
(cherry picked from commit bf43453c040ba0474e0cd71e1c5aa3b98edf13ff)

Closes #8984
2024-01-27 17:57:38 +02:00
Weblate
f601448a65 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Crocmou <slaanesh8854@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Lars <lars.erik.heloe@gmail.com>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: diaverso <alexito_perez.95@hotmail.com>
Co-authored-by: fordas <fordas15@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-01-27 17:37:43 +02:00
bakerboy448
64125a31b6 Improve Parsing Logging 2024-01-27 17:37:17 +02:00
Weblate
2f4da90d8a Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Crocmou <slaanesh8854@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: diaverso <alexito_perez.95@hotmail.com>
Co-authored-by: fordas <fordas15@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-01-27 16:36:08 +02:00
Bogdan
20d9db2cde New: Date added for files in movie details 2024-01-27 13:18:13 +02:00
Mark McDowall
5b7c0a94fb Fixed: History retention for Newsbin
(cherry picked from commit 0ea189d03c8c5e02c00b96a4281dd9e668d6a9ae)
2024-01-27 10:16:38 +02:00
Servarr
1416f7898e Automated API Docs update 2024-01-27 10:16:21 +02:00
Bogdan
f9cd9f3204 Language comment in Manual Import
Closes #9612
2024-01-26 11:58:51 +02:00
Mark McDowall
99ab65f790 New: Add recycle bin path for deleted movies to webhook/custom script
(cherry picked from commit a71d40edba1388d67e4deefd8bfc354a7a83c6b1)

Closes #9674
2024-01-26 11:44:41 +02:00
Bogdan
82fb355930 New: External link to TMDb for Cast/Crew
Fixes #9667
Closes #9668
2024-01-24 14:03:56 +02:00
Servarr
83d437cbb3 Automated API Docs update 2024-01-24 12:28:42 +02:00
Bogdan
4beb5b328b New: Option to disable Email encryption
* New: Option to disable Email encryption

(cherry picked from commit 7be5732a3a6679120b0f01bd1eb1207194f57f5e)

* Fix possible NullRef in Email Encryption migration

(cherry picked from commit 271266b10ac51ee6dd7a7024d346b631bd5397c2)

---------

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2024-01-24 12:11:51 +02:00
Bogdan
23830f50ac Fixed: Testing for disabled Notifications 2024-01-24 12:10:57 +02:00
Weblate
b808a92cdf Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translation: Servarr/Radarr
2024-01-24 09:41:04 +02:00
Mark McDowall
3185c73659 New: Optionally remove from queue by changing category to 'Post-Import Category' when configured
(cherry picked from commit 345854d0fe9b65a561fdab12aac688782a420aa5)

Closes #9680
2024-01-24 09:37:39 +02:00
Weblate
7dc9ec03a5 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Alexander <a.burdun@gmail.com>
Co-authored-by: Dani Talens <databio@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: fordas <fordas15@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: wilfriedarma <wilfriedarma.collet@gmail.com>
Co-authored-by: zichichi <sollami@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translation: Servarr/Radarr
2024-01-24 08:59:10 +02:00
Servarr
33228335e3 Automated API Docs update 2024-01-24 08:58:09 +02:00
Mark McDowall
833340f8bd New: Add size to more history events
(cherry picked from commit 0d064181941fc6d149fc2f891661e059758d5428)

Closes #9672
2024-01-24 08:46:54 +02:00
Mark McDowall
0ecb1d0706 New: Add download client name to pending items waiting for a specific client
(cherry picked from commit 3cd4c67ba12cd5e8cc00d3df8929555fc0ad5918)

Closes #9676
2024-01-24 08:41:27 +02:00
Bogdan
25b77eb4a2 Update database migration version translation token
(cherry picked from commit 7d0d503a5e132cda3c03d6f7cd7b51c9c80740de)

Closes #9679
2024-01-24 08:30:52 +02:00
Stevie Robinson
b946173c05 Add Regular Expression Custom Format translation
(cherry picked from commit 9f50166fa62a71d0a23e2c2d331651792285dc0e)

Closes #9678
2024-01-24 08:28:10 +02:00
Bogdan
e5ccc32a37 Fixed: Movie status after using movie editor
Fixes #9681
2024-01-24 08:20:02 +02:00
Bogdan
3aeb52c3fd Fixed: Sorting by name in Manage Indexer and Download Client modals 2024-01-22 14:13:22 +02:00
Servarr
c717989034 Automated API Docs update 2024-01-21 16:24:34 +02:00
Bogdan
806b89abbe Fixed: Use movie file from state for status label in add search results 2024-01-21 16:17:46 +02:00
Bogdan
cc7104a814 Movie stats for Calendar 2024-01-21 16:17:46 +02:00
Bogdan
84c2d7f69d Revert "Add SizeOnDisk and HasFile to MovieResource"
This reverts commit 0ae8952b38.
2024-01-21 16:17:46 +02:00
bakerboy448
fcd187970c Improve Release Title Custom Format debugging
(cherry picked from commit ec40bc6eea1eb282cb804b8dd5461bf5ade332e9)

Closes #9653
2024-01-21 07:34:12 +02:00
Bogdan
34eb59dde4 Bump version to 5.3.3 2024-01-21 07:32:09 +02:00
Weblate
31b66c6673 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Blair Noctis <fqmxz5hyfba7ft85@neon.casa>
Co-authored-by: Dani Talens <databio@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Julian Baquero <julian-baquero@upc.edu.co>
Co-authored-by: Koch Norbert <kochnorbert@icloud.com>
Co-authored-by: MaddionMax <kovacs.tamas@ius.hu>
Co-authored-by: Magyar <kochnorbert@icloud.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: blabla <romcrack56@gmail.com>
Co-authored-by: brn <barantsenkul@gmail.com>
Co-authored-by: fordas <fordas15@gmail.com>
Co-authored-by: horvi28 <horvi28@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-01-21 03:50:25 +02:00
servarr[bot]
06a96ef2d1 Fixed: Movies poster view on mobile devices (#9659)
(cherry picked from commit c0b30a50281c38a103c2f800064d0ec964fae6e0)

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2024-01-21 03:44:01 +02:00
Bogdan
c77ce2459c Transpile logical assignment operators with babel
(cherry picked from commit 3cf4d2907e32e81050f35cda042dcc2b4641d40d)
2024-01-21 03:43:33 +02:00
servarr[bot]
083989d151 New: Log warning if less than 1 GB free space during update
* New: Log warning if less than 1 GB free space during update

(cherry picked from commit e66ba84fc0b5b120dd4e87f6b8ae1b3c038ee72b)

---------

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2024-01-21 03:43:10 +02:00
Mark McDowall
c003fe16de Fixed: Don't clone indexer API Key
(cherry picked from commit d336aaf3f04136471970155b5a7cc876770c64ff)
2024-01-20 07:43:06 +02:00
Mark McDowall
bc9b2cd283 Refactor icons on full color calendar events
(cherry picked from commit 9884f6f282560ff2a0ea193e9306c6284cf8672c)

Closes #9646
2024-01-19 16:10:55 +02:00
Bogdan
d0e400c55a Wrap values in log messages in FileListParser
Closes #9644
2024-01-19 09:51:12 +02:00
Stevie Robinson
77863dc2cf New: Drop commands table content before postgres migration
Signed-off-by: Stevie Robinson <stevie.robinson@gmail.com>

(cherry picked from commit 8dd3b45c90209136c0bd0a861061c6d20837d62f)
2024-01-19 09:51:04 +02:00
Stevie Robinson
18dc6f60b0 Round off the seeded ratio when checking for removal candidates
Signed-off-by: Stevie Robinson <stevie.robinson@gmail.com>

(cherry picked from commit c6bb6ad8788fb1c20ed466a495f2b47034947145)
2024-01-19 08:15:59 +02:00
Bogdan
49501a55ae Check paged requests using PageSize for Import Lists 2024-01-18 09:30:28 +02:00
Weblate
d5d77a4f1a Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Blair Noctis <fqmxz5hyfba7ft85@neon.casa>
Co-authored-by: Dani Talens <databio@gmail.com>
Co-authored-by: Deleted User <noreply+2593@weblate.org>
Co-authored-by: Koch Norbert <kochnorbert@icloud.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2024-01-18 09:24:07 +02:00
Bogdan
0ae8952b38 Add SizeOnDisk and HasFile to MovieResource 2024-01-17 06:25:50 +02:00
Bogdan
6292ff76b0 Rename episode to movie 2024-01-17 05:21:25 +02:00
Bogdan
646d271e81 Add title to invalid Plex RSS item log
Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2024-01-17 01:15:57 +02:00
Bogdan
3d2ca830bc Fixed: Importing Plex RSS lists with invalid items 2024-01-17 01:13:21 +02:00
Bogdan
da02ec3b04 Add missing import needed for Added column 2024-01-17 00:49:17 +02:00
bakerboy448
cc9a443473 Update logging to indicate a hardlink is being attempted
(cherry picked from commit 16e5ffa467f72e52c750143c835f6ee1c1c2460b)

Closes #9611
2024-01-17 00:12:17 +02:00
Stevie Robinson
81b6bf521d Add missing translation keys from Indexer Settings
Signed-off-by: Stevie Robinson <stevie.robinson@gmail.com>
(cherry picked from commit 07fbb0d1f464513ed28721d6c91d428dd54818cf)

Closes #9627
2024-01-17 00:10:56 +02:00
Bogdan
7edb892eb4 Throw download as failed for invalid magnet links
(cherry picked from commit 091449d9bff9023ca27a85cc1048296f7d5ea37b)

Closes #9625
Fixes #9125
2024-01-17 00:07:04 +02:00
Blair Noctis
3b36921787 Fixed: Improve help text for download client priority
(cherry picked from commit 1bba7e177b5b4173e620cd014ffdc231023309a0)

Closes #9622
2024-01-17 00:06:12 +02:00
Rubicj
c2d8bc85d0 New: Added column in Queue
(cherry picked from commit 57445bbe57a84990e284ef97d42455a06587e1ee)

Closes #9621
2024-01-17 00:04:30 +02:00
Bogdan
3e55b1cf25 Fix Content-Type in FileList fixture 2024-01-16 21:51:55 +02:00
Bogdan
0b0c93081d Check Content-Type in FileList parser 2024-01-16 21:39:03 +02:00
Servarr
91fbad72c0 Automated API Docs update 2024-01-16 20:58:27 +02:00
Bogdan
35651ac59b New: Release Groups for movie table index
* New: Release Group for movie table index

Co-authored-by: Qstick <qstick@gmail.com>

* fixup! New: Release Group for movie table index

---------

Co-authored-by: Qstick <qstick@gmail.com>
2024-01-16 20:52:07 +02:00
Qstick
1932aec131 Improved http timeout handling
(cherry picked from commit f87a66fcba6ca9ca972fa1c747a940b216e0e5e3)
2024-01-16 08:48:21 +02:00
Stevie Robinson
ea470b4ee9 Sort Custom Filters
(cherry picked from commit e4b5d559df2d5f3d55e16aae5922509e84f31e64)
2024-01-16 08:05:18 +02:00
Qstick
1bb404a912 Fixed: Only use frames for Primary video stream for analysis 2024-01-15 23:16:22 -06:00
Weblate
374d20634d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Daniele Prevedello <dprevedello86@gmail.com>
Co-authored-by: DimitriDR <dimitridroeck@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Petr Vojar <vojar.petr@outlook.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: crayon3shawn <crayon3shawn@gmail.com>
Co-authored-by: hansaudun <hans@n5.no>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_TW/
Translation: Servarr/Radarr
2024-01-15 01:44:06 +02:00
Qstick
60d9aacac6 Build report can get sent before installer finished 2024-01-14 13:27:52 -06:00
Qstick
c5992ed944 Bump Inno version to 6.2.2 2024-01-14 12:59:58 -06:00
Mark McDowall
4c4073ce1c New: Support SABnzb's new format for sorters
(cherry picked from commit d484553b310af4257c841c37a503ef54650c1426)

Closes #9351
2024-01-14 18:08:18 +02:00
Jendrik Weise
d72f78d979 New: Custom import scripts can communicate information back
(cherry picked from commit b4ac495983d61819d9ab84f49c880957ba57418b)
2024-01-14 16:15:48 +02:00
Bogdan
dca9d69aaa Bump version to 5.3.2 2024-01-14 07:10:07 +02:00
Stevie Robinson
5a64826868 Add: New icon for deleted episodes with status missing from disk
Signed-off-by: Stevie Robinson <stevie.robinson@gmail.com>
(cherry picked from commit 79907c881cc92ce9ee3973d5cf21749fe5fc58da)

Closes #9604
2024-01-14 03:47:30 +02:00
Mark McDowall
cda40312e0 New: Optional directory setting for Aria2
(cherry picked from commit fd17df0dd03a5feb088c3241a247eac20f0e8c6c)

Closes #9602
2024-01-14 03:43:37 +02:00
Bogdan
907779b4ce Fetch movie file entity from database to broadcast 2024-01-14 03:42:03 +02:00
Mark McDowall
cc03651af5 Don't use TestCase for single test
(cherry picked from commit 541d3307e1466b0353dc4149f502a4b62b4de616)
2024-01-14 03:41:26 +02:00
servarr[bot]
1ae98d618c Fixed: Movie posters flickering when width changes repeatedly
(cherry picked from commit 53cf5308931069638c23925596a3fd8aaccc5d98)

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2024-01-14 03:40:54 +02:00
Bogdan
f5914da2f9 Remove double filtering in entity history repository 2024-01-12 22:05:51 +02:00
Bogdan
f7816aa5cd Fixed: Filter history by multiple event types in PG 2024-01-12 22:05:51 +02:00
Andrejs Ķīlis
a652ce50a9 Fixed: Latvian and Russian language parsing
Improved support for Latvian with test cases I have encountered in the wild and fixed a case where Russian is not recognized (RU instead of RUS).
2024-01-12 03:00:51 +02:00
Bogdan
58b726a292 Fixed: Improve torrent blocklist matching
Closes #9585
2024-01-12 02:56:32 +02:00
Bogdan
1d8cf6a7f5 Fixed: Persist release source for pending releases
Closes #9583
2024-01-12 02:54:31 +02:00
ilike2burnthing
2c3ad380ef Remove unsupported pagination for Nyaa
(cherry picked from commit fef525ddb8b5f91bb36b3c9e652663fccb098a00)

Closes #9582
2024-01-12 02:52:53 +02:00
Stevie Robinson
0e7874aacf Fix Missing HelpText Translation Keys
(cherry picked from commit 587b600d6c6bac64c99d12225360810ef283f0aa)

Closes #9576
2024-01-12 02:45:57 +02:00
Weblate
8638d82ad3 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Aleksandr <alyarmak@gmail.com>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Bradley BARBIER <bradley.barbier@outlook.fr>
Co-authored-by: Dani Talens <databio@gmail.com>
Co-authored-by: DimitriDR <dimitridroeck@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: HuaBing <admin@hbcraft.cn>
Co-authored-by: JJonttuu <oikeaihminen@protonmail.com>
Co-authored-by: Juan Lores <juan.lores@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Piotr Komborski <piotr+github@kombor.ski>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Watashi <drazy24@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: boan51204 <je.991707@gmail.com>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: liangyi <994302767@qq.com>
Co-authored-by: marius-tu <marius.tubbesing94@gmail.com>
Co-authored-by: ragote <ragote@pm.me>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: twobuttonbob <madinlol@gmail.com>
Co-authored-by: 饶志华 <879467666@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/lv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_TW/
Translation: Servarr/Radarr
2024-01-12 02:41:40 +02:00
Bogdan
f3d6a1f99d Fixed: Release source for release/push 2024-01-11 02:07:03 +02:00
Bogdan
fa036f5807 Sorting movie list by tags 2024-01-11 00:41:53 +02:00
Bogdan
a931f8a69f Fixed: Skip fewer slides with cast/crew on smaller screens
Fixes #9571
2024-01-10 20:51:40 +02:00
Bogdan
a491c9a4a0 Fixed: Parsing custom formats for releases titles containing colon 2024-01-10 20:34:24 +02:00
Bogdan
2aafb6369c Fix app name in healthcheck 2024-01-10 01:35:08 +02:00
Mark McDowall
ef8253044e Fixed: Blocklisting torrents from indexers that do not provide torrent hash
(cherry picked from commit 3541cd7ba877fb785c7f97123745abf51162eb8e)
2024-01-09 00:30:32 +02:00
Bogdan
c1feeb72ee New: Year specification for custom formats 2024-01-08 02:29:29 +02:00
Servarr
21560cd6cc Automated API Docs update 2024-01-07 16:36:16 +02:00
Bogdan
bda2b9b0b8 Fixed: Filter history by multiple event types 2024-01-07 16:07:36 +02:00
Bogdan
4630de9616 Bump version to 5.3.1 2024-01-07 11:10:52 +02:00
Bogdan
7e83180e50 Remove title for actions in movie history
Closes #9549
2024-01-04 13:24:28 +02:00
Stevie Robinson
e60eed49c7 Translate Notifications settings
(cherry picked from commit 8f7f23c9380036e87669fa663e846321cf7ebf87)

Closes #9550
2024-01-04 12:49:26 +02:00
Gabriel Patzleiner
74cfc94b4c New: Correctly parse German DL and ML tags in releases 2024-01-02 18:58:28 -06:00
Gabriel Patzleiner
213c55c7af Fixed: Don't parse some movies with German in the movie title
fixes #6474
2024-01-02 18:58:28 -06:00
Gabriel Patzleiner
c066fa5e27 Delete tests that are not needed and not working anymore since 7ec0fd1cea 2024-01-02 18:58:28 -06:00
Gabriel Patzleiner
2741ecb968 Added new IndexerBaseFixture to test Multi tag in releases 2024-01-02 18:58:28 -06:00
Qstick
7965c29425 Fixed: Change "Manual Import" to "Manage Files" in MovieDetails
Prevent confusion with interactive search icon being identical and align to Sonarr naming.
2024-01-01 11:35:11 -06:00
Bogdan
d2cbab70a9 New: Confirmation for searching movies 2024-01-01 17:35:01 +02:00
Weblate
16381a1aef Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Mario Rodriguez <mario2423@gmail.com>
Co-authored-by: Norbi <kovinor123@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2024-01-01 14:11:00 +02:00
Bogdan
b92e08b850 Fixed: Disable movie search button if none are listed 2024-01-01 08:20:35 +02:00
Bogdan
eab470c67f New: Movie search will look for movies that haven't been searched recently first 2024-01-01 08:20:35 +02:00
Mark McDowall
7f11659d95 New: Store last search time for MovieSearch
(cherry picked from commit 9af57c6786)
2024-01-01 08:20:35 +02:00
Mark McDowall
03dec07cbe Fixed: Disable SSL on start if certificate path is not set
(cherry picked from commit 4e19fec123900b8ba1252b640f26f2a4983683ff)
2023-12-31 18:40:21 -06:00
Qstick
554c696ee6 Fixed: MovieDetails size incorrect when moviefile store changes
Use movie prop instead

Closes #9309
2023-12-31 16:47:44 -06:00
Qstick
093f8a39fe New: Custom sort crew by job in movie details 2023-12-31 12:55:09 -06:00
Servarr
8a1663f136 Automated API Docs update 2023-12-31 12:03:51 -06:00
bakerboy448
251d2dde97 Improve Import Custom Format Compare Logging 2023-12-31 11:37:02 -06:00
Qstick
996542a4a5 Reduce size of Collection on Movie endpoint
Ensures we don't send false data and reduces the object size to only what's necessary here.

Closes #9521
2023-12-31 11:29:32 -06:00
randomllama
0914d6250c New: Add Movie Status to Kodi .nfo
Closes #9115

(cherry picked from commit b76de3987b0c30e6509d37d82e3163d067a9c6c8)
2023-12-31 11:19:25 -06:00
Bogdan
3ff8e511b5 New: Tags field for Discord 2023-12-31 18:58:39 +02:00
Qstick
3a7b27fb45 Fixed: Parse HebDubbed as Hebrew
Fixes #9513
2023-12-31 10:48:13 -06:00
Weblate
c81d2c97f5 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Koch Norbert <kochnorbert@icloud.com>
Co-authored-by: Nicola <nicola.neri@gmail.com>
Co-authored-by: SunStorm <me@sunstorm.rocks>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: chiral-lab <jan.eltner@googlemail.com>
Co-authored-by: chrizl <chrizl@gmail.com>
Co-authored-by: resi23 <x-resistant-x@gmx.de>
Co-authored-by: slammingdeath <sebastianbrudny97@gmail.com>
Co-authored-by: ube <ube@alienautopsy.net>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sv/
Translation: Servarr/Radarr
2023-12-31 12:26:08 +02:00
Bogdan
dae46524c4 Fix possible multiple enumeration in update collections 2023-12-31 09:49:17 +02:00
Stevie Robinson
3c6386f318 Translate fields on the backend
(cherry picked from commit 48b12f5b00429a7cd218d23f0544641b0da62a06)
2023-12-31 09:38:03 +02:00
Mark McDowall
1400a8806d New: Add qBittorrent option for Content Layout
(cherry picked from commit 4b22200708ca120cfdcf9cb796be92183adb95d1)

Closes #9522
2023-12-31 09:38:03 +02:00
Stevie Robinson
e3f33f5a61 New: Add sorting to Manage Indexer and Download Client modals
(cherry picked from commit 91053ca51ded804739f94ee936c1376a755dbe11)

Closes #9524
2023-12-31 09:38:03 +02:00
Stevie Robinson
e6f4b88cf3 New: Show Proper or Repack tag in interactive search
(cherry picked from commit efb000529b5dff42829df3ef151e4750a7b15cf6)

Closes #9523
2023-12-31 09:38:03 +02:00
Bogdan
b788464487 Fixed: Show errors when adding Root Folder
(cherry picked from commit 16d60a6586aeb458601214258da021ee154e5b6e)

Closes #9527
2023-12-31 09:38:03 +02:00
Bogdan
e29717ec6c New: Retry on failed downloads of torrent and nzb files
(cherry picked from commit bc20ef73bdd47b7cdad43d4c7d4b4bd534e49252)

Closes #9528
2023-12-31 09:38:03 +02:00
Bogdan
5d7e23092f Bump version to 5.3.0 2023-12-31 09:38:03 +02:00
Bogdan
9921d51451 Cleanup unused code in movie credit posters 2023-12-25 15:45:33 +02:00
Bogdan
213620cb29 Fixed: Navigation for cast and crew 2023-12-25 14:56:41 +02:00
Bogdan
bdc4aade0f Use extra release fields in PassThePopcorn parser 2023-12-24 06:56:48 +02:00
Weblate
b2300dbf41 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Pietro Ribeiro <xxb1exuv6@mozmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translation: Servarr/Radarr
2023-12-23 23:31:39 +02:00
Weblate
44289d30f9 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Aitzol Garmendia <aitzolgarmendia@gmail.com>
Co-authored-by: Andrés Reyes Monge <armonge@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Michael Schönenberger <muchi94@gmail.com>
Co-authored-by: VisoTC <szlytlyt@outlook.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: ηg <jonas.konrath@icloud.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-12-22 04:24:19 +02:00
luz paz
260fb88f85 Fix various typos
Found via `codespell -q 3`

(cherry picked from commit 209a250079fdf7ad2bc9168f81bfb45b9531d6b3)
2023-12-19 20:18:54 +02:00
Bogdan
119cdf6f09 Fixed: Cleanup orphaned import list movies by movie metadata 2023-12-18 00:51:59 +02:00
Bogdan
c8d30fd214 Cleanup convert root folders to TS 2023-12-17 23:23:08 +02:00
Bogdan
7e9e528d3b Fixed: Ignore empty tags when adding items to Flood
Fixed #8145
2023-12-17 22:09:13 +02:00
Bogdan
8554c0d9cb Refactor movie alternative titles connector 2023-12-17 19:57:22 +02:00
Bogdan
22cc34b4fe Bump version to 5.2.6 2023-12-17 16:01:10 +02:00
Weblate
990785ebfc Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Menno Liefstingh <mennoliefstingh@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: lifeisfreedom048 <koyuncu.ozgur@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translation: Servarr/Radarr
2023-12-16 02:41:57 +02:00
Bogdan
957be99401 Fixed: Bump media info revision for DV HDR10Plus 2023-12-16 02:41:34 +02:00
Bogdan
4bcde25e29 Improve messaging for accepted Custom Formats scoring upgrades
Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>

Closes #9496
2023-12-16 00:38:05 +02:00
Bogdan
1d70f36e7d New: 3D and HDR metadata for Trakt connection 2023-12-15 17:13:47 +02:00
Bogdan
cc0a448bc8 New: Rate limiting for Trakt connection 2023-12-15 17:13:47 +02:00
Bogdan
c9e977baea Simplify mapping in Trakt connection 2023-12-15 17:13:47 +02:00
Mark McDowall
6cb9a46cd4 Fixed: Imported movies updating on Calendar
(cherry picked from commit 5a3bc49392b700650a34536ff3794bce614f64a4)

Closes #9491
2023-12-15 16:50:06 +02:00
Agneev Mukherjee
eef379277a Enable browser navigation buttons for PWA
(cherry picked from commit da9a60691f363323565a293ed9eaeb6349ceccb6)

Closes #9487
2023-12-15 16:36:28 +02:00
Chad A Simmons
41fef47684 New: Support for DV HDR10Plus from media info 2023-12-15 03:36:32 +02:00
Weblate
fcda6faf3d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: ROSERAT Ugo <roserat.ugo@gmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: SHUAI.W <x@ousui.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/lv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-12-13 16:41:49 +02:00
Bogdan
79bbf9c50b Fixed: Movie status label in add movie search results 2023-12-12 21:55:41 +02:00
Bogdan
43d2f2804b New: IMDb ratings and genres in add movie search results 2023-12-12 21:55:09 +02:00
Qstick
fa62f3f66a Fixed: Correctly handle Migration when PG Host has ".db"
(cherry picked from commit 97ee24507f4306e3b62c3d00cd3ade6a09d1b957)

Closes #9478
2023-12-12 15:36:21 +02:00
Bogdan
229d91fe40 Implement DatabaseConnectionInfo
Co-authored-by: Qstick <qstick@gmail.com>
2023-12-12 15:36:14 +02:00
Bogdan
2673d1eee4 Fixed: Movie poster in search results after adding
Fixes #8029
2023-12-11 19:30:31 +02:00
Bogdan
e59fd1118f Fixed: Downloading status post-adding movie 2023-12-11 19:27:05 +02:00
Bogdan
c1fd33b152 Fix categories for NZBFinder 2023-12-10 15:50:19 +02:00
Bogdan
2f58c8676f Bump dotnet to 6.0.25 2023-12-10 15:35:59 +02:00
Fossil
defc448304 Update NZBFinder categories and remove OZnzb & NZB-Tortuga from default definitions (#9474)
NZB Finder will consolidate WEBDL & X265 into SD,HD,UHD so removed 2080 and 2090 categories.

OZnzb and NZB Tortuga are dead so removed it from the presets list.
2023-12-10 15:14:13 +02:00
Bogdan
3ec3358728 Bump version to 5.2.5 2023-12-10 13:47:06 +02:00
Weblate
d4072cdfe2 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Jurriaan Den Toonder <jur.den.toonder@gmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translation: Servarr/Radarr
2023-12-08 18:00:35 +02:00
Weblate
136a030c07 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Hajiroxx <luypanda@163.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-12-08 16:03:26 +02:00
Weblate
6d89ae89a4 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Augusto Poletti <augustpolet@gmail.com>
Co-authored-by: Dominika Matějková <dominika.matejkova@outlook.cz>
Co-authored-by: VisoTC <szlytlyt@outlook.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 米大饭 <1246333567@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-12-06 16:01:05 +02:00
Servarr
98e4273b7a Automated API Docs update 2023-12-06 16:00:42 +02:00
Bogdan
ecf9983ea6 Fix minimum availability label in movie table row 2023-12-06 14:35:55 +02:00
Bogdan
a059a700eb New: Minimum Availability in bulk manage import lists
Fixes #9461
2023-12-06 14:35:20 +02:00
Taloth Saldono
ced624c2ff Small helper in UI to access Radarr API more easily
(cherry picked from commit 090cdc364ef335fbfea8cf540696af813f6ecea4)
2023-12-06 13:16:02 +02:00
Bogdan
7c32061e17 Add existing flag for Discover Movie Posters 2023-12-06 13:12:49 +02:00
Bogdan
bc4847cdc7 New: Improve fields selection for Discord connection 2023-12-06 11:03:57 +02:00
Bogdan
65d79dd078 Fixed: Progress bar for collection movies in queue 2023-12-04 13:17:29 +02:00
Bogdan
238ddbbe1f Fixed: Improve Required Flags selection for indexers 2023-12-04 12:53:33 +02:00
Bogdan
3f444406da Fixed: (PassThePopcorn) Support for half leech releases 2023-12-04 12:34:22 +02:00
Bogdan
d7aaa1cdc2 Fixed: Cleanup orphaned movies 2023-12-03 22:02:56 +02:00
Mark McDowall
263534717d Always validate Custom Script path
(cherry picked from commit c922cc5dc617dd776d4523cbf62376821c5a4ad9)
2023-12-03 20:03:07 +02:00
Weblate
073d15160d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: David Molero <contact@dolvem.com>
Co-authored-by: Patatra <patrice.chevreau@gmail.com>
Co-authored-by: Zalhera <tobias.bechen@gmail.com>
Co-authored-by: liimee <git.taaa@fedora.email>
Co-authored-by: resi23 <x-resistant-x@gmx.de>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/id/
Translation: Servarr/Radarr
2023-12-01 04:03:43 +02:00
Stevie Robinson
c5075e5d49 Fixed Custom Format Deletion confirmation message
(cherry picked from commit b76bf373717edff8e475fde31fbaec86c65903fe)

Closes #9410
2023-11-26 08:43:02 +02:00
Weblate
fc345047ee Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Appoxo <appoxo@appoxo.de>
Co-authored-by: Charlie <zola@zipmail.pw>
Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-11-26 08:28:12 +02:00
Weblate
bffab87da7 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-11-26 08:26:37 +02:00
Bogdan
a8a9d3b833 Bump version to 5.2.4 2023-11-26 07:05:58 +02:00
Stevie Robinson
ff1987be84 New: Remove defunct Boxcar notifications
(cherry picked from commit c6ad2396bb98dc8eb1ad47bf5d066b227a47f8b5)

Closes #9451
2023-11-25 22:29:33 +02:00
Bogdan
cb08c0767d Switch assignment to operator 2023-11-22 21:50:29 +02:00
Bogdan
5f1d7ddc11 Improve discover movies sorting by release dates 2023-11-21 22:45:23 +02:00
Bogdan
0ba3c08ea6 Small UI fixes to discover movies 2023-11-21 22:37:36 +02:00
Bogdan
6b9a378eaf Fixed: Minimum refresh interval for import list presets 2023-11-21 19:52:58 +02:00
Bogdan
b4562e6236 Fixed: Movie grabbed history on interactive search 2023-11-21 03:45:19 +02:00
Bogdan
bbffff78ed Fixed: Disable swipe on movie details when a modal is open 2023-11-20 22:16:01 +02:00
Bogdan
740f0f1e5f Cleanup unused logic in Movie Details 2023-11-20 21:37:13 +02:00
Bogdan
45b38b44c1 Fixed: Interactive search modal on mobile 2023-11-20 07:52:48 +02:00
Mark McDowall
318d59bb99 Fixed force saving provider triggering testing
(cherry picked from commit 65cb1ccafd54479fa3fca1f1eaa4b96222b0176b)
2023-11-20 07:37:42 +02:00
Bogdan
ed54d071c4 Fixed: Wrap long lines in media info popup 2023-11-20 07:06:45 +02:00
Bogdan
cff15de4fc Translate custom format score for history actions 2023-11-20 05:48:02 +02:00
Bogdan
88c0e24c58 Fixed: Clear movie search results when navigating to another page
(cherry picked from commit 67dc8987970aa2a9eade48c02ae72be1851fa196)
2023-11-19 21:10:43 -06:00
Qstick
8e0645670b New: Rework Movie Details view 2023-11-19 21:10:43 -06:00
Qstick
40eeb31a21 New: Move Interactive search to toolbar 2023-11-19 21:10:43 -06:00
Qstick
3e534cf8bf Bump version to 5.2.3 2023-11-19 18:31:23 -06:00
Bogdan
c96b3c4b0b Fixed: Autotagging Genres are case insensitive
(cherry picked from commit 87ecbf39c1c0cc8a3a3f4ee1d1878b34ea49f6b8)

Closes #9436
2023-11-20 00:59:06 +02:00
Mark McDowall
78bc9f9b4b Fixed: Saving indexer, download client, etc settings
(cherry picked from commit 804a5921b3b620e2407d5d6a7fd69fb1fd9b0cbf)
2023-11-20 00:53:45 +02:00
Servarr
b737f05a83 Automated API Docs update 2023-11-19 22:40:17 +02:00
Bogdan
8d96fd2387 More cleanup appName tokens 2023-11-19 22:35:57 +02:00
servarr[bot]
6c487ead00 Fixed: Disable SSL when using the removed SslCertHash configuration (#9426)
(cherry picked from commit d95660d3c78d1ee11a7966d58e78a82a8df01393)

Co-authored-by: Mark McDowall <mark@mcdowall.ca>
2023-11-19 21:46:06 +02:00
Bogdan
22e3cf844c New: Confirmation before clearing blocklist
(cherry picked from commit 366d8a4e78e024bc045e4791d3a51af391f4e95a)

Closes #9429
Fixes #9401
2023-11-19 21:17:00 +02:00
Bogdan
14b4b5e122 Cleanup appName tokens
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>

Closes #9430
2023-11-19 21:14:48 +02:00
Mark McDowall
10f5f3c5c8 New: Require password confirmation when setting or changing password
(cherry picked from commit b248163df598dc611ee919d525eb7357256d73d5)
2023-11-19 21:10:52 +02:00
Bogdan
c687b552f0 Bump version to 5.2.2 2023-11-19 07:06:29 +02:00
Stevie Robinson
92c8c8a7f5 Translate System pages
(cherry picked from commit 93e8ff0ac7610fa8739f2e577ece98c2c06c8881)

Closes #8852
2023-11-18 23:44:43 +02:00
Stevie Robinson
86a16c3c0c Fix translation token for Update Check
(cherry picked from commit cd1d8a3ff04b0d06f6fa7dfeb7a7ab6dd88b36b3)

Closes #9341
2023-11-18 23:44:41 +02:00
Weblate
e8c280db34 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Baptiste Mongin <baptiste.mongin@gmail.com>
Co-authored-by: Francisco Cachado <franciscomcachado@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Javier Parada <jparada@gmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Ruben Lourenco <ruben.lourenco01@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: bowsefather <husseinali39@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translation: Servarr/Radarr
2023-11-18 03:21:28 +02:00
Nesego
ea65e2174c Translated using Weblate (French) [skip ci]
Currently translated at 100.0% (1336 of 1336 strings)

Translation: Servarr/Radarr
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
2023-11-18 03:01:28 +02:00
Weblate
4aa2466693 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Baptiste Mongin <baptiste.mongin@gmail.com>
Co-authored-by: Francisco Cachado <franciscomcachado@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Javier Parada <jparada@gmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Ruben Lourenco <ruben.lourenco01@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: bowsefather <husseinali39@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translation: Servarr/Radarr
2023-11-18 02:59:39 +02:00
Bogdan
4df0f0f721 Revert translation keys 2023-11-18 02:49:58 +02:00
Mark McDowall
d7bee375e8 Use named tokens for backend translations
(cherry picked from commit 11f96c31048c2d1aafca0c91736d439f7f9a95a8)
2023-11-18 02:37:33 +02:00
Bogdan
906295466d Use variable for App name in translations
Co-authored-by: Qstick <qstick@gmail.com>
2023-11-18 02:37:33 +02:00
Mark McDowall
f86060eca2 Don't retest unchanged providers
New: Don't retest connections, indexers, download clients, etc if re-saved with the exact same settings

Closes #9411
Fixes ##9397

(cherry picked from commit 71fd09f162b2880c461e03cba4317c34ee3203dc)
2023-11-17 16:27:42 +02:00
Mark McDowall
bf9a0b62f2 Rename 'ReturnUrl' to 'returnUrl' for forms auth redirection
(cherry picked from commit 812712e2843a738054c065a6d5c1b7c81c5f8e7b)
2023-11-17 03:30:03 +02:00
Bogdan
ccc62f0450 Fixed: Enforce validation warnings when testing providers
(cherry picked from commit c3b4126d0c4f449a41e2cf7ea438b20e25370995)
2023-11-17 02:40:39 +02:00
bakerboy448
524657ad78 Improve sample detection logging (#9405)
Sonarr 6181
2023-11-15 19:38:58 +02:00
Qstick
7a394ff864 Update menu background on dark theme 2023-11-14 20:57:26 -06:00
Bogdan
d8862eedd3 Fixed: Refresh discovery movies state on refresh lists 2023-11-14 20:36:12 +02:00
Bogdan
71f700e240 Fixed: (HDBits) Add labels for categories, codecs and mediums 2023-11-14 17:13:34 +02:00
Bogdan
ae5dd84e0a Fixed: (HDBits) Increase search limit to 100 releases 2023-11-14 15:13:45 +02:00
Bogdan
17b398cf62 Bump version to 5.2.1 2023-11-12 16:52:53 +02:00
Qstick
d00678c1ba Bump ffprobe to 5.1.4
(cherry picked from commit e68b13940d4dd4c5fd008884d909e614521c8cee)
2023-11-11 20:04:59 +02:00
Bogdan
03df9b7f07 Add troubleshooting link when movie searches fail 2023-11-11 18:45:34 +02:00
Bogdan
3442a0ecca Bump version to 5.2.0 2023-11-10 06:24:33 +02:00
Bogdan
3376a467ca Fixed: Record status for notifications on tests 2023-11-10 05:07:29 +02:00
Servarr
1650ce17fb Automated API Docs update 2023-11-10 03:33:52 +02:00
Bogdan
2f2004faa2 New: Resolve download client by name using 'downloadClient' for pushed releases
(cherry picked from commit 0496e728dc1e21b16b9ee2fee010de9707bdff85)
2023-11-10 03:14:38 +02:00
Mark McDowall
437e2f4597 Don't store successful results for invalid providers
(cherry picked from commit de23182d593e2284972103d505e66dd8d812dfdb)
2023-11-10 03:13:27 +02:00
Bogdan
17b8605751 Simply queue item for movie details page 2023-11-09 20:53:49 +02:00
Bogdan
b2a52e52b6 Fixed: (UI) Progress bar status for searching existing movies 2023-11-09 20:53:49 +02:00
Servarr
0f5fabdfcd Automated API Docs update 2023-11-09 15:11:53 +02:00
Bogdan
6362ee9b7d Fixed: (UI) Import Lists enabled status doesn't rely on automatic add
Fixes #9375
2023-11-09 14:27:10 +02:00
Bogdan
50465fd482 New: Add enabled to manage import lists bulk 2023-11-09 14:16:03 +02:00
Bogdan
54d447d55f New: Parse VIE as Vietnamese language 2023-11-08 20:37:07 +02:00
Bogdan
50f48277e5 Don't show already imported movies as downloading in Movies index 2023-11-08 17:49:29 +02:00
Weblate
c2e206b7ac Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Baptiste Mongin <baptiste.mongin@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Javier Parada <jparada@gmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Ruben Lourenco <ruben.lourenco01@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-11-07 20:29:36 +02:00
Bogdan
7a46de602f Increase the wait timeout for integration tests init 2023-11-06 00:29:02 +02:00
bakerboy448
89820c1ff7 Lower log level for missing translation/culture resource (#8956)
Fixes #8150
2023-11-04 16:21:47 +02:00
Stevie Robinson
67e6e129ff Fix event ids for history custom filters 2023-11-02 00:37:54 +02:00
Bogdan
b6001238e5 Sort root folders by path in UI
Fixes #9280
2023-11-01 13:13:21 +02:00
Stevie Robinson
7bbdcc81bb Use Diacritical.Net library for TitleFirstCharacter token
(cherry picked from commit 59ea524e0ce85333779f430b867e93aae366289f)

Closes #9324
2023-11-01 13:13:21 +02:00
Stevie Robinson
3e8cbc497e Fixed: Cleanup First Character in Title when using 'TitleFirstCharacter'
(cherry picked from commit b3c691859a0841cde9bb2655c01c240cc5279d74)

Closes #9249
2023-11-01 13:13:21 +02:00
Bogdan
60d2df043b Rename instances of Profile to QualityProfile
Closes #9337
2023-11-01 13:13:21 +02:00
Mark McDowall
da41cb8840 Fixed: Blocking unknown indexers from pushed releases
(cherry picked from commit 44d8dbaac81706691124ae5f8317289f0a3e5d73)
2023-10-30 14:21:29 +02:00
Bogdan
a4b7c99d91 Fix full disk releases regex for DVDs
(cherry picked from commit aa8659eecd0a0fedd56eb1066730d1d1ec32df0d)

Closes #9346
2023-10-29 18:50:38 +02:00
Bogdan
8fb21e073b Bump version to 5.1.3 2023-10-29 10:35:11 +02:00
Stevie Robinson
dbf424d454 New: Relative path as default Sort order on Manual Import
(cherry picked from commit 6e2162ebf4b3366df540bd35ad91bd5527976728)

Closes #9344
2023-10-29 01:12:45 +03:00
Bogdan
a6dda70c0a New: Add Download Client validation for indexers
(cherry picked from commit e53b7f8c945e3597ca1719961e82540f1f01f0e9)

Closes #9338
2023-10-29 01:05:50 +03:00
Bogdan
e6fa14b1e6 Allow 0 as valid value in QualityProfileExistsValidator
(cherry picked from commit 36ca24e55a5eda859047d82855f65c401cc0b30f)
2023-10-29 00:59:16 +03:00
Bogdan
b5c0d515ee Improve UI notice for delayed queue items
(cherry picked from commit f2cae4e2b2f87924973a00431be7216296648dac)
2023-10-29 00:59:02 +03:00
Bogdan
b7aee25d0d Set proper default props for Queue details and status
(cherry picked from commit dc099a77ca9e6993d386a2b70f1aff1fed34a32b)
2023-10-29 00:58:30 +03:00
Bogdan
233b85aaf3 Sort Custom Formats by name
(cherry picked from commit e9bb1d52a72b20a58d1a672ecfa3797eda6f081a)
2023-10-29 00:58:11 +03:00
Weblate
80db9a7dd4 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: ID-86 <id86dev@gmail.com>
Co-authored-by: Jordy <prive@jordyhoebergen.nl>
Co-authored-by: LeDaFeEs <leonardo.fonseca85300@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: bai0012 <baicongrui@gmail.com>
Co-authored-by: 無情天 <kofzhanganguo@126.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-10-28 22:05:58 +03:00
Bogdan
660d3d7643 Fixed: Don't reject DVDRip/DVDRemux as full DVD disk releases 2023-10-28 22:05:12 +03:00
Bogdan
d999aea36f Add missing translation in release profiles 2023-10-26 00:18:52 +03:00
Jordy
5d45f1de89 Update link to Docker instructions in readme (#9318) 2023-10-25 11:21:51 +03:00
769 changed files with 18684 additions and 12509 deletions

View File

@@ -2,7 +2,7 @@
[![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/servarr/-/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://wiki.servarr.com/radarr/installation#docker)
[![Docker Pulls](https://img.shields.io/docker/pulls/linuxserver/radarr.svg)](https://wiki.servarr.com/radarr/installation/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)

View File

@@ -9,15 +9,15 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '5.1.2'
majorVersion: '5.4.2'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.413'
nodeVersion: '16.X'
innoVersion: '6.2.0'
dotnetVersion: '6.0.417'
nodeVersion: '20.X'
innoVersion: '6.2.2'
windowsImage: 'windows-2022'
linuxImage: 'ubuntu-20.04'
macImage: 'macOS-11'
@@ -1242,6 +1242,7 @@ stages:
- stage: Report_Out
dependsOn:
- Analyze
- Installer
- Unit_Test
- Integration
- Automation

View File

@@ -254,7 +254,7 @@ InstallInno()
ProgressStart "Installing portable Inno Setup"
rm -rf _inno
curl -s --output innosetup.exe "https://files.jrsoftware.org/is/6/innosetup-${INNOVERSION:-6.2.0}.exe"
curl -s --output innosetup.exe "https://files.jrsoftware.org/is/6/innosetup-${INNOVERSION:-6.2.2}.exe"
mkdir _inno
./innosetup.exe //portable=1 //silent //currentuser //dir=.\\_inno
rm innosetup.exe

View File

@@ -2,6 +2,8 @@ const loose = true;
module.exports = {
plugins: [
'@babel/plugin-transform-logical-assignment-operators',
// Stage 1
'@babel/plugin-proposal-export-default-from',
['@babel/plugin-transform-optional-chaining', { loose }],

View File

@@ -36,6 +36,7 @@ class Blocklist extends Component {
lastToggled: null,
selectedState: {},
isConfirmRemoveModalOpen: false,
isConfirmClearModalOpen: false,
items: props.items
};
}
@@ -90,6 +91,19 @@ class Blocklist extends Component {
this.setState({ isConfirmRemoveModalOpen: false });
};
onClearBlocklistPress = () => {
this.setState({ isConfirmClearModalOpen: true });
};
onClearBlocklistConfirmed = () => {
this.props.onClearBlocklistPress();
this.setState({ isConfirmClearModalOpen: false });
};
onConfirmClearModalClose = () => {
this.setState({ isConfirmClearModalOpen: false });
};
//
// Render
@@ -103,7 +117,6 @@ class Blocklist extends Component {
totalRecords,
isRemoving,
isClearingBlocklistExecuting,
onClearBlocklistPress,
...otherProps
} = this.props;
@@ -111,7 +124,8 @@ class Blocklist extends Component {
allSelected,
allUnselected,
selectedState,
isConfirmRemoveModalOpen
isConfirmRemoveModalOpen,
isConfirmClearModalOpen
} = this.state;
const selectedIds = this.getSelectedIds();
@@ -131,8 +145,9 @@ class Blocklist extends Component {
<PageToolbarButton
label={translate('Clear')}
iconName={icons.CLEAR}
isDisabled={!items.length}
isSpinning={isClearingBlocklistExecuting}
onPress={onClearBlocklistPress}
onPress={this.onClearBlocklistPress}
/>
</PageToolbarSection>
@@ -215,6 +230,16 @@ class Blocklist extends Component {
onConfirm={this.onRemoveSelectedConfirmed}
onCancel={this.onConfirmRemoveModalClose}
/>
<ConfirmModal
isOpen={isConfirmClearModalOpen}
kind={kinds.DANGER}
title={translate('ClearBlocklist')}
message={translate('ClearBlocklistMessageText')}
confirmLabel={translate('Clear')}
onConfirm={this.onClearBlocklistConfirmed}
onCancel={this.onConfirmClearModalClose}
/>
</PageContent>
);
}

View File

@@ -6,7 +6,7 @@ import { icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './HistoryEventTypeCell.css';
function getIconName(eventType) {
function getIconName(eventType, data) {
switch (eventType) {
case 'grabbed':
return icons.DOWNLOADING;
@@ -17,7 +17,7 @@ function getIconName(eventType) {
case 'downloadFailed':
return icons.DOWNLOADING;
case 'movieFileDeleted':
return icons.DELETE;
return data.reason === 'MissingFromDisk' ? icons.FILE_MISSING : icons.DELETE;
case 'movieFileRenamed':
return icons.ORGANIZE;
case 'downloadIgnored':
@@ -47,7 +47,7 @@ function getTooltip(eventType, data) {
case 'downloadFailed':
return translate('MovieDownloadFailedTooltip');
case 'movieFileDeleted':
return translate('MovieFileDeletedTooltip');
return data.reason === 'MissingFromDisk' ? translate('MovieFileMissingTooltip') : translate('MovieFileDeletedTooltip');
case 'movieFileRenamed':
return translate('MovieFileRenamedTooltip');
case 'downloadIgnored':
@@ -58,7 +58,7 @@ function getTooltip(eventType, data) {
}
function HistoryEventTypeCell({ eventType, data }) {
const iconName = getIconName(eventType);
const iconName = getIconName(eventType, data);
const iconKind = getIconKind(eventType);
const tooltip = getTooltip(eventType, data);

View File

@@ -25,7 +25,7 @@ import toggleSelected from 'Utilities/Table/toggleSelected';
import QueueFilterModal from './QueueFilterModal';
import QueueOptionsConnector from './QueueOptionsConnector';
import QueueRowConnector from './QueueRowConnector';
import RemoveQueueItemsModal from './RemoveQueueItemsModal';
import RemoveQueueItemModal from './RemoveQueueItemModal';
class Queue extends Component {
@@ -307,9 +307,16 @@ class Queue extends Component {
}
</PageContentBody>
<RemoveQueueItemsModal
<RemoveQueueItemModal
isOpen={isConfirmRemoveModalOpen}
selectedCount={selectedCount}
canChangeCategory={isConfirmRemoveModalOpen && (
selectedIds.every((id) => {
const item = items.find((i) => i.id === id);
return !!(item && item.downloadClientHasPostImportCategory);
})
)}
canIgnore={isConfirmRemoveModalOpen && (
selectedIds.every((id) => {
const item = items.find((i) => i.id === id);
@@ -317,7 +324,7 @@ class Queue extends Component {
return !!(item && item.movieId);
})
)}
allPending={isConfirmRemoveModalOpen && (
pending={isConfirmRemoveModalOpen && (
selectedIds.every((id) => {
const item = items.find((i) => i.id === id);

View File

@@ -81,4 +81,9 @@ QueueDetails.propTypes = {
progressBar: PropTypes.node.isRequired
};
QueueDetails.defaultProps = {
trackedDownloadStatus: 'ok',
trackedDownloadState: 'downloading'
};
export default QueueDetails;

View File

@@ -4,7 +4,7 @@ import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import ProgressBar from 'Components/ProgressBar';
// import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import TableRow from 'Components/Table/TableRow';
@@ -96,7 +96,9 @@ class QueueRow extends Component {
indexer,
outputPath,
downloadClient,
downloadClientHasPostImportCategory,
estimatedCompletionTime,
added,
timeleft,
size,
sizeleft,
@@ -315,6 +317,15 @@ class QueueRow extends Component {
);
}
if (name === 'added') {
return (
<RelativeDateCellConnector
key={name}
date={added}
/>
);
}
if (name === 'actions') {
return (
<TableRowCell
@@ -363,6 +374,7 @@ class QueueRow extends Component {
<RemoveQueueItemModal
isOpen={isRemoveQueueItemModalOpen}
sourceTitle={title}
canChangeCategory={!!downloadClientHasPostImportCategory}
canIgnore={!!movie}
isPending={isPending}
onRemovePress={this.onRemoveQueueItemModalConfirmed}
@@ -392,7 +404,9 @@ QueueRow.propTypes = {
indexer: PropTypes.string,
outputPath: PropTypes.string,
downloadClient: PropTypes.string,
downloadClientHasPostImportCategory: PropTypes.bool,
estimatedCompletionTime: PropTypes.string,
added: PropTypes.string,
timeleft: PropTypes.string,
size: PropTypes.number,
year: PropTypes.number,

View File

@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React from 'react';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import { tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import QueueStatus from './QueueStatus';
import styles from './QueueStatusCell.css';
@@ -41,8 +40,8 @@ QueueStatusCell.propTypes = {
};
QueueStatusCell.defaultProps = {
trackedDownloadStatus: translate('Ok'),
trackedDownloadState: translate('Downloading')
trackedDownloadStatus: 'ok',
trackedDownloadState: 'downloading'
};
export default QueueStatusCell;

View File

@@ -1,171 +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 Button from 'Components/Link/Button';
import Modal from 'Components/Modal/Modal';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
class RemoveQueueItemModal extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
remove: true,
blocklist: false,
skipRedownload: false
};
}
//
// Control
resetState = function() {
this.setState({
remove: true,
blocklist: false,
skipRedownload: false
});
};
//
// Listeners
onRemoveChange = ({ value }) => {
this.setState({ remove: value });
};
onBlocklistChange = ({ value }) => {
this.setState({ blocklist: value });
};
onSkipRedownloadChange = ({ value }) => {
this.setState({ skipRedownload: value });
};
onRemoveConfirmed = () => {
const state = this.state;
this.resetState();
this.props.onRemovePress(state);
};
onModalClose = () => {
this.resetState();
this.props.onModalClose();
};
//
// Render
render() {
const {
isOpen,
sourceTitle,
canIgnore,
isPending
} = this.props;
const { remove, blocklist, skipRedownload } = this.state;
return (
<Modal
isOpen={isOpen}
size={sizes.MEDIUM}
onModalClose={this.onModalClose}
>
<ModalContent
onModalClose={this.onModalClose}
>
<ModalHeader>
{translate('RemoveQueueItem', { sourceTitle })}
</ModalHeader>
<ModalBody>
<div>
{translate('RemoveQueueItemConfirmation', { sourceTitle })}
</div>
{
isPending ?
null :
<FormGroup>
<FormLabel>{translate('RemoveFromDownloadClient')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="remove"
value={remove}
helpTextWarning={translate('RemoveFromDownloadClientHelpTextWarning')}
isDisabled={!canIgnore}
onChange={this.onRemoveChange}
/>
</FormGroup>
}
<FormGroup>
<FormLabel>{translate('BlocklistRelease')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="blocklist"
value={blocklist}
helpText={translate('BlocklistReleaseHelpText')}
onChange={this.onBlocklistChange}
/>
</FormGroup>
{
blocklist ?
<FormGroup>
<FormLabel>{translate('SkipRedownload')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="skipRedownload"
value={skipRedownload}
helpText={translate('SkipRedownloadHelpText')}
onChange={this.onSkipRedownloadChange}
/>
</FormGroup> :
null
}
</ModalBody>
<ModalFooter>
<Button onPress={this.onModalClose}>
{translate('Close')}
</Button>
<Button
kind={kinds.DANGER}
onPress={this.onRemoveConfirmed}
>
{translate('Remove')}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
}
RemoveQueueItemModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
sourceTitle: PropTypes.string.isRequired,
canIgnore: PropTypes.bool.isRequired,
isPending: PropTypes.bool.isRequired,
onRemovePress: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default RemoveQueueItemModal;

View File

@@ -0,0 +1,230 @@
import React, { useCallback, useMemo, useState } from 'react';
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 Modal from 'Components/Modal/Modal';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './RemoveQueueItemModal.css';
interface RemovePressProps {
remove: boolean;
changeCategory: boolean;
blocklist: boolean;
skipRedownload: boolean;
}
interface RemoveQueueItemModalProps {
isOpen: boolean;
sourceTitle: string;
canChangeCategory: boolean;
canIgnore: boolean;
isPending: boolean;
selectedCount?: number;
onRemovePress(props: RemovePressProps): void;
onModalClose: () => void;
}
type RemovalMethod = 'removeFromClient' | 'changeCategory' | 'ignore';
type BlocklistMethod =
| 'doNotBlocklist'
| 'blocklistAndSearch'
| 'blocklistOnly';
function RemoveQueueItemModal(props: RemoveQueueItemModalProps) {
const {
isOpen,
sourceTitle,
canIgnore,
canChangeCategory,
isPending,
selectedCount,
onRemovePress,
onModalClose,
} = props;
const multipleSelected = selectedCount && selectedCount > 1;
const [removalMethod, setRemovalMethod] =
useState<RemovalMethod>('removeFromClient');
const [blocklistMethod, setBlocklistMethod] =
useState<BlocklistMethod>('doNotBlocklist');
const { title, message } = useMemo(() => {
if (!selectedCount) {
return {
title: translate('RemoveQueueItem', { sourceTitle }),
message: translate('RemoveQueueItemConfirmation', { sourceTitle }),
};
}
if (selectedCount === 1) {
return {
title: translate('RemoveSelectedItem'),
message: translate('RemoveSelectedItemQueueMessageText'),
};
}
return {
title: translate('RemoveSelectedItems'),
message: translate('RemoveSelectedItemsQueueMessageText', {
selectedCount,
}),
};
}, [sourceTitle, selectedCount]);
const removalMethodOptions = useMemo(() => {
return [
{
key: 'removeFromClient',
value: translate('RemoveFromDownloadClient'),
hint: multipleSelected
? translate('RemoveMultipleFromDownloadClientHint')
: translate('RemoveFromDownloadClientHint'),
},
{
key: 'changeCategory',
value: translate('ChangeCategory'),
isDisabled: !canChangeCategory,
hint: multipleSelected
? translate('ChangeCategoryMultipleHint')
: translate('ChangeCategoryHint'),
},
{
key: 'ignore',
value: multipleSelected
? translate('IgnoreDownloads')
: translate('IgnoreDownload'),
isDisabled: !canIgnore,
hint: multipleSelected
? translate('IgnoreDownloadsHint')
: translate('IgnoreDownloadHint'),
},
];
}, [canChangeCategory, canIgnore, multipleSelected]);
const blocklistMethodOptions = useMemo(() => {
return [
{
key: 'doNotBlocklist',
value: translate('DoNotBlocklist'),
hint: translate('DoNotBlocklistHint'),
},
{
key: 'blocklistAndSearch',
value: translate('BlocklistAndSearch'),
hint: multipleSelected
? translate('BlocklistAndSearchMultipleHint')
: translate('BlocklistAndSearchHint'),
},
{
key: 'blocklistOnly',
value: translate('BlocklistOnly'),
hint: multipleSelected
? translate('BlocklistMultipleOnlyHint')
: translate('BlocklistOnlyHint'),
},
];
}, [multipleSelected]);
const handleRemovalMethodChange = useCallback(
({ value }: { value: RemovalMethod }) => {
setRemovalMethod(value);
},
[setRemovalMethod]
);
const handleBlocklistMethodChange = useCallback(
({ value }: { value: BlocklistMethod }) => {
setBlocklistMethod(value);
},
[setBlocklistMethod]
);
const handleConfirmRemove = useCallback(() => {
onRemovePress({
remove: removalMethod === 'removeFromClient',
changeCategory: removalMethod === 'changeCategory',
blocklist: blocklistMethod !== 'doNotBlocklist',
skipRedownload: blocklistMethod === 'blocklistOnly',
});
setRemovalMethod('removeFromClient');
setBlocklistMethod('doNotBlocklist');
}, [
removalMethod,
blocklistMethod,
setRemovalMethod,
setBlocklistMethod,
onRemovePress,
]);
const handleModalClose = useCallback(() => {
setRemovalMethod('removeFromClient');
setBlocklistMethod('doNotBlocklist');
onModalClose();
}, [setRemovalMethod, setBlocklistMethod, onModalClose]);
return (
<Modal isOpen={isOpen} size={sizes.MEDIUM} onModalClose={handleModalClose}>
<ModalContent onModalClose={handleModalClose}>
<ModalHeader>{title}</ModalHeader>
<ModalBody>
<div className={styles.message}>{message}</div>
{isPending ? null : (
<FormGroup>
<FormLabel>{translate('RemoveQueueItemRemovalMethod')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="removalMethod"
value={removalMethod}
values={removalMethodOptions}
isDisabled={!canChangeCategory && !canIgnore}
helpTextWarning={translate(
'RemoveQueueItemRemovalMethodHelpTextWarning'
)}
onChange={handleRemovalMethodChange}
/>
</FormGroup>
)}
<FormGroup>
<FormLabel>
{multipleSelected
? translate('BlocklistReleases')
: translate('BlocklistRelease')}
</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="blocklistMethod"
value={blocklistMethod}
values={blocklistMethodOptions}
helpText={translate('BlocklistReleaseHelpText')}
onChange={handleBlocklistMethodChange}
/>
</FormGroup>
</ModalBody>
<ModalFooter>
<Button onPress={handleModalClose}>{translate('Close')}</Button>
<Button kind={kinds.DANGER} onPress={handleConfirmRemove}>
{translate('Remove')}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
export default RemoveQueueItemModal;

View File

@@ -1,174 +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 Button from 'Components/Link/Button';
import Modal from 'Components/Modal/Modal';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds, sizes } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './RemoveQueueItemsModal.css';
class RemoveQueueItemsModal extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
remove: true,
blocklist: false,
skipRedownload: false
};
}
//
// Control
resetState = function() {
this.setState({
remove: true,
blocklist: false,
skipRedownload: false
});
};
//
// Listeners
onRemoveChange = ({ value }) => {
this.setState({ remove: value });
};
onBlocklistChange = ({ value }) => {
this.setState({ blocklist: value });
};
onSkipRedownloadChange = ({ value }) => {
this.setState({ skipRedownload: value });
};
onRemoveConfirmed = () => {
const state = this.state;
this.resetState();
this.props.onRemovePress(state);
};
onModalClose = () => {
this.resetState();
this.props.onModalClose();
};
//
// Render
render() {
const {
isOpen,
selectedCount,
canIgnore,
allPending
} = this.props;
const { remove, blocklist, skipRedownload } = this.state;
return (
<Modal
isOpen={isOpen}
size={sizes.MEDIUM}
onModalClose={this.onModalClose}
>
<ModalContent
onModalClose={this.onModalClose}
>
<ModalHeader>
{selectedCount > 1 ? translate('RemoveSelectedItems') : translate('RemoveSelectedItem')}
</ModalHeader>
<ModalBody>
<div className={styles.message}>
{selectedCount > 1 ? translate('RemoveSelectedItemsQueueMessageText', { selectedCount }) : translate('RemoveSelectedItemQueueMessageText')}
</div>
{
allPending ?
null :
<FormGroup>
<FormLabel>{translate('RemoveFromDownloadClient')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="remove"
value={remove}
helpTextWarning={translate('RemoveHelpTextWarning')}
isDisabled={!canIgnore}
onChange={this.onRemoveChange}
/>
</FormGroup>
}
<FormGroup>
<FormLabel>
{selectedCount > 1 ? translate('BlocklistReleases') : translate('BlocklistRelease')}
</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="blocklist"
value={blocklist}
helpText={translate('BlocklistReleaseHelpText')}
onChange={this.onBlocklistChange}
/>
</FormGroup>
{
blocklist ?
<FormGroup>
<FormLabel>{translate('SkipRedownload')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="skipRedownload"
value={skipRedownload}
helpText={translate('SkipRedownloadHelpText')}
onChange={this.onSkipRedownloadChange}
/>
</FormGroup> :
null
}
</ModalBody>
<ModalFooter>
<Button onPress={this.onModalClose}>
{translate('Close')}
</Button>
<Button
kind={kinds.DANGER}
onPress={this.onRemoveConfirmed}
>
{translate('Remove')}
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
}
RemoveQueueItemsModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
selectedCount: PropTypes.number.isRequired,
canIgnore: PropTypes.bool.isRequired,
allPending: PropTypes.bool.isRequired,
onRemovePress: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default RemoveQueueItemsModal;

View File

@@ -1,6 +1,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import formatTime from 'Utilities/Date/formatTime';
import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
@@ -25,11 +28,13 @@ function TimeleftCell(props) {
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
return (
<TableRowCell
className={styles.timeleft}
title={translate('DelayingDownloadUntil', { date, time })}
>
-
<TableRowCell className={styles.timeleft}>
<Tooltip
anchor={<Icon name={icons.INFO} />}
tooltip={translate('DelayingDownloadUntil', { date, time })}
kind={kinds.INVERSE}
position={tooltipPositions.TOP}
/>
</TableRowCell>
);
}
@@ -39,11 +44,13 @@ function TimeleftCell(props) {
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
return (
<TableRowCell
className={styles.timeleft}
title={translate('RetryingDownloadOn', { date, time })}
>
-
<TableRowCell className={styles.timeleft}>
<Tooltip
anchor={<Icon name={icons.INFO} />}
tooltip={translate('RetryingDownloadOn', { date, time })}
kind={kinds.INVERSE}
position={tooltipPositions.TOP}
/>
</TableRowCell>
);
}

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
import TextInput from 'Components/Form/TextInput';
import Icon from 'Components/Icon';
import Button from 'Components/Link/Button';
@@ -130,7 +131,12 @@ class AddNewMovie extends Component {
<div className={styles.helpText}>
{translate('FailedLoadingSearchResults')}
</div>
<div>{getErrorMessage(error)}</div>
<Alert kind={kinds.WARNING}>{getErrorMessage(error)}</Alert>
<div>
<Link to="https://wiki.servarr.com/radarr/troubleshooting#invalid-response-received-from-tmdb">
{translate('WhySearchesCouldBeFailing')}
</Link>
</div>
</div> : null
}

View File

@@ -3,10 +3,13 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
import { clearMovieFiles, fetchMovieFiles } from 'Store/Actions/movieFileActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
import parseUrl from 'Utilities/String/parseUrl';
import AddNewMovie from './AddNewMovie';
@@ -35,7 +38,9 @@ const mapDispatchToProps = {
fetchRootFolders,
fetchImportExclusions,
fetchQueueDetails,
clearQueueDetails
clearQueueDetails,
fetchMovieFiles,
clearMovieFiles
};
class AddNewMovieConnector extends Component {
@@ -55,6 +60,20 @@ class AddNewMovieConnector extends Component {
this.props.fetchQueueDetails();
}
componentDidUpdate(prevProps) {
const {
items
} = this.props;
if (hasDifferentItems(prevProps.items, items)) {
const movieIds = selectUniqueIds(items, 'internalId');
if (movieIds.length) {
this.props.fetchMovieFiles({ movieId: movieIds });
}
}
}
componentWillUnmount() {
if (this._movieLookupTimeout) {
clearTimeout(this._movieLookupTimeout);
@@ -62,6 +81,7 @@ class AddNewMovieConnector extends Component {
this.props.clearAddMovie();
this.props.clearQueueDetails();
this.props.clearMovieFiles();
}
//
@@ -107,12 +127,15 @@ class AddNewMovieConnector extends Component {
AddNewMovieConnector.propTypes = {
term: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
lookupMovie: PropTypes.func.isRequired,
clearAddMovie: PropTypes.func.isRequired,
fetchRootFolders: PropTypes.func.isRequired,
fetchImportExclusions: PropTypes.func.isRequired,
fetchQueueDetails: PropTypes.func.isRequired,
clearQueueDetails: PropTypes.func.isRequired
clearQueueDetails: PropTypes.func.isRequired,
fetchMovieFiles: PropTypes.func.isRequired,
clearMovieFiles: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector);

View File

@@ -85,8 +85,13 @@
margin-top: 20px;
}
.studio,
.genres {
margin-left: 5px;
}
.links {
margin-left: 8px;
margin-left: 5px;
pointer-events: all;
}

View File

@@ -5,6 +5,7 @@ interface CssExports {
'certification': string;
'content': string;
'exclusionIcon': string;
'genres': string;
'icons': string;
'links': string;
'overlay': string;
@@ -14,6 +15,7 @@ interface CssExports {
'runtime': string;
'searchResult': string;
'statusContainer': string;
'studio': string;
'title': string;
'titleContainer': string;
'titleRow': string;

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import Label from 'Components/Label';
import Link from 'Components/Link/Link';
import TmdbRating from 'Components/TmdbRating';
@@ -61,21 +62,22 @@ class AddNewMovieSearchResult extends Component {
titleSlug,
year,
studio,
genres,
status,
overview,
ratings,
folder,
images,
existingMovieId,
isExistingMovie,
isExclusionMovie,
isSmallScreen,
colorImpairedMode,
id,
monitored,
hasFile,
isAvailable,
queueStatus,
queueState,
movieFile,
queueItem,
runtime,
movieRuntimeFormat,
certification
@@ -85,6 +87,8 @@ class AddNewMovieSearchResult extends Component {
isNewAddMovieModalOpen
} = this.state;
const hasMovieFile = !!movieFile;
const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
const posterWidth = 167;
const posterHeight = 250;
@@ -120,13 +124,13 @@ class AddNewMovieSearchResult extends Component {
{
isExistingMovie &&
<MovieIndexProgressBar
movieId={existingMovieId}
movieFile={movieFile}
monitored={monitored}
hasFile={hasFile}
hasFile={hasMovieFile}
status={status}
width={posterWidth}
detailedProgressBar={true}
queueStatus={queueStatus}
queueState={queueState}
isAvailable={isAvailable}
/>
}
@@ -197,13 +201,46 @@ class AddNewMovieSearchResult extends Component {
/>
</Label>
{
ratings.imdb ?
<Label size={sizes.LARGE}>
<ImdbRating
ratings={ratings}
iconSize={13}
/>
</Label> :
null
}
{
!!studio &&
<Label size={sizes.LARGE}>
{studio}
<Icon
name={icons.STUDIO}
size={13}
/>
<span className={styles.studio}>
{studio}
</span>
</Label>
}
{
genres.length > 0 ?
<Label size={sizes.LARGE}>
<Icon
name={icons.GENRE}
size={13}
/>
<span className={styles.genres}>
{genres.slice(0, 3).join(', ')}
</span>
</Label> :
null
}
<Tooltip
anchor={
<Label
@@ -215,15 +252,15 @@ class AddNewMovieSearchResult extends Component {
/>
<span className={styles.links}>
Links
{translate('Links')}
</span>
</Label>
}
tooltip={
<MovieDetailsLinks
tmdbId={tmdbId}
youTubeTrailerId={youTubeTrailerId}
imdbId={imdbId}
youTubeTrailerId={youTubeTrailerId}
/>
}
canFlip={true}
@@ -234,9 +271,10 @@ class AddNewMovieSearchResult extends Component {
{
isExistingMovie && isSmallScreen &&
<MovieStatusLabel
hasMovieFiles={hasFile}
hasMovieFiles={hasMovieFile}
monitored={monitored}
isAvailable={isAvailable}
queueItem={queueItem}
id={id}
useLabel={true}
colorImpairedMode={colorImpairedMode}
@@ -273,25 +311,29 @@ AddNewMovieSearchResult.propTypes = {
titleSlug: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
studio: PropTypes.string,
genres: PropTypes.arrayOf(PropTypes.string),
status: PropTypes.string.isRequired,
overview: PropTypes.string,
ratings: PropTypes.object.isRequired,
folder: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
existingMovieId: PropTypes.number,
isExistingMovie: PropTypes.bool.isRequired,
isExclusionMovie: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
id: PropTypes.number,
queueItems: PropTypes.arrayOf(PropTypes.object),
monitored: PropTypes.bool.isRequired,
hasFile: PropTypes.bool.isRequired,
isAvailable: PropTypes.bool.isRequired,
movieFile: PropTypes.object,
queueItem: PropTypes.object,
colorImpairedMode: PropTypes.bool,
queueStatus: PropTypes.string,
queueState: PropTypes.string,
runtime: PropTypes.number.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired,
certification: PropTypes.string
};
AddNewMovieSearchResult.defaultProps = {
genres: []
};
export default AddNewMovieSearchResult;

View File

@@ -11,16 +11,21 @@ function createMapStateToProps() {
createExclusionMovieSelector(),
createDimensionsSelector(),
(state) => state.queue.details.items,
(state) => state.movieFiles.items,
(state, { internalId }) => internalId,
(isExistingMovie, isExclusionMovie, dimensions, queueItems, internalId) => {
const firstQueueItem = queueItems.find((q) => q.movieId === internalId && internalId > 0);
(state) => state.settings.ui.item.movieRuntimeFormat,
(isExistingMovie, isExclusionMovie, dimensions, queueItems, movieFiles, internalId, movieRuntimeFormat) => {
const queueItem = queueItems.find((item) => internalId > 0 && item.movieId === internalId);
const movieFile = movieFiles.find((item) => internalId > 0 && item.movieId === internalId);
return {
existingMovieId: internalId,
isExistingMovie,
isExclusionMovie,
isSmallScreen: dimensions.isSmallScreen,
queueStatus: firstQueueItem ? firstQueueItem.status : null,
queueState: firstQueueItem ? firstQueueItem.trackedDownloadState : null
queueItem,
movieFile,
movieRuntimeFormat
};
}
);

View File

@@ -10,6 +10,7 @@ import styles from './ImportMovieRow.css';
function ImportMovieRow(props) {
const {
id,
relativePath,
monitor,
qualityProfileId,
minimumAvailability,
@@ -31,7 +32,7 @@ function ImportMovieRow(props) {
/>
<VirtualTableRowCell className={styles.folder}>
{id}
{relativePath}
</VirtualTableRowCell>
<VirtualTableRowCell className={styles.movie}>
@@ -73,6 +74,7 @@ function ImportMovieRow(props) {
ImportMovieRow.propTypes = {
id: PropTypes.string.isRequired,
relativePath: PropTypes.string.isRequired,
monitor: PropTypes.string.isRequired,
qualityProfileId: PropTypes.number.isRequired,
minimumAvailability: PropTypes.string.isRequired,

View File

@@ -30,7 +30,7 @@ class ImportMovieTable extends Component {
unmappedFolders.forEach((unmappedFolder) => {
const id = unmappedFolder.name;
onMovieLookup(id, unmappedFolder.path);
onMovieLookup(id, unmappedFolder.path, unmappedFolder.relativePath);
onSetImportMovieValue({
id,

View File

@@ -25,10 +25,11 @@ function createMapStateToProps() {
function createMapDispatchToProps(dispatch, props) {
return {
onMovieLookup(name, path) {
onMovieLookup(name, path, relativePath) {
dispatch(queueLookupMovie({
name,
path,
relativePath,
term: name
}));
},

View File

@@ -32,7 +32,7 @@
.contentContainer {
z-index: $popperZIndex;
margin-top: 4px;
/* 400px container witdh with 8px padding on each side */
/* 400px container width with 8px padding on each side */
width: 384px;
}

View File

@@ -148,7 +148,7 @@ class ImportMovieSelectFolder extends Component {
className={styles.addErrorAlert}
kind={kinds.DANGER}
>
{translate('UnableToAddRootFolder')}
{translate('AddRootFolderError')}
<ul>
{

View File

@@ -5,12 +5,13 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { addRootFolder, deleteRootFolder, fetchRootFolders } from 'Store/Actions/rootFolderActions';
import createRootFoldersSelector from 'Store/Selectors/createRootFoldersSelector';
import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
import ImportMovieSelectFolder from './ImportMovieSelectFolder';
function createMapStateToProps() {
return createSelector(
(state) => state.rootFolders,
createRootFoldersSelector(),
createSystemStatusSelector(),
(rootFolders, systemStatus) => {
return {

View File

@@ -65,12 +65,12 @@ function AppUpdatedModalContent(props) {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('AppUpdated', { appName: 'Radarr' })}
{translate('AppUpdated')}
</ModalHeader>
<ModalBody>
<div>
<InlineMarkdown data={translate('AppUpdatedVersion', { appName: 'Radarr', version })} blockClassName={styles.version} />
<InlineMarkdown data={translate('AppUpdatedVersion', { version })} blockClassName={styles.version} />
</div>
{

View File

@@ -28,11 +28,11 @@ function ConnectionLostModal(props) {
<ModalBody>
<div>
{translate('ConnectionLostToBackend', { appName: 'Radarr' })}
{translate('ConnectionLostToBackend')}
</div>
<div className={styles.automatic}>
{translate('ConnectionLostReconnect', { appName: 'Radarr' })}
{translate('ConnectionLostReconnect')}
</div>
</ModalBody>
<ModalFooter>

View File

@@ -44,7 +44,16 @@ export interface CustomFilter {
filers: PropertyFilter[];
}
export interface AppSectionState {
dimensions: {
isSmallScreen: boolean;
width: number;
height: number;
};
}
interface AppState {
app: AppSectionState;
calendar: CalendarAppState;
commands: CommandAppState;
history: HistoryAppState;

View File

@@ -1,40 +1,10 @@
import ModelBase from 'App/ModelBase';
import Language from 'Language/Language';
import { QualityModel } from 'Quality/Quality';
import CustomFormat from 'typings/CustomFormat';
import Queue from 'typings/Queue';
import AppSectionState, {
AppSectionFilterState,
AppSectionItemState,
Error,
} from './AppSectionState';
export interface StatusMessage {
title: string;
messages: string[];
}
export interface Queue extends ModelBase {
languages: Language[];
quality: QualityModel;
customFormats: CustomFormat[];
size: number;
title: string;
sizeleft: number;
timeleft: string;
estimatedCompletionTime: string;
status: string;
trackedDownloadStatus: string;
trackedDownloadState: string;
statusMessages: StatusMessage[];
errorMessage: string;
downloadId: string;
protocol: string;
downloadClient: string;
outputPath: string;
movieHasFile: boolean;
movieId?: number;
}
export interface QueueDetailsAppState extends AppSectionState<Queue> {
params: unknown;
}

View File

@@ -147,7 +147,7 @@ class AgendaEvent extends Component {
className={styles.statusIcon}
name={icons.MOVIE_FILE}
kind={kinds.WARNING}
title={translate('QualityCutoffHasNotBeenMet')}
title={translate('QualityCutoffNotMet')}
/>
}
</div>

View File

@@ -33,9 +33,7 @@ class Calendar extends Component {
{
!isFetching && !!error &&
<Alert kind={kinds.DANGER}>
{translate('UnableToLoadTheCalendar')}
</Alert>
<Alert kind={kinds.DANGER}>{translate('CalendarLoadError')}</Alert>
}
{

View File

@@ -55,7 +55,7 @@ class CalendarConnector extends Component {
gotoCalendarToday
} = this.props;
registerPagePopulator(this.repopulate);
registerPagePopulator(this.repopulate, ['movieFileUpdated', 'movieFileDeleted']);
if (useCurrentPage) {
fetchCalendar();

View File

@@ -104,7 +104,7 @@ class CalendarPage extends Component {
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
label={translate('iCalLink')}
label={translate('ICalLink')}
iconName={icons.CALENDAR}
onPress={this.onGetCalendarLinkPress}
/>
@@ -112,7 +112,7 @@ class CalendarPage extends Component {
<PageToolbarSeparator />
<PageToolbarButton
label={translate('RSSSync')}
label={translate('RssSync')}
iconName={icons.RSS}
isSpinning={isRssSyncExecuting}
onPress={onRssSyncPress}
@@ -180,7 +180,7 @@ class CalendarPage extends Component {
{
!movieError && movieIsPopulated && !hasMovie &&
<NoMovie />
<NoMovie totalItems={0} />
}
{

View File

@@ -48,6 +48,10 @@ $fullColorGradient: rgba(244, 245, 246, 0.2);
.statusContainer {
display: flex;
align-items: center;
&:global(.fullColor) {
filter: var(--calendarFullColorFilter)
}
}
.statusIcon {

View File

@@ -76,12 +76,18 @@ class CalendarEvent extends Component {
{title}
</div>
<div className={styles.statusContainer}>
<div
className={classNames(
styles.statusContainer,
fullColorEvents && 'fullColor'
)}
>
{
queueItem ?
<span className={styles.statusIcon}>
<CalendarEventQueueDetails
{...queueItem}
fullColorEvents={fullColorEvents}
/>
</span> :
null
@@ -98,12 +104,14 @@ class CalendarEvent extends Component {
}
{
showCutoffUnmetIcon && !!movieFile && movieFile.qualityCutoffNotMet ?
showCutoffUnmetIcon &&
!!movieFile &&
movieFile.qualityCutoffNotMet ?
<Icon
className={styles.statusIcon}
name={icons.MOVIE_FILE}
kind={kinds.WARNING}
title={translate('QualityCutoffHasNotBeenMet')}
title={translate('QualityCutoffNotMet')}
/> :
null
}

View File

@@ -126,7 +126,7 @@ class CalendarHeader extends Component {
isDisabled={view === calendarViews.AGENDA}
onPress={onTodayPress}
>
Today
{translate('Today')}
</Button>
</div>

View File

@@ -20,10 +20,11 @@ function Legend(props) {
if (showCutoffUnmetIcon) {
iconsToShow.push(
<LegendIconItem
name={translate('CutoffUnmet')}
name={translate('CutoffNotMet')}
icon={icons.MOVIE_FILE}
kind={fullColorEvents ? kinds.DEFAULT : kinds.WARNING}
tooltip={translate('QualityOrLangCutoffHasNotBeenMet')}
kind={kinds.WARNING}
fullColorEvents={fullColorEvents}
tooltip={translate('QualityCutoffNotMet')}
/>
);
}

View File

@@ -4,4 +4,8 @@
.icon {
margin-right: 5px;
&:global(.fullColorEvents) {
filter: var(--calendarFullColorFilter)
}
}

View File

@@ -1,3 +1,4 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
@@ -6,9 +7,9 @@ import styles from './LegendIconItem.css';
function LegendIconItem(props) {
const {
name,
fullColorEvents,
icon,
kind,
darken,
tooltip
} = props;
@@ -18,9 +19,11 @@ function LegendIconItem(props) {
title={tooltip}
>
<Icon
className={styles.icon}
className={classNames(
styles.icon,
fullColorEvents && 'fullColorEvents'
)}
name={icon}
darken={darken}
kind={kind}
/>
@@ -31,14 +34,10 @@ function LegendIconItem(props) {
LegendIconItem.propTypes = {
name: PropTypes.string.isRequired,
fullColorEvents: PropTypes.bool.isRequired,
icon: PropTypes.object.isRequired,
kind: PropTypes.string.isRequired,
darken: PropTypes.bool.isRequired,
tooltip: PropTypes.string.isRequired
};
LegendIconItem.defaultProps = {
darken: false
};
export default LegendIconItem;

View File

@@ -135,7 +135,7 @@ class CalendarOptionsModalContent extends Component {
type={inputTypes.CHECK}
name="showCutoffUnmetIcon"
value={showCutoffUnmetIcon}
helpText={translate('ShowCutoffUnmetIconHelpText')}
helpText={translate('IconForCutoffUnmetHelpText')}
onChange={this.onOptionInputChange}
/>
</FormGroup>
@@ -177,7 +177,7 @@ class CalendarOptionsModalContent extends Component {
values={weekColumnOptions}
value={calendarWeekColumnHeader}
onChange={this.onGlobalInputChange}
helpText={translate('SettingsWeekColumnHeaderHelpText')}
helpText={translate('WeekColumnHeaderHelpText')}
/>
</FormGroup>

View File

@@ -109,7 +109,7 @@ class CalendarLinkModalContent extends Component {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('RadarrCalendarFeed')}
{translate('CalendarFeed')}
</ModalHeader>
<ModalBody>
@@ -121,19 +121,19 @@ class CalendarLinkModalContent extends Component {
type={inputTypes.CHECK}
name="unmonitored"
value={unmonitored}
helpText={translate('UnmonitoredHelpText')}
helpText={translate('ICalIncludeUnmonitoredMoviesHelpText')}
onChange={this.onInputChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowAsAllDayEvents')}</FormLabel>
<FormLabel>{translate('ICalShowAsAllDayEvents')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="asAllDay"
value={asAllDay}
helpText={translate('AsAllDayHelpText')}
helpText={translate('ICalShowAsAllDayEventsHelpText')}
onChange={this.onInputChange}
/>
</FormGroup>
@@ -145,7 +145,7 @@ class CalendarLinkModalContent extends Component {
type={inputTypes.TAG}
name="tags"
value={tags}
helpText={translate('TagsHelpText')}
helpText={translate('ICalTagsMoviesHelpText')}
onChange={this.onInputChange}
/>
</FormGroup>
@@ -160,7 +160,7 @@ class CalendarLinkModalContent extends Component {
name="iCalHttpUrl"
value={iCalHttpUrl}
readOnly={true}
helpText={translate('ICalHttpUrlHelpText')}
helpText={translate('ICalFeedHelpText')}
buttons={[
<ClipboardButton
key="copy"

View File

@@ -6,6 +6,7 @@ import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition';
import { executeCommand } from 'Store/Actions/commandActions';
import { saveMovieCollections, setMovieCollectionsFilter, setMovieCollectionsSort } from 'Store/Actions/movieCollectionActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import scrollPositions from 'Store/scrollPositions';
import createCollectionClientSideCollectionItemsSelector from 'Store/Selectors/createCollectionClientSideCollectionItemsSelector';
@@ -38,6 +39,12 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchRootFolders() {
dispatch(fetchRootFolders());
},
dispatchFetchQueueDetails() {
dispatch(fetchQueueDetails());
},
dispatchClearQueueDetails() {
dispatch(clearQueueDetails());
},
onUpdateSelectedPress(payload) {
dispatch(saveMovieCollections(payload));
},
@@ -63,10 +70,12 @@ class CollectionConnector extends Component {
componentDidMount() {
registerPagePopulator(this.repopulate);
this.props.dispatchFetchRootFolders();
this.props.dispatchFetchQueueDetails();
}
componentWillUnmount() {
unregisterPagePopulator(this.repopulate);
this.props.dispatchClearQueueDetails();
}
//
@@ -99,7 +108,9 @@ CollectionConnector.propTypes = {
isSmallScreen: PropTypes.bool.isRequired,
view: PropTypes.string.isRequired,
onUpdateSelectedPress: PropTypes.func.isRequired,
dispatchFetchRootFolders: PropTypes.func.isRequired
dispatchFetchRootFolders: PropTypes.func.isRequired,
dispatchFetchQueueDetails: PropTypes.func.isRequired,
dispatchClearQueueDetails: PropTypes.func.isRequired
};
export default withScrollPosition(

View File

@@ -14,6 +14,50 @@ import styles from './CollectionFooter.css';
const NO_CHANGE = 'noChange';
const monitoredOptions = [
{
key: NO_CHANGE,
get value() {
return translate('NoChange');
},
disabled: true
},
{
key: 'monitored',
get value() {
return translate('Monitored');
}
},
{
key: 'unmonitored',
get value() {
return translate('Unmonitored');
}
}
];
const searchOnAddOptions = [
{
key: NO_CHANGE,
get value() {
return translate('NoChange');
},
disabled: true
},
{
key: 'yes',
get value() {
return translate('Yes');
}
},
{
key: 'no',
get value() {
return translate('No');
}
}
];
class CollectionFooter extends Component {
//
@@ -23,12 +67,12 @@ class CollectionFooter extends Component {
super(props, context);
this.state = {
monitor: NO_CHANGE,
monitored: NO_CHANGE,
monitor: NO_CHANGE,
qualityProfileId: NO_CHANGE,
minimumAvailability: NO_CHANGE,
rootFolderPath: NO_CHANGE,
destinationRootFolder: null
searchOnAdd: NO_CHANGE
};
}
@@ -44,8 +88,9 @@ class CollectionFooter extends Component {
monitored: NO_CHANGE,
monitor: NO_CHANGE,
qualityProfileId: NO_CHANGE,
minimumAvailability: NO_CHANGE,
rootFolderPath: NO_CHANGE,
minimumAvailability: NO_CHANGE
searchOnAdd: NO_CHANGE
});
}
@@ -63,11 +108,12 @@ class CollectionFooter extends Component {
onUpdateSelectedPress = () => {
const {
monitor,
monitored,
monitor,
qualityProfileId,
minimumAvailability,
rootFolderPath
rootFolderPath,
searchOnAdd
} = this.state;
const changes = {};
@@ -92,6 +138,10 @@ class CollectionFooter extends Component {
changes.rootFolderPath = rootFolderPath;
}
if (searchOnAdd !== NO_CHANGE) {
changes.searchOnAdd = searchOnAdd === 'yes';
}
this.props.onUpdateSelectedPress(changes);
};
@@ -109,15 +159,10 @@ class CollectionFooter extends Component {
monitor,
qualityProfileId,
minimumAvailability,
rootFolderPath
rootFolderPath,
searchOnAdd
} = this.state;
const monitoredOptions = [
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: 'monitored', value: translate('Monitored') },
{ key: 'unmonitored', value: translate('Unmonitored') }
];
const selectedCount = selectedIds.length;
return (
@@ -125,7 +170,7 @@ class CollectionFooter extends Component {
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('MonitorCollection')}
isSaving={isSaving}
isSaving={isSaving && monitored !== NO_CHANGE}
/>
<SelectInput
@@ -140,7 +185,7 @@ class CollectionFooter extends Component {
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('MonitorMovies')}
isSaving={isSaving}
isSaving={isSaving && monitor !== NO_CHANGE}
/>
<SelectInput
@@ -198,10 +243,25 @@ class CollectionFooter extends Component {
/>
</div>
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('SearchMoviesOnAdd')}
isSaving={isSaving && searchOnAdd !== NO_CHANGE}
/>
<SelectInput
name="searchOnAdd"
value={searchOnAdd}
values={searchOnAddOptions}
isDisabled={!selectedCount}
onChange={this.onInputChange}
/>
</div>
<div className={styles.buttonContainer}>
<div className={styles.buttonContainerContent}>
<CollectionFooterLabel
label={translate('CollectionsSelectedInterp', [selectedCount])}
label={translate('CountCollectionsSelected', { count: selectedCount })}
isSaving={false}
/>

View File

@@ -70,6 +70,7 @@ class CollectionMovie extends Component {
hasFile,
folder,
isAvailable,
movieFile,
isExistingMovie,
posterWidth,
posterHeight,
@@ -131,6 +132,8 @@ class CollectionMovie extends Component {
id ?
<div className={styles.overlayStatus}>
<MovieIndexProgressBar
movieId={id}
movieFile={movieFile}
monitored={monitored}
hasFile={hasFile}
status={status}
@@ -180,6 +183,7 @@ CollectionMovie.propTypes = {
hasFile: PropTypes.bool,
folder: PropTypes.string,
isAvailable: PropTypes.bool,
movieFile: PropTypes.object,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired,

View File

@@ -74,11 +74,7 @@ CollectionMovieLabel.propTypes = {
CollectionMovieLabel.defaultProps = {
isSaving: false,
statistics: {
episodeFileCount: 0,
totalEpisodeCount: 0,
percentOfEpisodes: 0
}
statistics: {}
};
export default CollectionMovieLabel;

View File

@@ -1,9 +1,7 @@
.description {
line-height: $lineHeight;
}
.description {
margin-left: 0;
line-height: $lineHeight;
overflow-wrap: break-word;
}
@media (min-width: 768px) {

View File

@@ -1,3 +1,4 @@
import { maxBy } from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import FormInputGroup from 'Components/Form/FormInputGroup';
@@ -50,7 +51,7 @@ class FilterBuilderModalContent extends Component {
if (id) {
dispatchSetFilter({ selectedFilterKey: id });
} else {
const last = customFilters[customFilters.length -1];
const last = maxBy(customFilters, 'id');
dispatchSetFilter({ selectedFilterKey: last.id });
}
@@ -108,7 +109,7 @@ class FilterBuilderModalContent extends Component {
this.setState({
labelErrors: [
{
message: 'Label is required'
message: translate('LabelIsRequired')
}
]
});
@@ -146,13 +147,13 @@ class FilterBuilderModalContent extends Component {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Custom Filter
{translate('CustomFilter')}
</ModalHeader>
<ModalBody>
<div className={styles.labelContainer}>
<div className={styles.label}>
Label
{translate('Label')}
</div>
<div className={styles.labelInputContainer}>
@@ -166,9 +167,7 @@ class FilterBuilderModalContent extends Component {
</div>
</div>
<div className={styles.label}>
{translate('Filters')}
</div>
<div className={styles.label}>{translate('Filters')}</div>
<div className={styles.rows}>
{

View File

@@ -23,19 +23,19 @@ const EVENT_TYPE_OPTIONS = [
},
},
{
id: 5,
id: 6,
get name() {
return translate('Deleted');
},
},
{
id: 6,
id: 8,
get name() {
return translate('Renamed');
},
},
{
id: 7,
id: 9,
get name() {
return translate('Ignored');
},

View File

@@ -37,8 +37,8 @@ class CustomFilter extends Component {
dispatchSetFilter
} = this.props;
// Assume that delete and then unmounting means the delete was successful.
// Moving this check to a ancestor would be more accurate, but would have
// Assume that delete and then unmounting means the deletion was successful.
// Moving this check to an ancestor would be more accurate, but would have
// more boilerplate.
if (this.state.isDeleting && id === selectedFilterKey) {
dispatchSetFilter({ selectedFilterKey: 'all' });

View File

@@ -30,22 +30,24 @@ function CustomFiltersModalContent(props) {
<ModalBody>
{
customFilters.map((customFilter) => {
return (
<CustomFilter
key={customFilter.id}
id={customFilter.id}
label={customFilter.label}
filters={customFilter.filters}
selectedFilterKey={selectedFilterKey}
isDeleting={isDeleting}
deleteError={deleteError}
dispatchSetFilter={dispatchSetFilter}
dispatchDeleteCustomFilter={dispatchDeleteCustomFilter}
onEditPress={onEditCustomFilter}
/>
);
})
customFilters
.sort((a, b) => a.label.localeCompare(b.label))
.map((customFilter) => {
return (
<CustomFilter
key={customFilter.id}
id={customFilter.id}
label={customFilter.label}
filters={customFilter.filters}
selectedFilterKey={selectedFilterKey}
isDeleting={isDeleting}
deleteError={deleteError}
dispatchSetFilter={dispatchSetFilter}
dispatchDeleteCustomFilter={dispatchDeleteCustomFilter}
onEditPress={onEditCustomFilter}
/>
);
})
}
<div className={styles.addButtonContainer}>

View File

@@ -25,7 +25,8 @@ function createMapStateToProps() {
const values = _.map(filteredItems.sort(sortByName), (downloadClient) => {
return {
key: downloadClient.id,
value: downloadClient.name
value: downloadClient.name,
hint: `(${downloadClient.id})`
};
});

View File

@@ -267,6 +267,7 @@ FormInputGroup.propTypes = {
name: PropTypes.string.isRequired,
value: PropTypes.any,
values: PropTypes.arrayOf(PropTypes.any),
isDisabled: PropTypes.bool,
type: PropTypes.string.isRequired,
kind: PropTypes.oneOf(kinds.all),
min: PropTypes.number,
@@ -281,6 +282,7 @@ FormInputGroup.propTypes = {
includeNoChange: PropTypes.bool,
includeNoChangeDisabled: PropTypes.bool,
selectedValueOptions: PropTypes.object,
indexerFlags: PropTypes.number,
pending: PropTypes.bool,
errors: PropTypes.arrayOf(PropTypes.object),
warnings: PropTypes.arrayOf(PropTypes.object),

View File

@@ -4,22 +4,18 @@ import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import EnhancedSelectInput from './EnhancedSelectInput';
interface IndexerFlagsSelectInputProps {
name: string;
indexerFlags: number;
onChange(payload: object): void;
}
const selectIndexerFlagsValues = (selectedFlags: number) =>
createSelector(
(state: AppState) => state.settings.indexerFlags,
(indexerFlags) => {
const value = indexerFlags.items
.filter(
// eslint-disable-next-line no-bitwise
(item) => (selectedFlags & item.id) === item.id
)
.map(({ id }) => id);
const value = indexerFlags.items.reduce((acc: number[], { id }) => {
// eslint-disable-next-line no-bitwise
if ((selectedFlags & id) === id) {
acc.push(id);
}
return acc;
}, []);
const values = indexerFlags.items.map(({ id, name }) => ({
key: id,
@@ -33,6 +29,12 @@ const selectIndexerFlagsValues = (selectedFlags: number) =>
}
);
interface IndexerFlagsSelectInputProps {
name: string;
indexerFlags: number;
onChange(payload: object): void;
}
function IndexerFlagsSelectInput(props: IndexerFlagsSelectInputProps) {
const { indexerFlags, onChange } = props;

View File

@@ -3,6 +3,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { addRootFolder } from 'Store/Actions/rootFolderActions';
import createRootFoldersSelector from 'Store/Selectors/createRootFoldersSelector';
import translate from 'Utilities/String/translate';
import RootFolderSelectInput from './RootFolderSelectInput';
@@ -10,7 +11,7 @@ const ADD_NEW_KEY = 'addNew';
function createMapStateToProps() {
return createSelector(
(state) => state.rootFolders,
createRootFoldersSelector(),
(state, { value }) => value,
(state, { includeMissingValue }) => includeMissingValue,
(state, { includeNoChange }) => includeNoChange,

View File

@@ -91,6 +91,7 @@ class TextTagInputConnector extends Component {
render() {
return (
<TagInput
delimiters={['Tab', 'Enter', ',']}
tagList={[]}
onTagAdd={this.onTagAdd}
onTagDelete={this.onTagDelete}

View File

@@ -12,18 +12,10 @@
.info {
color: var(--infoColor);
&:global(.darken) {
color: color(var(--infoColor) shade(30%));
}
}
.pink {
color: var(--pink);
&:global(.darken) {
color: color(var(--pink) shade(30%));
}
}
.success {

View File

@@ -18,7 +18,6 @@ class Icon extends PureComponent {
kind,
size,
title,
darken,
isSpinning,
...otherProps
} = this.props;
@@ -27,8 +26,7 @@ class Icon extends PureComponent {
<FontAwesomeIcon
className={classNames(
className,
styles[kind],
darken && 'darken'
styles[kind]
)}
icon={name}
spin={isSpinning}
@@ -61,7 +59,6 @@ Icon.propTypes = {
kind: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
darken: PropTypes.bool.isRequired,
isSpinning: PropTypes.bool.isRequired,
fixedWidth: PropTypes.bool.isRequired
};
@@ -69,7 +66,6 @@ Icon.propTypes = {
Icon.defaultProps = {
kind: kinds.DEFAULT,
size: 14,
darken: false,
isSpinning: false,
fixedWidth: false
};

View File

@@ -19,7 +19,7 @@ function ImportListList({ lists, importListList }) {
return (
<Label
key={list.id}
kind={kinds.INFO}
kind={kinds.SUCCESS}
size={sizes.MEDIUM}
>
{list.name}

View File

@@ -40,18 +40,26 @@ class FilterMenuContent extends Component {
}
{
customFilters.map((filter) => {
return (
<FilterMenuItem
key={filter.id}
filterKey={filter.id}
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
</FilterMenuItem>
);
})
customFilters.length > 0 ?
<MenuItemSeparator /> :
null
}
{
customFilters
.sort((a, b) => a.label.localeCompare(b.label))
.map((filter) => {
return (
<FilterMenuItem
key={filter.id}
filterKey={filter.id}
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
</FilterMenuItem>
);
})
}
{

View File

@@ -63,6 +63,12 @@
width: 1280px;
}
.extraExtraLarge {
composes: modal;
width: 1600px;
}
@media only screen and (max-width: $breakpointExtraLarge) {
.modal.extraLarge {
width: 90%;
@@ -90,7 +96,8 @@
.modal.small,
.modal.medium,
.modal.large,
.modal.extraLarge {
.modal.extraLarge,
.modal.extraExtraLarge {
max-height: 100%;
width: 100%;
height: 100% !important;

View File

@@ -1,6 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'extraExtraLarge': string;
'extraLarge': string;
'large': string;
'medium': string;

View File

@@ -101,7 +101,7 @@ const links = [
to: '/settings/downloadclients'
},
{
title: () => translate('Lists'),
title: () => translate('ImportLists'),
to: '/settings/importlists'
},
{
@@ -121,7 +121,7 @@ const links = [
to: '/settings/general'
},
{
title: () => translate('UI'),
title: () => translate('Ui'),
to: '/settings/ui'
}
]

View File

@@ -167,7 +167,7 @@ class SignalRConnector extends Component {
const resource = body.resource;
const status = resource.status;
// Both sucessful and failed commands need to be
// Both successful and failed commands need to be
// completed, otherwise they spin until they timeout.
if (status === 'completed' || status === 'failed') {
@@ -187,6 +187,8 @@ class SignalRConnector extends Component {
repopulatePage('movieFileUpdated');
} else if (body.action === 'deleted') {
this.props.dispatchRemoveItem({ section, id: body.resource.id });
repopulatePage('movieFileDeleted');
}
};

View File

@@ -15,5 +15,5 @@
"start_url": "../../../../",
"theme_color": "#3a3f51",
"background_color": "#3a3f51",
"display": "standalone"
"display": "minimal-ui"
}

View File

@@ -0,0 +1,120 @@
import createAjaxRequest from 'Utilities/createAjaxRequest';
// This file contains some helpers for power users in a browser console
let hasWarned = false;
function checkActivationWarning() {
if (!hasWarned) {
console.log('Activated RadarrApi console helpers.');
console.warn('Be warned: There will be no further confirmation checks.');
hasWarned = true;
}
}
function attachAsyncActions(promise) {
promise.filter = function() {
const args = arguments;
const res = this.then((d) => d.filter(...args));
attachAsyncActions(res);
return res;
};
promise.map = function() {
const args = arguments;
const res = this.then((d) => d.map(...args));
attachAsyncActions(res);
return res;
};
promise.all = function() {
const res = this.then((d) => Promise.all(d));
attachAsyncActions(res);
return res;
};
promise.forEach = function(action) {
const res = this.then((d) => Promise.all(d.map(action)));
attachAsyncActions(res);
return res;
};
}
class ResourceApi {
constructor(api, url) {
this.api = api;
this.url = url;
}
single(id) {
return this.api.fetch(`${this.url}/${id}`);
}
all() {
return this.api.fetch(this.url);
}
filter(pred) {
return this.all().filter(pred);
}
update(resource) {
return this.api.fetch(`${this.url}/${resource.id}`, { method: 'PUT', data: resource });
}
delete(resource) {
if (typeof resource === 'object' && resource !== null && resource.id) {
resource = resource.id;
}
if (!resource || !Number.isInteger(resource)) {
throw Error('Invalid resource', resource);
}
return this.api.fetch(`${this.url}/${resource}`, { method: 'DELETE' });
}
fetch(url, options) {
return this.api.fetch(`${this.url}${url}`, options);
}
}
class ConsoleApi {
constructor() {
this.movie = new ResourceApi(this, '/movie');
}
resource(url) {
return new ResourceApi(this, url);
}
fetch(url, options) {
checkActivationWarning();
options = options || {};
const req = {
url,
method: options.method || 'GET'
};
if (options.data) {
req.dataType = 'json';
req.data = JSON.stringify(options.data);
}
const promise = createAjaxRequest(req).request;
promise.fail((xhr) => {
console.error(`Failed to fetch ${url}`, xhr);
});
attachAsyncActions(promise);
return promise;
}
}
window.RadarrApi = new ConsoleApi();
export default ConsoleApi;

View File

@@ -329,10 +329,7 @@ class DiscoverMovie extends Component {
null
}
{
(view === 'posters' || view === 'overview') &&
<PageToolbarSeparator />
}
<PageToolbarSeparator />
<DiscoverMovieViewMenu
view={view}

View File

@@ -78,7 +78,8 @@ function createMapDispatchToProps(dispatch, props) {
onImportListSyncPress() {
dispatch(executeCommand({
name: commandNames.IMPORT_LIST_SYNC
name: commandNames.IMPORT_LIST_SYNC,
commandFinished: this.dispatchFetchListMovies
}));
}
};

View File

@@ -97,6 +97,8 @@ class DiscoverMovieOverview extends Component {
isExisting,
isExcluded,
isRecommendation,
isPopular,
isTrending,
isSelected,
overviewOptions,
...otherProps
@@ -214,6 +216,26 @@ class DiscoverMovieOverview extends Component {
null
}
{
isPopular ?
<Label
kind={kinds.INFO}
>
{translate('Popular')}
</Label> :
null
}
{
isTrending ?
<Label
kind={kinds.INFO}
>
{translate('Trending')}
</Label> :
null
}
<ImportListListConnector
lists={lists}
/>
@@ -283,6 +305,8 @@ DiscoverMovieOverview.propTypes = {
isExisting: PropTypes.bool.isRequired,
isExcluded: PropTypes.bool.isRequired,
isRecommendation: PropTypes.bool.isRequired,
isPopular: PropTypes.bool.isRequired,
isTrending: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
onSelectedChange: PropTypes.func.isRequired

View File

@@ -50,7 +50,7 @@ $hoverScale: 1.05;
.title {
@add-mixin truncate;
background-color: #fafbfc;
background-color: var(--movieBackgroundColor);
text-align: center;
font-size: $smallFontSize;
}
@@ -68,6 +68,19 @@ $hoverScale: 1.05;
color: var(--white);
}
.existing {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 0;
height: 0;
border-width: 25px 25px 0 0;
border-style: solid;
border-color: #37bc9b transparent transparent;
color: var(--white);
}
.controls {
position: absolute;
bottom: 10px;

View File

@@ -7,6 +7,7 @@ interface CssExports {
'controls': string;
'editorSelect': string;
'excluded': string;
'existing': string;
'externalLinks': string;
'link': string;
'overlayTitle': string;

View File

@@ -92,6 +92,7 @@ class DiscoverMoviePoster extends Component {
showRelativeDates,
shortDateFormat,
timeFormat,
movieRuntimeFormat,
...otherProps
} = this.props;
@@ -110,7 +111,7 @@ class DiscoverMoviePoster extends Component {
return (
<div className={styles.content}>
<div className={styles.posterContainer}>
<div className={styles.posterContainer} title={title}>
{
<div className={styles.editorSelect}>
<CheckInput
@@ -158,6 +159,14 @@ class DiscoverMoviePoster extends Component {
/>
}
{
isExisting &&
<div
className={styles.existing}
title={translate('Existing')}
/>
}
<Link
className={styles.link}
style={elementStyle}
@@ -185,7 +194,7 @@ class DiscoverMoviePoster extends Component {
{
showTitle &&
<div className={styles.title}>
<div className={styles.title} title={title}>
{title}
</div>
}
@@ -194,6 +203,7 @@ class DiscoverMoviePoster extends Component {
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
timeFormat={timeFormat}
movieRuntimeFormat={movieRuntimeFormat}
{...otherProps}
/>
@@ -236,6 +246,7 @@ DiscoverMoviePoster.propTypes = {
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired,
isExisting: PropTypes.bool.isRequired,
isExcluded: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,

View File

@@ -5,9 +5,11 @@ import DiscoverMoviePoster from './DiscoverMoviePoster';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.ui.item.movieRuntimeFormat,
createDimensionsSelector(),
( dimensions) => {
(movieRuntimeFormat, dimensions) => {
return {
movieRuntimeFormat,
isSmallScreen: dimensions.isSmallScreen
};
}

View File

@@ -1,5 +1,5 @@
.info {
background-color: #fafbfc;
background-color: var(--movieBackgroundColor);
text-align: center;
font-size: $smallFontSize;
}

View File

@@ -1,9 +1,12 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import TmdbRating from 'Components/TmdbRating';
import { icons } from 'Helpers/Props';
import { getMovieStatusDetails } from 'Movie/MovieStatus';
import formatRuntime from 'Utilities/Date/formatRuntime';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
import translate from 'Utilities/String/translate';
import styles from './DiscoverMoviePosterInfo.css';
function DiscoverMoviePosterInfo(props) {
@@ -19,12 +22,13 @@ function DiscoverMoviePosterInfo(props) {
sortKey,
showRelativeDates,
shortDateFormat,
timeFormat
timeFormat,
movieRuntimeFormat
} = props;
if (sortKey === 'status' && status) {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('Status')}>
{getMovieStatusDetails(status).title}
</div>
);
@@ -32,7 +36,7 @@ function DiscoverMoviePosterInfo(props) {
if (sortKey === 'studio' && studio) {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('Studio')}>
{studio}
</div>
);
@@ -50,8 +54,8 @@ function DiscoverMoviePosterInfo(props) {
);
return (
<div className={styles.info}>
{`In Cinemas ${inCinemasDate}`}
<div className={styles.info} title={translate('InCinemas')}>
<Icon name={icons.IN_CINEMAS} /> {inCinemasDate}
</div>
);
}
@@ -68,8 +72,8 @@ function DiscoverMoviePosterInfo(props) {
);
return (
<div className={styles.info}>
{`Digital ${digitalReleaseDate}`}
<div className={styles.info} title={translate('DigitalRelease')}>
<Icon name={icons.MOVIE_FILE} /> {digitalReleaseDate}
</div>
);
}
@@ -86,15 +90,15 @@ function DiscoverMoviePosterInfo(props) {
);
return (
<div className={styles.info}>
{`Released ${physicalReleaseDate}`}
<div className={styles.info} title={translate('PhysicalRelease')}>
<Icon name={icons.DISC} /> {physicalReleaseDate}
</div>
);
}
if (sortKey === 'certification' && certification) {
return (
<div className={styles.info}>
<div className={styles.info} title={translate('Certification')}>
{certification}
</div>
);
@@ -102,8 +106,8 @@ function DiscoverMoviePosterInfo(props) {
if (sortKey === 'runtime' && runtime) {
return (
<div className={styles.info}>
{formatRuntime(runtime)}
<div className={styles.info} title={translate('Runtime')}>
{formatRuntime(runtime, movieRuntimeFormat)}
</div>
);
}
@@ -111,9 +115,7 @@ function DiscoverMoviePosterInfo(props) {
if (sortKey === 'ratings' && ratings) {
return (
<div className={styles.info}>
<TmdbRating
ratings={ratings}
/>
<TmdbRating ratings={ratings} />
</div>
);
}
@@ -133,7 +135,8 @@ DiscoverMoviePosterInfo.propTypes = {
sortKey: PropTypes.string.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired
timeFormat: PropTypes.string.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired
};
export default DiscoverMoviePosterInfo;

View File

@@ -57,10 +57,12 @@
flex: 0 0 115px;
}
.isTrending,
.isPopular,
.isRecommendation {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 50px;
flex: 0 0 30px;
}
.actions {

View File

@@ -7,7 +7,9 @@ interface CssExports {
'digitalRelease': string;
'genres': string;
'inCinemas': string;
'isPopular': string;
'isRecommendation': string;
'isTrending': string;
'lists': string;
'originalLanguage': string;
'physicalRelease': string;

View File

@@ -7,6 +7,7 @@ import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
import { icons } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import DiscoverMovieTableOptionsConnector from './DiscoverMovieTableOptionsConnector';
import styles from './DiscoverMovieHeader.css';
@@ -98,6 +99,43 @@ class DiscoverMovieHeader extends Component {
<Icon
name={icons.RECOMMENDED}
size={12}
title={translate('Recommendation')}
/>
</VirtualTableHeaderCell>
);
}
if (name === 'isTrending') {
return (
<VirtualTableHeaderCell
key={name}
className={styles[name]}
name={name}
isSortable={true}
{...otherProps}
>
<Icon
name={icons.TRENDING}
size={12}
title={translate('Trending')}
/>
</VirtualTableHeaderCell>
);
}
if (name === 'isPopular') {
return (
<VirtualTableHeaderCell
key={name}
className={styles[name]}
name={name}
isSortable={true}
{...otherProps}
>
<Icon
name={icons.POPULAR}
size={12}
title={translate('Popular')}
/>
</VirtualTableHeaderCell>
);

View File

@@ -76,10 +76,12 @@
flex: 1 0 110px;
}
.isTrending,
.isPopular,
.isRecommendation {
composes: cell;
flex: 0 0 50px;
flex: 0 0 30px;
}
.actions {
@@ -95,6 +97,11 @@
margin-top: 0;
}
.statusIcon {
width: 20px !important;
text-align: center;
}
.externalLinks {
margin-right: 0.5em;
}

View File

@@ -12,7 +12,9 @@ interface CssExports {
'externalLinks': string;
'genres': string;
'inCinemas': string;
'isPopular': string;
'isRecommendation': string;
'isTrending': string;
'lists': string;
'originalLanguage': string;
'physicalRelease': string;
@@ -21,6 +23,7 @@ interface CssExports {
'runtime': string;
'sortTitle': string;
'status': string;
'statusIcon': string;
'studio': string;
}
export const cssExports: CssExports;

View File

@@ -76,11 +76,14 @@ class DiscoverMovieRow extends Component {
ratings,
popularity,
certification,
movieRuntimeFormat,
collection,
columns,
isExisting,
isExcluded,
isRecommendation,
isTrending,
isPopular,
isSelected,
lists,
onSelectedChange
@@ -230,7 +233,7 @@ class DiscoverMovieRow extends Component {
key={name}
className={styles[name]}
>
{formatRuntime(runtime)}
{formatRuntime(runtime, movieRuntimeFormat)}
</VirtualTableRowCell>
);
}
@@ -304,6 +307,7 @@ class DiscoverMovieRow extends Component {
{
isRecommendation ?
<Icon
className={styles.statusIcon}
name={icons.RECOMMENDED}
size={12}
title={translate('MovieIsRecommend')}
@@ -314,6 +318,46 @@ class DiscoverMovieRow extends Component {
);
}
if (name === 'isTrending') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{
isTrending ?
<Icon
className={styles.statusIcon}
name={icons.TRENDING}
size={12}
title={translate('MovieIsTrending')}
/> :
null
}
</VirtualTableRowCell>
);
}
if (name === 'isPopular') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
{
isPopular ?
<Icon
className={styles.statusIcon}
name={icons.POPULAR}
size={12}
title={translate('MovieIsPopular')}
/> :
null
}
</VirtualTableRowCell>
);
}
if (name === 'actions') {
return (
<VirtualTableRowCell
@@ -397,11 +441,14 @@ DiscoverMovieRow.propTypes = {
popularity: PropTypes.number.isRequired,
certification: PropTypes.string,
collection: PropTypes.object,
movieRuntimeFormat: PropTypes.string.isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
isExisting: PropTypes.bool.isRequired,
isExcluded: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
isRecommendation: PropTypes.bool.isRequired,
isPopular: PropTypes.bool.isRequired,
isTrending: PropTypes.bool.isRequired,
lists: PropTypes.arrayOf(PropTypes.number).isRequired,
onSelectedChange: PropTypes.func.isRequired
};

View File

@@ -5,9 +5,11 @@ import DiscoverMovieRow from './DiscoverMovieRow';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.ui.item.movieRuntimeFormat,
createDimensionsSelector(),
(dimensions) => {
(movieRuntimeFormat, dimensions) => {
return {
movieRuntimeFormat,
isSmallScreen: dimensions.isSmallScreen
};
}

View File

@@ -34,7 +34,8 @@ function AuthenticationRequiredModalContent(props) {
authenticationMethod,
authenticationRequired,
username,
password
password,
passwordConfirmation
} = settings;
const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none';
@@ -63,7 +64,7 @@ function AuthenticationRequiredModalContent(props) {
className={styles.authRequiredAlert}
kind={kinds.WARNING}
>
{translate('AuthenticationRequiredWarning', { appName: 'Radarr' })}
{translate('AuthenticationRequiredWarning')}
</Alert>
{
@@ -76,7 +77,7 @@ function AuthenticationRequiredModalContent(props) {
type={inputTypes.SELECT}
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText', { appName: 'Radarr' })}
helpText={translate('AuthenticationMethodHelpText')}
helpTextWarning={authenticationMethod.value === 'none' ? translate('AuthenticationMethodHelpTextWarning') : undefined}
helpLink="https://wiki.servarr.com/radarr/faq#forced-authentication"
onChange={onInputChange}
@@ -120,6 +121,18 @@ function AuthenticationRequiredModalContent(props) {
{...password}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="passwordConfirmation"
onChange={onInputChange}
helpTextWarning={passwordConfirmation?.value ? undefined : translate('AuthenticationRequiredPasswordConfirmationHelpTextWarning')}
{...passwordConfirmation}
/>
</FormGroup>
</div> :
null
}

View File

@@ -23,6 +23,7 @@ import {
import {
faArrowCircleLeft as fasArrowCircleLeft,
faArrowCircleRight as fasArrowCircleRight,
faArrowTrendUp as fasArrowTrendUp,
faAsterisk as fasAsterisk,
faBackward as fasBackward,
faBan as fasBan,
@@ -59,6 +60,7 @@ import {
faEye as fasEye,
faFastBackward as fasFastBackward,
faFastForward as fasFastForward,
faFileCircleQuestion as fasFileCircleQuestion,
faFileExport as fasFileExport,
faFileInvoice as farFileInvoice,
faFilm as fasFilm,
@@ -159,6 +161,7 @@ export const EXPORT = fasFileExport;
export const EXTERNAL_LINK = fasExternalLinkAlt;
export const FATAL = fasTimesCircle;
export const FILE = farFile;
export const FILE_MISSING = fasFileCircleQuestion;
export const FILM = fasFilm;
export const FILTER = fasFilter;
export const FLAG = fasFlag;
@@ -231,6 +234,7 @@ export const TAGS = fasTags;
export const TBA = fasQuestionCircle;
export const TEST = fasVial;
export const TRANSLATE = fasLanguage;
export const TRENDING = fasArrowTrendUp;
export const UNGROUP = farObjectUngroup;
export const UNKNOWN = fasQuestion;
export const UNMONITORED = farBookmark;

View File

@@ -3,5 +3,6 @@ export const SMALL = 'small';
export const MEDIUM = 'medium';
export const LARGE = 'large';
export const EXTRA_LARGE = 'extraLarge';
export const EXTRA_EXTRA_LARGE = 'extraExtraLarge';
export const all = [EXTRA_SMALL, SMALL, MEDIUM, LARGE, EXTRA_LARGE];
export const all = [EXTRA_SMALL, SMALL, MEDIUM, LARGE, EXTRA_LARGE, EXTRA_EXTRA_LARGE];

View File

@@ -0,0 +1,34 @@
import React from 'react';
import Modal from 'Components/Modal/Modal';
import SelectIndexerFlagsModalContent from './SelectIndexerFlagsModalContent';
interface SelectIndexerFlagsModalProps {
isOpen: boolean;
indexerFlags: number;
modalTitle: string;
onIndexerFlagsSelect(indexerFlags: number): void;
onModalClose(): void;
}
function SelectIndexerFlagsModal(props: SelectIndexerFlagsModalProps) {
const {
isOpen,
indexerFlags,
modalTitle,
onIndexerFlagsSelect,
onModalClose,
} = props;
return (
<Modal isOpen={isOpen} onModalClose={onModalClose}>
<SelectIndexerFlagsModalContent
indexerFlags={indexerFlags}
modalTitle={modalTitle}
onIndexerFlagsSelect={onIndexerFlagsSelect}
onModalClose={onModalClose}
/>
</Modal>
);
}
export default SelectIndexerFlagsModal;

View File

@@ -0,0 +1,7 @@
.modalBody {
composes: modalBody from '~Components/Modal/ModalBody.css';
display: flex;
flex: 1 1 auto;
flex-direction: column;
}

View File

@@ -0,0 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'modalBody': string;
}
export const cssExports: CssExports;
export default cssExports;

View File

@@ -0,0 +1,75 @@
import React, { useCallback, useState } 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, kinds, scrollDirections } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './SelectIndexerFlagsModalContent.css';
interface SelectIndexerFlagsModalContentProps {
indexerFlags: number;
modalTitle: string;
onIndexerFlagsSelect(indexerFlags: number): void;
onModalClose(): void;
}
function SelectIndexerFlagsModalContent(
props: SelectIndexerFlagsModalContentProps
) {
const { modalTitle, onIndexerFlagsSelect, onModalClose } = props;
const [indexerFlags, setIndexerFlags] = useState(props.indexerFlags);
const onIndexerFlagsChange = useCallback(
({ value }: { value: number }) => {
setIndexerFlags(value);
},
[setIndexerFlags]
);
const onIndexerFlagsSelectWrapper = useCallback(() => {
onIndexerFlagsSelect(indexerFlags);
}, [indexerFlags, onIndexerFlagsSelect]);
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('SetIndexerFlagsModalTitle', { modalTitle })}
</ModalHeader>
<ModalBody
className={styles.modalBody}
scrollDirection={scrollDirections.NONE}
>
<Form>
<FormGroup>
<FormLabel>{translate('IndexerFlags')}</FormLabel>
<FormInputGroup
type={inputTypes.INDEXER_FLAGS_SELECT}
name="indexerFlags"
indexerFlags={indexerFlags}
autoFocus={true}
onChange={onIndexerFlagsChange}
/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>{translate('Cancel')}</Button>
<Button kind={kinds.SUCCESS} onPress={onIndexerFlagsSelectWrapper}>
{translate('SetIndexerFlags')}
</Button>
</ModalFooter>
</ModalContent>
);
}
export default SelectIndexerFlagsModalContent;

View File

@@ -26,6 +26,7 @@ import usePrevious from 'Helpers/Hooks/usePrevious';
import useSelectState from 'Helpers/Hooks/useSelectState';
import { align, icons, kinds, scrollDirections } from 'Helpers/Props';
import ImportMode from 'InteractiveImport/ImportMode';
import SelectIndexerFlagsModal from 'InteractiveImport/IndexerFlags/SelectIndexerFlagsModal';
import InteractiveImport, {
InteractiveImportCommandOptions,
} from 'InteractiveImport/InteractiveImport';
@@ -59,7 +60,13 @@ import getSelectedIds from 'Utilities/Table/getSelectedIds';
import InteractiveImportRow from './InteractiveImportRow';
import styles from './InteractiveImportModalContent.css';
type SelectType = 'select' | 'movie' | 'releaseGroup' | 'quality' | 'language';
type SelectType =
| 'select'
| 'movie'
| 'releaseGroup'
| 'quality'
| 'language'
| 'indexerFlags';
type FilterExistingFiles = 'all' | 'new';
@@ -113,6 +120,15 @@ const COLUMNS = [
isSortable: true,
isVisible: true,
},
{
name: 'indexerFlags',
label: React.createElement(Icon, {
name: icons.FLAG,
title: () => translate('IndexerFlags'),
}),
isSortable: true,
isVisible: true,
},
{
name: 'rejections',
label: React.createElement(Icon, {
@@ -242,25 +258,6 @@ function InteractiveImportModalContent(
const [interactiveImportErrorMessage, setInteractiveImportErrorMessage] =
useState<string | null>(null);
const [selectState, setSelectState] = useSelectState();
const [bulkSelectOptions, setBulkSelectOptions] = useState([
{
key: 'select',
value: translate('SelectDropdown'),
disabled: true,
},
{
key: 'quality',
value: translate('SelectQuality'),
},
{
key: 'releaseGroup',
value: translate('SelectReleaseGroup'),
},
{
key: 'language',
value: translate('SelectLanguage'),
},
]);
const { allSelected, allUnselected, selectedState } = selectState;
const previousIsDeleting = usePrevious(isDeleting);
const dispatch = useDispatch();
@@ -276,26 +273,60 @@ function InteractiveImportModalContent(
}
}
const showIndexerFlags = items.some((item) => item.indexerFlags);
if (!showIndexerFlags) {
const indexerFlagsColumn = result.find((c) => c.name === 'indexerFlags');
if (indexerFlagsColumn) {
indexerFlagsColumn.isVisible = false;
}
}
return result;
}, [showMovie]);
}, [showMovie, items]);
const selectedIds: number[] = useMemo(() => {
return getSelectedIds(selectedState);
}, [selectedState]);
const bulkSelectOptions = useMemo(() => {
const options = [
{
key: 'select',
value: translate('SelectDropdown'),
disabled: true,
},
{
key: 'quality',
value: translate('SelectQuality'),
},
{
key: 'releaseGroup',
value: translate('SelectReleaseGroup'),
},
{
key: 'language',
value: translate('SelectLanguage'),
},
{
key: 'indexerFlags',
value: translate('SelectIndexerFlags'),
},
];
if (allowMovieChange) {
options.splice(1, 0, {
key: 'movie',
value: translate('SelectMovie'),
});
}
return options;
}, [allowMovieChange]);
useEffect(
() => {
if (allowMovieChange) {
const newBulkSelectOptions = [...bulkSelectOptions];
newBulkSelectOptions.splice(1, 0, {
key: 'movie',
value: translate('SelectMovie'),
});
setBulkSelectOptions(newBulkSelectOptions);
}
if (initialSortKey) {
const sortProps: { sortKey: string; sortDirection?: string } = {
sortKey: initialSortKey,
@@ -415,7 +446,14 @@ function InteractiveImportModalContent(
const isSelected = selectedIds.indexOf(item.id) > -1;
if (isSelected) {
const { movie, releaseGroup, quality, languages, movieFileId } = item;
const {
movie,
releaseGroup,
quality,
languages,
indexerFlags,
movieFileId,
} = item;
if (!movie) {
setInteractiveImportErrorMessage(
@@ -449,6 +487,7 @@ function InteractiveImportModalContent(
releaseGroup,
quality,
languages,
indexerFlags,
});
return;
@@ -462,6 +501,7 @@ function InteractiveImportModalContent(
releaseGroup,
quality,
languages,
indexerFlags,
downloadId,
movieFileId,
});
@@ -619,6 +659,22 @@ function InteractiveImportModalContent(
[selectedIds, dispatch]
);
const onIndexerFlagsSelect = useCallback(
(indexerFlags: number) => {
dispatch(
updateInteractiveImportItems({
ids: selectedIds,
indexerFlags,
})
);
dispatch(reprocessInteractiveImportItems({ ids: selectedIds }));
setSelectModalOpen(null);
},
[selectedIds, dispatch]
);
const errorMessage = getErrorMessage(
error,
translate('InteractiveImportLoadError')
@@ -793,6 +849,14 @@ function InteractiveImportModalContent(
onModalClose={onSelectModalClose}
/>
<SelectIndexerFlagsModal
isOpen={selectModalOpen === 'indexerFlags'}
indexerFlags={0}
modalTitle={modalTitle}
onIndexerFlagsSelect={onIndexerFlagsSelect}
onModalClose={onSelectModalClose}
/>
<ConfirmModal
isOpen={isConfirmDeleteModalOpen}
kind={kinds.DANGER}

View File

@@ -8,11 +8,13 @@ import Column from 'Components/Table/Column';
import TableRow from 'Components/Table/TableRow';
import Popover from 'Components/Tooltip/Popover';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import SelectIndexerFlagsModal from 'InteractiveImport/IndexerFlags/SelectIndexerFlagsModal';
import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal';
import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal';
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
import Language from 'Language/Language';
import IndexerFlags from 'Movie/IndexerFlags';
import Movie from 'Movie/Movie';
import MovieFormats from 'Movie/MovieFormats';
import MovieLanguage from 'Movie/MovieLanguage';
@@ -30,7 +32,12 @@ import translate from 'Utilities/String/translate';
import InteractiveImportRowCellPlaceholder from './InteractiveImportRowCellPlaceholder';
import styles from './InteractiveImportRow.css';
type SelectType = 'movie' | 'releaseGroup' | 'quality' | 'language';
type SelectType =
| 'movie'
| 'releaseGroup'
| 'quality'
| 'language'
| 'indexerFlags';
type SelectedChangeProps = SelectStateInputProps & {
hasMovieFileId: boolean;
@@ -47,6 +54,7 @@ interface InteractiveImportRowProps {
size: number;
customFormats?: object[];
customFormatScore?: number;
indexerFlags: number;
rejections: Rejection[];
columns: Column[];
movieFileId?: number;
@@ -69,6 +77,7 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
size,
customFormats,
customFormatScore,
indexerFlags,
rejections,
isSelected,
modalTitle,
@@ -84,6 +93,10 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
() => columns.find((c) => c.name === 'movie')?.isVisible ?? false,
[columns]
);
const isIndexerFlagsColumnVisible = useMemo(
() => columns.find((c) => c.name === 'indexerFlags')?.isVisible ?? false,
[columns]
);
const [selectModalOpen, setSelectModalOpen] = useState<SelectType | null>(
null
@@ -223,12 +236,34 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
[id, dispatch, setSelectModalOpen, selectRowAfterChange]
);
const onSelectIndexerFlagsPress = useCallback(() => {
setSelectModalOpen('indexerFlags');
}, [setSelectModalOpen]);
const onIndexerFlagsSelect = useCallback(
(indexerFlags: number) => {
dispatch(
updateInteractiveImportItem({
id,
indexerFlags,
})
);
dispatch(reprocessInteractiveImportItems({ ids: [id] }));
setSelectModalOpen(null);
selectRowAfterChange();
},
[id, dispatch, setSelectModalOpen, selectRowAfterChange]
);
const movieTitle = movie ? movie.title : '';
const showMoviePlaceholder = isSelected && !movie;
const showReleaseGroupPlaceholder = isSelected && !releaseGroup;
const showQualityPlaceholder = isSelected && !quality;
const showLanguagePlaceholder = isSelected && !languages;
const showIndexerFlagsPlaceholder = isSelected && !indexerFlags;
return (
<TableRow>
@@ -311,6 +346,28 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
) : null}
</TableRowCell>
{isIndexerFlagsColumnVisible ? (
<TableRowCellButton
title={translate('ClickToChangeIndexerFlags')}
onPress={onSelectIndexerFlagsPress}
>
{showIndexerFlagsPlaceholder ? (
<InteractiveImportRowCellPlaceholder isOptional={true} />
) : (
<>
{indexerFlags ? (
<Popover
anchor={<Icon name={icons.FLAG} kind={kinds.PRIMARY} />}
title={translate('IndexerFlags')}
body={<IndexerFlags indexerFlags={indexerFlags} />}
position={tooltipPositions.LEFT}
/>
) : null}
</>
)}
</TableRowCellButton>
) : null}
<TableRowCell>
{rejections.length ? (
<Popover
@@ -361,6 +418,14 @@ function InteractiveImportRow(props: InteractiveImportRowProps) {
onLanguagesSelect={onLanguagesSelect}
onModalClose={onSelectModalClose}
/>
<SelectIndexerFlagsModal
isOpen={selectModalOpen === 'indexerFlags'}
indexerFlags={indexerFlags ?? 0}
modalTitle={modalTitle}
onIndexerFlagsSelect={onIndexerFlagsSelect}
onModalClose={onSelectModalClose}
/>
</TableRow>
);
}

View File

@@ -11,6 +11,7 @@ export interface InteractiveImportCommandOptions {
releaseGroup?: string;
quality: QualityModel;
languages: Language[];
indexerFlags: number;
downloadId?: string;
movieFileId?: number;
}
@@ -27,6 +28,7 @@ interface InteractiveImport extends ModelBase {
movie?: Movie;
qualityWeight: number;
customFormats: object[];
indexerFlags: number;
rejections: Rejection[];
movieFileId?: number;
}

View File

@@ -3,13 +3,16 @@ import React, { Fragment } from 'react';
import Alert from 'Components/Alert';
import Icon from 'Components/Icon';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
import PageMenuButton from 'Components/Menu/PageMenuButton';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import { icons, kinds, sortDirections } from 'Helpers/Props';
import { align, icons, kinds, sortDirections } from 'Helpers/Props';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate';
import InteractiveSearchFilterModalConnector from './InteractiveSearchFilterModalConnector';
import InteractiveSearchRowConnector from './InteractiveSearchRowConnector';
import styles from './InteractiveSearchContent.css';
import styles from './InteractiveSearch.css';
const columns = [
{
@@ -24,23 +27,6 @@ const columns = [
isSortable: true,
isVisible: true
},
{
name: 'releaseWeight',
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, {
name: icons.DANGER,
title: () => translate('Rejections')
}),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'title',
label: () => translate('Title'),
@@ -84,12 +70,6 @@ const columns = [
isSortable: true,
isVisible: true
},
{
name: 'customFormat',
label: () => translate('Formats'),
isSortable: true,
isVisible: true
},
{
name: 'customFormatScore',
label: React.createElement(Icon, {
@@ -107,10 +87,27 @@ const columns = [
}),
isSortable: true,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, {
name: icons.DANGER,
title: () => translate('Rejections')
}),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'releaseWeight',
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
}
];
function InteractiveSearchContent(props) {
function InteractiveSearch(props) {
const {
searchPayload,
isFetching,
@@ -118,18 +115,36 @@ function InteractiveSearchContent(props) {
error,
totalReleasesCount,
items,
selectedFilterKey,
filters,
customFilters,
sortKey,
sortDirection,
longDateFormat,
timeFormat,
onSortPress,
onFilterSelect,
onGrabPress
} = props;
const errorMessage = getErrorMessage(error);
const type = 'movies';
return (
<div>
<div className={styles.filterMenuContainer}>
<FilterMenu
alignMenu={align.RIGHT}
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
buttonComponent={PageMenuButton}
filterModalConnectorComponent={InteractiveSearchFilterModalConnector}
filterModalConnectorComponentProps={{ type }}
onFilterSelect={onFilterSelect}
/>
</div>
{
isFetching ? <LoadingIndicator /> : null
}
@@ -203,19 +218,23 @@ function InteractiveSearchContent(props) {
);
}
InteractiveSearchContent.propTypes = {
InteractiveSearch.propTypes = {
searchPayload: PropTypes.object.isRequired,
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,
totalReleasesCount: PropTypes.number.isRequired,
items: 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.string,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
onSortPress: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired
};
export default InteractiveSearchContent;
export default InteractiveSearch;

View File

@@ -2,10 +2,11 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearMovieHistory, fetchMovieHistory } from 'Store/Actions/movieHistoryActions';
import * as releaseActions from 'Store/Actions/releaseActions';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import InteractiveSearchContent from './InteractiveSearchContent';
import InteractiveSearch from './InteractiveSearch';
function createMapStateToProps(appState) {
return createSelector(
@@ -29,8 +30,12 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(releaseActions.fetchReleases(payload));
},
dispatchClearReleases(payload) {
dispatch(releaseActions.clearReleases(payload));
dispatchFetchMovieHistory({ movieId }) {
dispatch(fetchMovieHistory({ movieId }));
},
dispatchClearMovieHistory() {
dispatch(clearMovieHistory());
},
onSortPress(sortKey, sortDirection) {
@@ -38,8 +43,7 @@ function createMapDispatchToProps(dispatch, props) {
},
onFilterSelect(selectedFilterKey) {
const action = releaseActions.setReleasesFilter;
dispatch(action({ selectedFilterKey }));
dispatch(releaseActions.setReleasesFilter({ selectedFilterKey }));
},
onGrabPress(payload) {
@@ -48,7 +52,7 @@ function createMapDispatchToProps(dispatch, props) {
};
}
class InteractiveSearchContentConnector extends Component {
class InteractiveSearchConnector extends Component {
//
// Lifecycle
@@ -57,7 +61,8 @@ class InteractiveSearchContentConnector extends Component {
const {
searchPayload,
isPopulated,
dispatchFetchReleases
dispatchFetchReleases,
dispatchFetchMovieHistory
} = this.props;
// If search results are not yet isPopulated fetch them,
@@ -65,6 +70,12 @@ class InteractiveSearchContentConnector extends Component {
if (!isPopulated) {
dispatchFetchReleases(searchPayload);
}
dispatchFetchMovieHistory(searchPayload);
}
componentWillUnmount() {
this.props.dispatchClearMovieHistory();
}
//
@@ -73,24 +84,26 @@ class InteractiveSearchContentConnector extends Component {
render() {
const {
dispatchFetchReleases,
dispatchClearReleases,
dispatchFetchMovieHistory,
dispatchClearMovieHistory,
...otherProps
} = this.props;
return (
<InteractiveSearchContent
<InteractiveSearch
{...otherProps}
/>
);
}
}
InteractiveSearchContentConnector.propTypes = {
InteractiveSearchConnector.propTypes = {
searchPayload: PropTypes.object.isRequired,
isPopulated: PropTypes.bool.isRequired,
dispatchFetchReleases: PropTypes.func.isRequired,
dispatchClearReleases: PropTypes.func.isRequired
dispatchFetchMovieHistory: PropTypes.func.isRequired,
dispatchClearMovieHistory: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchContentConnector);
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchConnector);

View File

@@ -4,7 +4,7 @@ import FilterMenu from 'Components/Menu/FilterMenu';
import PageMenuButton from 'Components/Menu/PageMenuButton';
import { align } from 'Helpers/Props';
import InteractiveSearchFilterModalConnector from './InteractiveSearchFilterModalConnector';
import styles from './InteractiveSearchContent.css';
import styles from './InteractiveSearch.css';
function InteractiveSearchFilterMenu(props) {
const {

View File

@@ -1,23 +1,29 @@
.cell {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
}
.protocol {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 80px;
}
.titleContent {
display: flex;
align-items: center;
justify-content: space-between;
word-break: break-all;
}
.indexer {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 85px;
}
.quality,
.customFormat,
.languages {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
}
.quality {
white-space: nowrap;
}
.languages {
@@ -25,7 +31,7 @@
}
.customFormatScore {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 55px;
font-weight: bold;
@@ -34,30 +40,26 @@
.rejected,
.indexerFlags {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 50px;
}
.age,
.size {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
white-space: nowrap;
}
.peers {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 75px;
}
.titleContent {
overflow-wrap: break-word;
}
.history {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 75px;
}
@@ -67,7 +69,7 @@
}
.download {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 80px;
}

Some files were not shown because too many files have changed in this diff Show More