1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-18 21:35:51 -04:00

Compare commits

...

530 Commits

Author SHA1 Message Date
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
Weblate 3e5089719c Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Ruben Lourenco <ruben.lourenco01@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: jianl <jianjianfengyun@126.com>
Co-authored-by: 宿命 <331874545@qq.com>
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/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-10-22 10:53:19 +03:00
Bogdan ec69dfaabb Bump version to 5.1.2 2023-10-22 09:37:23 +03:00
Qstick aa13a40bad Fixed: Update movie collection status in Radarr if removed on TMDB 2023-10-21 20:11:49 -05:00
Bogdan 9b458812f1 Fixed: Set Busy Timeout for SQLite 2023-10-21 22:47:19 +03:00
Bogdan 1bdc48a889 Revert "Bump SQLite to 3.42.0 (1.0.118)"
This reverts commit e3160466e0.
2023-10-20 22:28:49 +03:00
Servarr e5d479a162 Automated API Docs update 2023-10-17 19:13:07 +03:00
Bogdan 9a50fcb82a Sort movies by name in filter builder 2023-10-17 18:59:34 +03:00
Stevie Robinson f2357e0b60 Fixed: Reduce font size for series title on series details
(cherry picked from commit 03f5174a4b2a005aab8d1a1540f4bcb272682f2e)

Closes #9301
Closes #9302
2023-10-17 18:23:33 +03:00
Mark McDowall 0591d05c3b New: History custom filters
(cherry picked from commit 2fe8f3084c90688e6dd01d600796396e74f43ff9)

Closes #9298
2023-10-17 18:23:07 +03:00
Mark McDowall 299d50d56c Cleanup Calendar custom filters
(cherry picked from commit fd789343b587da252461d84bafba2d72651a11df)

Closes #9296
2023-10-17 14:41:55 +03:00
Mark McDowall 7d3c01114b New: Queue custom filters
(cherry picked from commit e357d17b187378b92377f8acb077b12c1e7ea527)

Closes #9297
2023-10-17 14:38:49 +03:00
bakerboy448 70376af70b Fixed: Re-run Removed Movie health check after movie is deleted (#9277) 2023-10-17 12:39:20 +03:00
Bogdan 9ef031bd9e Fixed: Don't die when adding existing exclusions 2023-10-16 05:45:24 +03:00
Weblate 3a9b276c43 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: DavidHenryThoreau <sorau@protonmail.com>
Co-authored-by: Dlgeri123 <bornemiszageri@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: bai0012 <baicongrui@gmail.com>
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/zh_CN/
Translation: Servarr/Radarr
2023-10-15 18:33:49 +03:00
Bogdan aabf209a07 Bump version to 5.1.1 2023-10-15 07:52:43 +03:00
Mark McDowall 79c03f2fe6 Fixed: Reject full DVD disk releases
(cherry picked from commit df2e867528249cf707788d8341c4a26293e179ba)
2023-10-14 21:06:36 -04:00
Bogdan 9b36404071 Fixed: Don't die in Collections when a collection doesn't have movies 2023-10-14 20:11:36 +03:00
Bogdan ecfaea3885 Fixed: Don't die in FileNameBuilder when OriginalTitle is null 2023-10-13 19:49:31 +03:00
Bogdan bfbeb4c62e Fixed: Ignore case when cleansing announce URLs 2023-10-12 05:03:22 +03:00
Bogdan 4b98d27f31 New: Tooltips for dates in MovieReleaseDates 2023-10-11 15:02:43 +03:00
Weblate 604d74270d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: He Zhu <zhuhe202@qq.com>
Co-authored-by: Timo <Tclemens@live.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 宿命 <331874545@qq.com>
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/zh_CN/
Translation: Servarr/Radarr
2023-10-11 06:33:42 +03:00
Bogdan 15bb9139d1 New: Sort movies by release dates 2023-10-11 06:32:30 +03:00
Servarr 32722eb704 Automated API Docs update 2023-10-11 05:07:00 +03:00
Mark McDowall e0c8a8f0d6 New: Download client option for redownloading failed releases from Interactive Search
(cherry picked from commit 87e0a7983a437a4d166aa8b9c9eaf78ea5431969)

Closes #9260
2023-10-11 04:50:39 +03:00
Bogdan a3bb0541f0 Prevent NullRef on header assert 2023-10-11 04:29:20 +03:00
Bogdan e78bc34514 Fixed: Fetch import lists without depending on Automatic Add 2023-10-11 03:38:28 +03:00
Servarr 35c4538288 Automated API Docs update 2023-10-11 02:27:16 +03:00
Bogdan 3981e816cd Remove PagingResourceFilter 2023-10-11 02:19:28 +03:00
Mark McDowall 9354031571 Log executing health check
Towards #6076

(cherry picked from commit 78b39bd2fecda60e04a1fef17ae17f62bd2b6914)
2023-10-10 07:04:52 +03:00
Mark McDowall a01328dc8c Paging params in API docs
(cherry picked from commit bfaa7291e14a8d3847ef2154a52c363944560803)

Closes #9248
2023-10-10 07:03:41 +03:00
Stevie Robinson 8cb6295ddc New: Additional tooltips for icon buttons
(cherry picked from commit 8c07f0d3d19a48ed96d1ded54399c66bf2977b2a)

Closes #9253
2023-10-10 06:51:57 +03:00
Bogdan 99f7d8bcf5 New: Auto tag based on movie's quality profile
(cherry picked from commit 6de3e7c950bd939bab96ef2ae74337108ad5a212)

Closes #9254
2023-10-10 06:50:36 +03:00
Bogdan f13d479b88 Add status test all button for IndexerLongTermStatusCheck
(cherry picked from commit 4ffa1816bd2305550abee20cea27e1296a99ddf6)
2023-10-10 06:48:04 +03:00
Bogdan 23eb637bc3 Fixed: Avoid logging evaluations when not using any Remote Path Mappings
(cherry picked from commit 44eb729ccc13237f4439006159bd616e8bdb5750)
2023-10-10 06:47:49 +03:00
Bogdan 3a786d0b9d Fixed: Displaying multiple values when adding custom filters
Closes #5810
2023-10-10 05:55:55 +03:00
Bogdan 6fb127235c Fixed: Calendar's agenda on mobile 2023-10-10 01:42:46 +03:00
Qstick 5517e578b6 Bump version to 5.1.0 2023-10-07 23:07:42 -05:00
nuxen bced2e7b2e Fixed: Updated BR-DISK quality parsing 2023-10-08 06:49:37 +03:00
Bogdan f7313369b5 Fixed: Show year in collection movies as labels 2023-10-08 06:12:18 +03:00
Servarr b14e93e11f Automated API Docs update 2023-10-08 01:50:59 +03:00
Bogdan f5692d6cf1 Fixed: Show year and fix sorting for collection movies 2023-10-08 01:41:24 +03:00
Weblate a2d505c795 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: blankhang <blankhang@gmail.com>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
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-07 16:53:23 -05:00
Qstick 3d46bd2d8f Revert cover mapping for collections, optimize translation mapping 2023-10-07 15:43:59 -05:00
Bogdan 017f272201 Log Notifiarr errors as warnings 2023-10-07 22:56:22 +03:00
Bogdan c221e2097a Prevent NullRef for cases when media covers have nullable urls 2023-10-05 02:42:18 +03:00
Bogdan a61804e949 Fixed localization test 2023-10-05 01:45:55 +03:00
Bogdan cb2bed93cb Fixed: Sorting by movie title in Blocklist and History
Fixes #9234
2023-10-05 01:02:35 +03:00
Weblate 2bea61bae5 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Garkus98 <ivan12061998@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: 宿命 <331874545@qq.com>
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/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-10-04 08:43:53 +03:00
Mark McDowall 7922109f01 Fixed a potential issue when extra files for multiple movies have the same relative path
(cherry picked from commit a6a68b4cae7688506c45ff6cf10989fe6596c274)

Closes #7222
2023-10-04 00:09:58 +03:00
Mark McDowall 46dd72e0cd New: Validate that naming formats don't contain illegal characters
(cherry picked from commit 145c644c9d8f1636027da8a782a7e74f3182c678)

Closes #5382
2023-10-03 23:49:30 +03:00
Mark McDowall 4e3535f1fe Fixed Misaligned table border
(cherry picked from commit aa938d911b61b08185dc57a0887f3f33e3c6e1f2)

Closes #8176
2023-10-03 23:36:45 +03:00
Mark McDowall 3468f1144d New: Calendar month view will scroll to today on load and press
(cherry picked from commit 7c0d3444376caa8a116b5c2084821c326beb01a1)

Closes #8501
2023-10-03 21:42:50 +03:00
Bogdan 572c410f54 Add runtime param to ServerSideNotificationService 2023-10-02 18:16:43 +03:00
Bogdan 1762a189d2 Fixed: (PassThePopcorn) Disable grouping 2023-10-02 03:38:24 +03:00
Mark McDowall e2f5f2f73a Fixed: Completed downloads in Qbit missing import path
(cherry picked from commit 35365665cfd436ac276dd9591e23333bd26cf789)

Closes #9221
2023-10-01 17:13:24 +03:00
Weblate ade387ba74 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mr cmuc <github@nextcos.de>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translation: Servarr/Radarr
2023-10-01 17:11:28 +03:00
Stevie Robinson 6b9a622328 Fixed: qBittorent history retention to allow at least 14 days seeding
(cherry picked from commit 33b87acabf2b4c71ee24cda1a466dec6f4f76996)
2023-10-01 17:11:05 +03:00
bakerboy448 ba5028bebb Fixed: Only apply remote path mappings for completed items in Qbit
(cherry picked from commit 583eb52ddc01b608ab6cb17e863a8830c17b7b75)
2023-10-01 17:10:47 +03:00
Stevie Robinson 33d1d1f875 Fixed: SABnzbd history retention to allow at least 14 days
(cherry picked from commit a3938d8e0264b48b35f4715cbc15329fb489218a)

Closes #9217
2023-09-27 23:14:34 +03:00
Weblate fb60dcb5bf Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Jaspils <jasperkemper@gmail.com>
Co-authored-by: SKAL <sir_kalot@yahoo.it>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 宿命 <331874545@qq.com>
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/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-09-27 19:45:22 +03:00
Bogdan ddf23530fc Bump version to 5.0.3 2023-09-24 16:22:06 +03:00
Bogdan 30b1edbff0 Add content summary for bulk movie info 2023-09-20 20:58:39 +03:00
Bogdan f20c260a4f Avoid returning null in static resource mapper Task 2023-09-19 20:15:59 +03:00
Bogdan 2fcbac49c7 Fixed: Add support for TMDb in Plex Watchlist RSS
Fixes #9208
2023-09-19 19:10:20 +03:00
Mark McDowall 3248e7f476 Fixed: Pushed releases not being properly rejected
(cherry picked from commit 07f816ffb18ac34090c2f8ba25147737299b361d)

Closes #9204
2023-09-19 14:04:01 +03:00
Mark McDowall ce145a3050 Optional 'downloadClientId' for pushed releases
(cherry picked from commit fa5bfc3742c24c5730b77bf8178a423d98fdf50e)

Closes #9190
2023-09-19 14:01:45 +03:00
Bogdan 3bc4197b4a Preserve the protocol for fanart images
(cherry picked from commit d8633b968830fd20d73612e9f0d0559b0bcb304c)

Closes #9205
2023-09-19 14:01:39 +03:00
Bogdan 552b8f91d2 Fixed: Skip parsing releases without title
(cherry picked from commit c7824bb593291634bf14a5f7aa689666969b03bf)
2023-09-19 13:58:11 +03:00
Bogdan e9e36ae56a Revert "New: Optional 'downloadClientId' for pushed releases"
This reverts commit 4e01fa57fd.

Closes #9202
2023-09-19 04:07:27 +03:00
Bogdan 450d6c0c80 Replace support-requests with label-actions 2023-09-19 02:05:48 +03:00
Servarr 9eece2965a Automated API Docs update 2023-09-18 16:04:17 +03:00
Stevie Robinson cd5d4f993a Add health check for dl clients removing completed downloads + enable for sab and qbit
(cherry picked from commit 7f2cd8a0e99b537a1c616998514bacdd8468a016)

Closes #9195
2023-09-18 15:28:13 +03:00
Bogdan fe7203815d Preserve the protocol in Movie Image
(cherry picked from commit a2f16bddfd7dfba207c5feaaf472913c38dc3e25)

Closes #9198
2023-09-18 15:24:06 +03:00
Mark McDowall 4e01fa57fd New: Optional 'downloadClientId' for pushed releases
(cherry picked from commit fa5bfc3742c24c5730b77bf8178a423d98fdf50e)

Closes #9190
2023-09-18 15:18:55 +03:00
Bogdan bbeb4d7b5f Log request failures in Notifiarr 2023-09-18 14:57:05 +03:00
Mark McDowall 49dac0ebaa New: Don't treat 400 responses from Notifiarr as errors
(cherry picked from commit 5eb420bbe12f59d0a5392abf3d351be28ca210e6)

Closes #9194
2023-09-18 14:53:09 +03:00
Mark McDowall ea8f5c7b9f Fixed: Skip free space check only applies during import
(cherry picked from commit 5ff254b6468fc66a337dc0a13f4be53a997c52fd)

Closes #9191
2023-09-18 14:48:55 +03:00
Mark McDowall 24a17a9240 Fixed: Don't try to create metadata images if source files doesn't exist
(cherry picked from commit 9a1022386a031c928fc0495d6ab990ebce605ec1)

Closes #9189
2023-09-18 14:47:03 +03:00
Weblate 97c2d4f9db Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Daghriry <mdaghriri@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Gyuyeop Kim <rlarbduq777@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mati300m <mateusz.smolec@gmail.com>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
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/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-09-18 14:43:29 +03:00
Qstick b7cafb2917 Fixed: Show correct error on unauthorized caps call
(cherry picked from commit f2b0fc946e1fb1b4649f1b46a003bd2add09a461)
2023-09-18 14:42:50 +03:00
Mark McDowall 2a2667a2ec Fixed: Don't allow quality profile to be created without all qualities
(cherry picked from commit 32e1ae2f64827272d351991838200884876e52b4)
2023-09-18 14:42:06 +03:00
Bogdan 27da524391 Use async requests for media cover proxy
(cherry picked from commit ad1f185330a30a2a9d27c9d3f18d384e66727c2a)

Closes #9183
2023-09-18 03:46:52 +03:00
Bogdan 4bd1c14db9 Log exceptions for failed fetches in Radarr import lists
Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
(cherry picked from commit c1d9187bb66c0524048020613d816918b84b5532)

Closes #9186
2023-09-18 03:46:46 +03:00
Bogdan 608e2e7307 Use await on reading the response content
(cherry picked from commit 82d586e7015d7ea06356ca436024a8af5a4fb677)
2023-09-18 03:22:14 +03:00
Qstick cff54d76b9 Fix regression in collections endpoint speed 2023-09-17 00:14:28 -05:00
Mark McDowall 3244282a83 Less logging when no import lists are enabled
(cherry picked from commit 7be4840f028f24e3920bd395a4e15eb5e643e46f)

Closes #9040
2023-09-15 15:22:59 +03:00
Weblate 1d488df242 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Akashi2020 <dieux02400@gmail.com>
Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: Anthony Veaudry <anthonyveaudry@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Herve Lauwerier <hervelauwerier@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-09-14 23:34:25 +03:00
Bogdan 22927224c6 Fix lint issues in AppUpdatedModalContent 2023-09-14 23:32:33 +03:00
Stevie Robinson 51149bccdd Translate Updated and Connection Lost Modals in frontend
(cherry picked from commit 074aa6f4457bf83173e6ba7209c452a6e0659a35)

Closes #8994
2023-09-14 23:04:49 +03:00
Stevie Robinson 4bbc166040 Translate Frontend Organize + Rename modal
(cherry picked from commit 866fbc7f093c34e4414734f90e756e2f6870d84a)

Closes #9054
2023-09-14 23:04:44 +03:00
Bogdan 11c7446cbe Save Whitelisted Subtitle Tags as string
Fixes #9134
2023-09-14 22:37:53 +03:00
Mark McDowall dce637905a Mock debouncer for testing
(cherry picked from commit bb7b2808e2f70389157408809ec47cc8860b4938)
2023-09-14 22:19:12 +03:00
Mark McDowall 7d85922f8d Fixed: Duplicate notifications for failed health checks
(cherry picked from commit c0e54773e213f526a5046fa46aa7b57532471128)
2023-09-14 22:19:12 +03:00
Bogdan 80f6033595 Fixed: Ignore invalid mount points
Fixes #9176
2023-09-13 22:21:43 +03:00
Weblate 78b8747b50 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Richard de Souza Leite <rs9010482@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: volrod64 <sebsogamer@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
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-09-13 19:16:37 +03:00
Stevie Robinson c2df194d49 Translate Frontend Utilities
(cherry picked from commit 3f0e8ce8634b085d49638d11df96109797ac9cef)

Closes #9129
2023-09-12 20:11:18 +03:00
Stevie Robinson 4a41c67dfe Fix missing translations and correct some keys
(cherry picked from commit ce4ac7594192fa8f63ba239607be61d229c24ce1)
2023-09-12 19:33:32 +03:00
Stevie Robinson 85d51e485a Translate Activity pages
(cherry picked from commit 322836e2b3726b653bf4a7f01ea7018ef44a77bd)
2023-09-12 19:33:32 +03:00
Bogdan 50e2e9edef Add custom format score to history details 2023-09-12 19:33:32 +03:00
Bogdan 703c251b5c Fix some translations 2023-09-12 19:33:32 +03:00
Mark McDowall a798556d32 New: Show detailed queue status on Calendar
(cherry picked from commit 8fff59ff107d9a9fcfc0de1acb6aa635565e5d9b)
2023-09-12 19:33:32 +03:00
Bogdan 69253a4ac4 Fix status style for unmonitored events 2023-09-12 12:05:59 +03:00
Mark McDowall 4e827e726f New: Calendar option for full color events
(cherry picked from commit 0210b5c5c1b5c56dce6f4c9f3f56366adba950d3)
2023-09-11 22:54:45 +03:00
Bogdan e3abda9afc Ensure the images are mapped correctly after updating a movie 2023-09-11 18:53:34 +03:00
Steven Lu 0386ea9b71 Updating Steven Lu movies URL 2023-09-11 17:49:35 +03:00
Bogdan f0fcd23248 Fix custom formats with indexer flags in queue 2023-09-11 11:10:38 +03:00
Mark McDowall 18f22d7ada Fixed: Parsing of multiple languages from Newznab/Torznab indexer releases
(cherry picked from commit 2a241294b5eeb9e95c46e030828191da09d05e88)

Closes #9159
2023-09-11 10:45:23 +03:00
Servarr 1c4b5f2abf Automated API Docs update 2023-09-10 22:17:06 -04:00
Mark McDowall b48b970f25 Map Clearlogo images to cover type
(cherry picked from commit 809788eb2ed7e448f7f23101ae535533de57cd02)
2023-09-10 22:05:03 -04:00
Qstick e715557a0d Fixed: Tweak all movies endpoint for better performance from Radarr lists 2023-09-10 22:04:23 -04:00
Qstick 248ac9619c Fixed: Images for some movies not downloading
Closes #8006

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-09-10 22:04:23 -04:00
Denis Gheorghescu feff609685 New: Add support for Pushcut notifications 2023-09-10 23:29:54 +03:00
Bogdan 07cfbb59da Add media proxy for collections, credits and discovery images 2023-09-10 22:41:26 +03:00
Weblate 9db0058114 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Shiessis <shiessis@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/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
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/uk/
Translation: Servarr/Radarr
2023-09-10 20:29:24 +03:00
Weblate 8d7f6b9de8 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: ChewyGlitter <lulu3dddsss@gmail.com>
Co-authored-by: DavidJares <david.jares@me.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: He Zhu <zhuhe202@qq.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/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-09-10 00:26:49 -05:00
Bogdan 28c566a071 Hide obsolete indexer flags from UI 2023-09-10 08:18:23 +03:00
Bogdan e5963c9ee1 Add rename deprecated indexer flags migration 2023-09-09 13:13:56 +03:00
Bogdan 336cb4a2bc Improve messaging for failed movie details data 2023-09-09 13:13:56 +03:00
Bogdan ff3d38a515 New: Add support for additional Torznab indexer flags 2023-09-09 07:54:37 +03:00
Bogdan a2bde5e016 Fixed: Calculating seed time for qBittorrent
(cherry picked from commit 1b3ff64cc521396f9f1623617052c497649325a8)
2023-09-08 04:25:55 +03:00
Bogdan cb04ef960e Fixed: macOS version detection
(cherry picked from commit 060be6177a5477c94823e6a423c42064dedc1afb)
2023-09-08 04:14:47 +03:00
Servarr ba732847ef Automated API Docs update 2023-09-06 12:37:12 +03:00
Bogdan 1865257544 Include indexer flags to show the correct custom formats in movie file history 2023-09-06 12:29:37 +03:00
Bogdan 58e0b19d06 Include indexer flags to show the correct custom formats in movie imported history 2023-09-06 09:56:10 +03:00
Bogdan 05c5bcbe15 Bump ImageSharp 2023-09-05 03:18:27 +03:00
Bogdan d6749a0c8e Migrate to merged proposals now included in babel/present-env
Bump core-js too.
2023-09-04 00:50:20 +03:00
Bogdan 72fe25d7b2 Bump dotnet to 6.0.21 2023-09-04 00:50:20 +03:00
Bogdan 0598d46ee8 Bump version to 5.0.2 2023-09-03 07:28:12 +03:00
Bogdan e73d05c0fe Check if import list items are valid before importing
Co-authored-by: Qstick <qstick@gmail.com>
2023-09-03 04:21:10 +03:00
Bakerboy448 9a0ca650a3 Fixed: Dont Parse 24-bit as group 2023-09-02 20:16:40 -05:00
Qstick ac6da13a82 Avoid double ToList conversion in ImportList fetch 2023-09-02 15:17:06 -05:00
Bogdan 61ffc50b7f Use paths relative to the frontend source root 2023-09-02 05:41:39 +03:00
Stevie Robinson fcd8a4a873 Translate Frontend Store
Fixed indexer copy translation

(cherry picked from commit d31fcbb2dfe98a540a359b98b204d101d554cf03)
(cherry picked from commit 276352dda478aaa7be7d0fc744548adddec6e6b6)

Closes #9118
Closes #9121
2023-09-02 05:37:13 +03:00
Stevie Robinson 093bb94e42 Fixed: Fallback to English translations if invalid UI language in config
(cherry picked from commit 4c7201741276eccaea2fb1f33daecc31e8b2d54e)

Close #9112
2023-09-02 05:29:36 +03:00
Bogdan 14b9dd77af Display a not allowed cursor for disabled select options 2023-09-02 05:18:35 +03:00
Bogdan d6b62e738a Fixed: Increase timeout when downloading updates
(cherry picked from commit 467ce70291c793042ffb3ed8942c42e7bc1424d5)
2023-09-01 04:04:07 +03:00
Bogdan 53254f6aeb Fix showing Grab ID in history details modal 2023-08-29 22:36:33 +03:00
Bogdan 756384d94a Simplify user check in Authentication Required for newer installs 2023-08-29 19:57:48 +03:00
Bogdan 7f172dcfd1 Fix user check in Authentication Required for newer installs 2023-08-29 18:54:12 +03:00
Mark McDowall 02998cd59a Fixed: Auto Tag required not showing in the UI correctly
(cherry picked from commit 08939f2fb4b6f7aca4916d8bd3b60535f3a992da)
2023-08-29 08:31:10 +03:00
Stevie Robinson 37aa739611 Add info box under health messages
(cherry picked from commit 936ef9f461c3e80a36099508c420dc44d8cd293c)

Closes #9095
2023-08-29 05:43:12 +03:00
Bogdan 0e2c98827f Remove column labels from Interactive Search 2023-08-29 05:31:50 +03:00
Bogdan 27f45b8fd6 Add missing app name token for translations 2023-08-29 03:29:46 +03:00
Bogdan 2210ce9394 Improve messaging in Authentication Required modal 2023-08-29 01:42:30 +03:00
Bogdan bbef1590a3 Remove duplicate Language interface 2023-08-29 01:35:55 +03:00
Bogdan feb3131ad4 Fix download tooltip in interactive search 2023-08-28 03:36:32 +03:00
Weblate 89f5595e64 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: ChewyGlitter <lulu3dddsss@gmail.com>
Co-authored-by: DavidJares <david.jares@me.com>
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/cs/
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-08-27 19:20:29 +03:00
Bogdan cf9cff61b5 Bump version to 5.0.1 2023-08-27 08:02:02 +03:00
Bogdan 6de0feda65 Filter movies by TmdbId and ImdbId in Select movies Modal 2023-08-26 20:41:54 +03:00
Stevie Robinson 0f699a01f7 Add translations to frontend/InteractiveImport
(cherry picked from commit 060b66aa398f7e676b789354361b6fe95a96ff17)

Closes #9027
2023-08-23 20:20:44 +03:00
Stevie Robinson be20a9d116 Translate Frontend InteractiveSearch
(cherry picked from commit efca70438899c2f22e2be060011b58325e4f4705)

Closes #9027
2023-08-23 19:42:45 +03:00
Stevie Robinson 4c2fcef742 Translate Frontend Parse modal
(cherry picked from commit c14fd2b4a3cc2d0b270c5abe02240b22632e34b5)

Closes #9051
2023-08-23 16:35:12 +03:00
Weblate 15a4c3b742 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: DavidJares <david.jares@me.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Renan da Mota Ciciliato <renanciciliato@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/ca/
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/fr/
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/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translation: Servarr/Radarr
2023-08-23 05:00:46 +03:00
Bogdan 7b4f908f6d Prevent health checks warnings for disabled notifications
(cherry picked from commit 5a7f42a63e25d6abdb187c37e92a908a6b85fb4d)
2023-08-23 04:59:46 +03:00
Weblate 1b4dd405be Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: DavidJares <david.jares@me.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Renan da Mota Ciciliato <renanciciliato@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/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translation: Servarr/Radarr
2023-08-23 04:59:19 +03:00
Servarr 135de2cad4 Automated API Docs update 2023-08-22 23:59:28 +03:00
Bogdan 174ea347a8 Cleanup InteractiveSearchRowProps 2023-08-22 23:28:34 +03:00
Mark McDowall 9b4f80535e Override release grab modal
New: Option to override release and grab
New: Option to select download client when multiple of the same type are configured

(cherry picked from commit 07f0fbf9a51d54e44681fd0f74df4e048bff561a)
2023-08-22 23:20:47 +03:00
Bogdan 07b69e665d Fix translation usage for IMDbId and TMDBId 2023-08-22 23:20:47 +03:00
Jendrik Weise 99441dfa67 Prevent exception when renaming after script import
(cherry picked from commit 2166e4dce419ae477f2e4ce297bee2d8324a190e)

Closes #9050
2023-08-22 16:32:42 +03:00
Bogdan 8e80c85f03 Revert "Switch to Parallel.ForEach for list processing with MaxParallelism"
This reverts commit 0f93e04186.
2023-08-22 06:05:17 +03:00
Bogdan 429217d1d4 Remove Reddit from issue templates 2023-08-22 02:54:34 +03:00
Servarr 8257e01995 Automated API Docs update 2023-08-21 21:52:23 +03:00
Qstick bd3fad9636 Rename Source to QualitySource 2023-08-20 22:53:11 -05:00
Servarr 3cbdba51e9 Automated API Docs update 2023-08-20 22:16:01 -05:00
Qstick c70ce92ee9 New: Cleanup Alternative Title model and code 2023-08-20 22:07:33 -05:00
Qstick c1a3a8249b Use default MemoryAllocator for ImageSharp resizing 2023-08-20 20:21:13 -05:00
Qstick 0f93e04186 Switch to Parallel.ForEach for list processing with MaxParallelism 2023-08-20 20:21:13 -05:00
Qstick fef666831f Fixed: Ignore case when comparing torrent infohash
(cherry picked from commit 7986488c6d1687b0810b3bcac2c1dae725e770ac)
2023-08-20 16:09:18 -05:00
Qstick 681a36e34f New: Added additional term for matching French language releases
Closes #7209
2023-08-20 15:08:50 -05:00
Servarr 726b71027e Automated API Docs update 2023-08-20 23:03:00 +03:00
Qstick a8feef7e88 Fix using in CalendarController 2023-08-20 14:52:55 -05:00
Qstick 70b725a2dc New: Use file's format title for quality if parsed
Closes #7993

(cherry picked from commit 599ad86657bbb8125c4354000cfc94331041f984)
2023-08-20 14:52:55 -05:00
Qstick 4b3bd86e0f Improvements to Calendar translation mapping 2023-08-20 14:29:23 -05:00
Mark McDowall 3878196f39 New: Calendar filtering by tags
Closes #8502

(cherry picked from commit 62b948b24c4b9c572db225cb19985444d3d80c0f)
2023-08-20 14:29:23 -05:00
Mark McDowall a39cafe404 Improve CF calculation for files without scene name
Fixed: Use original filename instead of complete path when calculating CF for existing file without scene name

(cherry picked from commit 997aabbc3cfc3c9c5c220786d1d08cfceec5e2f2)

Closes #8115
2023-08-20 22:08:27 +03:00
Mark McDowall d9e337f2fb Fixed: Search for newly added movie if disk rescanning is disabled after refresh
(cherry picked from commit 00ab449ebeb53893b8d4c939e072451845a4d69e)

Closes #7543
2023-08-20 22:08:27 +03:00
Qstick 3412e4139e Added table identifier to OrderBy to avoid column ambiguity on joins
Co-Authored-By: Richard <1252123+kharenis@users.noreply.github.com>

(cherry picked from commit c57ceac4debf7419be84096f997ba7b75c906586)
2023-08-20 14:04:26 -05:00
Servarr b7bacf785c Automated API Docs update 2023-08-20 13:59:52 -05:00
Mark McDowall c6e3f3c26c New: Added Mediainfo Video Dynamic Range column for movies
(cherry picked from commit ae0e23fc8ee450a20b43ca622eeccd0759451a2f)

Closes #7247
2023-08-20 21:45:50 +03:00
Mark McDowall e4c5fc5c6e Sync LocalizationService tests with upstream
(cherry picked from commit 9c7fab69fd008a423f3607de71e0c76200e84ea5)

Closes #8978
2023-08-20 21:45:50 +03:00
Mark McDowall 3c42ad0f7f Fixed: Allow Min/Max age to be the same for year auto tagging
(cherry picked from commit fc6ac3ddf191025d4ebe3af542fbd97ef981f0ca)
2023-08-20 21:26:27 +03:00
ItsME6969 5236d46c2b FIxed: Correctly parse German scene bluray REMUXes (#8643) 2023-08-20 11:23:04 -05:00
Servarr 6f54a9e452 Automated API Docs update 2023-08-20 18:40:46 +03:00
Bogdan 4b9107465c New: Add table options for movie files details 2023-08-20 18:27:20 +03:00
Mark McDowall 329e43c331 Fixed: Unknown audio language appearing as 'root'
(cherry picked from commit 5411863f6a00071201dd50dc6d2f33477e6ffb29)
2023-08-20 18:27:20 +03:00
Mark McDowall f05f25af0c Fixed: Invalid audio language leading to UI error
(cherry picked from commit 8fbbe21d814ccdeda7727b5fb83f99ea81f5b225)
2023-08-20 18:27:20 +03:00
Mark McDowall e50abd276e Fixed: Displaying audio and subtitle languages in UI
(cherry picked from commit 139412284276479921632ee5ef1dabe76c5388b4)

Rename LocalizationLanguageResource to avoid collision with LanguageResource

(cherry picked from commit d2cd3f77169887086980feac3bab1f16301d189e)
2023-08-20 18:27:20 +03:00
Mark McDowall 933d9e074c Option to show audio/subtitle language on movie details (first two unique languages will be shown)
(cherry picked from commit c10677dfe7098295fde39517b3983e8f3f22823d)
2023-08-20 18:27:20 +03:00
Weblate 993e4ca298 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
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/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translation: Servarr/Radarr
2023-08-20 09:21:28 -05:00
bakerboy448 58eb24ff89 New: Default RSS Sync Interval to 30 minutes 2023-08-20 09:14:31 -05:00
Bogdan 9516729385 Fix typo in queryTranslations 2023-08-20 13:09:19 +03:00
Mark McDowall d626f0487d Fixed: Don't reimport the same file from the same release unless grabbed again
(cherry picked from commit 0274778679a8fd485a651eea9d293463528244fd)

Closes #9055
2023-08-20 13:06:42 +03:00
Bogdan 1350ccb236 Fix translations for queue actions and security setting 2023-08-19 23:38:04 +03:00
Bogdan 63d05a6e78 Prevent useless builds 2023-08-19 17:21:34 +03:00
Servarr f60b27355b Automated API Docs update 2023-08-19 13:55:14 +03:00
Stevie Robinson abd63ea2a4 Add info box to Remote Path Mappings Settings
(cherry picked from commit d8f3d7d3eafeafd8d4372db0076a63f935a29218)

Closes #9039
2023-08-19 13:24:39 +03:00
Mark McDowall 655f49b8c9 Fixed: Allow decimals for Custom Format size
(cherry picked from commit 7f5ddff568ce9f87bd45420cbd36690b190bd633)

Closes #9043
Fixes #6147
2023-08-19 13:24:39 +03:00
Stevie Robinson d8c1fe5486 Fix Typo in QualitySource Enum
(cherry picked from commit 1bcef1b4a5dda8a473bb9b3316ea8b09cc1ee022)
2023-08-19 13:14:44 +03:00
Mark McDowall 8afe4e8979 New: Success check mark on blue buttons is now white instead of green
(cherry picked from commit 566fae9d5857a10bd69c718368e7847e5a733faa)
2023-08-19 12:48:45 +03:00
Qstick 1935abbde2 Fix grammar error for collections selection 2023-08-18 23:31:37 -05:00
Mark McDowall fdc6c66f7a Fixed: Ignore IOException deleting download folder after import
(cherry picked from commit d05cb40088a51eef5a2830bf2b55f5d05955578f)
2023-08-18 21:28:38 -05:00
Bogdan def127b93f Fix flaky automation tests 2023-08-18 21:21:17 -05:00
Mark McDowall c75d398f14 New: Status message when downloading metadata in qBittorrent
(cherry picked from commit 8aa872edf4737798d4836f68fbd0697ee0511c41)
2023-08-18 21:14:33 -05:00
nuxen d4fada9b4e fix(parser): added more tests and moved YTS 2023-08-18 21:13:05 -05:00
nuxen 111c081545 fix(parser): not correctly recognizing YIFY RlsGrp 2023-08-18 21:13:05 -05:00
bakerboy448 7f3e7b360b Remove reddit from readme 2023-08-18 12:06:18 +03:00
Weblate 329e37774f Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: w2861 <hfagfc@163.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/id/
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/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translation: Servarr/Radarr
2023-08-18 12:05:56 +03:00
Mark McDowall 4a4037323e Fixed: Hidden files being ignored
(cherry picked from commit d493f8762fcb1684b44e182753c21d7a493db787)

Closes #9023
2023-08-18 11:23:22 +03:00
Bogdan 2d72c1ef34 Replace docker detection for cgroup v2
(cherry picked from commit 78d4dee4610c5f3f90cc69469004008aa64900b8)
2023-08-18 10:57:39 +03:00
Qstick 337d01e4ed Add housekeeper for orphaned list movies 2023-08-17 22:47:07 -05:00
Qstick 927ae86e44 Fixed: Don't Clean if no lists synced
Fixes #9011
2023-08-17 22:47:07 -05:00
Qstick fefdd71b6d Fixed: Avoid error in manual interaction notifications 2023-08-17 22:41:24 -05:00
jack-mil 328850627a New: Improved Discord add/delete notifications
(cherry picked from commit 1a4403e0ab9ab824c97acf97174f894b3770f2ef)

Closes #8886
2023-08-17 23:54:05 +03:00
Bogdan f412228383 Change DownloadReport to private 2023-08-17 23:09:54 +03:00
Stevie Robinson dc82d0b6dd Fix RemoveHelpTextWarning > RemoveFromDownloadClientHelpTextWarning
(cherry picked from commit 901b6d20841bfcb2a3724fe27b0fbddf5e41d669)

Closes #8969
2023-08-17 23:09:16 +03:00
Qstick 0e83c42f3a Cleanup other provider status code
(cherry picked from commit c281a7818adce8db728d2a104f4444cb9c0baf2c)
2023-08-17 23:01:59 +03:00
Qstick fa80e8b7a2 New: Notifications (Connect) Status
(cherry picked from commit e3545801721e00d4e5cac3fa534e66dcbe9d2d05)
(cherry picked from commit cb27b05a6c046ca0a6e4998f7e7ecd6b45add1a2)
2023-08-17 23:01:59 +03:00
Bogdan c03453f6f7 Add default update branches as autocomplete values 2023-08-17 22:42:27 +03:00
Mark McDowall 3ffb36a2df Fixed: Don't block updates under docker unless configured in package_info
(cherry picked from commit 5a7e34e291c2715aa67161e5c455d25e80f498df)
2023-08-17 22:42:27 +03:00
Bogdan 0a04fad85b Show warning when using the docker update mechanism
(cherry picked from commit cc538c4b2d33a1734c45c0667776d946596107e9)
2023-08-17 22:42:27 +03:00
Weblate 3c7f7f2e03 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Robert A. Viana <robert.abreu@outlook.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-08-17 14:30:16 +03:00
Servarr 32ec9d4872 Automated API Docs update 2023-08-16 21:39:20 -05:00
Qstick c8e04f0c35 Bump Nlog and NUnit 2023-08-16 20:51:25 -05:00
Qstick d6f849ac95 Bump dotnet packages 2023-08-16 20:47:19 -05:00
Qstick fcea483612 Bump Newtonsoft.Json to 13.0.3 2023-08-16 20:43:41 -05:00
Qstick bcd87a3a30 Bump DryIoc to 5.4.1 2023-08-16 20:34:25 -05:00
Qstick e3bcc3da3f Bump Dapper to 2.0.143 2023-08-16 20:33:52 -05:00
Qstick 056c2b5233 Rename Profiles to QualityProfiles 2023-08-16 20:04:42 -05:00
Servarr a946546793 Automated API Docs update 2023-08-15 16:14:16 +03:00
Qstick f9f44aec7a Fixed: Creating new Delay Profile
Fixes #8077

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-08-14 22:09:49 -05:00
ricci2511 99ff6aa9c4 New: Convert restrictions to release profiles 2023-08-14 21:26:22 -05:00
Mark McDowall ca93a72d63 New: Show all options when authentication modal is open
(cherry picked from commit c7d6c0f45264944bb5c00374ff025344218ef7eb)
2023-08-14 20:05:03 -05:00
Mark McDowall 0c6eae256b Don't replace private values that haven't been set
(cherry picked from commit 52760e0908fa9852ed8a770f1916bb582eb8c8b4)
2023-08-14 20:05:03 -05:00
Mark McDowall 508a15e09a New: Don't return API Keys and Passwords via the API
(cherry picked from commit 570be882154e73f8ad1de5b16b957bcb964697fd)
2023-08-14 20:05:03 -05:00
Qstick 180dafe696 Handle auth options correctly in Security Settings
(cherry picked from commit 0fad20e327503bac767c4df4c893f5e418866831)
2023-08-14 20:05:03 -05:00
Qstick e3160466e0 Bump SQLite to 3.42.0 (1.0.118) 2023-08-14 20:05:03 -05:00
Marty Zalega 9ccefe0095 Don't lowercase UrlBase in ConfigFileProvider
UrlBase should honour the case it is given.

(cherry picked from commit e1de523c89f7649e64f520b090bbdb2f56cc4b85)
2023-08-14 20:05:03 -05:00
Mark McDowall 104aadfdb7 New: Migrate user passwords to Pbkdf2
(cherry picked from commit 269e72a2193b584476bec338ef41e6fb2e5cbea6)
2023-08-14 20:05:03 -05:00
Qstick 8911386ed0 New: Rework and Require Authentication
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-08-14 20:05:03 -05:00
Qstick 1e6540a419 Bump Version to 5
(cherry picked from commit 21afbbc66d294cfeda47b7dacb785a17dae8eb1c)
2023-08-14 20:05:03 -05:00
Weblate 693f8dc391 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: David Molero <contact@dolvem.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: deepserket <deepserket@gmail.com>
Co-authored-by: matt <diabolino7@pm.me>
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/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/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/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translation: Servarr/Radarr
2023-08-15 01:55:13 +03:00
Servarr 576e1e76af Automated API Docs update 2023-08-15 01:44:17 +03:00
Mark McDowall 1f8877d192 New: Add bypass if above Custom Format Score to Delay Profile
(cherry picked from commit 4ed4ca4804ce973c1b88c1c4ede8ae00547ac834)
2023-08-14 22:14:29 +03:00
Bogdan 8c93123126 New: Default name when adding providers 2023-08-14 02:35:00 +03:00
Bogdan dd614ac005 Use named tokens in frontend translate function 2023-08-13 23:09:58 +03:00
Mark McDowall 82de5d6f9a New: Auto tag series based on Original Language
(cherry picked from commit 2a7964bc16fa32bc0000bb7326795d02cc41bfed)
2023-08-13 21:21:02 +03:00
1158 changed files with 29915 additions and 18532 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
name: Bug Report name: Bug Report
description: 'Report a new bug, if you are not 100% certain this is a bug please go to our Reddit or Discord first' description: 'Report a new bug, if you are not 100% certain this is a bug please go to our Discord first'
labels: ['Type: Bug', 'Status: Needs Triage'] labels: ['Type: Bug', 'Status: Needs Triage']
body: body:
- type: checkboxes - type: checkboxes
-3
View File
@@ -3,6 +3,3 @@ contact_links:
- name: Support via Discord - name: Support via Discord
url: https://radarr.video/discord url: https://radarr.video/discord
about: Chat with users and devs on support and setup related topics. about: Chat with users and devs on support and setup related topics.
- name: Support via Reddit
url: https://reddit.com/r/radarr
about: Discuss and search thru support topics.
+16
View File
@@ -0,0 +1,16 @@
# Configuration for Label Actions - https://github.com/dessant/label-actions
'Type: Support':
comment: >
:wave: @{issue-author}, we use the issue tracker exclusively
for bug reports and feature requests. However, this issue appears
to be a support request. Please hop over onto our [Discord](https://radarr.video/discord).
close: true
close-reason: 'not planned'
'Status: Logs Needed':
comment: >
:wave: @{issue-author}, In order to help you further we'll need to see logs.
You'll need to enable trace logging and replicate the problem that you encountered.
Guidance on how to enable trace logging can be found in
our [troubleshooting guide](https://wiki.servarr.com/radarr/troubleshooting#logging-and-log-files).
+17
View File
@@ -0,0 +1,17 @@
name: 'Label Actions'
on:
issues:
types: [labeled, unlabeled]
permissions:
contents: read
issues: write
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/label-actions@v3
with:
process-only: 'issues'
-36
View File
@@ -1,36 +0,0 @@
name: 'Support requests'
on:
issues:
types: [labeled, unlabeled, reopened]
permissions: {}
jobs:
support:
permissions:
issues: write # to modify issues
runs-on: ubuntu-latest
steps:
- uses: dessant/support-requests@v3
with:
github-token: ${{ github.token }}
support-label: 'Type: Support'
issue-comment: >
:wave: @{issue-author}, we use the issue tracker exclusively
for bug reports and feature requests. However, this issue appears
to be a support request. Please hop over onto our [Discord](https://radarr.video/discord)
or [Subreddit](https://reddit.com/r/radarr)
close-issue: true
lock-issue: false
- uses: dessant/support-requests@v3
with:
github-token: ${{ github.token }}
support-label: 'Status: Logs Needed'
issue-comment: >
:wave: @{issue-author}, In order to help you further we'll need to see logs.
You'll need to enable trace logging and replicate the problem that you encountered.
Guidance on how to enable trace logging can be found in
our [troubleshooting guide](https://wiki.servarr.com/radarr/troubleshooting#logging-and-log-files).
close-issue: false
lock-issue: false
+1 -2
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) [![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) [![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) ![Github Downloads](https://img.shields.io/github/downloads/Radarr/Radarr/total.svg)
[![Backers on Open Collective](https://opencollective.com/Radarr/backers/badge.svg)](#backers) [![Backers on Open Collective](https://opencollective.com/Radarr/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/Radarr/sponsors/badge.svg)](#sponsors) [![Sponsors on Open Collective](https://opencollective.com/Radarr/sponsors/badge.svg)](#sponsors)
@@ -35,7 +35,6 @@ Note that only one type of a given movie is supported. If you want both an 4k ve
[![Wiki](https://img.shields.io/badge/servarr-wiki-181717.svg?maxAge=60)](https://wiki.servarr.com/radarr) [![Wiki](https://img.shields.io/badge/servarr-wiki-181717.svg?maxAge=60)](https://wiki.servarr.com/radarr)
[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60)](https://radarr.video/discord) [![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60)](https://radarr.video/discord)
[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60)](https://www.reddit.com/r/Radarr)
Note: GitHub Issues are for Bugs and Feature Requests Only Note: GitHub Issues are for Bugs and Feature Requests Only
+9 -3
View File
@@ -9,15 +9,15 @@ variables:
testsFolder: './_tests' testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.7.5' majorVersion: '5.3.4'
minorVersion: $[counter('minorVersion', 2000)] minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)' radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)' buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr' sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com' sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.408' dotnetVersion: '6.0.417'
nodeVersion: '16.X' nodeVersion: '16.X'
innoVersion: '6.2.0' innoVersion: '6.2.2'
windowsImage: 'windows-2022' windowsImage: 'windows-2022'
linuxImage: 'ubuntu-20.04' linuxImage: 'ubuntu-20.04'
macImage: 'macOS-11' macImage: 'macOS-11'
@@ -27,6 +27,10 @@ trigger:
include: include:
- develop - develop
- master - master
paths:
exclude:
- .github
- src/Radarr.Api.*/openapi.json
pr: pr:
branches: branches:
@@ -34,6 +38,7 @@ pr:
- develop - develop
paths: paths:
exclude: exclude:
- .github
- src/NzbDrone.Core/Localization/Core - src/NzbDrone.Core/Localization/Core
- src/Radarr.Api.*/openapi.json - src/Radarr.Api.*/openapi.json
@@ -1237,6 +1242,7 @@ stages:
- stage: Report_Out - stage: Report_Out
dependsOn: dependsOn:
- Analyze - Analyze
- Installer
- Unit_Test - Unit_Test
- Integration - Integration
- Automation - Automation
+1 -1
View File
@@ -254,7 +254,7 @@ InstallInno()
ProgressStart "Installing portable Inno Setup" ProgressStart "Installing portable Inno Setup"
rm -rf _inno 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 mkdir _inno
./innosetup.exe //portable=1 //silent //currentuser //dir=.\\_inno ./innosetup.exe //portable=1 //silent //currentuser //dir=.\\_inno
rm innosetup.exe rm innosetup.exe
+6 -4
View File
@@ -2,16 +2,18 @@ const loose = true;
module.exports = { module.exports = {
plugins: [ plugins: [
'@babel/plugin-transform-logical-assignment-operators',
// Stage 1 // Stage 1
'@babel/plugin-proposal-export-default-from', '@babel/plugin-proposal-export-default-from',
['@babel/plugin-proposal-optional-chaining', { loose }], ['@babel/plugin-transform-optional-chaining', { loose }],
['@babel/plugin-proposal-nullish-coalescing-operator', { loose }], ['@babel/plugin-transform-nullish-coalescing-operator', { loose }],
// Stage 2 // Stage 2
'@babel/plugin-proposal-export-namespace-from', '@babel/plugin-transform-export-namespace-from',
// Stage 3 // Stage 3
['@babel/plugin-proposal-class-properties', { loose }], ['@babel/plugin-transform-class-properties', { loose }],
'@babel/plugin-syntax-dynamic-import' '@babel/plugin-syntax-dynamic-import'
], ],
env: { env: {
+30 -5
View File
@@ -36,6 +36,7 @@ class Blocklist extends Component {
lastToggled: null, lastToggled: null,
selectedState: {}, selectedState: {},
isConfirmRemoveModalOpen: false, isConfirmRemoveModalOpen: false,
isConfirmClearModalOpen: false,
items: props.items items: props.items
}; };
} }
@@ -90,6 +91,19 @@ class Blocklist extends Component {
this.setState({ isConfirmRemoveModalOpen: false }); this.setState({ isConfirmRemoveModalOpen: false });
}; };
onClearBlocklistPress = () => {
this.setState({ isConfirmClearModalOpen: true });
};
onClearBlocklistConfirmed = () => {
this.props.onClearBlocklistPress();
this.setState({ isConfirmClearModalOpen: false });
};
onConfirmClearModalClose = () => {
this.setState({ isConfirmClearModalOpen: false });
};
// //
// Render // Render
@@ -103,7 +117,6 @@ class Blocklist extends Component {
totalRecords, totalRecords,
isRemoving, isRemoving,
isClearingBlocklistExecuting, isClearingBlocklistExecuting,
onClearBlocklistPress,
...otherProps ...otherProps
} = this.props; } = this.props;
@@ -111,7 +124,8 @@ class Blocklist extends Component {
allSelected, allSelected,
allUnselected, allUnselected,
selectedState, selectedState,
isConfirmRemoveModalOpen isConfirmRemoveModalOpen,
isConfirmClearModalOpen
} = this.state; } = this.state;
const selectedIds = this.getSelectedIds(); const selectedIds = this.getSelectedIds();
@@ -131,8 +145,9 @@ class Blocklist extends Component {
<PageToolbarButton <PageToolbarButton
label={translate('Clear')} label={translate('Clear')}
iconName={icons.CLEAR} iconName={icons.CLEAR}
isDisabled={!items.length}
isSpinning={isClearingBlocklistExecuting} isSpinning={isClearingBlocklistExecuting}
onPress={onClearBlocklistPress} onPress={this.onClearBlocklistPress}
/> />
</PageToolbarSection> </PageToolbarSection>
@@ -158,7 +173,7 @@ class Blocklist extends Component {
{ {
!isFetching && !!error && !isFetching && !!error &&
<Alert kind={kinds.DANGER}> <Alert kind={kinds.DANGER}>
{translate('UnableToLoadBlocklist')} {translate('BlocklistLoadError')}
</Alert> </Alert>
} }
@@ -210,11 +225,21 @@ class Blocklist extends Component {
isOpen={isConfirmRemoveModalOpen} isOpen={isConfirmRemoveModalOpen}
kind={kinds.DANGER} kind={kinds.DANGER}
title={translate('RemoveSelected')} title={translate('RemoveSelected')}
message={translate('RemoveSelectedItemBlocklistMessageText')} message={translate('RemoveSelectedBlocklistMessageText')}
confirmLabel={translate('RemoveSelected')} confirmLabel={translate('RemoveSelected')}
onConfirm={this.onRemoveSelectedConfirmed} onConfirm={this.onRemoveSelectedConfirmed}
onCancel={this.onConfirmRemoveModalClose} 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> </PageContent>
); );
} }
@@ -82,7 +82,7 @@ class BlocklistRow extends Component {
return null; return null;
} }
if (name === 'movies.sortTitle') { if (name === 'movieMetadata.sortTitle') {
return ( return (
<TableRowCell key={name}> <TableRowCell key={name}>
<MovieTitleLink <MovieTitleLink
@@ -7,6 +7,7 @@ import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionList
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import formatDateTime from 'Utilities/Date/formatDateTime'; import formatDateTime from 'Utilities/Date/formatDateTime';
import formatAge from 'Utilities/Number/formatAge'; import formatAge from 'Utilities/Number/formatAge';
import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import styles from './HistoryDetails.css'; import styles from './HistoryDetails.css';
@@ -15,6 +16,7 @@ function HistoryDetails(props) {
eventType, eventType,
sourceTitle, sourceTitle,
data, data,
downloadId,
shortDateFormat, shortDateFormat,
timeFormat timeFormat
} = props; } = props;
@@ -23,11 +25,11 @@ function HistoryDetails(props) {
const { const {
indexer, indexer,
releaseGroup, releaseGroup,
movieMatchType,
customFormatScore,
nzbInfoUrl, nzbInfoUrl,
downloadClient, downloadClient,
downloadClientName, downloadClientName,
downloadId,
movieMatchType,
age, age,
ageHours, ageHours,
ageMinutes, ageMinutes,
@@ -45,33 +47,31 @@ function HistoryDetails(props) {
/> />
{ {
!!indexer && indexer ?
<DescriptionListItem <DescriptionListItem
title={translate('Indexer')} title={translate('Indexer')}
data={indexer} data={indexer}
/> /> :
null
} }
{ {
!!releaseGroup && releaseGroup ?
<DescriptionListItem <DescriptionListItem
descriptionClassName={styles.description} descriptionClassName={styles.description}
title={translate('ReleaseGroup')} title={translate('ReleaseGroup')}
data={releaseGroup} data={releaseGroup}
/> /> :
null
} }
{ {
!!nzbInfoUrl && customFormatScore && customFormatScore !== '0' ?
<span> <DescriptionListItem
<DescriptionListItemTitle> title={translate('CustomFormatScore')}
Info URL data={formatCustomFormatScore(customFormatScore)}
</DescriptionListItemTitle> /> :
null
<DescriptionListItemDescription>
<Link to={nzbInfoUrl}>{nzbInfoUrl}</Link>
</DescriptionListItemDescription>
</span>
} }
{ {
@@ -84,6 +84,20 @@ function HistoryDetails(props) {
null null
} }
{
nzbInfoUrl ?
<span>
<DescriptionListItemTitle>
{translate('InfoUrl')}
</DescriptionListItemTitle>
<DescriptionListItemDescription>
<Link to={nzbInfoUrl}>{nzbInfoUrl}</Link>
</DescriptionListItemDescription>
</span> :
null
}
{ {
downloadClientNameInfo ? downloadClientNameInfo ?
<DescriptionListItem <DescriptionListItem
@@ -94,27 +108,30 @@ function HistoryDetails(props) {
} }
{ {
!!downloadId && downloadId ?
<DescriptionListItem <DescriptionListItem
title={translate('GrabID')} title={translate('GrabId')}
data={downloadId} data={downloadId}
/> /> :
null
} }
{ {
!!indexer && indexer ?
<DescriptionListItem <DescriptionListItem
title={translate('AgeWhenGrabbed')} title={translate('AgeWhenGrabbed')}
data={formatAge(age, ageHours, ageMinutes)} data={formatAge(age, ageHours, ageMinutes)}
/> /> :
null
} }
{ {
!!publishedDate && publishedDate ?
<DescriptionListItem <DescriptionListItem
title={translate('PublishedDate')} title={translate('PublishedDate')}
data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })} data={formatDateTime(publishedDate, shortDateFormat, timeFormat, { includeSeconds: true })}
/> /> :
null
} }
</DescriptionList> </DescriptionList>
); );
@@ -134,11 +151,21 @@ function HistoryDetails(props) {
/> />
{ {
!!message && downloadId ?
<DescriptionListItem
title={translate('GrabId')}
data={downloadId}
/> :
null
}
{
message ?
<DescriptionListItem <DescriptionListItem
title={translate('Message')} title={translate('Message')}
data={message} data={message}
/> /> :
null
} }
</DescriptionList> </DescriptionList>
); );
@@ -146,6 +173,7 @@ function HistoryDetails(props) {
if (eventType === 'downloadFolderImported') { if (eventType === 'downloadFolderImported') {
const { const {
customFormatScore,
droppedPath, droppedPath,
importedPath importedPath
} = data; } = data;
@@ -159,21 +187,32 @@ function HistoryDetails(props) {
/> />
{ {
!!droppedPath && droppedPath ?
<DescriptionListItem <DescriptionListItem
descriptionClassName={styles.description} descriptionClassName={styles.description}
title={translate('Source')} title={translate('Source')}
data={droppedPath} data={droppedPath}
/> /> :
null
} }
{ {
!!importedPath && importedPath ?
<DescriptionListItem <DescriptionListItem
descriptionClassName={styles.description} descriptionClassName={styles.description}
title={translate('ImportedTo')} title={translate('ImportedTo')}
data={importedPath} data={importedPath}
/> /> :
null
}
{
customFormatScore && customFormatScore !== '0' ?
<DescriptionListItem
title={translate('CustomFormatScore')}
data={formatCustomFormatScore(customFormatScore)}
/> :
null
} }
</DescriptionList> </DescriptionList>
); );
@@ -181,20 +220,21 @@ function HistoryDetails(props) {
if (eventType === 'movieFileDeleted') { if (eventType === 'movieFileDeleted') {
const { const {
reason reason,
customFormatScore
} = data; } = data;
let reasonMessage = ''; let reasonMessage = '';
switch (reason) { switch (reason) {
case 'Manual': case 'Manual':
reasonMessage = translate('FileWasDeletedByViaUI'); reasonMessage = translate('DeletedReasonManual');
break; break;
case 'MissingFromDisk': case 'MissingFromDisk':
reasonMessage = translate('MissingFromDisk'); reasonMessage = translate('DeletedReasonMissingFromDisk');
break; break;
case 'Upgrade': case 'Upgrade':
reasonMessage = translate('FileWasDeletedByUpgrade'); reasonMessage = translate('DeletedReasonUpgrade');
break; break;
default: default:
reasonMessage = ''; reasonMessage = '';
@@ -211,6 +251,15 @@ function HistoryDetails(props) {
title={translate('Reason')} title={translate('Reason')}
data={reasonMessage} data={reasonMessage}
/> />
{
customFormatScore && customFormatScore !== '0' ?
<DescriptionListItem
title={translate('CustomFormatScore')}
data={formatCustomFormatScore(customFormatScore)}
/> :
null
}
</DescriptionList> </DescriptionList>
); );
} }
@@ -262,11 +311,21 @@ function HistoryDetails(props) {
/> />
{ {
!!message && downloadId ?
<DescriptionListItem
title={translate('GrabId')}
data={downloadId}
/> :
null
}
{
message ?
<DescriptionListItem <DescriptionListItem
title={translate('Message')} title={translate('Message')}
data={message} data={message}
/> /> :
null
} }
</DescriptionList> </DescriptionList>
); );
@@ -287,6 +346,7 @@ HistoryDetails.propTypes = {
eventType: PropTypes.string.isRequired, eventType: PropTypes.string.isRequired,
sourceTitle: PropTypes.string.isRequired, sourceTitle: PropTypes.string.isRequired,
data: PropTypes.object.isRequired, data: PropTypes.object.isRequired,
downloadId: PropTypes.string,
shortDateFormat: PropTypes.string.isRequired, shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired timeFormat: PropTypes.string.isRequired
}; };
@@ -15,19 +15,19 @@ import styles from './HistoryDetailsModal.css';
function getHeaderTitle(eventType) { function getHeaderTitle(eventType) {
switch (eventType) { switch (eventType) {
case 'grabbed': case 'grabbed':
return 'Grabbed'; return translate('Grabbed');
case 'downloadFailed': case 'downloadFailed':
return 'Download Failed'; return translate('DownloadFailed');
case 'downloadFolderImported': case 'downloadFolderImported':
return 'Movie Imported'; return translate('MovieImported');
case 'movieFileDeleted': case 'movieFileDeleted':
return 'Movie File Deleted'; return translate('MovieFileDeleted');
case 'movieFileRenamed': case 'movieFileRenamed':
return 'Movie File Renamed'; return translate('MovieFileRenamed');
case 'downloadIgnored': case 'downloadIgnored':
return 'Download Ignored'; return translate('DownloadIgnored');
default: default:
return 'Unknown'; return translate('Unknown');
} }
} }
@@ -37,6 +37,7 @@ function HistoryDetailsModal(props) {
eventType, eventType,
sourceTitle, sourceTitle,
data, data,
downloadId,
isMarkingAsFailed, isMarkingAsFailed,
shortDateFormat, shortDateFormat,
timeFormat, timeFormat,
@@ -59,6 +60,7 @@ function HistoryDetailsModal(props) {
eventType={eventType} eventType={eventType}
sourceTitle={sourceTitle} sourceTitle={sourceTitle}
data={data} data={data}
downloadId={downloadId}
shortDateFormat={shortDateFormat} shortDateFormat={shortDateFormat}
timeFormat={timeFormat} timeFormat={timeFormat}
/> />
@@ -73,7 +75,7 @@ function HistoryDetailsModal(props) {
isSpinning={isMarkingAsFailed} isSpinning={isMarkingAsFailed}
onPress={onMarkAsFailedPress} onPress={onMarkAsFailedPress}
> >
Mark as Failed {translate('MarkAsFailed')}
</SpinnerButton> </SpinnerButton>
} }
@@ -93,6 +95,7 @@ HistoryDetailsModal.propTypes = {
eventType: PropTypes.string.isRequired, eventType: PropTypes.string.isRequired,
sourceTitle: PropTypes.string.isRequired, sourceTitle: PropTypes.string.isRequired,
data: PropTypes.object.isRequired, data: PropTypes.object.isRequired,
downloadId: PropTypes.string,
isMarkingAsFailed: PropTypes.bool.isRequired, isMarkingAsFailed: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired, shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired, timeFormat: PropTypes.string.isRequired,
+8 -4
View File
@@ -14,6 +14,7 @@ import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptions
import TablePager from 'Components/Table/TablePager'; import TablePager from 'Components/Table/TablePager';
import { align, icons, kinds } from 'Helpers/Props'; import { align, icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import HistoryFilterModal from './HistoryFilterModal';
import HistoryRowConnector from './HistoryRowConnector'; import HistoryRowConnector from './HistoryRowConnector';
class History extends Component { class History extends Component {
@@ -33,6 +34,7 @@ class History extends Component {
columns, columns,
selectedFilterKey, selectedFilterKey,
filters, filters,
customFilters,
totalRecords, totalRecords,
onFilterSelect, onFilterSelect,
onFirstPagePress, onFirstPagePress,
@@ -70,7 +72,8 @@ class History extends Component {
alignMenu={align.RIGHT} alignMenu={align.RIGHT}
selectedFilterKey={selectedFilterKey} selectedFilterKey={selectedFilterKey}
filters={filters} filters={filters}
customFilters={[]} customFilters={customFilters}
filterModalConnectorComponent={HistoryFilterModal}
onFilterSelect={onFilterSelect} onFilterSelect={onFilterSelect}
/> />
</PageToolbarSection> </PageToolbarSection>
@@ -85,7 +88,7 @@ class History extends Component {
{ {
!isFetchingAny && hasError && !isFetchingAny && hasError &&
<Alert kind={kinds.DANGER}> <Alert kind={kinds.DANGER}>
{translate('UnableToLoadHistory')} {translate('HistoryLoadError')}
</Alert> </Alert>
} }
@@ -95,7 +98,7 @@ class History extends Component {
isPopulated && !hasError && !items.length && isPopulated && !hasError && !items.length &&
<Alert kind={kinds.INFO}> <Alert kind={kinds.INFO}>
{translate('NoHistory')} {translate('NoHistoryFound')}
</Alert> </Alert>
} }
@@ -144,8 +147,9 @@ History.propTypes = {
moviesError: PropTypes.object, moviesError: PropTypes.object,
items: PropTypes.arrayOf(PropTypes.object).isRequired, items: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired, columns: PropTypes.arrayOf(PropTypes.object).isRequired,
selectedFilterKey: PropTypes.string.isRequired, selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired, filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
totalRecords: PropTypes.number, totalRecords: PropTypes.number,
onFilterSelect: PropTypes.func.isRequired, onFilterSelect: PropTypes.func.isRequired,
onFirstPagePress: PropTypes.func.isRequired onFirstPagePress: PropTypes.func.isRequired
@@ -4,6 +4,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import withCurrentPage from 'Components/withCurrentPage'; import withCurrentPage from 'Components/withCurrentPage';
import * as historyActions from 'Store/Actions/historyActions'; import * as historyActions from 'Store/Actions/historyActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
import History from './History'; import History from './History';
@@ -11,11 +12,13 @@ function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.history, (state) => state.history,
(state) => state.movies, (state) => state.movies,
(history, movies) => { createCustomFiltersSelector('history'),
(history, movies, customFilters) => {
return { return {
isMoviesFetching: movies.isFetching, isMoviesFetching: movies.isFetching,
isMoviesPopulated: movies.isPopulated, isMoviesPopulated: movies.isPopulated,
moviesError: movies.error, moviesError: movies.error,
customFilters,
...history ...history
}; };
} }
@@ -3,9 +3,10 @@ import React from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell';
import { icons, kinds } from 'Helpers/Props'; import { icons, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './HistoryEventTypeCell.css'; import styles from './HistoryEventTypeCell.css';
function getIconName(eventType) { function getIconName(eventType, data) {
switch (eventType) { switch (eventType) {
case 'grabbed': case 'grabbed':
return icons.DOWNLOADING; return icons.DOWNLOADING;
@@ -16,7 +17,7 @@ function getIconName(eventType) {
case 'downloadFailed': case 'downloadFailed':
return icons.DOWNLOADING; return icons.DOWNLOADING;
case 'movieFileDeleted': case 'movieFileDeleted':
return icons.DELETE; return data.reason === 'MissingFromDisk' ? icons.FILE_MISSING : icons.DELETE;
case 'movieFileRenamed': case 'movieFileRenamed':
return icons.ORGANIZE; return icons.ORGANIZE;
case 'downloadIgnored': case 'downloadIgnored':
@@ -38,26 +39,26 @@ function getIconKind(eventType) {
function getTooltip(eventType, data) { function getTooltip(eventType, data) {
switch (eventType) { switch (eventType) {
case 'grabbed': case 'grabbed':
return `Movie grabbed from ${data.indexer} and sent to ${data.downloadClient}`; return translate('MovieGrabbedHistoryTooltip', { indexer: data.indexer, downloadClient: data.downloadClient });
case 'movieFolderImported': case 'movieFolderImported':
return 'Movie imported from movie folder'; return translate('MovieFolderImportedTooltip');
case 'downloadFolderImported': case 'downloadFolderImported':
return 'Movie downloaded successfully and picked up from download client'; return translate('MovieImportedTooltip');
case 'downloadFailed': case 'downloadFailed':
return 'Movie download failed'; return translate('MovieDownloadFailedTooltip');
case 'movieFileDeleted': case 'movieFileDeleted':
return 'Movie file deleted'; return data.reason === 'MissingFromDisk' ? translate('MovieFileMissingTooltip') : translate('MovieFileDeletedTooltip');
case 'movieFileRenamed': case 'movieFileRenamed':
return 'Movie file renamed'; return translate('MovieFileRenamedTooltip');
case 'downloadIgnored': case 'downloadIgnored':
return 'Movie Download Ignored'; return translate('MovieDownloadIgnoredTooltip');
default: default:
return 'Unknown event'; return translate('UnknownEventTooltip');
} }
} }
function HistoryEventTypeCell({ eventType, data }) { function HistoryEventTypeCell({ eventType, data }) {
const iconName = getIconName(eventType); const iconName = getIconName(eventType, data);
const iconKind = getIconKind(eventType); const iconKind = getIconKind(eventType);
const tooltip = getTooltip(eventType, data); const tooltip = getTooltip(eventType, data);
@@ -0,0 +1,54 @@
import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import FilterModal from 'Components/Filter/FilterModal';
import { setHistoryFilter } from 'Store/Actions/historyActions';
function createHistorySelector() {
return createSelector(
(state: AppState) => state.history.items,
(queueItems) => {
return queueItems;
}
);
}
function createFilterBuilderPropsSelector() {
return createSelector(
(state: AppState) => state.history.filterBuilderProps,
(filterBuilderProps) => {
return filterBuilderProps;
}
);
}
interface HistoryFilterModalProps {
isOpen: boolean;
}
export default function HistoryFilterModal(props: HistoryFilterModalProps) {
const sectionItems = useSelector(createHistorySelector());
const filterBuilderProps = useSelector(createFilterBuilderPropsSelector());
const customFilterType = 'history';
const dispatch = useDispatch();
const dispatchSetFilter = useCallback(
(payload: unknown) => {
dispatch(setHistoryFilter(payload));
},
[dispatch]
);
return (
<FilterModal
// TODO: Don't spread all the props
{...props}
sectionItems={sectionItems}
filterBuilderProps={filterBuilderProps}
customFilterType={customFilterType}
dispatchSetFilter={dispatchSetFilter}
/>
);
}
+10 -5
View File
@@ -64,6 +64,7 @@ class HistoryRow extends Component {
sourceTitle, sourceTitle,
date, date,
data, data,
downloadId,
isMarkingAsFailed, isMarkingAsFailed,
columns, columns,
shortDateFormat, shortDateFormat,
@@ -98,7 +99,7 @@ class HistoryRow extends Component {
); );
} }
if (name === 'movies.sortTitle') { if (name === 'movieMetadata.sortTitle') {
return ( return (
<TableRowCell key={name}> <TableRowCell key={name}>
<MovieTitleLink <MovieTitleLink
@@ -216,10 +217,12 @@ class HistoryRow extends Component {
key={name} key={name}
className={styles.details} className={styles.details}
> >
<IconButton <div className={styles.actionContents}>
name={icons.INFO} <IconButton
onPress={this.onDetailsPress} name={icons.INFO}
/> onPress={this.onDetailsPress}
/>
</div>
</TableRowCell> </TableRowCell>
); );
} }
@@ -233,6 +236,7 @@ class HistoryRow extends Component {
eventType={eventType} eventType={eventType}
sourceTitle={sourceTitle} sourceTitle={sourceTitle}
data={data} data={data}
downloadId={downloadId}
isMarkingAsFailed={isMarkingAsFailed} isMarkingAsFailed={isMarkingAsFailed}
shortDateFormat={shortDateFormat} shortDateFormat={shortDateFormat}
timeFormat={timeFormat} timeFormat={timeFormat}
@@ -257,6 +261,7 @@ HistoryRow.propTypes = {
sourceTitle: PropTypes.string.isRequired, sourceTitle: PropTypes.string.isRequired,
date: PropTypes.string.isRequired, date: PropTypes.string.isRequired,
data: PropTypes.object.isRequired, data: PropTypes.object.isRequired,
downloadId: PropTypes.string,
isMarkingAsFailed: PropTypes.bool, isMarkingAsFailed: PropTypes.bool,
markAsFailedError: PropTypes.object, markAsFailedError: PropTypes.object,
columns: PropTypes.arrayOf(PropTypes.object).isRequired, columns: PropTypes.arrayOf(PropTypes.object).isRequired,
+42 -6
View File
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Alert from 'Components/Alert'; import Alert from 'Components/Alert';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
import PageContent from 'Components/Page/PageContent'; import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody'; import PageContentBody from 'Components/Page/PageContentBody';
import PageToolbar from 'Components/Page/Toolbar/PageToolbar'; import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
@@ -21,9 +22,10 @@ import getSelectedIds from 'Utilities/Table/getSelectedIds';
import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState'; import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
import selectAll from 'Utilities/Table/selectAll'; import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected'; import toggleSelected from 'Utilities/Table/toggleSelected';
import QueueFilterModal from './QueueFilterModal';
import QueueOptionsConnector from './QueueOptionsConnector'; import QueueOptionsConnector from './QueueOptionsConnector';
import QueueRowConnector from './QueueRowConnector'; import QueueRowConnector from './QueueRowConnector';
import RemoveQueueItemsModal from './RemoveQueueItemsModal'; import RemoveQueueItemModal from './RemoveQueueItemModal';
class Queue extends Component { class Queue extends Component {
@@ -153,11 +155,16 @@ class Queue extends Component {
isMoviesPopulated, isMoviesPopulated,
moviesError, moviesError,
columns, columns,
selectedFilterKey,
filters,
customFilters,
count,
totalRecords, totalRecords,
isGrabbing, isGrabbing,
isRemoving, isRemoving,
isRefreshMonitoredDownloadsExecuting, isRefreshMonitoredDownloadsExecuting,
onRefreshPress, onRefreshPress,
onFilterSelect,
...otherProps ...otherProps
} = this.props; } = this.props;
@@ -220,6 +227,15 @@ class Queue extends Component {
iconName={icons.TABLE} iconName={icons.TABLE}
/> />
</TableOptionsModalWrapper> </TableOptionsModalWrapper>
<FilterMenu
alignMenu={align.RIGHT}
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
filterModalConnectorComponent={QueueFilterModal}
onFilterSelect={onFilterSelect}
/>
</PageToolbarSection> </PageToolbarSection>
</PageToolbar> </PageToolbar>
@@ -233,7 +249,7 @@ class Queue extends Component {
{ {
!isRefreshing && hasError ? !isRefreshing && hasError ?
<Alert kind={kinds.DANGER}> <Alert kind={kinds.DANGER}>
{translate('FailedToLoadQueue')} {translate('QueueLoadError')}
</Alert> : </Alert> :
null null
} }
@@ -241,7 +257,11 @@ class Queue extends Component {
{ {
isAllPopulated && !hasError && !items.length ? isAllPopulated && !hasError && !items.length ?
<Alert kind={kinds.INFO}> <Alert kind={kinds.INFO}>
{translate('QueueIsEmpty')} {
selectedFilterKey !== 'all' && count > 0 ?
translate('QueueFilterHasNoItems') :
translate('QueueIsEmpty')
}
</Alert> : </Alert> :
null null
} }
@@ -287,9 +307,16 @@ class Queue extends Component {
} }
</PageContentBody> </PageContentBody>
<RemoveQueueItemsModal <RemoveQueueItemModal
isOpen={isConfirmRemoveModalOpen} isOpen={isConfirmRemoveModalOpen}
selectedCount={selectedCount} selectedCount={selectedCount}
canChangeCategory={isConfirmRemoveModalOpen && (
selectedIds.every((id) => {
const item = items.find((i) => i.id === id);
return !!(item && item.downloadClientHasPostImportCategory);
})
)}
canIgnore={isConfirmRemoveModalOpen && ( canIgnore={isConfirmRemoveModalOpen && (
selectedIds.every((id) => { selectedIds.every((id) => {
const item = items.find((i) => i.id === id); const item = items.find((i) => i.id === id);
@@ -297,7 +324,7 @@ class Queue extends Component {
return !!(item && item.movieId); return !!(item && item.movieId);
}) })
)} )}
allPending={isConfirmRemoveModalOpen && ( pending={isConfirmRemoveModalOpen && (
selectedIds.every((id) => { selectedIds.every((id) => {
const item = items.find((i) => i.id === id); const item = items.find((i) => i.id === id);
@@ -325,13 +352,22 @@ Queue.propTypes = {
moviesError: PropTypes.object, moviesError: PropTypes.object,
items: PropTypes.arrayOf(PropTypes.object).isRequired, items: PropTypes.arrayOf(PropTypes.object).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired, columns: PropTypes.arrayOf(PropTypes.object).isRequired,
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
count: PropTypes.number.isRequired,
totalRecords: PropTypes.number, totalRecords: PropTypes.number,
isGrabbing: PropTypes.bool.isRequired, isGrabbing: PropTypes.bool.isRequired,
isRemoving: PropTypes.bool.isRequired, isRemoving: PropTypes.bool.isRequired,
isRefreshMonitoredDownloadsExecuting: PropTypes.bool.isRequired, isRefreshMonitoredDownloadsExecuting: PropTypes.bool.isRequired,
onRefreshPress: PropTypes.func.isRequired, onRefreshPress: PropTypes.func.isRequired,
onGrabSelectedPress: PropTypes.func.isRequired, onGrabSelectedPress: PropTypes.func.isRequired,
onRemoveSelectedPress: PropTypes.func.isRequired onRemoveSelectedPress: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired
};
Queue.defaultProps = {
count: 0
}; };
export default Queue; export default Queue;
+12 -1
View File
@@ -6,6 +6,7 @@ import * as commandNames from 'Commands/commandNames';
import withCurrentPage from 'Components/withCurrentPage'; import withCurrentPage from 'Components/withCurrentPage';
import { executeCommand } from 'Store/Actions/commandActions'; import { executeCommand } from 'Store/Actions/commandActions';
import * as queueActions from 'Store/Actions/queueActions'; import * as queueActions from 'Store/Actions/queueActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator'; import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
import Queue from './Queue'; import Queue from './Queue';
@@ -15,12 +16,16 @@ function createMapStateToProps() {
(state) => state.movies, (state) => state.movies,
(state) => state.queue.options, (state) => state.queue.options,
(state) => state.queue.paged, (state) => state.queue.paged,
(state) => state.queue.status.item,
createCustomFiltersSelector('queue'),
createCommandExecutingSelector(commandNames.REFRESH_MONITORED_DOWNLOADS), createCommandExecutingSelector(commandNames.REFRESH_MONITORED_DOWNLOADS),
(movies, options, queue, isRefreshMonitoredDownloadsExecuting) => { (movies, options, queue, status, customFilters, isRefreshMonitoredDownloadsExecuting) => {
return { return {
count: options.includeUnknownMovieItems ? status.totalCount : status.count,
isMoviesFetching: movies.isFetching, isMoviesFetching: movies.isFetching,
isMoviesPopulated: movies.isPopulated, isMoviesPopulated: movies.isPopulated,
moviesError: movies.error, moviesError: movies.error,
customFilters,
isRefreshMonitoredDownloadsExecuting, isRefreshMonitoredDownloadsExecuting,
...options, ...options,
...queue ...queue
@@ -106,6 +111,10 @@ class QueueConnector extends Component {
this.props.setQueueSort({ sortKey }); this.props.setQueueSort({ sortKey });
}; };
onFilterSelect = (selectedFilterKey) => {
this.props.setQueueFilter({ selectedFilterKey });
};
onTableOptionChange = (payload) => { onTableOptionChange = (payload) => {
this.props.setQueueTableOption(payload); this.props.setQueueTableOption(payload);
@@ -140,6 +149,7 @@ class QueueConnector extends Component {
onLastPagePress={this.onLastPagePress} onLastPagePress={this.onLastPagePress}
onPageSelect={this.onPageSelect} onPageSelect={this.onPageSelect}
onSortPress={this.onSortPress} onSortPress={this.onSortPress}
onFilterSelect={this.onFilterSelect}
onTableOptionChange={this.onTableOptionChange} onTableOptionChange={this.onTableOptionChange}
onRefreshPress={this.onRefreshPress} onRefreshPress={this.onRefreshPress}
onGrabSelectedPress={this.onGrabSelectedPress} onGrabSelectedPress={this.onGrabSelectedPress}
@@ -162,6 +172,7 @@ QueueConnector.propTypes = {
gotoQueueLastPage: PropTypes.func.isRequired, gotoQueueLastPage: PropTypes.func.isRequired,
gotoQueuePage: PropTypes.func.isRequired, gotoQueuePage: PropTypes.func.isRequired,
setQueueSort: PropTypes.func.isRequired, setQueueSort: PropTypes.func.isRequired,
setQueueFilter: PropTypes.func.isRequired,
setQueueTableOption: PropTypes.func.isRequired, setQueueTableOption: PropTypes.func.isRequired,
clearQueue: PropTypes.func.isRequired, clearQueue: PropTypes.func.isRequired,
grabQueueItems: PropTypes.func.isRequired, grabQueueItems: PropTypes.func.isRequired,
@@ -0,0 +1,5 @@
.progressBarContainer {
display: flex;
justify-content: center;
width: 100%;
}
@@ -1,7 +1,7 @@
// This file is automatically generated. // This file is automatically generated.
// Please do not change this file! // Please do not change this file!
interface CssExports { interface CssExports {
'addCustomFormatMessage': string; 'progressBarContainer': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
export default cssExports; export default cssExports;
+43 -82
View File
@@ -1,116 +1,71 @@
import moment from 'moment';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import { icons, kinds } from 'Helpers/Props'; import Popover from 'Components/Tooltip/Popover';
import { icons, tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import QueueStatus from './QueueStatus';
import styles from './QueueDetails.css';
function QueueDetails(props) { function QueueDetails(props) {
const { const {
title, title,
size, size,
sizeleft, sizeleft,
estimatedCompletionTime,
status, status,
trackedDownloadState, trackedDownloadState,
trackedDownloadStatus, trackedDownloadStatus,
statusMessages,
errorMessage, errorMessage,
progressBar progressBar
} = props; } = props;
const progress = size ? (100 - sizeleft / size * 100) : 0; const progress = size ? (100 - sizeleft / size * 100) : 0;
const isDownloading = status === 'downloading';
const isPaused = status === 'paused';
const hasWarning = trackedDownloadStatus === 'warning';
const hasError = trackedDownloadStatus === 'error';
if (status === 'pending') { if (
return ( (isDownloading || isPaused) &&
<Icon !hasWarning &&
name={icons.PENDING} !hasError
title={translate('ReleaseWillBeProcessedInterp', [moment(estimatedCompletionTime).fromNow()])} ) {
/> const state = isPaused ? translate('Paused') : translate('Downloading');
);
}
if (status === 'completed') { if (progress < 5) {
if (errorMessage) {
return ( return (
<Icon <Icon
name={icons.DOWNLOAD} name={icons.DOWNLOADING}
kind={kinds.DANGER} title={`${state} - ${progress.toFixed(1)}% ${title}`}
title={translate('ImportFailedInterp', [errorMessage])}
/> />
); );
} }
if (trackedDownloadStatus === 'warning') {
return (
<Icon
name={icons.DOWNLOAD}
kind={kinds.WARNING}
title={translate('UnableToImportCheckLogs')}
/>
);
}
if (trackedDownloadState === 'importPending') {
return (
<Icon
name={icons.DOWNLOAD}
kind={kinds.PURPLE}
title={`${translate('Downloaded')} - ${translate('WaitingToImport')}`}
/>
);
}
if (trackedDownloadState === 'importing') {
return (
<Icon
name={icons.DOWNLOAD}
kind={kinds.PURPLE}
title={`${translate('Downloaded')} - ${translate('Importing')}`}
/>
);
}
}
if (errorMessage) {
return ( return (
<Icon <Popover
name={icons.DOWNLOADING} className={styles.progressBarContainer}
kind={kinds.DANGER} anchor={progressBar}
title={translate('DownloadFailedInterp', [errorMessage])} title={`${state} - ${progress.toFixed(1)}%`}
body={
<div>{title}</div>
}
position={tooltipPositions.LEFT}
/> />
); );
} }
if (status === 'failed') { return (
return ( <QueueStatus
<Icon sourceTitle={title}
name={icons.DOWNLOADING} status={status}
kind={kinds.DANGER} trackedDownloadStatus={trackedDownloadStatus}
title={translate('DownloadFailedCheckDownloadClientForMoreDetails')} trackedDownloadState={trackedDownloadState}
/> statusMessages={statusMessages}
); errorMessage={errorMessage}
} position={tooltipPositions.LEFT}
/>
if (status === 'warning') { );
return (
<Icon
name={icons.DOWNLOADING}
kind={kinds.WARNING}
title={translate('DownloadWarningCheckDownloadClientForMoreDetails')}
/>
);
}
if (progress < 5) {
return (
<Icon
name={icons.DOWNLOADING}
title={translate('MovieIsDownloadingInterp', [progress.toFixed(1), title])}
/>
);
}
return progressBar;
} }
QueueDetails.propTypes = { QueueDetails.propTypes = {
@@ -121,8 +76,14 @@ QueueDetails.propTypes = {
status: PropTypes.string.isRequired, status: PropTypes.string.isRequired,
trackedDownloadState: PropTypes.string.isRequired, trackedDownloadState: PropTypes.string.isRequired,
trackedDownloadStatus: PropTypes.string.isRequired, trackedDownloadStatus: PropTypes.string.isRequired,
statusMessages: PropTypes.arrayOf(PropTypes.object),
errorMessage: PropTypes.string, errorMessage: PropTypes.string,
progressBar: PropTypes.node.isRequired progressBar: PropTypes.node.isRequired
}; };
QueueDetails.defaultProps = {
trackedDownloadStatus: 'ok',
trackedDownloadState: 'downloading'
};
export default QueueDetails; export default QueueDetails;
@@ -0,0 +1,54 @@
import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import FilterModal from 'Components/Filter/FilterModal';
import { setQueueFilter } from 'Store/Actions/queueActions';
function createQueueSelector() {
return createSelector(
(state: AppState) => state.queue.paged.items,
(queueItems) => {
return queueItems;
}
);
}
function createFilterBuilderPropsSelector() {
return createSelector(
(state: AppState) => state.queue.paged.filterBuilderProps,
(filterBuilderProps) => {
return filterBuilderProps;
}
);
}
interface QueueFilterModalProps {
isOpen: boolean;
}
export default function QueueFilterModal(props: QueueFilterModalProps) {
const sectionItems = useSelector(createQueueSelector());
const filterBuilderProps = useSelector(createFilterBuilderPropsSelector());
const customFilterType = 'queue';
const dispatch = useDispatch();
const dispatchSetFilter = useCallback(
(payload: unknown) => {
dispatch(setQueueFilter(payload));
},
[dispatch]
);
return (
<FilterModal
// TODO: Don't spread all the props
{...props}
sectionItems={sectionItems}
filterBuilderProps={filterBuilderProps}
customFilterType={customFilterType}
dispatchSetFilter={dispatchSetFilter}
/>
);
}
+1 -1
View File
@@ -61,7 +61,7 @@ class QueueOptions extends Component {
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="includeUnknownMovieItems" name="includeUnknownMovieItems"
value={includeUnknownMovieItems} value={includeUnknownMovieItems}
helpText={translate('IncludeUnknownMovieItemsHelpText')} helpText={translate('ShowUnknownMovieItemsHelpText')}
onChange={this.onOptionChange} onChange={this.onOptionChange}
/> />
</FormGroup> </FormGroup>
+15 -1
View File
@@ -4,7 +4,7 @@ import ProtocolLabel from 'Activity/Queue/ProtocolLabel';
import IconButton from 'Components/Link/IconButton'; import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import ProgressBar from 'Components/ProgressBar'; 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 TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
import TableRow from 'Components/Table/TableRow'; import TableRow from 'Components/Table/TableRow';
@@ -96,7 +96,9 @@ class QueueRow extends Component {
indexer, indexer,
outputPath, outputPath,
downloadClient, downloadClient,
downloadClientHasPostImportCategory,
estimatedCompletionTime, estimatedCompletionTime,
added,
timeleft, timeleft,
size, size,
sizeleft, sizeleft,
@@ -315,6 +317,15 @@ class QueueRow extends Component {
); );
} }
if (name === 'added') {
return (
<RelativeDateCellConnector
key={name}
date={added}
/>
);
}
if (name === 'actions') { if (name === 'actions') {
return ( return (
<TableRowCell <TableRowCell
@@ -363,6 +374,7 @@ class QueueRow extends Component {
<RemoveQueueItemModal <RemoveQueueItemModal
isOpen={isRemoveQueueItemModalOpen} isOpen={isRemoveQueueItemModalOpen}
sourceTitle={title} sourceTitle={title}
canChangeCategory={!!downloadClientHasPostImportCategory}
canIgnore={!!movie} canIgnore={!!movie}
isPending={isPending} isPending={isPending}
onRemovePress={this.onRemoveQueueItemModalConfirmed} onRemovePress={this.onRemoveQueueItemModalConfirmed}
@@ -392,7 +404,9 @@ QueueRow.propTypes = {
indexer: PropTypes.string, indexer: PropTypes.string,
outputPath: PropTypes.string, outputPath: PropTypes.string,
downloadClient: PropTypes.string, downloadClient: PropTypes.string,
downloadClientHasPostImportCategory: PropTypes.bool,
estimatedCompletionTime: PropTypes.string, estimatedCompletionTime: PropTypes.string,
added: PropTypes.string,
timeleft: PropTypes.string, timeleft: PropTypes.string,
size: PropTypes.number, size: PropTypes.number,
year: PropTypes.number, year: PropTypes.number,
@@ -0,0 +1,3 @@
.noMessages {
margin-bottom: 10px;
}
+7
View File
@@ -0,0 +1,7 @@
// This file is automatically generated.
// Please do not change this file!
interface CssExports {
'noMessages': string;
}
export const cssExports: CssExports;
export default cssExports;
+162
View File
@@ -0,0 +1,162 @@
import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import Popover from 'Components/Tooltip/Popover';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './QueueStatus.css';
function getDetailedPopoverBody(statusMessages) {
return (
<div>
{
statusMessages.map(({ title, messages }) => {
return (
<div
key={title}
className={messages.length ? undefined: styles.noMessages}
>
{title}
<ul>
{
messages.map((message) => {
return (
<li key={message}>
{message}
</li>
);
})
}
</ul>
</div>
);
})
}
</div>
);
}
function QueueStatus(props) {
const {
sourceTitle,
status,
trackedDownloadStatus,
trackedDownloadState,
statusMessages,
errorMessage,
position,
canFlip
} = props;
const hasWarning = trackedDownloadStatus === 'warning';
const hasError = trackedDownloadStatus === 'error';
// status === 'downloading'
let iconName = icons.DOWNLOADING;
let iconKind = kinds.DEFAULT;
let title = translate('Downloading');
if (status === 'paused') {
iconName = icons.PAUSED;
title = translate('Paused');
}
if (status === 'queued') {
iconName = icons.QUEUED;
title = translate('Queued');
}
if (status === 'completed') {
iconName = icons.DOWNLOADED;
title = translate('Downloaded');
if (trackedDownloadState === 'importPending') {
title += ` - ${translate('WaitingToImport')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'importing') {
title += ` - ${translate('Importing')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'failedPending') {
title += ` - ${translate('WaitingToProcess')}`;
iconKind = kinds.DANGER;
}
}
if (hasWarning) {
iconKind = kinds.WARNING;
}
if (status === 'delay') {
iconName = icons.PENDING;
title = translate('Pending');
}
if (status === 'downloadClientUnavailable') {
iconName = icons.PENDING;
iconKind = kinds.WARNING;
title = translate('PendingDownloadClientUnavailable');
}
if (status === 'failed') {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = translate('DownloadFailed');
}
if (status === 'warning') {
iconName = icons.DOWNLOADING;
iconKind = kinds.WARNING;
const warningMessage = errorMessage || translate('CheckDownloadClientForDetails');
title = translate('DownloadWarning', { warningMessage });
}
if (hasError) {
if (status === 'completed') {
iconName = icons.DOWNLOAD;
iconKind = kinds.DANGER;
title = translate('ImportFailed', { sourceTitle });
} else {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = translate('DownloadFailed');
}
}
return (
<Popover
anchor={
<Icon
name={iconName}
kind={iconKind}
/>
}
title={title}
body={hasWarning || hasError ? getDetailedPopoverBody(statusMessages) : sourceTitle}
position={position}
canFlip={canFlip}
/>
);
}
QueueStatus.propTypes = {
sourceTitle: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
trackedDownloadStatus: PropTypes.string.isRequired,
trackedDownloadState: PropTypes.string.isRequired,
statusMessages: PropTypes.arrayOf(PropTypes.object),
errorMessage: PropTypes.string,
position: PropTypes.oneOf(tooltipPositions.all).isRequired,
canFlip: PropTypes.bool.isRequired
};
QueueStatus.defaultProps = {
trackedDownloadStatus: 'ok',
trackedDownloadState: 'downloading',
canFlip: false
};
export default QueueStatus;
+11 -121
View File
@@ -1,39 +1,10 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell';
import Popover from 'Components/Tooltip/Popover'; import { tooltipPositions } from 'Helpers/Props';
import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import QueueStatus from './QueueStatus';
import translate from 'Utilities/String/translate';
import styles from './QueueStatusCell.css'; import styles from './QueueStatusCell.css';
function getDetailedPopoverBody(statusMessages) {
return (
<div>
{
statusMessages.map(({ title, messages }) => {
return (
<div key={title}>
{title}
<ul>
{
messages.map((message) => {
return (
<li key={message}>
{message}
</li>
);
})
}
</ul>
</div>
);
})
}
</div>
);
}
function QueueStatusCell(props) { function QueueStatusCell(props) {
const { const {
sourceTitle, sourceTitle,
@@ -44,97 +15,16 @@ function QueueStatusCell(props) {
errorMessage errorMessage
} = props; } = props;
const hasWarning = trackedDownloadStatus === 'warning';
const hasError = trackedDownloadStatus === 'error';
// status === 'downloading'
let iconName = icons.DOWNLOADING;
let iconKind = kinds.DEFAULT;
let title = translate('Downloading');
if (status === 'paused') {
iconName = icons.PAUSED;
title = translate('Paused');
}
if (status === 'queued') {
iconName = icons.QUEUED;
title = translate('Queued');
}
if (status === 'completed') {
iconName = icons.DOWNLOADED;
title = translate('Downloaded');
if (trackedDownloadState === 'importPending') {
title += ` - ${translate('WaitingToImport')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'importing') {
title += ` - ${translate('Importing')}`;
iconKind = kinds.PURPLE;
}
if (trackedDownloadState === 'failedPending') {
title += ` - ${translate('WaitingToProcess')}`;
iconKind = kinds.DANGER;
}
}
if (hasWarning) {
iconKind = kinds.WARNING;
}
if (status === 'delay') {
iconName = icons.PENDING;
title = translate('Pending');
}
if (status === 'DownloadClientUnavailable') {
iconName = icons.PENDING;
iconKind = kinds.WARNING;
title = `${translate('Pending')} - ${translate('DownloadClientUnavailable')}`;
}
if (status === 'failed') {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = translate('DownloadFailed');
}
if (status === 'warning') {
iconName = icons.DOWNLOADING;
iconKind = kinds.WARNING;
const warningMessage = errorMessage || translate('CheckDownloadClientForDetails');
title = translate('DownloadWarning', [warningMessage]);
}
if (hasError) {
if (status === 'completed') {
iconName = icons.DOWNLOAD;
iconKind = kinds.DANGER;
title = translate('ImportFailed', [sourceTitle]);
} else {
iconName = icons.DOWNLOADING;
iconKind = kinds.DANGER;
title = translate('DownloadFailed');
}
}
return ( return (
<TableRowCell className={styles.status}> <TableRowCell className={styles.status}>
<Popover <QueueStatus
anchor={ sourceTitle={sourceTitle}
<Icon status={status}
name={iconName} trackedDownloadStatus={trackedDownloadStatus}
kind={iconKind} trackedDownloadState={trackedDownloadState}
/> statusMessages={statusMessages}
} errorMessage={errorMessage}
title={title}
body={hasWarning || hasError ? getDetailedPopoverBody(statusMessages) : sourceTitle}
position={tooltipPositions.RIGHT} position={tooltipPositions.RIGHT}
canFlip={false}
/> />
</TableRowCell> </TableRowCell>
); );
@@ -150,8 +40,8 @@ QueueStatusCell.propTypes = {
}; };
QueueStatusCell.defaultProps = { QueueStatusCell.defaultProps = {
trackedDownloadStatus: translate('Ok'), trackedDownloadStatus: 'ok',
trackedDownloadState: translate('Downloading') trackedDownloadState: 'downloading'
}; };
export default QueueStatusCell; export default QueueStatusCell;
@@ -1,170 +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('Remove')} - {sourceTitle}
</ModalHeader>
<ModalBody>
<div>
{translate('RemoveFromQueueText', [sourceTitle])}
</div>
{
isPending ?
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>{translate('BlocklistRelease')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="blocklist"
value={blocklist}
helpText={translate('BlocklistHelpText')}
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}
>
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;
@@ -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;
@@ -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('BlocklistHelpText')}
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;
+17 -10
View File
@@ -1,6 +1,9 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Icon from 'Components/Icon';
import TableRowCell from 'Components/Table/Cells/TableRowCell'; 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 formatTime from 'Utilities/Date/formatTime';
import formatTimeSpan from 'Utilities/Date/formatTimeSpan'; import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
import getRelativeDate from 'Utilities/Date/getRelativeDate'; import getRelativeDate from 'Utilities/Date/getRelativeDate';
@@ -25,11 +28,13 @@ function TimeleftCell(props) {
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true }); const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
return ( return (
<TableRowCell <TableRowCell className={styles.timeleft}>
className={styles.timeleft} <Tooltip
title={translate('DelayingDownloadUntilInterp', [date, time])} anchor={<Icon name={icons.INFO} />}
> tooltip={translate('DelayingDownloadUntil', { date, time })}
- kind={kinds.INVERSE}
position={tooltipPositions.TOP}
/>
</TableRowCell> </TableRowCell>
); );
} }
@@ -39,11 +44,13 @@ function TimeleftCell(props) {
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true }); const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
return ( return (
<TableRowCell <TableRowCell className={styles.timeleft}>
className={styles.timeleft} <Tooltip
title={translate('RetryingDownloadInterp', [date, time])} anchor={<Icon name={icons.INFO} />}
> tooltip={translate('RetryingDownloadOn', { date, time })}
- kind={kinds.INVERSE}
position={tooltipPositions.TOP}
/>
</TableRowCell> </TableRowCell>
); );
} }
@@ -1,5 +1,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Alert from 'Components/Alert';
import TextInput from 'Components/Form/TextInput'; import TextInput from 'Components/Form/TextInput';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import Button from 'Components/Link/Button'; import Button from 'Components/Link/Button';
@@ -130,7 +131,12 @@ class AddNewMovie extends Component {
<div className={styles.helpText}> <div className={styles.helpText}>
{translate('FailedLoadingSearchResults')} {translate('FailedLoadingSearchResults')}
</div> </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 </div> : null
} }
@@ -155,7 +161,7 @@ class AddNewMovie extends Component {
!isFetching && !error && !items.length && !!term && !isFetching && !error && !items.length && !!term &&
<div className={styles.message}> <div className={styles.message}>
<div className={styles.noResults}> <div className={styles.noResults}>
{translate('CouldNotFindResults', [term])} {translate('CouldNotFindResults', { term })}
</div> </div>
<div> <div>
{translate('YouCanAlsoSearch')} {translate('YouCanAlsoSearch')}
@@ -3,10 +3,13 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions'; import { clearAddMovie, lookupMovie } from 'Store/Actions/addMovieActions';
import { clearMovieFiles, fetchMovieFiles } from 'Store/Actions/movieFileActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions'; import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions'; import { fetchImportExclusions } from 'Store/Actions/Settings/importExclusions';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; 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 parseUrl from 'Utilities/String/parseUrl';
import AddNewMovie from './AddNewMovie'; import AddNewMovie from './AddNewMovie';
@@ -35,7 +38,9 @@ const mapDispatchToProps = {
fetchRootFolders, fetchRootFolders,
fetchImportExclusions, fetchImportExclusions,
fetchQueueDetails, fetchQueueDetails,
clearQueueDetails clearQueueDetails,
fetchMovieFiles,
clearMovieFiles
}; };
class AddNewMovieConnector extends Component { class AddNewMovieConnector extends Component {
@@ -55,6 +60,20 @@ class AddNewMovieConnector extends Component {
this.props.fetchQueueDetails(); 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() { componentWillUnmount() {
if (this._movieLookupTimeout) { if (this._movieLookupTimeout) {
clearTimeout(this._movieLookupTimeout); clearTimeout(this._movieLookupTimeout);
@@ -62,6 +81,7 @@ class AddNewMovieConnector extends Component {
this.props.clearAddMovie(); this.props.clearAddMovie();
this.props.clearQueueDetails(); this.props.clearQueueDetails();
this.props.clearMovieFiles();
} }
// //
@@ -107,12 +127,15 @@ class AddNewMovieConnector extends Component {
AddNewMovieConnector.propTypes = { AddNewMovieConnector.propTypes = {
term: PropTypes.string, term: PropTypes.string,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
lookupMovie: PropTypes.func.isRequired, lookupMovie: PropTypes.func.isRequired,
clearAddMovie: PropTypes.func.isRequired, clearAddMovie: PropTypes.func.isRequired,
fetchRootFolders: PropTypes.func.isRequired, fetchRootFolders: PropTypes.func.isRequired,
fetchImportExclusions: PropTypes.func.isRequired, fetchImportExclusions: PropTypes.func.isRequired,
fetchQueueDetails: 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); export default connect(createMapStateToProps, mapDispatchToProps)(AddNewMovieConnector);
@@ -85,8 +85,13 @@
margin-top: 20px; margin-top: 20px;
} }
.studio,
.genres {
margin-left: 5px;
}
.links { .links {
margin-left: 8px; margin-left: 5px;
pointer-events: all; pointer-events: all;
} }
@@ -5,6 +5,7 @@ interface CssExports {
'certification': string; 'certification': string;
'content': string; 'content': string;
'exclusionIcon': string; 'exclusionIcon': string;
'genres': string;
'icons': string; 'icons': string;
'links': string; 'links': string;
'overlay': string; 'overlay': string;
@@ -14,6 +15,7 @@ interface CssExports {
'runtime': string; 'runtime': string;
'searchResult': string; 'searchResult': string;
'statusContainer': string; 'statusContainer': string;
'studio': string;
'title': string; 'title': string;
'titleContainer': string; 'titleContainer': string;
'titleRow': string; 'titleRow': string;
@@ -1,6 +1,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import Label from 'Components/Label'; import Label from 'Components/Label';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import TmdbRating from 'Components/TmdbRating'; import TmdbRating from 'Components/TmdbRating';
@@ -61,21 +62,22 @@ class AddNewMovieSearchResult extends Component {
titleSlug, titleSlug,
year, year,
studio, studio,
genres,
status, status,
overview, overview,
ratings, ratings,
folder, folder,
images, images,
existingMovieId,
isExistingMovie, isExistingMovie,
isExclusionMovie, isExclusionMovie,
isSmallScreen, isSmallScreen,
colorImpairedMode, colorImpairedMode,
id, id,
monitored, monitored,
hasFile,
isAvailable, isAvailable,
queueStatus, movieFile,
queueState, queueItem,
runtime, runtime,
movieRuntimeFormat, movieRuntimeFormat,
certification certification
@@ -85,6 +87,8 @@ class AddNewMovieSearchResult extends Component {
isNewAddMovieModalOpen isNewAddMovieModalOpen
} = this.state; } = this.state;
const hasMovieFile = !!movieFile;
const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress }; const linkProps = isExistingMovie ? { to: `/movie/${titleSlug}` } : { onPress: this.onPress };
const posterWidth = 167; const posterWidth = 167;
const posterHeight = 250; const posterHeight = 250;
@@ -120,13 +124,13 @@ class AddNewMovieSearchResult extends Component {
{ {
isExistingMovie && isExistingMovie &&
<MovieIndexProgressBar <MovieIndexProgressBar
movieId={existingMovieId}
movieFile={movieFile}
monitored={monitored} monitored={monitored}
hasFile={hasFile} hasFile={hasMovieFile}
status={status} status={status}
width={posterWidth} width={posterWidth}
detailedProgressBar={true} detailedProgressBar={true}
queueStatus={queueStatus}
queueState={queueState}
isAvailable={isAvailable} isAvailable={isAvailable}
/> />
} }
@@ -197,13 +201,46 @@ class AddNewMovieSearchResult extends Component {
/> />
</Label> </Label>
{
ratings.imdb ?
<Label size={sizes.LARGE}>
<ImdbRating
ratings={ratings}
iconSize={13}
/>
</Label> :
null
}
{ {
!!studio && !!studio &&
<Label size={sizes.LARGE}> <Label size={sizes.LARGE}>
{studio} <Icon
name={icons.STUDIO}
size={13}
/>
<span className={styles.studio}>
{studio}
</span>
</Label> </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 <Tooltip
anchor={ anchor={
<Label <Label
@@ -215,15 +252,15 @@ class AddNewMovieSearchResult extends Component {
/> />
<span className={styles.links}> <span className={styles.links}>
Links {translate('Links')}
</span> </span>
</Label> </Label>
} }
tooltip={ tooltip={
<MovieDetailsLinks <MovieDetailsLinks
tmdbId={tmdbId} tmdbId={tmdbId}
youTubeTrailerId={youTubeTrailerId}
imdbId={imdbId} imdbId={imdbId}
youTubeTrailerId={youTubeTrailerId}
/> />
} }
canFlip={true} canFlip={true}
@@ -234,9 +271,10 @@ class AddNewMovieSearchResult extends Component {
{ {
isExistingMovie && isSmallScreen && isExistingMovie && isSmallScreen &&
<MovieStatusLabel <MovieStatusLabel
hasMovieFiles={hasFile} hasMovieFiles={hasMovieFile}
monitored={monitored} monitored={monitored}
isAvailable={isAvailable} isAvailable={isAvailable}
queueItem={queueItem}
id={id} id={id}
useLabel={true} useLabel={true}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
@@ -273,25 +311,29 @@ AddNewMovieSearchResult.propTypes = {
titleSlug: PropTypes.string.isRequired, titleSlug: PropTypes.string.isRequired,
year: PropTypes.number.isRequired, year: PropTypes.number.isRequired,
studio: PropTypes.string, studio: PropTypes.string,
genres: PropTypes.arrayOf(PropTypes.string),
status: PropTypes.string.isRequired, status: PropTypes.string.isRequired,
overview: PropTypes.string, overview: PropTypes.string,
ratings: PropTypes.object.isRequired, ratings: PropTypes.object.isRequired,
folder: PropTypes.string.isRequired, folder: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired, images: PropTypes.arrayOf(PropTypes.object).isRequired,
existingMovieId: PropTypes.number,
isExistingMovie: PropTypes.bool.isRequired, isExistingMovie: PropTypes.bool.isRequired,
isExclusionMovie: PropTypes.bool.isRequired, isExclusionMovie: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired, isSmallScreen: PropTypes.bool.isRequired,
id: PropTypes.number, id: PropTypes.number,
queueItems: PropTypes.arrayOf(PropTypes.object),
monitored: PropTypes.bool.isRequired, monitored: PropTypes.bool.isRequired,
hasFile: PropTypes.bool.isRequired,
isAvailable: PropTypes.bool.isRequired, isAvailable: PropTypes.bool.isRequired,
movieFile: PropTypes.object,
queueItem: PropTypes.object,
colorImpairedMode: PropTypes.bool, colorImpairedMode: PropTypes.bool,
queueStatus: PropTypes.string,
queueState: PropTypes.string,
runtime: PropTypes.number.isRequired, runtime: PropTypes.number.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired, movieRuntimeFormat: PropTypes.string.isRequired,
certification: PropTypes.string certification: PropTypes.string
}; };
AddNewMovieSearchResult.defaultProps = {
genres: []
};
export default AddNewMovieSearchResult; export default AddNewMovieSearchResult;
@@ -11,16 +11,21 @@ function createMapStateToProps() {
createExclusionMovieSelector(), createExclusionMovieSelector(),
createDimensionsSelector(), createDimensionsSelector(),
(state) => state.queue.details.items, (state) => state.queue.details.items,
(state) => state.movieFiles.items,
(state, { internalId }) => internalId, (state, { internalId }) => internalId,
(isExistingMovie, isExclusionMovie, dimensions, queueItems, internalId) => { (state) => state.settings.ui.item.movieRuntimeFormat,
const firstQueueItem = queueItems.find((q) => q.movieId === internalId && internalId > 0); (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 { return {
existingMovieId: internalId,
isExistingMovie, isExistingMovie,
isExclusionMovie, isExclusionMovie,
isSmallScreen: dimensions.isSmallScreen, isSmallScreen: dimensions.isSmallScreen,
queueStatus: firstQueueItem ? firstQueueItem.status : null, queueItem,
queueState: firstQueueItem ? firstQueueItem.trackedDownloadState : null movieFile,
movieRuntimeFormat
}; };
} }
); );
@@ -119,7 +119,7 @@ class ImportMovie extends Component {
rootFoldersPopulated && rootFoldersPopulated &&
!unmappedFolders.length ? !unmappedFolders.length ?
<Alert kind={kinds.INFO}> <Alert kind={kinds.INFO}>
{translate('AllMoviesInPathHaveBeenImported', [path])} {translate('AllMoviesInPathHaveBeenImported', { path })}
</Alert> : </Alert> :
null null
} }
@@ -10,6 +10,7 @@ import styles from './ImportMovieRow.css';
function ImportMovieRow(props) { function ImportMovieRow(props) {
const { const {
id, id,
relativePath,
monitor, monitor,
qualityProfileId, qualityProfileId,
minimumAvailability, minimumAvailability,
@@ -31,7 +32,7 @@ function ImportMovieRow(props) {
/> />
<VirtualTableRowCell className={styles.folder}> <VirtualTableRowCell className={styles.folder}>
{id} {relativePath}
</VirtualTableRowCell> </VirtualTableRowCell>
<VirtualTableRowCell className={styles.movie}> <VirtualTableRowCell className={styles.movie}>
@@ -73,6 +74,7 @@ function ImportMovieRow(props) {
ImportMovieRow.propTypes = { ImportMovieRow.propTypes = {
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
relativePath: PropTypes.string.isRequired,
monitor: PropTypes.string.isRequired, monitor: PropTypes.string.isRequired,
qualityProfileId: PropTypes.number.isRequired, qualityProfileId: PropTypes.number.isRequired,
minimumAvailability: PropTypes.string.isRequired, minimumAvailability: PropTypes.string.isRequired,
@@ -30,7 +30,7 @@ class ImportMovieTable extends Component {
unmappedFolders.forEach((unmappedFolder) => { unmappedFolders.forEach((unmappedFolder) => {
const id = unmappedFolder.name; const id = unmappedFolder.name;
onMovieLookup(id, unmappedFolder.path); onMovieLookup(id, unmappedFolder.path, unmappedFolder.relativePath);
onSetImportMovieValue({ onSetImportMovieValue({
id, id,
@@ -25,10 +25,11 @@ function createMapStateToProps() {
function createMapDispatchToProps(dispatch, props) { function createMapDispatchToProps(dispatch, props) {
return { return {
onMovieLookup(name, path) { onMovieLookup(name, path, relativePath) {
dispatch(queueLookupMovie({ dispatch(queueLookupMovie({
name, name,
path, path,
relativePath,
term: name term: name
})); }));
}, },
@@ -32,7 +32,7 @@
.contentContainer { .contentContainer {
z-index: $popperZIndex; z-index: $popperZIndex;
margin-top: 4px; margin-top: 4px;
/* 400px container witdh with 8px padding on each side */ /* 400px container width with 8px padding on each side */
width: 384px; width: 384px;
} }
@@ -148,7 +148,7 @@ class ImportMovieSelectFolder extends Component {
className={styles.addErrorAlert} className={styles.addErrorAlert}
kind={kinds.DANGER} kind={kinds.DANGER}
> >
{translate('UnableToAddRootFolder')} {translate('AddRootFolderError')}
<ul> <ul>
{ {
@@ -5,12 +5,13 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { addRootFolder, deleteRootFolder, fetchRootFolders } from 'Store/Actions/rootFolderActions'; import { addRootFolder, deleteRootFolder, fetchRootFolders } from 'Store/Actions/rootFolderActions';
import createRootFoldersSelector from 'Store/Selectors/createRootFoldersSelector';
import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector'; import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
import ImportMovieSelectFolder from './ImportMovieSelectFolder'; import ImportMovieSelectFolder from './ImportMovieSelectFolder';
function createMapStateToProps() { function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.rootFolders, createRootFoldersSelector(),
createSystemStatusSelector(), createSystemStatusSelector(),
(rootFolders, systemStatus) => { (rootFolders, systemStatus) => {
return { return {
@@ -1,6 +1,7 @@
.version { .version {
margin: 0 3px; margin: 0 3px;
font-weight: bold; font-weight: bold;
font-family: var(--defaultFontFamily);
} }
.maintenance { .maintenance {
+6 -5
View File
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Button from 'Components/Link/Button'; import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
import ModalBody from 'Components/Modal/ModalBody'; import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent'; import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter'; import ModalFooter from 'Components/Modal/ModalFooter';
@@ -64,20 +65,20 @@ function AppUpdatedModalContent(props) {
return ( return (
<ModalContent onModalClose={onModalClose}> <ModalContent onModalClose={onModalClose}>
<ModalHeader> <ModalHeader>
{translate('RadarrUpdated')} {translate('AppUpdated')}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<div dangerouslySetInnerHTML={{ __html: translate('VersionUpdateText', [`<span className=${styles.version}>${version}</span>`]) }} /> <div>
<InlineMarkdown data={translate('AppUpdatedVersion', { version })} blockClassName={styles.version} />
</div>
{ {
isPopulated && !error && !!update && isPopulated && !error && !!update &&
<div> <div>
{ {
!update.changes && !update.changes &&
<div className={styles.maintenance}> <div className={styles.maintenance}>{translate('MaintenanceRelease')}</div>
{translate('MaintenanceRelease')}
</div>
} }
{ {
+2 -2
View File
@@ -28,11 +28,11 @@ function ConnectionLostModal(props) {
<ModalBody> <ModalBody>
<div> <div>
{translate('ConnectionLostMessage')} {translate('ConnectionLostToBackend')}
</div> </div>
<div className={styles.automatic}> <div className={styles.automatic}>
{translate('ConnectionLostAutomaticMessage')} {translate('ConnectionLostReconnect')}
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
@@ -1,4 +1,5 @@
import SortDirection from 'Helpers/Props/SortDirection'; import SortDirection from 'Helpers/Props/SortDirection';
import { FilterBuilderProp } from './AppState';
export interface Error { export interface Error {
responseJSON: { responseJSON: {
@@ -20,6 +21,10 @@ export interface PagedAppSectionState {
pageSize: number; pageSize: number;
} }
export interface AppSectionFilterState<T> {
filterBuilderProps: FilterBuilderProp<T>[];
}
export interface AppSectionSchemaState<T> { export interface AppSectionSchemaState<T> {
isSchemaFetching: boolean; isSchemaFetching: boolean;
isSchemaPopulated: boolean; isSchemaPopulated: boolean;
+13
View File
@@ -1,5 +1,7 @@
import InteractiveImportAppState from 'App/State/InteractiveImportAppState'; import InteractiveImportAppState from 'App/State/InteractiveImportAppState';
import CalendarAppState from './CalendarAppState';
import CommandAppState from './CommandAppState'; import CommandAppState from './CommandAppState';
import HistoryAppState from './HistoryAppState';
import MovieCollectionAppState from './MovieCollectionAppState'; import MovieCollectionAppState from './MovieCollectionAppState';
import MovieFilesAppState from './MovieFilesAppState'; import MovieFilesAppState from './MovieFilesAppState';
import MoviesAppState, { MovieIndexAppState } from './MoviesAppState'; import MoviesAppState, { MovieIndexAppState } from './MoviesAppState';
@@ -42,8 +44,19 @@ export interface CustomFilter {
filers: PropertyFilter[]; filers: PropertyFilter[];
} }
export interface AppSectionState {
dimensions: {
isSmallScreen: boolean;
width: number;
height: number;
};
}
interface AppState { interface AppState {
app: AppSectionState;
calendar: CalendarAppState;
commands: CommandAppState; commands: CommandAppState;
history: HistoryAppState;
interactiveImport: InteractiveImportAppState; interactiveImport: InteractiveImportAppState;
movieCollections: MovieCollectionAppState; movieCollections: MovieCollectionAppState;
movieFiles: MovieFilesAppState; movieFiles: MovieFilesAppState;
@@ -0,0 +1,10 @@
import AppSectionState, {
AppSectionFilterState,
} from 'App/State/AppSectionState';
import Movie from 'Movie/Movie';
interface CalendarAppState
extends AppSectionState<Movie>,
AppSectionFilterState<Movie> {}
export default CalendarAppState;
+10
View File
@@ -0,0 +1,10 @@
import AppSectionState, {
AppSectionFilterState,
} from 'App/State/AppSectionState';
import History from 'typings/History';
interface HistoryAppState
extends AppSectionState<History>,
AppSectionFilterState<History> {}
export default HistoryAppState;
@@ -1,7 +1,7 @@
import AppSectionState from 'App/State/AppSectionState'; import AppSectionState from 'App/State/AppSectionState';
import RecentFolder from 'InteractiveImport/Folder/RecentFolder'; import RecentFolder from 'InteractiveImport/Folder/RecentFolder';
import ImportMode from '../../InteractiveImport/ImportMode'; import ImportMode from 'InteractiveImport/ImportMode';
import InteractiveImport from '../../InteractiveImport/InteractiveImport'; import InteractiveImport from 'InteractiveImport/InteractiveImport';
interface InteractiveImportAppState extends AppSectionState<InteractiveImport> { interface InteractiveImportAppState extends AppSectionState<InteractiveImport> {
originalItems: InteractiveImport[]; originalItems: InteractiveImport[];
@@ -1,6 +1,8 @@
import AppSectionState from 'App/State/AppSectionState'; import AppSectionState from 'App/State/AppSectionState';
import MovieCollection from 'typings/MovieCollection'; import MovieCollection from 'typings/MovieCollection';
type MovieCollectionAppState = AppSectionState<MovieCollection>; interface MovieCollectionAppState extends AppSectionState<MovieCollection> {
itemMap: Record<number, number>;
}
export default MovieCollectionAppState; export default MovieCollectionAppState;
+9 -33
View File
@@ -1,41 +1,17 @@
import ModelBase from 'App/ModelBase'; import Queue from 'typings/Queue';
import Language from 'Language/Language'; import AppSectionState, {
import { QualityModel } from 'Quality/Quality'; AppSectionFilterState,
import CustomFormat from 'typings/CustomFormat'; AppSectionItemState,
import AppSectionState, { AppSectionItemState, Error } from './AppSectionState'; 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> { export interface QueueDetailsAppState extends AppSectionState<Queue> {
params: unknown; params: unknown;
} }
export interface QueuePagedAppState extends AppSectionState<Queue> { export interface QueuePagedAppState
extends AppSectionState<Queue>,
AppSectionFilterState<Queue> {
isGrabbing: boolean; isGrabbing: boolean;
grabError: Error; grabError: Error;
isRemoving: boolean; isRemoving: boolean;
@@ -8,6 +8,7 @@ import Language from 'Language/Language';
import DownloadClient from 'typings/DownloadClient'; import DownloadClient from 'typings/DownloadClient';
import ImportList from 'typings/ImportList'; import ImportList from 'typings/ImportList';
import Indexer from 'typings/Indexer'; import Indexer from 'typings/Indexer';
import IndexerFlag from 'typings/IndexerFlag';
import Notification from 'typings/Notification'; import Notification from 'typings/Notification';
import QualityProfile from 'typings/QualityProfile'; import QualityProfile from 'typings/QualityProfile';
import { UiSettings } from 'typings/UiSettings'; import { UiSettings } from 'typings/UiSettings';
@@ -35,12 +36,14 @@ export interface QualityProfilesAppState
extends AppSectionState<QualityProfile>, extends AppSectionState<QualityProfile>,
AppSectionSchemaState<QualityProfile> {} AppSectionSchemaState<QualityProfile> {}
export type IndexerFlagSettingsAppState = AppSectionState<IndexerFlag>;
export type LanguageSettingsAppState = AppSectionState<Language>; export type LanguageSettingsAppState = AppSectionState<Language>;
export type UiSettingsAppState = AppSectionItemState<UiSettings>; export type UiSettingsAppState = AppSectionItemState<UiSettings>;
interface SettingsAppState { interface SettingsAppState {
downloadClients: DownloadClientAppState; downloadClients: DownloadClientAppState;
importLists: ImportListAppState; importLists: ImportListAppState;
indexerFlags: IndexerFlagSettingsAppState;
indexers: IndexerAppState; indexers: IndexerAppState;
languages: LanguageSettingsAppState; languages: LanguageSettingsAppState;
notifications: NotificationAppState; notifications: NotificationAppState;
+2 -2
View File
@@ -42,9 +42,9 @@ function Agenda(props) {
<div className={styles.agenda}> <div className={styles.agenda}>
{ {
items.map((item, index) => { items.map((item, index) => {
const momentDate = moment(item.inCinemas); const momentDate = moment(item.sortDate);
const showDate = index === 0 || const showDate = index === 0 ||
!moment(items[index - 1].inCinemas).isSame(momentDate, 'day'); !moment(items[index - 1].sortDate).isSame(momentDate, 'day');
return ( return (
<AgendaEventConnector <AgendaEventConnector
+21 -7
View File
@@ -1,17 +1,28 @@
.event { .event {
display: flex; position: relative;
overflow-x: hidden;
padding: 5px; padding: 5px;
border-bottom: 1px solid var(--borderColor); border-bottom: 1px solid var(--borderColor);
font-size: $defaultFontSize; }
.underlay {
@add-mixin cover;
&:hover { &:hover {
background-color: var(--tableRowHoverBackgroundColor); background-color: var(--tableRowHoverBackgroundColor);
} }
} }
.link { .overlay {
composes: link from '~Calendar/Events/CalendarEvent.css'; @add-mixin linkOverlay;
position: relative;
display: flex;
overflow-x: hidden;
font-size: $defaultFontSize;
&:global(.colorImpaired) {
border-left-width: 5px;
}
} }
.eventWrapper { .eventWrapper {
@@ -44,6 +55,8 @@
.statusIcon { .statusIcon {
margin-left: 3px; margin-left: 3px;
cursor: default;
pointer-events: all;
} }
/* /*
@@ -75,7 +88,7 @@
} }
@media only screen and (max-width: $breakpointSmall) { @media only screen and (max-width: $breakpointSmall) {
.event { .overlay {
flex-direction: column; flex-direction: column;
} }
@@ -95,6 +108,7 @@
} }
} }
.dateIcon { .releaseIcon {
margin-right: 20px;
width: 25px; width: 25px;
} }
+3 -2
View File
@@ -3,18 +3,19 @@
interface CssExports { interface CssExports {
'continuing': string; 'continuing': string;
'date': string; 'date': string;
'dateIcon': string;
'downloaded': string; 'downloaded': string;
'event': string; 'event': string;
'eventWrapper': string; 'eventWrapper': string;
'genres': string; 'genres': string;
'link': string;
'missingMonitored': string; 'missingMonitored': string;
'missingUnmonitored': string; 'missingUnmonitored': string;
'movieTitle': string; 'movieTitle': string;
'overlay': string;
'queue': string; 'queue': string;
'releaseIcon': string;
'statusIcon': string; 'statusIcon': string;
'time': string; 'time': string;
'underlay': string;
'unmonitored': string; 'unmonitored': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
+13 -16
View File
@@ -87,25 +87,24 @@ class AgendaEvent extends Component {
const link = `/movie/${titleSlug}`; const link = `/movie/${titleSlug}`;
return ( return (
<div> <div className={styles.event}>
<Link <Link
className={classNames( className={styles.underlay}
styles.event,
styles.link
)}
to={link} to={link}
> />
<div className={styles.dateIcon}>
<div className={styles.overlay}>
<div className={styles.date}>
{showDate ? startTime.format(longDateFormat) : null}
</div>
<div className={styles.releaseIcon}>
<Icon <Icon
name={releaseIcon} name={releaseIcon}
kind={kinds.DEFAULT} kind={kinds.DEFAULT}
/> />
</div> </div>
<div className={styles.date}>
{(showDate) ? startTime.format(longDateFormat) : null}
</div>
<div <div
className={classNames( className={classNames(
styles.eventWrapper, styles.eventWrapper,
@@ -143,18 +142,16 @@ class AgendaEvent extends Component {
} }
{ {
showCutoffUnmetIcon && showCutoffUnmetIcon && !!movieFile && movieFile.qualityCutoffNotMet &&
!!movieFile &&
movieFile.qualityCutoffNotMet &&
<Icon <Icon
className={styles.statusIcon} className={styles.statusIcon}
name={icons.MOVIE_FILE} name={icons.MOVIE_FILE}
kind={kinds.WARNING} kind={kinds.WARNING}
title={translate('QualityCutoffHasNotBeenMet')} title={translate('QualityCutoffNotMet')}
/> />
} }
</div> </div>
</Link> </div>
</div> </div>
); );
} }
+1 -3
View File
@@ -33,9 +33,7 @@ class Calendar extends Component {
{ {
!isFetching && !!error && !isFetching && !!error &&
<Alert kind={kinds.DANGER}> <Alert kind={kinds.DANGER}>{translate('CalendarLoadError')}</Alert>
{translate('UnableToLoadTheCalendar')}
</Alert>
} }
{ {
+1 -1
View File
@@ -55,7 +55,7 @@ class CalendarConnector extends Component {
gotoCalendarToday gotoCalendarToday
} = this.props; } = this.props;
registerPagePopulator(this.repopulate); registerPagePopulator(this.repopulate, ['movieFileUpdated', 'movieFileDeleted']);
if (useCurrentPage) { if (useCurrentPage) {
fetchCalendar(); fetchCalendar();
@@ -0,0 +1,54 @@
import React, { useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
import FilterModal from 'Components/Filter/FilterModal';
import { setCalendarFilter } from 'Store/Actions/calendarActions';
function createCalendarSelector() {
return createSelector(
(state: AppState) => state.calendar.items,
(calendar) => {
return calendar;
}
);
}
function createFilterBuilderPropsSelector() {
return createSelector(
(state: AppState) => state.calendar.filterBuilderProps,
(filterBuilderProps) => {
return filterBuilderProps;
}
);
}
interface CalendarFilterModalProps {
isOpen: boolean;
}
export default function CalendarFilterModal(props: CalendarFilterModalProps) {
const sectionItems = useSelector(createCalendarSelector());
const filterBuilderProps = useSelector(createFilterBuilderPropsSelector());
const customFilterType = 'calendar';
const dispatch = useDispatch();
const dispatchSetFilter = useCallback(
(payload: unknown) => {
dispatch(setCalendarFilter(payload));
},
[dispatch]
);
return (
<FilterModal
// TODO: Don't spread all the props
{...props}
sectionItems={sectionItems}
filterBuilderProps={filterBuilderProps}
customFilterType={customFilterType}
dispatchSetFilter={dispatchSetFilter}
/>
);
}
+8 -4
View File
@@ -14,6 +14,7 @@ import NoMovie from 'Movie/NoMovie';
import getErrorMessage from 'Utilities/Object/getErrorMessage'; import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate'; import translate from 'Utilities/String/translate';
import CalendarConnector from './CalendarConnector'; import CalendarConnector from './CalendarConnector';
import CalendarFilterModal from './CalendarFilterModal';
import CalendarLinkModal from './iCal/CalendarLinkModal'; import CalendarLinkModal from './iCal/CalendarLinkModal';
import LegendConnector from './Legend/LegendConnector'; import LegendConnector from './Legend/LegendConnector';
import CalendarOptionsModal from './Options/CalendarOptionsModal'; import CalendarOptionsModal from './Options/CalendarOptionsModal';
@@ -83,6 +84,7 @@ class CalendarPage extends Component {
movieIsFetching, movieIsFetching,
movieIsPopulated, movieIsPopulated,
missingMovieIds, missingMovieIds,
customFilters,
isRssSyncExecuting, isRssSyncExecuting,
isSearchingForMissing, isSearchingForMissing,
useCurrentPage, useCurrentPage,
@@ -102,7 +104,7 @@ class CalendarPage extends Component {
<PageToolbar> <PageToolbar>
<PageToolbarSection> <PageToolbarSection>
<PageToolbarButton <PageToolbarButton
label={translate('iCalLink')} label={translate('ICalLink')}
iconName={icons.CALENDAR} iconName={icons.CALENDAR}
onPress={this.onGetCalendarLinkPress} onPress={this.onGetCalendarLinkPress}
/> />
@@ -110,7 +112,7 @@ class CalendarPage extends Component {
<PageToolbarSeparator /> <PageToolbarSeparator />
<PageToolbarButton <PageToolbarButton
label={translate('RSSSync')} label={translate('RssSync')}
iconName={icons.RSS} iconName={icons.RSS}
isSpinning={isRssSyncExecuting} isSpinning={isRssSyncExecuting}
onPress={onRssSyncPress} onPress={onRssSyncPress}
@@ -137,7 +139,8 @@ class CalendarPage extends Component {
isDisabled={!hasMovie} isDisabled={!hasMovie}
selectedFilterKey={selectedFilterKey} selectedFilterKey={selectedFilterKey}
filters={filters} filters={filters}
customFilters={[]} customFilters={customFilters}
filterModalConnectorComponent={CalendarFilterModal}
onFilterSelect={onFilterSelect} onFilterSelect={onFilterSelect}
/> />
</PageToolbarSection> </PageToolbarSection>
@@ -177,7 +180,7 @@ class CalendarPage extends Component {
{ {
!movieError && movieIsPopulated && !hasMovie && !movieError && movieIsPopulated && !hasMovie &&
<NoMovie /> <NoMovie totalItems={0} />
} }
{ {
@@ -208,6 +211,7 @@ CalendarPage.propTypes = {
movieIsFetching: PropTypes.bool.isRequired, movieIsFetching: PropTypes.bool.isRequired,
movieIsPopulated: PropTypes.bool.isRequired, movieIsPopulated: PropTypes.bool.isRequired,
missingMovieIds: PropTypes.arrayOf(PropTypes.number).isRequired, missingMovieIds: PropTypes.arrayOf(PropTypes.number).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
isRssSyncExecuting: PropTypes.bool.isRequired, isRssSyncExecuting: PropTypes.bool.isRequired,
isSearchingForMissing: PropTypes.bool.isRequired, isSearchingForMissing: PropTypes.bool.isRequired,
useCurrentPage: PropTypes.bool.isRequired, useCurrentPage: PropTypes.bool.isRequired,
@@ -5,6 +5,7 @@ import * as commandNames from 'Commands/commandNames';
import withCurrentPage from 'Components/withCurrentPage'; import withCurrentPage from 'Components/withCurrentPage';
import { searchMissing, setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions'; import { searchMissing, setCalendarDaysCount, setCalendarFilter } from 'Store/Actions/calendarActions';
import { executeCommand } from 'Store/Actions/commandActions'; import { executeCommand } from 'Store/Actions/commandActions';
import { createCustomFiltersSelector } from 'Store/Selectors/createClientSideCollectionSelector';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector'; import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import createCommandsSelector from 'Store/Selectors/createCommandsSelector'; import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
import createMovieCountSelector from 'Store/Selectors/createMovieCountSelector'; import createMovieCountSelector from 'Store/Selectors/createMovieCountSelector';
@@ -59,6 +60,7 @@ function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.calendar.selectedFilterKey, (state) => state.calendar.selectedFilterKey,
(state) => state.calendar.filters, (state) => state.calendar.filters,
createCustomFiltersSelector('calendar'),
createMovieCountSelector(), createMovieCountSelector(),
createUISettingsSelector(), createUISettingsSelector(),
createMissingMovieIdsSelector(), createMissingMovieIdsSelector(),
@@ -67,6 +69,7 @@ function createMapStateToProps() {
( (
selectedFilterKey, selectedFilterKey,
filters, filters,
customFilters,
movieCount, movieCount,
uiSettings, uiSettings,
missingMovieIds, missingMovieIds,
@@ -76,6 +79,7 @@ function createMapStateToProps() {
return { return {
selectedFilterKey, selectedFilterKey,
filters, filters,
customFilters,
colorImpairedMode: uiSettings.enableColorImpairedMode, colorImpairedMode: uiSettings.enableColorImpairedMode,
hasMovie: !!movieCount.count, hasMovie: !!movieCount.count,
movieError: movieCount.error, movieError: movieCount.error,
-64
View File
@@ -1,64 +0,0 @@
import classNames from 'classnames';
import moment from 'moment';
import PropTypes from 'prop-types';
import React from 'react';
import * as calendarViews from 'Calendar/calendarViews';
import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector';
import styles from './CalendarDay.css';
function CalendarDay(props) {
const {
date,
time,
isTodaysDate,
events,
view,
onEventModalOpenToggle
} = props;
return (
<div className={classNames(
styles.day,
view === calendarViews.DAY && styles.isSingleDay
)}
>
{
view === calendarViews.MONTH &&
<div className={classNames(
styles.dayOfMonth,
isTodaysDate && styles.isToday,
!moment(date).isSame(moment(time), 'month') && styles.isDifferentMonth
)}
>
{moment(date).date()}
</div>
}
<div>
{
events.map((event) => {
return (
<CalendarEventConnector
key={event.id}
movieId={event.id}
date={date}
{...event}
onEventModalOpenToggle={onEventModalOpenToggle}
/>
);
})
}
</div>
</div>
);
}
CalendarDay.propTypes = {
date: PropTypes.string.isRequired,
time: PropTypes.string.isRequired,
isTodaysDate: PropTypes.bool.isRequired,
events: PropTypes.arrayOf(PropTypes.object).isRequired,
view: PropTypes.string.isRequired,
onEventModalOpenToggle: PropTypes.func.isRequired
};
export default CalendarDay;
+67
View File
@@ -0,0 +1,67 @@
import classNames from 'classnames';
import moment from 'moment';
import React from 'react';
import * as calendarViews from 'Calendar/calendarViews';
import CalendarEventConnector from 'Calendar/Events/CalendarEventConnector';
import CalendarEvent from 'typings/CalendarEvent';
import styles from './CalendarDay.css';
interface CalendarDayProps {
date: string;
time: string;
isTodaysDate: boolean;
events: CalendarEvent[];
view: string;
onEventModalOpenToggle(...args: unknown[]): unknown;
}
function CalendarDay(props: CalendarDayProps) {
const { date, time, isTodaysDate, events, view, onEventModalOpenToggle } =
props;
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (isTodaysDate && view === calendarViews.MONTH && ref.current) {
ref.current.scrollIntoView();
}
}, [time, isTodaysDate, view]);
return (
<div
ref={ref}
className={classNames(
styles.day,
view === calendarViews.DAY && styles.isSingleDay
)}
>
{view === calendarViews.MONTH && (
<div
className={classNames(
styles.dayOfMonth,
isTodaysDate && styles.isToday,
!moment(date).isSame(moment(time), 'month') &&
styles.isDifferentMonth
)}
>
{moment(date).date()}
</div>
)}
<div>
{events.map((event) => {
return (
<CalendarEventConnector
key={event.id}
{...event}
movieId={event.id}
date={date as string}
onEventModalOpenToggle={onEventModalOpenToggle}
/>
);
})}
</div>
</div>
);
}
export default CalendarDay;
+76 -15
View File
@@ -1,9 +1,22 @@
$fullColorGradient: rgba(244, 245, 246, 0.2);
.event { .event {
overflow-x: hidden; position: relative;
margin: 4px 2px; margin: 4px 2px;
padding: 5px; padding: 5px;
border-bottom: 1px solid var(--calendarBorderColor); border-bottom: 1px solid var(--calendarBorderColor);
border-left: 4px solid var(--calendarBorderColor); border-left: 4px solid var(--calendarBorderColor);
}
.underlay {
@add-mixin cover;
}
.overlay {
@add-mixin linkOverlay;
position: relative;
overflow-x: hidden;
font-size: 12px; font-size: 12px;
&:global(.colorImpaired) { &:global(.colorImpaired) {
@@ -11,18 +24,6 @@
} }
} }
.link {
composes: link from '~Components/Link/Link.css';
display: block;
color: var(--defaultColor);
&:hover {
color: var(--defaultColor);
text-decoration: none;
}
}
.info, .info,
.movieInfo { .movieInfo {
display: flex; display: flex;
@@ -44,8 +45,19 @@
font-size: $defaultFontSize; font-size: $defaultFontSize;
} }
.statusContainer {
display: flex;
align-items: center;
&:global(.fullColor) {
filter: var(--calendarFullColorFilter)
}
}
.statusIcon { .statusIcon {
margin-left: 3px; margin-left: 3px;
cursor: default;
pointer-events: all;
} }
/* /*
@@ -55,35 +67,84 @@
.downloaded { .downloaded {
border-left-color: var(--successColor) !important; border-left-color: var(--successColor) !important;
&:global(.fullColor) {
background-color: rgba(39, 194, 76, 0.4) !important;
}
&:global(.colorImpaired) { &:global(.colorImpaired) {
border-left-color: color(var(--successColor), saturation(+15%)) !important; border-left-color: color(#27c24c saturation(+15%)) !important;
} }
} }
.queue { .queue {
border-left-color: var(--purple) !important; border-left-color: var(--purple) !important;
&:global(.fullColor) {
background-color: rgba(122, 67, 182, 0.4) !important;
}
} }
.unmonitored { .unmonitored {
border-left-color: var(--gray) !important; border-left-color: var(--gray) !important;
&:global(.fullColor) {
background-color: rgba(173, 173, 173, 0.5) !important;
}
&:global(.colorImpaired) {
background: repeating-linear-gradient(45deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px);
}
&:global(.fullColor.colorImpaired) {
background: repeating-linear-gradient(45deg, $fullColorGradient, $fullColorGradient 5px, transparent 5px, transparent 10px);
}
} }
.missingUnmonitored { .missingUnmonitored {
border-left-color: var(--warningColor) !important; border-left-color: var(--warningColor) !important;
&:global(.fullColor) {
background-color: rgba(255, 165, 0, 0.6) !important;
}
&:global(.colorImpaired) { &:global(.colorImpaired) {
background: repeating-linear-gradient(45deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px); background: repeating-linear-gradient(90deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px);
}
&:global(.fullColor.colorImpaired) {
background: repeating-linear-gradient(90deg, $fullColorGradient, $fullColorGradient 5px, transparent 5px, transparent 10px);
} }
} }
.missingMonitored { .missingMonitored {
border-left-color: var(--dangerColor) !important; border-left-color: var(--dangerColor) !important;
&:global(.fullColor) {
background-color: rgba(240, 80, 80, 0.6) !important;
}
&:global(.colorImpaired) { &:global(.colorImpaired) {
border-left-color: color(#f05050 saturation(+15%)) !important;
background: repeating-linear-gradient(90deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px); background: repeating-linear-gradient(90deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px);
} }
&:global(.fullColor.colorImpaired) {
background: repeating-linear-gradient(90deg, $fullColorGradient, $fullColorGradient 5px, transparent 5px, transparent 10px);
}
} }
.continuing { .continuing {
border-left-color: var(--primaryColor) !important; border-left-color: var(--primaryColor) !important;
&:global(.fullColor) {
background-color: rgba(93, 156, 236, 0.4) !important;
}
&:global(.colorImpaired) {
background: repeating-linear-gradient(90deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px);
}
&:global(.fullColor.colorImpaired) {
background: repeating-linear-gradient(90deg, $fullColorGradient, $fullColorGradient 5px, transparent 5px, transparent 10px);
}
} }
+3 -1
View File
@@ -6,13 +6,15 @@ interface CssExports {
'event': string; 'event': string;
'genres': string; 'genres': string;
'info': string; 'info': string;
'link': string;
'missingMonitored': string; 'missingMonitored': string;
'missingUnmonitored': string; 'missingUnmonitored': string;
'movieInfo': string; 'movieInfo': string;
'movieTitle': string; 'movieTitle': string;
'overlay': string;
'queue': string; 'queue': string;
'statusContainer': string;
'statusIcon': string; 'statusIcon': string;
'underlay': string;
'unmonitored': string; 'unmonitored': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
+67 -49
View File
@@ -25,6 +25,7 @@ class CalendarEvent extends Component {
title, title,
titleSlug, titleSlug,
genres, genres,
date,
monitored, monitored,
certification, certification,
hasFile, hasFile,
@@ -32,8 +33,8 @@ class CalendarEvent extends Component {
queueItem, queueItem,
showMovieInformation, showMovieInformation,
showCutoffUnmetIcon, showCutoffUnmetIcon,
colorImpairedMode, fullColorEvents,
date colorImpairedMode
} = this.props; } = this.props;
const isDownloading = !!(queueItem || grabbed); const isDownloading = !!(queueItem || grabbed);
@@ -56,64 +57,79 @@ class CalendarEvent extends Component {
} }
return ( return (
<div> <div
className={classNames(
styles.event,
styles[statusStyle],
colorImpairedMode && 'colorImpaired',
fullColorEvents && 'fullColor'
)}
>
<Link <Link
className={classNames( className={styles.underlay}
styles.event,
styles.link,
styles[statusStyle],
colorImpairedMode && 'colorImpaired'
)}
// component="div"
to={link} to={link}
> />
<div className={styles.overlay} >
<div className={styles.info}> <div className={styles.info}>
<div className={styles.movieTitle}> <div className={styles.movieTitle}>
{title} {title}
</div> </div>
{ <div
!!queueItem && className={classNames(
<span className={styles.statusIcon}> styles.statusContainer,
<CalendarEventQueueDetails fullColorEvents && 'fullColor'
{...queueItem} )}
/> >
</span> {
} queueItem ?
<span className={styles.statusIcon}>
<CalendarEventQueueDetails
{...queueItem}
fullColorEvents={fullColorEvents}
/>
</span> :
null
}
{ {
!queueItem && grabbed && !queueItem && grabbed ?
<Icon <Icon
className={styles.statusIcon} className={styles.statusIcon}
name={icons.DOWNLOADING} name={icons.DOWNLOADING}
title={translate('MovieIsDownloading')} title={translate('MovieIsDownloading')}
/> /> :
} null
}
{ {
showCutoffUnmetIcon && showCutoffUnmetIcon &&
!!movieFile && !!movieFile &&
movieFile.qualityCutoffNotMet && movieFile.qualityCutoffNotMet ?
<Icon <Icon
className={styles.statusIcon} className={styles.statusIcon}
name={icons.MOVIE_FILE} name={icons.MOVIE_FILE}
kind={kinds.WARNING} kind={kinds.WARNING}
title={translate('QualityCutoffHasNotBeenMet')} title={translate('QualityCutoffNotMet')}
/> /> :
} null
}
</div>
</div> </div>
{ {
showMovieInformation && showMovieInformation ?
<div className={styles.movieInfo}> <div className={styles.movieInfo}>
<div className={styles.genres}> <div className={styles.genres}>
{joinedGenres} {joinedGenres}
</div> </div>
</div> </div> :
null
} }
{ {
showMovieInformation && showMovieInformation ?
<div className={styles.movieInfo}> <div className={styles.movieInfo}>
<div className={styles.genres}> <div className={styles.genres}>
{eventType.join(', ')} {eventType.join(', ')}
@@ -121,10 +137,10 @@ class CalendarEvent extends Component {
<div> <div>
{certification} {certification}
</div> </div>
</div> </div> :
null
} }
</Link> </div>
</div> </div>
); );
} }
@@ -140,16 +156,18 @@ CalendarEvent.propTypes = {
inCinemas: PropTypes.string, inCinemas: PropTypes.string,
physicalRelease: PropTypes.string, physicalRelease: PropTypes.string,
digitalRelease: PropTypes.string, digitalRelease: PropTypes.string,
date: PropTypes.string.isRequired,
monitored: PropTypes.bool.isRequired, monitored: PropTypes.bool.isRequired,
certification: PropTypes.string, certification: PropTypes.string,
hasFile: PropTypes.bool.isRequired, hasFile: PropTypes.bool.isRequired,
grabbed: PropTypes.bool, grabbed: PropTypes.bool,
queueItem: PropTypes.object, queueItem: PropTypes.object,
showMovieInformation: PropTypes.bool.isRequired, // These props come from the connector, not marked as required to appease TS for now.
showCutoffUnmetIcon: PropTypes.bool.isRequired, showMovieInformation: PropTypes.bool,
timeFormat: PropTypes.string.isRequired, showCutoffUnmetIcon: PropTypes.bool,
colorImpairedMode: PropTypes.bool.isRequired, fullColorEvents: PropTypes.bool,
date: PropTypes.string.isRequired timeFormat: PropTypes.string,
colorImpairedMode: PropTypes.bool
}; };
CalendarEvent.defaultProps = { CalendarEvent.defaultProps = {
@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import QueueDetails from 'Activity/Queue/QueueDetails'; import QueueDetails from 'Activity/Queue/QueueDetails';
import CircularProgressBar from 'Components/CircularProgressBar'; import CircularProgressBar from 'Components/CircularProgressBar';
import translate from 'Utilities/String/translate';
function CalendarEventQueueDetails(props) { function CalendarEventQueueDetails(props) {
const { const {
@@ -13,6 +12,7 @@ function CalendarEventQueueDetails(props) {
status, status,
trackedDownloadState, trackedDownloadState,
trackedDownloadStatus, trackedDownloadStatus,
statusMessages,
errorMessage errorMessage
} = props; } = props;
@@ -27,16 +27,15 @@ function CalendarEventQueueDetails(props) {
status={status} status={status}
trackedDownloadState={trackedDownloadState} trackedDownloadState={trackedDownloadState}
trackedDownloadStatus={trackedDownloadStatus} trackedDownloadStatus={trackedDownloadStatus}
statusMessages={statusMessages}
errorMessage={errorMessage} errorMessage={errorMessage}
progressBar={ progressBar={
<div title={translate('MovieIsDownloadingInterp', [progress.toFixed(1), title])}> <CircularProgressBar
<CircularProgressBar progress={progress}
progress={progress} size={20}
size={20} strokeWidth={2}
strokeWidth={2} strokeColor={'#7a43b6'}
strokeColor={'#7a43b6'} />
/>
</div>
} }
/> />
); );
@@ -50,6 +49,7 @@ CalendarEventQueueDetails.propTypes = {
status: PropTypes.string.isRequired, status: PropTypes.string.isRequired,
trackedDownloadState: PropTypes.string.isRequired, trackedDownloadState: PropTypes.string.isRequired,
trackedDownloadStatus: PropTypes.string.isRequired, trackedDownloadStatus: PropTypes.string.isRequired,
statusMessages: PropTypes.arrayOf(PropTypes.object),
errorMessage: PropTypes.string errorMessage: PropTypes.string
}; };
@@ -126,7 +126,7 @@ class CalendarHeader extends Component {
isDisabled={view === calendarViews.AGENDA} isDisabled={view === calendarViews.AGENDA}
onPress={onTodayPress} onPress={onTodayPress}
> >
Today {translate('Today')}
</Button> </Button>
</div> </div>
+27 -8
View File
@@ -8,19 +8,23 @@ import styles from './Legend.css';
function Legend(props) { function Legend(props) {
const { const {
view,
showCutoffUnmetIcon, showCutoffUnmetIcon,
fullColorEvents,
colorImpairedMode colorImpairedMode
} = props; } = props;
const iconsToShow = []; const iconsToShow = [];
const isAgendaView = view === 'agenda';
if (showCutoffUnmetIcon) { if (showCutoffUnmetIcon) {
iconsToShow.push( iconsToShow.push(
<LegendIconItem <LegendIconItem
name={translate('CutoffUnmet')} name={translate('CutoffNotMet')}
icon={icons.MOVIE_FILE} icon={icons.MOVIE_FILE}
kind={kinds.WARNING} kind={kinds.WARNING}
tooltip={translate('QualityOrLangCutoffHasNotBeenMet')} fullColorEvents={fullColorEvents}
tooltip={translate('QualityCutoffNotMet')}
/> />
); );
} }
@@ -29,45 +33,58 @@ function Legend(props) {
<div className={styles.legend}> <div className={styles.legend}>
<div> <div>
<LegendItem <LegendItem
style='ended' status="downloaded"
name={translate('DownloadedAndMonitored')} name={translate('DownloadedAndMonitored')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
<LegendItem <LegendItem
style='availNotMonitored' status="unmonitored"
name={translate('DownloadedButNotMonitored')} name={translate('DownloadedButNotMonitored')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
</div> </div>
<div> <div>
<LegendItem <LegendItem
style='missingMonitored' status="missingMonitored"
name={translate('MissingMonitoredAndConsideredAvailable')} name={translate('MissingMonitoredAndConsideredAvailable')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
<LegendItem <LegendItem
style='missingUnmonitored' status="missingUnmonitored"
name={translate('MissingNotMonitored')} name={translate('MissingNotMonitored')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
</div> </div>
<div> <div>
<LegendItem <LegendItem
style='queue' status="queue"
name={translate('Queued')} name={translate('Queued')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
<LegendItem <LegendItem
style='continuing' status="continuing"
name={translate('Unreleased')} name={translate('Unreleased')}
isAgendaView={isAgendaView}
fullColorEvents={fullColorEvents}
colorImpairedMode={colorImpairedMode} colorImpairedMode={colorImpairedMode}
/> />
</div> </div>
{ {
iconsToShow.length > 0 && iconsToShow.length > 0 &&
<div> <div>
@@ -79,7 +96,9 @@ function Legend(props) {
} }
Legend.propTypes = { Legend.propTypes = {
view: PropTypes.string.isRequired,
showCutoffUnmetIcon: PropTypes.bool.isRequired, showCutoffUnmetIcon: PropTypes.bool.isRequired,
fullColorEvents: PropTypes.bool.isRequired,
colorImpairedMode: PropTypes.bool.isRequired colorImpairedMode: PropTypes.bool.isRequired
}; };
@@ -6,10 +6,12 @@ import Legend from './Legend';
function createMapStateToProps() { function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.calendar.options, (state) => state.calendar.options,
(state) => state.calendar.view,
createUISettingsSelector(), createUISettingsSelector(),
(calendarOptions, uiSettings) => { (calendarOptions, view, uiSettings) => {
return { return {
...calendarOptions, ...calendarOptions,
view,
colorImpairedMode: uiSettings.enableColorImpairedMode colorImpairedMode: uiSettings.enableColorImpairedMode
}; };
} }
@@ -4,4 +4,8 @@
.icon { .icon {
margin-right: 5px; margin-right: 5px;
&:global(.fullColorEvents) {
filter: var(--calendarFullColorFilter)
}
} }
@@ -1,3 +1,4 @@
import classNames from 'classnames';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
@@ -6,6 +7,7 @@ import styles from './LegendIconItem.css';
function LegendIconItem(props) { function LegendIconItem(props) {
const { const {
name, name,
fullColorEvents,
icon, icon,
kind, kind,
tooltip tooltip
@@ -17,7 +19,10 @@ function LegendIconItem(props) {
title={tooltip} title={tooltip}
> >
<Icon <Icon
className={styles.icon} className={classNames(
styles.icon,
fullColorEvents && 'fullColorEvents'
)}
name={icon} name={icon}
kind={kind} kind={kind}
/> />
@@ -29,6 +34,7 @@ function LegendIconItem(props) {
LegendIconItem.propTypes = { LegendIconItem.propTypes = {
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
fullColorEvents: PropTypes.bool.isRequired,
icon: PropTypes.object.isRequired, icon: PropTypes.object.isRequired,
kind: PropTypes.string.isRequired, kind: PropTypes.string.isRequired,
tooltip: PropTypes.string.isRequired tooltip: PropTypes.string.isRequired
+21 -58
View File
@@ -1,74 +1,37 @@
.legendItemContainer {
margin-right: 5px;
width: 220px;
}
.legendItem { .legendItem {
display: inline-flex; margin: 3px 0;
margin-top: -1px; margin-right: 6px;
vertical-align: middle; padding-left: 5px;
line-height: 16px; width: 220px;
border-left-width: 4px;
border-left-style: solid;
cursor: default;
} }
.legendItemColor { /*
margin-right: 8px; * Status
width: 30px; */
height: 16px;
border-radius: 4px; .downloaded {
composes: downloaded from '~Calendar/Events/CalendarEvent.css';
} }
.queue { .queue {
composes: legendItemColor; composes: queue from '~Calendar/Events/CalendarEvent.css';
background-color: var(--queueColor);
} }
.continuing { .unmonitored {
composes: legendItemColor; composes: unmonitored from '~Calendar/Events/CalendarEvent.css';
background-color: var(--primaryColor);
}
.availNotMonitored {
composes: legendItemColor;
background-color: var(--darkGray);
}
.ended {
composes: legendItemColor;
background-color: var(--successColor);
}
.missingMonitored {
composes: legendItemColor;
background-color: var(--dangerColor);
&:global(.colorImpaired) {
background: repeating-linear-gradient(90deg, color(var(--dangerColor) shade(5%)), color(var(--dangerColor) shade(5%)) 5px, color(var(--dangerColor) shade(15%)) 5px, color(var(--dangerColor) shade(15%)) 10px);
}
} }
.missingUnmonitored { .missingUnmonitored {
composes: legendItemColor; composes: missingUnmonitored from '~Calendar/Events/CalendarEvent.css';
background-color: var(--warningColor);
&:global(.colorImpaired) {
background: repeating-linear-gradient(45deg, var(--warningColor), var(--warningColor) 5px, color(var(--warningColor) tint(15%)) 5px, color(var(--warningColor) tint(15%)) 10px);
}
} }
.missingMonitoredColorImpaired { .missingMonitored {
background: repeating-linear-gradient(90deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px); composes: missingMonitored from '~Calendar/Events/CalendarEvent.css';
} }
.missingUnmonitoredColorImpaired { .continuing {
background: repeating-linear-gradient(45deg, var(--colorImpairedGradientDark), var(--colorImpairedGradientDark) 5px, var(--colorImpairedGradient) 5px, var(--colorImpairedGradient) 10px); composes: continuing from '~Calendar/Events/CalendarEvent.css';
}
.legendItemText {
display: inline-block;
} }
+2 -7
View File
@@ -1,18 +1,13 @@
// This file is automatically generated. // This file is automatically generated.
// Please do not change this file! // Please do not change this file!
interface CssExports { interface CssExports {
'availNotMonitored': string;
'continuing': string; 'continuing': string;
'ended': string; 'downloaded': string;
'legendItem': string; 'legendItem': string;
'legendItemColor': string;
'legendItemContainer': string;
'legendItemText': string;
'missingMonitored': string; 'missingMonitored': string;
'missingMonitoredColorImpaired': string;
'missingUnmonitored': string; 'missingUnmonitored': string;
'missingUnmonitoredColorImpaired': string;
'queue': string; 'queue': string;
'unmonitored': string;
} }
export const cssExports: CssExports; export const cssExports: CssExports;
export default cssExports; export default cssExports;
+15 -13
View File
@@ -6,29 +6,31 @@ import styles from './LegendItem.css';
function LegendItem(props) { function LegendItem(props) {
const { const {
name, name,
style, status,
isAgendaView,
fullColorEvents,
colorImpairedMode colorImpairedMode
} = props; } = props;
return ( return (
<div className={styles.legendItemContainer}> <div
<div className={classNames(
className={classNames( styles.legendItem,
styles.legendItem, styles[status],
styles[style], colorImpairedMode && 'colorImpaired',
colorImpairedMode && 'colorImpaired' fullColorEvents && !isAgendaView && 'fullColor'
)} )}
/> >
<div className={classNames(styles.legendItemText, colorImpairedMode && styles[`${style}ColorImpaired`])}> {name}
{name}
</div>
</div> </div>
); );
} }
LegendItem.propTypes = { LegendItem.propTypes = {
name: PropTypes.string.isRequired, name: PropTypes.string.isRequired,
style: PropTypes.string.isRequired, status: PropTypes.string.isRequired,
isAgendaView: PropTypes.bool.isRequired,
fullColorEvents: PropTypes.bool.isRequired,
colorImpairedMode: PropTypes.bool.isRequired colorImpairedMode: PropTypes.bool.isRequired
}; };
@@ -26,14 +26,16 @@ class CalendarOptionsModalContent extends Component {
firstDayOfWeek, firstDayOfWeek,
calendarWeekColumnHeader, calendarWeekColumnHeader,
timeFormat, timeFormat,
enableColorImpairedMode enableColorImpairedMode,
fullColorEvents
} = props; } = props;
this.state = { this.state = {
firstDayOfWeek, firstDayOfWeek,
calendarWeekColumnHeader, calendarWeekColumnHeader,
timeFormat, timeFormat,
enableColorImpairedMode enableColorImpairedMode,
fullColorEvents
}; };
} }
@@ -94,6 +96,7 @@ class CalendarOptionsModalContent extends Component {
const { const {
showMovieInformation, showMovieInformation,
showCutoffUnmetIcon, showCutoffUnmetIcon,
fullColorEvents,
onModalClose onModalClose
} = this.props; } = this.props;
@@ -132,7 +135,19 @@ class CalendarOptionsModalContent extends Component {
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="showCutoffUnmetIcon" name="showCutoffUnmetIcon"
value={showCutoffUnmetIcon} value={showCutoffUnmetIcon}
helpText={translate('ShowCutoffUnmetIconHelpText')} helpText={translate('IconForCutoffUnmetHelpText')}
onChange={this.onOptionInputChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('FullColorEvents')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="fullColorEvents"
value={fullColorEvents}
helpText={translate('FullColorEventsHelpText')}
onChange={this.onOptionInputChange} onChange={this.onOptionInputChange}
/> />
</FormGroup> </FormGroup>
@@ -162,7 +177,7 @@ class CalendarOptionsModalContent extends Component {
values={weekColumnOptions} values={weekColumnOptions}
value={calendarWeekColumnHeader} value={calendarWeekColumnHeader}
onChange={this.onGlobalInputChange} onChange={this.onGlobalInputChange}
helpText={translate('SettingsWeekColumnHeaderHelpText')} helpText={translate('WeekColumnHeaderHelpText')}
/> />
</FormGroup> </FormGroup>
@@ -176,7 +191,9 @@ class CalendarOptionsModalContent extends Component {
value={timeFormat} value={timeFormat}
onChange={this.onGlobalInputChange} onChange={this.onGlobalInputChange}
/> />
</FormGroup><FormGroup> </FormGroup>
<FormGroup>
<FormLabel>{translate('EnableColorImpairedMode')}</FormLabel> <FormLabel>{translate('EnableColorImpairedMode')}</FormLabel>
<FormInputGroup <FormInputGroup
@@ -187,7 +204,6 @@ class CalendarOptionsModalContent extends Component {
onChange={this.onGlobalInputChange} onChange={this.onGlobalInputChange}
/> />
</FormGroup> </FormGroup>
</Form> </Form>
</FieldSet> </FieldSet>
</ModalBody> </ModalBody>
@@ -209,6 +225,7 @@ CalendarOptionsModalContent.propTypes = {
calendarWeekColumnHeader: PropTypes.string.isRequired, calendarWeekColumnHeader: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired, timeFormat: PropTypes.string.isRequired,
enableColorImpairedMode: PropTypes.bool.isRequired, enableColorImpairedMode: PropTypes.bool.isRequired,
fullColorEvents: PropTypes.bool.isRequired,
dispatchSetCalendarOption: PropTypes.func.isRequired, dispatchSetCalendarOption: PropTypes.func.isRequired,
dispatchSaveUISettings: PropTypes.func.isRequired, dispatchSaveUISettings: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired onModalClose: PropTypes.func.isRequired
@@ -109,7 +109,7 @@ class CalendarLinkModalContent extends Component {
return ( return (
<ModalContent onModalClose={onModalClose}> <ModalContent onModalClose={onModalClose}>
<ModalHeader> <ModalHeader>
{translate('RadarrCalendarFeed')} {translate('CalendarFeed')}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
@@ -121,19 +121,19 @@ class CalendarLinkModalContent extends Component {
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="unmonitored" name="unmonitored"
value={unmonitored} value={unmonitored}
helpText={translate('UnmonitoredHelpText')} helpText={translate('ICalIncludeUnmonitoredMoviesHelpText')}
onChange={this.onInputChange} onChange={this.onInputChange}
/> />
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<FormLabel>{translate('ShowAsAllDayEvents')}</FormLabel> <FormLabel>{translate('ICalShowAsAllDayEvents')}</FormLabel>
<FormInputGroup <FormInputGroup
type={inputTypes.CHECK} type={inputTypes.CHECK}
name="asAllDay" name="asAllDay"
value={asAllDay} value={asAllDay}
helpText={translate('AsAllDayHelpText')} helpText={translate('ICalShowAsAllDayEventsHelpText')}
onChange={this.onInputChange} onChange={this.onInputChange}
/> />
</FormGroup> </FormGroup>
@@ -145,7 +145,7 @@ class CalendarLinkModalContent extends Component {
type={inputTypes.TAG} type={inputTypes.TAG}
name="tags" name="tags"
value={tags} value={tags}
helpText={translate('TagsHelpText')} helpText={translate('ICalTagsMoviesHelpText')}
onChange={this.onInputChange} onChange={this.onInputChange}
/> />
</FormGroup> </FormGroup>
@@ -160,7 +160,7 @@ class CalendarLinkModalContent extends Component {
name="iCalHttpUrl" name="iCalHttpUrl"
value={iCalHttpUrl} value={iCalHttpUrl}
readOnly={true} readOnly={true}
helpText={translate('ICalHttpUrlHelpText')} helpText={translate('ICalFeedHelpText')}
buttons={[ buttons={[
<ClipboardButton <ClipboardButton
key="copy" key="copy"
+12 -1
View File
@@ -6,6 +6,7 @@ import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition'; import withScrollPosition from 'Components/withScrollPosition';
import { executeCommand } from 'Store/Actions/commandActions'; import { executeCommand } from 'Store/Actions/commandActions';
import { saveMovieCollections, setMovieCollectionsFilter, setMovieCollectionsSort } from 'Store/Actions/movieCollectionActions'; import { saveMovieCollections, setMovieCollectionsFilter, setMovieCollectionsSort } from 'Store/Actions/movieCollectionActions';
import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions'; import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import scrollPositions from 'Store/scrollPositions'; import scrollPositions from 'Store/scrollPositions';
import createCollectionClientSideCollectionItemsSelector from 'Store/Selectors/createCollectionClientSideCollectionItemsSelector'; import createCollectionClientSideCollectionItemsSelector from 'Store/Selectors/createCollectionClientSideCollectionItemsSelector';
@@ -38,6 +39,12 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchRootFolders() { dispatchFetchRootFolders() {
dispatch(fetchRootFolders()); dispatch(fetchRootFolders());
}, },
dispatchFetchQueueDetails() {
dispatch(fetchQueueDetails());
},
dispatchClearQueueDetails() {
dispatch(clearQueueDetails());
},
onUpdateSelectedPress(payload) { onUpdateSelectedPress(payload) {
dispatch(saveMovieCollections(payload)); dispatch(saveMovieCollections(payload));
}, },
@@ -63,10 +70,12 @@ class CollectionConnector extends Component {
componentDidMount() { componentDidMount() {
registerPagePopulator(this.repopulate); registerPagePopulator(this.repopulate);
this.props.dispatchFetchRootFolders(); this.props.dispatchFetchRootFolders();
this.props.dispatchFetchQueueDetails();
} }
componentWillUnmount() { componentWillUnmount() {
unregisterPagePopulator(this.repopulate); unregisterPagePopulator(this.repopulate);
this.props.dispatchClearQueueDetails();
} }
// //
@@ -99,7 +108,9 @@ CollectionConnector.propTypes = {
isSmallScreen: PropTypes.bool.isRequired, isSmallScreen: PropTypes.bool.isRequired,
view: PropTypes.string.isRequired, view: PropTypes.string.isRequired,
onUpdateSelectedPress: PropTypes.func.isRequired, onUpdateSelectedPress: PropTypes.func.isRequired,
dispatchFetchRootFolders: PropTypes.func.isRequired dispatchFetchRootFolders: PropTypes.func.isRequired,
dispatchFetchQueueDetails: PropTypes.func.isRequired,
dispatchClearQueueDetails: PropTypes.func.isRequired
}; };
export default withScrollPosition( export default withScrollPosition(
+75 -15
View File
@@ -14,6 +14,50 @@ import styles from './CollectionFooter.css';
const NO_CHANGE = 'noChange'; 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 { class CollectionFooter extends Component {
// //
@@ -23,12 +67,12 @@ class CollectionFooter extends Component {
super(props, context); super(props, context);
this.state = { this.state = {
monitor: NO_CHANGE,
monitored: NO_CHANGE, monitored: NO_CHANGE,
monitor: NO_CHANGE,
qualityProfileId: NO_CHANGE, qualityProfileId: NO_CHANGE,
minimumAvailability: NO_CHANGE, minimumAvailability: NO_CHANGE,
rootFolderPath: NO_CHANGE, rootFolderPath: NO_CHANGE,
destinationRootFolder: null searchOnAdd: NO_CHANGE
}; };
} }
@@ -44,8 +88,9 @@ class CollectionFooter extends Component {
monitored: NO_CHANGE, monitored: NO_CHANGE,
monitor: NO_CHANGE, monitor: NO_CHANGE,
qualityProfileId: NO_CHANGE, qualityProfileId: NO_CHANGE,
minimumAvailability: NO_CHANGE,
rootFolderPath: NO_CHANGE, rootFolderPath: NO_CHANGE,
minimumAvailability: NO_CHANGE searchOnAdd: NO_CHANGE
}); });
} }
@@ -63,11 +108,12 @@ class CollectionFooter extends Component {
onUpdateSelectedPress = () => { onUpdateSelectedPress = () => {
const { const {
monitor,
monitored, monitored,
monitor,
qualityProfileId, qualityProfileId,
minimumAvailability, minimumAvailability,
rootFolderPath rootFolderPath,
searchOnAdd
} = this.state; } = this.state;
const changes = {}; const changes = {};
@@ -92,6 +138,10 @@ class CollectionFooter extends Component {
changes.rootFolderPath = rootFolderPath; changes.rootFolderPath = rootFolderPath;
} }
if (searchOnAdd !== NO_CHANGE) {
changes.searchOnAdd = searchOnAdd === 'yes';
}
this.props.onUpdateSelectedPress(changes); this.props.onUpdateSelectedPress(changes);
}; };
@@ -109,15 +159,10 @@ class CollectionFooter extends Component {
monitor, monitor,
qualityProfileId, qualityProfileId,
minimumAvailability, minimumAvailability,
rootFolderPath rootFolderPath,
searchOnAdd
} = this.state; } = 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; const selectedCount = selectedIds.length;
return ( return (
@@ -125,7 +170,7 @@ class CollectionFooter extends Component {
<div className={styles.inputContainer}> <div className={styles.inputContainer}>
<CollectionFooterLabel <CollectionFooterLabel
label={translate('MonitorCollection')} label={translate('MonitorCollection')}
isSaving={isSaving} isSaving={isSaving && monitored !== NO_CHANGE}
/> />
<SelectInput <SelectInput
@@ -140,7 +185,7 @@ class CollectionFooter extends Component {
<div className={styles.inputContainer}> <div className={styles.inputContainer}>
<CollectionFooterLabel <CollectionFooterLabel
label={translate('MonitorMovies')} label={translate('MonitorMovies')}
isSaving={isSaving} isSaving={isSaving && monitor !== NO_CHANGE}
/> />
<SelectInput <SelectInput
@@ -198,10 +243,25 @@ class CollectionFooter extends Component {
/> />
</div> </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.buttonContainer}>
<div className={styles.buttonContainerContent}> <div className={styles.buttonContainerContent}>
<CollectionFooterLabel <CollectionFooterLabel
label={translate('CollectionsSelectedInterp', [selectedCount])} label={translate('CountCollectionsSelected', { count: selectedCount })}
isSaving={false} isSaving={false}
/> />
@@ -21,6 +21,7 @@ function createMapStateToProps() {
return { return {
...collection, ...collection,
movies: [...collection.movies].sort((a, b) => b.year - a.year),
genres: Array.from(new Set(allGenres)).slice(0, 3) genres: Array.from(new Set(allGenres)).slice(0, 3)
}; };
} }
@@ -61,6 +61,7 @@ class CollectionMovie extends Component {
const { const {
id, id,
title, title,
status,
overview, overview,
year, year,
tmdbId, tmdbId,
@@ -69,6 +70,7 @@ class CollectionMovie extends Component {
hasFile, hasFile,
folder, folder,
isAvailable, isAvailable,
movieFile,
isExistingMovie, isExistingMovie,
posterWidth, posterWidth,
posterHeight, posterHeight,
@@ -123,13 +125,15 @@ class CollectionMovie extends Component {
<div className={styles.overlay}> <div className={styles.overlay}>
<div className={styles.overlayTitle}> <div className={styles.overlayTitle}>
{title} {title} {year > 0 ? `(${year})` : ''}
</div> </div>
{ {
id && id ?
<div className={styles.overlayStatus}> <div className={styles.overlayStatus}>
<MovieIndexProgressBar <MovieIndexProgressBar
movieId={id}
movieFile={movieFile}
monitored={monitored} monitored={monitored}
hasFile={hasFile} hasFile={hasFile}
status={status} status={status}
@@ -138,7 +142,8 @@ class CollectionMovie extends Component {
detailedProgressBar={detailedProgressBar} detailedProgressBar={detailedProgressBar}
isAvailable={isAvailable} isAvailable={isAvailable}
/> />
</div> </div> :
null
} }
</div> </div>
</Link> </Link>
@@ -171,12 +176,14 @@ CollectionMovie.propTypes = {
id: PropTypes.number, id: PropTypes.number,
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
year: PropTypes.number.isRequired, year: PropTypes.number.isRequired,
status: PropTypes.string.isRequired,
overview: PropTypes.string.isRequired, overview: PropTypes.string.isRequired,
monitored: PropTypes.bool, monitored: PropTypes.bool,
collectionId: PropTypes.number.isRequired, collectionId: PropTypes.number.isRequired,
hasFile: PropTypes.bool, hasFile: PropTypes.bool,
folder: PropTypes.string, folder: PropTypes.string,
isAvailable: PropTypes.bool, isAvailable: PropTypes.bool,
movieFile: PropTypes.object,
images: PropTypes.arrayOf(PropTypes.object).isRequired, images: PropTypes.arrayOf(PropTypes.object).isRequired,
posterWidth: PropTypes.number.isRequired, posterWidth: PropTypes.number.isRequired,
posterHeight: PropTypes.number.isRequired, posterHeight: PropTypes.number.isRequired,
@@ -5,7 +5,7 @@
margin: 2px 4px; margin: 2px 4px;
border: 1px solid var(--borderColor); border: 1px solid var(--borderColor);
border-radius: 4px; border-radius: 4px;
background-color: #eee; background-color: var(--inputBackgroundColor);
cursor: default; cursor: default;
} }
@@ -17,7 +17,7 @@
padding: 0 4px; padding: 0 4px;
border-left: 4px; border-left: 4px;
border-left-style: solid; border-left-style: solid;
background-color: var(--white); background-color: var(--themeLightColor);
color: var(--defaultColor); color: var(--defaultColor);
} }
@@ -14,6 +14,7 @@ class CollectionMovieLabel extends Component {
const { const {
id, id,
title, title,
year,
status, status,
monitored, monitored,
isAvailable, isAvailable,
@@ -35,9 +36,7 @@ class CollectionMovieLabel extends Component {
} }
<span> <span>
{ {title} {year > 0 ? `(${year})` : ''}
title
}
</span> </span>
</div> </div>
@@ -62,6 +61,7 @@ class CollectionMovieLabel extends Component {
CollectionMovieLabel.propTypes = { CollectionMovieLabel.propTypes = {
id: PropTypes.number, id: PropTypes.number,
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
status: PropTypes.string, status: PropTypes.string,
isAvailable: PropTypes.bool, isAvailable: PropTypes.bool,
monitored: PropTypes.bool, monitored: PropTypes.bool,
@@ -74,11 +74,7 @@ CollectionMovieLabel.propTypes = {
CollectionMovieLabel.defaultProps = { CollectionMovieLabel.defaultProps = {
isSaving: false, isSaving: false,
statistics: { statistics: {}
episodeFileCount: 0,
totalEpisodeCount: 0,
percentOfEpisodes: 0
}
}; };
export default CollectionMovieLabel; export default CollectionMovieLabel;
@@ -28,7 +28,6 @@ function calculatePosterWidth(posterSize, isSmallScreen) {
} }
function calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions) { function calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions) {
const heights = [ const heights = [
overviewOptions.showPosters ? posterHeight : 75, overviewOptions.showPosters ? posterHeight : 75,
isSmallScreen ? columnPaddingSmallScreen : columnPadding isSmallScreen ? columnPaddingSmallScreen : columnPadding
@@ -122,8 +121,8 @@ class CollectionOverviews extends Component {
overviewOptions overviewOptions
} = this.props; } = this.props;
const posterWidth = calculatePosterWidth(overviewOptions.size, isSmallScreen); const posterWidth = overviewOptions.showPosters ? calculatePosterWidth(overviewOptions.size, isSmallScreen) : 0;
const posterHeight = calculatePosterHeight(posterWidth); const posterHeight = overviewOptions.showPosters ? calculatePosterHeight(posterWidth) : 0;
const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions); const rowHeight = calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions);
this.setState({ this.setState({
@@ -10,6 +10,7 @@ class DescriptionListItem extends Component {
render() { render() {
const { const {
className,
titleClassName, titleClassName,
descriptionClassName, descriptionClassName,
title, title,
@@ -17,7 +18,7 @@ class DescriptionListItem extends Component {
} = this.props; } = this.props;
return ( return (
<div> <div className={className}>
<DescriptionListItemTitle <DescriptionListItemTitle
className={titleClassName} className={titleClassName}
> >
@@ -35,6 +36,7 @@ class DescriptionListItem extends Component {
} }
DescriptionListItem.propTypes = { DescriptionListItem.propTypes = {
className: PropTypes.string,
titleClassName: PropTypes.string, titleClassName: PropTypes.string,
descriptionClassName: PropTypes.string, descriptionClassName: PropTypes.string,
title: PropTypes.string, title: PropTypes.string,
@@ -1,9 +1,7 @@
.description {
line-height: $lineHeight;
}
.description { .description {
margin-left: 0; margin-left: 0;
line-height: $lineHeight;
overflow-wrap: break-word;
} }
@media (min-width: 768px) { @media (min-width: 768px) {
@@ -6,9 +6,12 @@ import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Prop
import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue'; import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue'; import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector'; import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
import HistoryEventTypeFilterBuilderRowValue from './HistoryEventTypeFilterBuilderRowValue';
import ImportListFilterBuilderRowValueConnector from './ImportListFilterBuilderRowValueConnector'; import ImportListFilterBuilderRowValueConnector from './ImportListFilterBuilderRowValueConnector';
import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector'; import IndexerFilterBuilderRowValueConnector from './IndexerFilterBuilderRowValueConnector';
import LanguageFilterBuilderRowValue from './LanguageFilterBuilderRowValue';
import MinimumAvailabilityFilterBuilderRowValue from './MinimumAvailabilityFilterBuilderRowValue'; import MinimumAvailabilityFilterBuilderRowValue from './MinimumAvailabilityFilterBuilderRowValue';
import MovieFilterBuilderRowValue from './MovieFilterBuilderRowValue';
import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue'; import ProtocolFilterBuilderRowValue from './ProtocolFilterBuilderRowValue';
import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector'; import QualityFilterBuilderRowValueConnector from './QualityFilterBuilderRowValueConnector';
import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector'; import QualityProfileFilterBuilderRowValueConnector from './QualityProfileFilterBuilderRowValueConnector';
@@ -58,9 +61,15 @@ function getRowValueConnector(selectedFilterBuilderProp) {
case filterBuilderValueTypes.DATE: case filterBuilderValueTypes.DATE:
return DateFilterBuilderRowValue; return DateFilterBuilderRowValue;
case filterBuilderValueTypes.HISTORY_EVENT_TYPE:
return HistoryEventTypeFilterBuilderRowValue;
case filterBuilderValueTypes.INDEXER: case filterBuilderValueTypes.INDEXER:
return IndexerFilterBuilderRowValueConnector; return IndexerFilterBuilderRowValueConnector;
case filterBuilderValueTypes.LANGUAGE:
return LanguageFilterBuilderRowValue;
case filterBuilderValueTypes.PROTOCOL: case filterBuilderValueTypes.PROTOCOL:
return ProtocolFilterBuilderRowValue; return ProtocolFilterBuilderRowValue;
@@ -70,6 +79,9 @@ function getRowValueConnector(selectedFilterBuilderProp) {
case filterBuilderValueTypes.QUALITY_PROFILE: case filterBuilderValueTypes.QUALITY_PROFILE:
return QualityProfileFilterBuilderRowValueConnector; return QualityProfileFilterBuilderRowValueConnector;
case filterBuilderValueTypes.MOVIE:
return MovieFilterBuilderRowValue;
case filterBuilderValueTypes.RELEASE_STATUS: case filterBuilderValueTypes.RELEASE_STATUS:
return ReleaseStatusFilterBuilderRowValue; return ReleaseStatusFilterBuilderRowValue;
@@ -0,0 +1,16 @@
import { FilterBuilderProp } from 'App/State/AppState';
interface FilterBuilderRowOnChangeProps {
name: string;
value: unknown[];
}
interface FilterBuilderRowValueProps {
filterType?: string;
filterValue: string | number | object | string[] | number[] | object[];
selectedFilterBuilderProp: FilterBuilderProp<unknown>;
sectionItem: unknown[];
onChange: (payload: FilterBuilderRowOnChangeProps) => void;
}
export default FilterBuilderRowValueProps;
@@ -1,5 +1,5 @@
.tag { .tag {
height: 21px; display: flex;
&.isLastTag { &.isLastTag {
.or { .or {
@@ -18,4 +18,5 @@
.or { .or {
margin: 0 3px; margin: 0 3px;
color: var(--themeDarkColor); color: var(--themeDarkColor);
line-height: 31px;
} }
@@ -2,11 +2,12 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import TagInputTag from 'Components/Form/TagInputTag'; import TagInputTag from 'Components/Form/TagInputTag';
import { kinds } from 'Helpers/Props'; import { kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './FilterBuilderRowValueTag.css'; import styles from './FilterBuilderRowValueTag.css';
function FilterBuilderRowValueTag(props) { function FilterBuilderRowValueTag(props) {
return ( return (
<span <div
className={styles.tag} className={styles.tag}
> >
<TagInputTag <TagInputTag
@@ -15,12 +16,13 @@ function FilterBuilderRowValueTag(props) {
/> />
{ {
!props.isLastTag && props.isLastTag ?
<span className={styles.or}> null :
or <div className={styles.or}>
</span> {translate('Or')}
</div>
} }
</span> </div>
); );
} }
@@ -0,0 +1,51 @@
import React from 'react';
import translate from 'Utilities/String/translate';
import FilterBuilderRowValue from './FilterBuilderRowValue';
import FilterBuilderRowValueProps from './FilterBuilderRowValueProps';
const EVENT_TYPE_OPTIONS = [
{
id: 1,
get name() {
return translate('Grabbed');
},
},
{
id: 3,
get name() {
return translate('Imported');
},
},
{
id: 4,
get name() {
return translate('Failed');
},
},
{
id: 6,
get name() {
return translate('Deleted');
},
},
{
id: 8,
get name() {
return translate('Renamed');
},
},
{
id: 9,
get name() {
return translate('Ignored');
},
},
];
function HistoryEventTypeFilterBuilderRowValue(
props: FilterBuilderRowValueProps
) {
return <FilterBuilderRowValue {...props} tagList={EVENT_TYPE_OPTIONS} />;
}
export default HistoryEventTypeFilterBuilderRowValue;
@@ -0,0 +1,13 @@
import React from 'react';
import { useSelector } from 'react-redux';
import createLanguagesSelector from 'Store/Selectors/createLanguagesSelector';
import FilterBuilderRowValue from './FilterBuilderRowValue';
import FilterBuilderRowValueProps from './FilterBuilderRowValueProps';
function LanguageFilterBuilderRowValue(props: FilterBuilderRowValueProps) {
const { items } = useSelector(createLanguagesSelector());
return <FilterBuilderRowValue {...props} tagList={items} />;
}
export default LanguageFilterBuilderRowValue;

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