Compare commits

...

440 Commits

Author SHA1 Message Date
Bogdan
7c38ec2baa Fixed: (AvistaZ) Improve message for failed logins 2023-12-02 12:07:40 +02:00
Bogdan
dcfdd49119 Rollback YamlDotNet 2023-12-02 11:30:59 +02:00
Weblate
badb9dee61 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Appoxo <appoxo@appoxo.de>
Co-authored-by: David Molero <contact@dolvem.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
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/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-12-01 04:03:11 +02:00
Bogdan
12ca705556 Fixed: (AvistaZ) Increase rate limit and use workaround for Retry-After in auth 2023-11-30 01:57:32 +02:00
Bogdan
a0d0e3e232 Fixed: (OPS) Use canUseToken for download links when using Use Freeleech Tokens 2023-11-29 08:22:17 +02:00
Bogdan
e12cd68772 Fixed: (RED/OPS) Add log score to release titles 2023-11-29 08:18:24 +02:00
Bogdan
9dc117191e Minor cleanup for BTN 2023-11-28 09:22:13 +02:00
Bogdan
fdaca64d60 Fixed: (BTN) Add MST, indexer flags and parse IMDb ID 2023-11-28 03:54:47 +02:00
Bogdan
6d134750ff New: (Redacted) Add Freeload Only option 2023-11-27 12:06:18 +02:00
Bogdan
bbf9945b49 Add missing CSS typing 2023-11-27 05:34:03 +02:00
Bogdan
b66a85269f Add color to links in info inputs 2023-11-27 03:02:03 +02:00
Bogdan
81e9c29d54 Bump version to 1.11.0 2023-11-26 22:46:36 +02:00
Weblate
3df33e1a86 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
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/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-11-25 22:32:05 +02:00
Stevie Robinson
c19802c471 New: Remove defunct Boxcar notifications
(cherry picked from commit c6ad2396bb98dc8eb1ad47bf5d066b227a47f8b5)
2023-11-25 22:27:12 +02:00
Bogdan
36c8806f88 New: Add Freeleech Only for HDS, iS and XS 2023-11-25 22:22:56 +02:00
Bogdan
0d69a42ae0 Fix Localization test 2023-11-25 05:59:03 +02:00
Stevie Robinson
fc482d4808 Fixed: Fallback to English translations if invalid UI language in config
(cherry picked from commit 4c7201741276eccaea2fb1f33daecc31e8b2d54e)
2023-11-25 05:30:23 +02:00
Mark McDowall
fab4bd5ead Initial support to use named tokens for backend translations
(cherry picked from commit 11f96c31048c2d1aafca0c91736d439f7f9a95a8)
2023-11-25 05:18:48 +02:00
Bogdan
9c243c7e0d Fixed: (Redacted) Treat freeload torrents as neutral leech
Towards #1933
2023-11-24 22:36:40 +02:00
Bogdan
c107011659 Use album year in Redacted/Orpheus 2023-11-24 22:35:56 +02:00
Bogdan
c690e9a50a New: Add NeutralLeech to indexer flags 2023-11-24 22:31:00 +02:00
Bogdan
c4b0ecdafe Bump dotnet to 6.0.25 2023-11-23 23:44:05 +02:00
Bogdan
f2a709f725 Remove OZnzb from default definitions
Fixes #1932
2023-11-23 23:09:04 +02:00
Bogdan
01a9799ce8 BB has shutdown 2023-11-23 05:53:52 +02:00
Bogdan
8ac68e8946 Fixed: (Cardigann) Use of the default value for new select settings
Fixes #1929
2023-11-23 04:11:56 +02:00
Bogdan
6cb787c17b Fix title in tests 2023-11-22 07:57:37 +02:00
Bogdan
51259ceb30 Fixed: (HDBits) Enable Use Filenames by default 2023-11-22 07:26:43 +02:00
Weblate
92cf329174 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>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translation: Servarr/Prowlarr
2023-11-21 17:49:53 +02:00
Bogdan
257c9ab248 Return 429 right away after release search 2023-11-20 02:38:26 +02:00
Servarr
cad42fd005 Automated API Docs update 2023-11-19 22:39:39 +02:00
Bogdan
d7927f60fe Cleanup appName tokens
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>
2023-11-19 22:32:43 +02:00
Mark McDowall
26a657fa77 New: Require password confirmation when setting or changing password
(cherry picked from commit b248163df598dc611ee919d525eb7357256d73d5)
2023-11-19 22:20:29 +02:00
Mark McDowall
7fa4daae9b Fixed: Disable SSL when using the removed SslCertHash configuration
(cherry picked from commit d95660d3c78d1ee11a7966d58e78a82a8df01393)
2023-11-19 22:18:32 +02:00
Stevie Robinson
e1b063eaa5 Fixed: Replacing 'appName' translation token
(cherry picked from commit 2e51b8792db0d3ec402672dc92c95f3cb886ef44)
2023-11-19 22:17:28 +02:00
Bogdan
75f00436ec Bump version to 1.10.5 2023-11-19 07:05:56 +02:00
Bogdan
343d7088c9 Fixed: Don't die on info indexer when the definition is missing 2023-11-19 01:36:50 +02:00
Bogdan
709dfe453b Fix AB tests 2023-11-18 06:08:12 +02:00
Bogdan
3130fac106 New: (AnimeBytes) Filter old releases on RSS 2023-11-18 05:07:10 +02:00
Weblate
28004dfae1 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Dlgeri123 <bornemiszageri@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Jhonata da Rocha <jhonata182@gmail.com>
Co-authored-by: Jordy <prive@jordyhoebergen.nl>
Co-authored-by: LandonLi <lxx4work@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: hpoon <henry.yh.poon@gmail.com>
Co-authored-by: jianl <jianjianfengyun@126.com>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-11-18 03:13:20 +02:00
Bogdan
9b34c89bc8 Fixed: Enforce validation warnings when testing providers
(cherry picked from commit c3b4126d0c4f449a41e2cf7ea438b20e25370995)
2023-11-17 05:26:04 +02:00
Mark McDowall
28e90acd0d Rename 'ReturnUrl' to 'returnUrl' for forms auth redirection
(cherry picked from commit 812712e2843a738054c065a6d5c1b7c81c5f8e7b)
2023-11-17 05:25:41 +02:00
Erik P
9d11d7e17f Fixed: (PTP) Add IMDb ID to TV Search capabilities (#1920)
Co-authored-by: Erik Persson <erik@erikpersson.me>
2023-11-16 19:33:53 +02:00
Bogdan
2cbdb5bcba New: (HDBits) Add Use Filenames option 2023-11-16 18:50:24 +02:00
Bogdan
118bfb8c28 Fixed: (AvistaZ) Increase rate limit to 5 seconds 2023-11-16 18:50:20 +02:00
Bogdan
942477ecf9 Fixed: (HDBits) Add labels for codecs and mediums 2023-11-14 17:21:07 +02:00
Bogdan
4b4589ed27 Improvements to download factor and show Freeleech only for HDB 2023-11-13 16:23:10 +02:00
Bogdan
bd0609639e New: (HDBits) Add pagination support 2023-11-13 02:54:28 +02:00
Bogdan
ccdad3a44c Bump version to 1.10.4 2023-11-12 16:49:35 +02:00
Bogdan
d99da0481b Fix AvistaZ tests 2023-11-12 15:22:35 +02:00
Bogdan
da1965b18e Fixed: (AvistaZ) Fix PublishDate timezone
Fixes #1917
2023-11-12 14:58:56 +02:00
Bogdan
493114f4e8 Fixed: Record status for notifications on tests 2023-11-10 05:34:15 +02:00
Mark McDowall
6969326092 Don't store status results for invalid providers
(cherry picked from commit de23182d593e2284972103d505e66dd8d812dfdb)
(cherry picked from commit 44d8dbaac81706691124ae5f8317289f0a3e5d73)
2023-11-10 04:01:04 +02:00
Bogdan
95f899131d Fix count in OrpheusFixture 2023-11-07 15:38:49 +02:00
Bogdan
0ba4f3e692 Fixed: (Orpheus) Filter old releases on RSS 2023-11-07 15:03:50 +02:00
Bogdan
a7c00a0fd7 Fixed: (Redacted) Filter old releases on RSS 2023-11-07 15:03:49 +02:00
Bogdan
c84ff60ec9 Fixed: (PTP) Add TV search capabilities 2023-11-05 21:00:24 +02:00
Bogdan
b3f6f54e6e Fixed: (PTP) Add support for TV searches 2023-11-05 20:53:21 +02:00
Bogdan
ed272aaf74 Increase the timeout for CheckHealth command 2023-11-05 20:17:02 +02:00
Bogdan
c0b10f889b Prevent NullRef on header assert 2023-11-05 19:58:30 +02:00
Bogdan
bbfb92bbd8 Bump version to 1.10.3 2023-11-05 11:10:44 +02:00
Bogdan
793de05e3d Fixed: (Beyond-HD) Types filtering 2023-11-04 17:36:01 +02:00
Bogdan
1b1f9d16be Remove default definitions for dead indexers 2023-11-04 16:30:40 +02:00
Bogdan
051dea30c2 Fixed: (Beyond-HD) Category filtering 2023-11-04 16:27:39 +02:00
Bogdan
75d8a3d1d0 Fixed: (FileList) Change TZ to account DST 2023-11-02 19:40:38 +02:00
Bogdan
edf41e2ead Bump version to 1.10.2 2023-10-29 10:35:43 +02:00
Bogdan
c15c71386d New: Set busy timeout for SQLite
(cherry picked from commit 192eb7b62ae60f300a9371ce3ed2e0056b5a1f4d)
2023-10-29 01:28:13 +03:00
Bogdan
71a19efd9a Improve appearance of info fields 2023-10-27 20:54:50 +03:00
Bogdan
2c6c0fcc81 Allow 0 as value in download client Id validation 2023-10-25 17:11:48 +03:00
Bogdan
203e2dbb10 Remove mandatory validation for download client in indexers 2023-10-25 16:24:30 +03:00
Bogdan
6169fc2fa3 New: Add Download Client validation for indexers 2023-10-25 15:55:38 +03:00
Bogdan
768ce14afb Fix integration tests for indexers 2023-10-25 14:17:22 +03:00
Servarr
31d32e8c30 Automated API Docs update 2023-10-25 13:38:07 +03:00
Bogdan
7a61761b2b Add schema endpoint for app profiles 2023-10-25 13:25:16 +03:00
Bogdan
3963807c96 New: Add App Profile validation for indexers
Fixes #1903
2023-10-25 13:04:02 +03:00
Bogdan
e0f6726a3d Fixed: Detect Raw search in Generic Torznab/Newznab feeds
Fixes #1895
2023-10-25 11:51:31 +03:00
Weblate
dd25bff3d6 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dlgeri123 <bornemiszageri@gmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Jhonata da Rocha <jhonata182@gmail.com>
Co-authored-by: LandonLi <lxx4work@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: hpoon <henry.yh.poon@gmail.com>
Co-authored-by: jianl <jianjianfengyun@126.com>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-10-25 11:26:16 +03:00
Jordy
d834c4292e Update link to Docker instructions in readme (#1905) 2023-10-25 11:16:13 +03:00
Bogdan
7e8272ec2b Bump version to 1.10.1 2023-10-22 09:32:32 +03:00
Bogdan
62548f32fe Fixed: (FileList) Skip ID searches for daily episodes 2023-10-21 12:46:50 +03:00
Bogdan
db9f061564 Return TV category if season/episode detected in title for PTP 2023-10-20 00:13:55 +03:00
Bogdan
b37d8799a0 Add acronym for PrivateHD 2023-10-16 18:45:06 +03:00
DaftFuzz
4366530409 Fixed: Calculating value for peers filter (#1900)
Co-authored-by: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-10-16 18:21:40 +03:00
Bogdan
c7959f735e Bump version to 1.10.0 2023-10-15 21:46:33 +03:00
Gabe
be3ee00e1f Fixed: Remove Defunct Tracker PirateTheNet
PTN closed down for good.

They had an official announcement to close down on the 14th October.

Aither offered to accept refugees. See /forums/topics/2535 on aither for more context.
Description

The definition is no longer needed as the tracker ceased all operation.
2023-10-15 19:22:06 +03:00
Bogdan
dace1982d6 Fixed: (FileList) Use air date in search query 2023-10-15 17:44:50 +03:00
Bogdan
980bd35f95 Revert dependencies update 2023-10-14 15:34:41 +03:00
Bogdan
4b2f81bee8 Update postcss, webpack and core-js 2023-10-14 15:19:56 +03:00
Bogdan
30eb481c65 Add year to releases for AnimeBytes 2023-10-14 10:17:54 +03:00
Bogdan
29f1c36f54 Prevent NullRef in Nebulance with null TvMazeIds 2023-10-13 18:55:04 +03:00
Bogdan
f1c01343bf New: (Nebulance) Parse TvMazeId and scene attributes 2023-10-13 14:27:32 +03:00
Weblate
bae79b22ad Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: DavidHenryThoreau <sorau@protonmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translation: Servarr/Prowlarr
2023-10-13 11:55:11 +03:00
Bogdan
229d879f86 New: Show indexer categories in Add Indexer modal 2023-10-13 09:39:51 +03:00
bakerboy448
d1cee950a4 Fixed: New Indexer URL for DICMusic 2023-10-13 04:21:09 +03:00
Bogdan
7e32b54547 Fixed: Prevent NullRef in NewznabRequestGenerator for missing definition 2023-10-12 06:50:13 +03:00
Bogdan
b1f7d30021 Fixed: Ignore case when cleansing announce URLs 2023-10-12 05:10:26 +03:00
Mark McDowall
c41a7e0ccc Fixed: Duplicate notifications for failed health checks
(cherry picked from commit c0e54773e213f526a5046fa46aa7b57532471128)

Mock debouncer for testing

(cherry picked from commit bb7b2808e2f70389157408809ec47cc8860b4938)
2023-10-11 03:34:18 +03:00
Weblate
42c533386b Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Timo <Tclemens@live.com>
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/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-10-11 02:52:16 +03:00
Servarr
bdae7a2cdc Automated API Docs update 2023-10-11 02:51:54 +03:00
Mark McDowall
5e8d3542f4 Log executing health check
(cherry picked from commit 78b39bd2fecda60e04a1fef17ae17f62bd2b6914)
2023-10-11 02:33:38 +03:00
Mark McDowall
d9d2aa8493 Sync label styling for FormLabel
(cherry picked from commit 87e0a7983a437a4d166aa8b9c9eaf78ea5431969)
2023-10-11 02:30:18 +03:00
Stevie Robinson
09bf1500d6 New: Additional tooltips for icon buttons
(cherry picked from commit 8c07f0d3d19a48ed96d1ded54399c66bf2977b2a)
2023-10-11 02:24:32 +03:00
Mark McDowall
34464160cb Paging params in API docs
(cherry picked from commit bfaa7291e14a8d3847ef2154a52c363944560803)
2023-10-11 02:17:27 +03:00
Bogdan
bada5fe309 New: Add TorrentNetwork 2023-10-10 13:29:26 +03:00
Bogdan
b088febbc4 Use async for http client test 2023-10-10 03:05:16 +03:00
Bogdan
1a307b8e21 Fix test for http client 2023-10-10 03:02:35 +03:00
Bogdan
32db2af0ea Improved http timeout handling
Co-authored-by: Qstick <qstick@gmail.com>
2023-10-10 02:41:05 +03:00
Bogdan
e602862102 Fixed: (FileList) Remove dead domain 2023-10-08 21:31:38 +03:00
Bogdan
bd5336e4c4 Bump version to 1.9.4 2023-10-08 07:08:25 +03:00
Mark McDowall
c664eaa9b5 New: Don't treat 400 responses from Notifiarr as errors
(cherry picked from commit 5eb420bbe12f59d0a5392abf3d351be28ca210e6)
2023-10-07 23:02:44 +03:00
Bogdan
b7e57f0c08 Fixed: (Nebulance) Filter releases by season and episode for ID based searches 2023-10-07 03:09:44 +03:00
Bogdan
c06bf0e4ea Fixed: (TorrentDay) Update categories
Fixes #1888
2023-10-05 22:41:59 +03:00
Bogdan
c6db30c35a Parse description in RSS Parser 2023-10-05 01:54:40 +03:00
Bogdan
75c30dd318 Add year to XML results 2023-10-04 19:51:49 +03:00
Bogdan
6e7bf55dbd Add poster URL to PassThePopcorn 2023-10-04 19:16:55 +03:00
Bogdan
eb642dd2f9 Fix document being disposed before returning 2023-10-04 18:36:31 +03:00
Bogdan
19a196e2c7 Ensure the correct use of disposable parsed documents 2023-10-04 18:11:23 +03:00
Weblate
93ec6cf89b Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dimitri <dimitridroeck@gmail.com>
Co-authored-by: Garkus98 <ivan12061998@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: RicardoVelaC <ricardovelac@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-10-04 07:00:00 +03:00
Bogdan
52c6b56a4c Cleanup BooleanConverter to STJson 2023-10-04 05:19:03 +03:00
Bogdan
82688d8a55 Use ExecuteAuth in AvistazBase 2023-10-04 04:27:04 +03:00
Bogdan
c81cbc801a Fixed: (AvistaZBase) Parse response with STJson
Also ensure GetToken is using a proxied request and rate limit
2023-10-04 02:27:32 +03:00
Bogdan
993d189c61 Fixed: (Nebulance) Parse response with STJson 2023-10-04 02:27:29 +03:00
Bogdan
1901af5a51 Fixed: (BeyondHD) Parse response with STJson 2023-10-04 02:27:24 +03:00
Bogdan
c1b399be39 Fixed: (FileList) Parse response with STJson 2023-10-04 02:27:19 +03:00
Bogdan
2100e96570 Fixed: (PassThePopcorn) Use UTC for publish dates 2023-10-02 04:35:57 +03:00
Bogdan
3ff144421d Fixed: (PassThePopcorn) Cleanup and ensure pagination is working in Radarr 2023-10-02 02:55:34 +03:00
Bogdan
f37ccba3f9 Fixed: (Shizaproject) Title improvements 2023-10-02 00:47:33 +03:00
Bogdan
181cb2e0fe Revert "New: (Orpheus) Add options to prevent downloads without FL tokens"
This reverts commit 93c81bb7d3.
2023-10-01 19:47:28 +03:00
Bogdan
93c81bb7d3 New: (Orpheus) Add options to prevent downloads without FL tokens 2023-10-01 17:03:43 +03:00
Weblate
7dd289b5f9 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Jaspils <jasperkemper@gmail.com>
Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-10-01 17:03:03 +03:00
Bogdan
09cef8cf94 Bump version to 1.9.3 2023-10-01 17:01:35 +03:00
Bogdan
ca08c818e6 Fixed: (TorrentPotato) Use full IMDb Id 2023-09-30 22:41:25 +03:00
Bogdan
3e95bc4056 Fixed: (TorrentPotato) Title not being decoded 2023-09-30 22:15:25 +03:00
ilike2burnthing
e241112915 Fixed: (Shizaproject) Available again 2023-09-29 22:13:14 +03:00
Bogdan
0d98c12fa2 Fix the description for Use Filenames for Single Episodes 2023-09-29 20:45:04 +03:00
Bogdan
a0bcf5c9ae Allow using filename for single episodes along with generated titles in AnimeBytes 2023-09-29 20:26:35 +03:00
Bogdan
e318a47b3a Extend the torrent settings interface in TorrentPotato settings class 2023-09-27 23:23:43 +03:00
Bogdan
b8df720c6c Bump version to 1.9.2 2023-09-24 16:22:57 +03:00
Bogdan
9625be723d Fixed: (Search) Releases deduplication 2023-09-22 19:54:11 +03:00
Bogdan
d4b037db78 New: (AlphaRatio) Add pagination support 2023-09-21 20:46:34 +03:00
Bogdan
add2988789 Fixed: (Cardigann) Fallback variables to empty string to prevent NullRef 2023-09-20 02:54:25 +03:00
Bogdan
9869c2272a Avoid returning null in static resource mapper Task 2023-09-19 20:17:05 +03:00
Bogdan
4c8b0c9eec Fixed: Ignore releases without title 2023-09-19 14:06:15 +03:00
Bogdan
43cb22ff2b Bump migration timeout to 10 minutes 2023-09-19 00:57:06 +03:00
Bogdan
3cabc0589a Simplify use the group name when the release name is empty 2023-09-18 21:17:36 +03:00
Bogdan
cdb3ed36f6 Fixed: (Nebulance) Use the group name when the release name is empty 2023-09-18 21:16:13 +03:00
Bogdan
840f2ae3e6 Sync static resource controller with upstream
(cherry picked from commit ad1f185330a30a2a9d27c9d3f18d384e66727c2a)
2023-09-18 03:53:14 +03:00
Bogdan
3ed6ef0336 Use await on reading the response content
(cherry picked from commit 82d586e7015d7ea06356ca436024a8af5a4fb677)
2023-09-18 03:49:31 +03:00
Bogdan
c2ae0cce03 Bump version to 1.9.1 2023-09-17 12:01:01 +03:00
Weblate
934b908b37 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: stormaac <yxc.frank@gmail.com>
Co-authored-by: 宿命 <331874545@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-09-16 08:51:49 -04:00
Weblate
6c831f11a6 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: leotpp <yangdom_li@126.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2023-09-15 21:49:25 -05:00
Bogdan
9adbfd2391 Return 1 seeder as fallback only in Torrent RSS Feed 2023-09-14 21:48:32 +03:00
bakerboy448
4a7cc82f0d Correction to Improve tags helptext and add warnings 2023-09-14 20:56:24 +03:00
bakerboy448
c061c309bd Improve tags helptext and add warnings 2023-09-14 20:48:28 +03:00
Bogdan
0f3a77c336 Return 1 seeder as fallback in Torrent RSS Feed 2023-09-14 18:55:07 +03:00
Bogdan
478d5a624f Fixed: (Animedia) Removed
Co-authored-by: ilike2burnthing <59480337+ilike2burnthing@users.noreply.github.com>
2023-09-14 18:42:41 +03:00
Bogdan
3283d144f5 Ignore invalid cookies when adding response cookies to CookieContainer
Fixes #1868
2023-09-14 18:22:53 +03:00
Bogdan
1a9ec4febd Fixed: (Apps) Check if the indexers have valid settings 2023-09-14 17:50:54 +03:00
Bogdan
0598211319 Fixed: Ignore inaccessible mount points
(cherry picked from commit 60f18249b05daa20523542beef54bc126d963d1e)
2023-09-14 12:15:37 +03:00
Bogdan
0b0d6b7590 Fixed: (SubsPlease) Update category mappings for movie releases
Co-authored-by: Lemres <45440100+Calemy@users.noreply.github.com>

Fixes #1866
2023-09-13 12:30:06 +03:00
Servarr
86cec51ebe Automated API Docs update 2023-09-12 22:59:27 +03:00
Bogdan
80e5ac4aa9 New: Add custom filter by protocol for indexer stats 2023-09-12 15:25:48 +03:00
Bogdan
ee5ed0c91b Sonarr > Prowlarr 2023-09-11 11:59:51 +03:00
Denis Gheorghescu
ba278930ed New: Pushcut notifications
(cherry picked from commit 5f09f2b25f9144666b8e5182e20e263e74d5f5ca)
2023-09-11 11:57:35 +03:00
Mark McDowall
6449b89eb6 Fixed parsing of multiple languages from Newznab indexer releases
(cherry picked from commit 2a241294b5eeb9e95c46e030828191da09d05e88)
2023-09-11 11:29:07 +03:00
Weblate
73b85e240e 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>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2023-09-10 20:30:01 +03:00
Bogdan
6338460ff4 Bump version to 1.9.0 2023-09-10 19:09:26 +03:00
Bogdan
0463e66881 Rename ISearchForNzb to IReleaseSearchService 2023-09-10 11:19:17 +03:00
Bogdan
bd75621437 Update magnet trackers 2023-09-10 09:46:39 +03:00
Weblate
9615c1183d Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translation: Servarr/Prowlarr
2023-09-10 08:33:44 +03:00
Weblate
bbf042ed55 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: 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/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-09-10 00:31:50 -05:00
Bogdan
98e948dbb2 Fix indexer flags column label 2023-09-09 14:15:58 +03:00
Bogdan
2af9f7eb8d Fixed: macOS version detection
(cherry picked from commit 060be6177a5477c94823e6a423c42064dedc1afb)
2023-09-08 05:10:05 +03:00
Bogdan
96413f99c7 New: Add hour as interval unit for indexer limits 2023-09-06 17:08:33 +03:00
Bogdan
d44b946d30 Add hourly limits as defaults for FL and BTN 2023-09-06 17:08:33 +03:00
Bogdan
fe9cad5697 Move clone button to the left 2023-09-04 11:00:37 +03:00
Servarr
098be3cff6 Automated API Docs update 2023-09-04 07:03:50 +03:00
Bogdan
8f2fea0be8 Fixed: (Nebulance) Add fallback TV search without season/episode 2023-09-04 06:58:24 +03:00
Qstick
8d035c6c1f New: Add support for MaxAge to Newznab API 2023-09-03 22:36:11 -05:00
Bogdan
7dbfa74c40 Add external links for indexer history 2023-09-04 05:53:33 +03:00
Qstick
caaf50ed9c New: Save categories to history for grabs 2023-09-03 20:30:44 -05:00
Bogdan
b472a022a6 Add history parameters to indexer history 2023-09-04 04:12:56 +03:00
Qstick
0a439a4a96 Show all queries in Total Queries block 2023-09-03 20:11:58 -05:00
Bogdan
4410636b97 Use method group in History controller 2023-09-04 02:22:23 +03:00
Servarr
ba3ebc7574 Automated API Docs update 2023-09-04 02:14:55 +03:00
Bogdan
2ce49a0785 Migrate to merged proposals now included in babel/present-env
Bump core-js too.
2023-09-04 02:09:04 +03:00
Qstick
d7df946c2b New: Summary Stats 2023-09-03 18:04:39 -05:00
Qstick
3dd3c80b54 New: Indexer history in indexer info modal 2023-09-03 18:04:39 -05:00
Qstick
0f160707d3 Chart style updates 2023-09-03 18:04:39 -05:00
Qstick
b608e38454 New: Custom Filters for Stats 2023-09-03 18:04:39 -05:00
Bogdan
c873b3ffac New: (UI) Add clone indexer in info modal 2023-09-03 23:08:15 +03:00
Bogdan
07b98f4137 Move scene flag to TorrentInfo and return tag in response 2023-09-03 23:07:59 +03:00
Bogdan
09606af351 Bump dotnet to 6.0.21 2023-09-03 10:33:50 -05:00
Bogdan
1d79b92fca Bump version to 1.8.6 2023-09-03 07:26:15 +03:00
Stevie Robinson
fbcf1b03c5 Translate Frontend Store
(cherry picked from commit d31fcbb2dfe98a540a359b98b204d101d554cf03)
2023-09-02 06:04:57 +03:00
Bogdan
dee98ac46f Display a not allowed cursor for disabled select options 2023-09-02 03:47:07 +03:00
Bogdan
4267b8a244 Cleanse API Keys from sync requests sent to applications 2023-09-02 02:07:26 +03:00
Bogdan
00dc55996c Remove Label and Unit columns from Apps Fields 2023-09-02 01:59:11 +03:00
Bogdan
b912cc6110 Some logging improvements for filtered releases
Closes #1847
2023-09-02 00:47:47 +03:00
Bogdan
56f0c137f8 Fixed translations for history parameters 2023-09-01 15:50:22 +03:00
Bogdan
1b8ff9b989 Simplify user check in Authentication Required for newer installs 2023-08-29 19:12:06 +03:00
Bogdan
bfecf35a8b Fix user check in Authentication Required for newer installs 2023-08-29 18:56:21 +03:00
Bogdan
80da5ce165 Add missing app name token for translation 2023-08-29 03:18:11 +03:00
Bogdan
60ca0db26f Improve messaging in Authentication Required modal
Co-authored-by: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-08-29 03:09:42 +03:00
Bogdan
288a3d1495 Fix loading translations 2023-08-29 03:05:51 +03:00
Weblate
4c42907eb2 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: 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/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-08-27 19:21:30 +03:00
Bogdan
6300eb1442 Bump version to 1.8.5 2023-08-27 08:00:53 +03:00
Bogdan
e4c0edf24c Remove Reddit from issue templates 2023-08-26 21:14:23 +03:00
Bogdan
74a9fa784a Fixed: (Nebulance) Detect TV UHD releases 2023-08-26 20:21:41 +03:00
ilike2burnthing
1b0c9adf24 Remove Reddit from issues config 2023-08-22 00:30:49 +03:00
Bogdan
0eaa538e8a Allow deselecting values when using search through url query params 2023-08-21 21:32:26 +03:00
Bogdan
39a54eb8f6 Prevent health checks warnings for disabled notifications 2023-08-21 21:04:30 +03:00
Bogdan
5ad6237785 Improve music and console search results for AnimeBytes
Also prevent duplicate categories showing in the indexer info modal
2023-08-21 18:08:43 +03:00
Bogdan
9fee4f914f Bump version to 1.8.4 2023-08-20 12:23:24 +03:00
Weblate
ba2aab6bb3 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Fixer <ygj59783@zslsz.com>
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>
Co-authored-by: w2861 <hfagfc@163.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-08-20 03:52:43 +03:00
Bogdan
5c8ae82f11 Prevent useless builds 2023-08-19 16:23:16 +03:00
Servarr
bcbeac1e83 Automated API Docs update [skip ci] 2023-08-19 13:55:35 +03:00
Mark McDowall
b36d793d85 Allow decimals in number inputs
(cherry picked from commit 7f5ddff568ce9f87bd45420cbd36690b190bd633)
2023-08-19 13:49:18 +03:00
Mark McDowall
b0162ccc5b New: Success check mark on blue buttons is now white instead of green
(cherry picked from commit 566fae9d5857a10bd69c718368e7847e5a733faa)
2023-08-19 13:47:56 +03:00
Robin Dadswell
f0892eb4b8 Adds Pipeline testing for Postgres15 Databases 2023-08-18 21:12:09 +03:00
Robin Dadswell
e456979467 bump Npgsql to 7.0.4 2023-08-18 21:12:09 +03:00
Bogdan
66ca47b615 Fix flaky automation tests 2023-08-18 20:36:44 +03:00
Weblate
2b7771bfe0 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Fixer <ygj59783@zslsz.com>
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>
Co-authored-by: w2861 <hfagfc@163.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-08-18 11:40:45 +03:00
Mark McDowall
955bc472a1 Fixed: Hidden files being ignored
(cherry picked from commit d493f8762fcb1684b44e182753c21d7a493db787)
2023-08-18 11:33:21 +03:00
Bogdan
e024bba6b6 Replace docker detection for cgroup v2
(cherry picked from commit 78d4dee4610c5f3f90cc69469004008aa64900b8)
2023-08-18 11:32:39 +03:00
Bogdan
aeb3b7d8b5 Add retry to flaky automation tests 2023-08-17 14:38:48 +03:00
bakerboy448
a7b25b8b93 Remove reddit from readme 2023-08-16 17:25:12 +03:00
Qstick
130257fdd4 New: Notifications (Connect) Status
(cherry picked from commit e3545801721e00d4e5cac3fa534e66dcbe9d2d05)
2023-08-14 16:07:23 +03:00
Qstick
b618f23bc0 Cleanup other provider status code
(cherry picked from commit c281a7818adce8db728d2a104f4444cb9c0baf2c)
2023-08-14 16:07:23 +03:00
Bogdan
a758161e31 New: Default name when adding providers 2023-08-14 16:07:23 +03:00
Weblate
27928103c5 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translation: Servarr/Prowlarr
2023-08-14 14:06:06 +03:00
Weblate
d5b3961e8a 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>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translation: Servarr/Prowlarr
2023-08-14 13:48:57 +03:00
Stevie Robinson
307adf053e Translate Updated and Connection Lost Modals in frontend
(cherry picked from commit 074aa6f4457bf83173e6ba7209c452a6e0659a35)
2023-08-14 01:22:09 +03:00
Bogdan
31261f66ad Use named tokens in frontend translate function 2023-08-13 22:59:56 +03:00
Bogdan
5dbb59dfaa Bump version to 1.8.3 2023-08-13 13:04:41 +03:00
Weblate
25c1803d0e Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Nir Israel Hen <nirisraelh@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: wilfriedarma <wilfriedarma.collet@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translation: Servarr/Prowlarr
2023-08-13 12:51:24 +03:00
Bogdan
9f4c9d3344 Show successful grabs in Search with green icon 2023-08-12 12:12:51 +03:00
Bogdan
dfb00d9bb1 Fixed: Ensure grab notifications are sent according to tags requirements 2023-08-12 12:07:17 +03:00
Bogdan
f7727855b5 Rework adding one minute back-off level for all providers
(cherry picked from commit d8f314ff0ef64e8d90b21b7865e46be74db5e570)
2023-08-12 09:32:07 +03:00
Stepan Goremykin
1e4c67dcdb Update FluentAssertions
(cherry picked from commit 951a9ade00d7c9105f03608cb598450d706b826f)
2023-08-12 09:28:42 +03:00
Robin Dadswell
26afcb0071 Fixed: PostgreSQL timezone issues
(cherry picked from commit d55864f86914199aa0c4ee37df1e42e6ad71ef4f)
2023-08-10 23:03:27 +01:00
Bogdan
7a937e85a4 Fixed: Retain user settings not-affiliated with Prowlarr 2023-08-10 18:05:00 +03:00
Bogdan
7cd82321b4 Bump Npgsql version to 6.0.9
Fixes #1819
2023-08-09 23:41:09 +03:00
Bogdan
8c9adba516 Fixed color for links 2023-08-09 19:30:25 +03:00
Bogdan
03fa9254e3 Prevent NullRef in IsPathValid for null paths 2023-08-09 13:35:13 +03:00
Weblate
e66ecf5c95 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: byakurau <byakurau1@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-08-08 18:49:41 +03:00
Bogdan
e0dddfa215 Remove Order and Help columns from Apps Fields 2023-08-08 18:30:25 +03:00
Bogdan
bcb8afadf8 New: Add Content Summary for requests to apps 2023-08-08 18:26:09 +03:00
Bogdan
fc4a0979c3 Fixed: Detect Docker when using control group v2 2023-08-07 19:15:21 +03:00
Bogdan
5f643b2ced Fixed: (Indexers) Don't fetch releases when using unsupported capabilities 2023-08-06 20:30:59 +03:00
Bogdan
6f09b0f4f5 Bump version to 1.8.2 2023-08-06 08:42:24 +03:00
Qstick
95c2531107 Filter user issues from Sentry
(cherry picked from commit 03d361f5537bfc0caba1b86085f974570942fdbc)
2023-08-05 21:38:44 +03:00
Bogdan
f83828cc22 Fixed border for actions in health status 2023-08-05 17:56:13 +03:00
Bogdan
cdea548ce2 New: Add internal links for apps and download clients health checks 2023-08-05 14:26:53 +03:00
Bogdan
cae1da0ce2 Fixed: (Apps) Lower the severity for testing messages 2023-08-05 14:12:06 +03:00
Bogdan
765f354c51 New: Add test all action for apps and download clients to status health 2023-08-05 14:11:50 +03:00
Bogdan
5cbbffb018 Fix translation typo in sync level options 2023-08-05 14:11:50 +03:00
Bogdan
b2c5448cbf Fixed: Run health checks for applications and download clients on bulk events 2023-08-05 11:40:15 +03:00
Bogdan
3dae84705c Fixed: Ensure failing providers are marked as failed when testing all 2023-08-05 10:02:55 +03:00
Weblate
2321d278d6 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Albert <zuozl1992@foxmail.com>
Co-authored-by: Fixer <ygj59783@zslsz.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Ivan Mazzoli <dreadtank27@gmail.com>
Co-authored-by: Magnus <magnus.fladvad@gmail.com>
Co-authored-by: Stjepan <stjepstjepanovic@gmail.com>
Co-authored-by: Thirrian <matthiaslantermann@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: stormaac <yxc.frank@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-08-04 21:07:31 +03:00
TwentyNine78
ea73466f6a Fixed: Compatibility with the new Download Station API
(cherry picked from commit 49e90463e57929e7b9885f1b7b0eb05bd7cc3ebe)
2023-08-04 21:06:45 +03:00
Bogdan
6961c5a1c6 Fixed: (AlphaRatio) Use FL tokens only if canUseToken is true
Fixes #1811
2023-08-04 17:20:28 +03:00
Mark McDowall
141f1597dc New: Ignore inaccessible files with getting files
(cherry picked from commit e5aa8584100d96a2077c57f74ae5b2ceab63de19)
2023-08-04 13:17:37 +03:00
Bogdan
1100f350ae Fix translations for option values 2023-08-04 07:05:31 +03:00
Bogdan
3c5eefc349 New: Health check for indexers with invalid download client
(cherry picked from commit 377fce6fe15c0875c4bd33f1371a31af79c9310c)
2023-08-04 06:50:48 +03:00
Mark McDowall
0bfb557470 Prevent NullRef in ContainsInvalidPathChars
(cherry picked from commit 5f7217844533907d7fc6287a48efb31987736c4c)
2023-08-04 06:43:40 +03:00
Servarr
c93d6cff63 Automated API Docs update [skip ci] 2023-08-03 17:40:31 +03:00
Bogdan
7e4980b855 New: Add translations for columns 2023-08-03 17:20:36 +03:00
Bogdan
419ef4b3bf New: More translations for columns
(cherry picked from commit aee8579d1823b7dfb94c0055fe33b5fb5a7fbf17)
2023-08-03 16:10:13 +03:00
Mark McDowall
c56d49ab60 Fixed: Translations for columns
(cherry picked from commit 6d53d2a153a98070c42d0619c15902b6bd5dfab4)
2023-08-03 16:07:00 +03:00
Mark McDowall
1a40924db3 Fixed: Improve translation loading
(cherry picked from commit 73c5ec1da4dd00301e1b0dddbcea37590a99b045)
2023-08-03 16:05:39 +03:00
Mark McDowall
d55906d49a UI loading improvements
Fixed: Caching for dynamically loaded JS files
Fixed: Incorrect caching of initialize.js
(cherry picked from commit f0cb5b81f140c67fa84162e094cc4e0f3476f5da)
2023-08-03 15:57:52 +03:00
Bogdan
bc53fab966 Fixed: Don't fetch capabilities for disabled Newznab/Torznab indexers on create
Also prevent NullRef in GetProxy since definition is null when using FetchCapabilities on add
2023-08-02 14:54:01 +03:00
Bogdan
d897b50f80 New: (UI) Show Magnet Link in search results if any 2023-08-01 13:29:12 +03:00
Bogdan
cc66cee71c Fixed: (Apps) Avoid force saving remote indexers when it's not necessary 2023-07-31 10:33:57 +03:00
Bogdan
f5e96f3f51 Ensure yarn packages are installed when running only LintUI 2023-07-31 08:18:45 +03:00
Mark McDowall
d52e1259a1 Re-order frontend build steps
(cherry picked from commit 97ad6682f7d54af8886144bc5a179fa7242f1f1f)
2023-07-31 07:56:20 +03:00
Bogdan
72e6d66269 New: (Apps) Add force sync indexers for applications 2023-07-31 07:22:08 +03:00
Bogdan
e51b85449d Convert store selectors to Typescript 2023-07-30 21:06:44 +03:00
Bogdan
efd5e92ca5 Support categories with Transmission 2023-07-30 12:38:33 +03:00
Bogdan
d153746a98 Bump version to 1.8.1 2023-07-30 10:45:08 +03:00
Bogdan
a1927e1e0f Sort indexers by name in search footer dropdown 2023-07-29 13:48:10 +03:00
Bogdan
630a4ce800 Fixed: Ensure failing indexers are marked as failed when testing all
(cherry picked from commit b407eba61284d5fb855df6a2868805853aa6f448)
2023-07-29 12:14:58 +03:00
Bogdan
8b1dd78300 Fixed: (Apps) Ensure populated capabilities for Torznab/Newznab definitions 2023-07-29 12:08:48 +03:00
Bogdan
cab50b35aa Convert some selectors to Typescript 2023-07-29 03:14:47 +03:00
Weblate
eee1be784b Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Fixer <ygj59783@zslsz.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translation: Servarr/Prowlarr
2023-07-28 12:55:09 +03:00
Bogdan
269dc5688b New: (IPTorrents) Add new base url 2023-07-27 12:18:49 +03:00
Weblate
9bed795c89 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-07-27 12:14:26 +03:00
Bogdan
3b5f151252 New: Set default names for providers in Add Modals 2023-07-27 02:58:07 +03:00
Weblate
b3a541c9ff Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Dortlix <jeremy.boely@hotmail.fr>
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: aguillement <adrien.guillement@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translation: Servarr/Prowlarr
2023-07-26 07:18:25 +03:00
Bogdan
bc90fa2d3f Add unit to history cleanup days option 2023-07-26 07:17:06 +03:00
Bogdan
4b0a896434 Fixed: (Cardigann) Improvements to automatic logins with captcha 2023-07-26 05:35:42 +03:00
Bogdan
6be0e08635 Convert Delete Indexer to Typescript 2023-07-25 05:50:45 +03:00
Bogdan
f618901048 Convert Indexer Stats to Typescript 2023-07-25 05:50:45 +03:00
Weblate
809ed940e6 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: SHUAI.W <x@ousui.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-07-25 01:05:11 +03:00
Qstick
7b14c2ee66 Bump version to 1.8.0 2023-07-23 23:25:30 -05:00
Qstick
4528d03931 Update Sentry DSN 2023-07-23 21:49:21 -05:00
Bogdan
e0b30d34b1 New: (Apps) Add Go To Application in UI 2023-07-23 22:03:49 +03:00
Bogdan
8edf483e69 Bump version to 1.7.4 2023-07-23 07:09:59 +03:00
Bogdan
cea6aae9e1 Add support for deprecated values in field select options
(cherry picked from commit d9786887f3fe30ef60ad9c50b3272bf60dfef309)
2023-07-23 05:05:41 +03:00
Bogdan
1697cee680 Add hover background color in Indexer Table Index 2023-07-22 05:34:39 +03:00
Bogdan
ce8c90a125 Added magnetUrl prop in Search Index Row 2023-07-22 05:34:39 +03:00
Weblate
c8ad3d6edd Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-07-21 13:25:57 +03:00
Bogdan
ebe01913c2 Fix selecting guids from search results 2023-07-21 10:35:04 +03:00
Mark McDowall
07cb19f9f3 Sort available filters options in custom filters
(cherry picked from commit 9e694c7b06c6d54fd652792fa1d81cc27ec1f311)
2023-07-21 07:40:36 +03:00
Bogdan
7f51c44829 Fixed: (UI) Ensure proper parsing for size values in custom filters 2023-07-21 07:26:43 +03:00
Bogdan
07f816f9fd Fixed: (BeyondHD) Add search types option 2023-07-21 01:24:29 +03:00
Bogdan
a4a50b880c Add GetAttribute for enums 2023-07-21 01:24:29 +03:00
Bogdan
79361d92cb Ensure No search results found isn't shown without a search 2023-07-20 23:05:48 +03:00
Bogdan
ecda75152e Cache busting for CSS files 2023-07-20 19:57:45 +03:00
Bogdan
37a4e7c228 Rename decisions to releases in Search Controller 2023-07-20 19:25:04 +03:00
Bogdan
1a66d23bfe Fixed: (UI) Improved mobile search form and show indexer flags 2023-07-20 19:24:00 +03:00
Bogdan
a26aa4bd1e New: (UI) Show indexer id as hint in IndexerSelect 2023-07-20 18:46:12 +03:00
Bogdan
a5d83459e9 New: (BeyondHD) Add pagination support 2023-07-20 15:54:05 +03:00
Mark McDowall
4bfaab4b21 Typings cleanup and improvements
(cherry picked from commit b2c43fb2a67965d68d3d35b72302b0cddb5aca23)
2023-07-20 14:40:21 +03:00
Bogdan
5764950b10 Show implementation name in Application Modal's header 2023-07-20 14:40:21 +03:00
Mark McDowall
470b57316a Add type number to value prop in HintedSelectInputSelectedValue
(cherry picked from commit fea66cb7bccc7e94523614db38b157fa38f55ea5)
2023-07-20 14:40:21 +03:00
Bogdan
f546b9a3b0 Fixed: (SubsPlease) Update indexer urls 2023-07-20 02:45:07 +03:00
Bogdan
cc28c90e39 Combine cleanse rules for passkey and rsskey 2023-07-20 02:20:55 +03:00
Mark McDowall
6e21e892bc Fix chunk IDs and source map file names
(cherry picked from commit bb8fed94eb2c44040031643e8c20ff72de759535)
2023-07-20 01:03:16 +03:00
Weblate
62d868f0e9 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-07-19 15:08:48 +03:00
Bogdan
27b36fe501 Tidy up input fields on mobile in Add Indexer Modal 2023-07-19 05:35:26 +03:00
Mark McDowall
fc80efd15f Fixed: List jump bar click issues
(cherry picked from commit 9c7378625112088d022239fdbdb90c0dc941d61d)
2023-07-18 23:37:26 +03:00
Bogdan
9b75ba6ca0 New: (BeyondHD) Add internal indexer flag 2023-07-18 04:47:05 +03:00
Bogdan
d42649c4df New: (BeyondHD) Add limited, refund and rewind search options 2023-07-18 04:47:05 +03:00
Bogdan
53adfb750c New: (Shazbat) Add scene indexer flag to all releases 2023-07-18 04:19:41 +03:00
Bogdan
ac487f9b40 Fixed: (BeyondHD) Add search by freeleech only 2023-07-17 20:25:20 +03:00
Bogdan
6dd354bf1a Fixed: (BeyondHD) Searching ImdbId has priority over TmdbId. 2023-07-17 19:40:14 +03:00
Weblate
b747d0a321 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Godwhitelight <godwhitelight1@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Qstick <qstick@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/id/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2023-07-17 06:57:53 +03:00
Weblate
0e6cec6f54 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Godwhitelight <godwhitelight1@gmail.com>
Co-authored-by: Guy Porat <guyporatmail@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translation: Servarr/Prowlarr
2023-07-16 22:54:31 +03:00
Weblate
65cf7c1009 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translation: Servarr/Prowlarr
2023-07-16 19:42:54 +03:00
Weblate
5f9c3585f4 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translation: Servarr/Prowlarr
2023-07-16 19:42:19 +03:00
Weblate
a9d1d4be90 Multiple Translations updated by Weblate
ignore-downstream

Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/
Translation: Servarr/Prowlarr
2023-07-16 19:41:26 +03:00
Weblate
a94ed11b21 Translations update from Servarr Weblate
Co-authored-by: MoowGlax <matthieu.derouet.pro@gmail.com>
Co-authored-by: Thodoris Kalatzis <teo.kal@hotmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: emacsdias <emacs.dias@gmail.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: splifter <a.strahlke@gmail.com>
Co-authored-by: victor22265 <843427709@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-07-16 11:32:06 -05:00
Bogdan
3fab8fb0db Fixed: (Search) Ensure TvMazeId is parsed correctly on a repeat search 2023-07-16 17:04:08 +03:00
Mark McDowall
5e52627799 Fixed: Ensure translations are fetched before loading app
(cherry picked from commit ad2721dc55f3233e4c299babe5744418bc530418)
2023-07-16 08:29:30 +03:00
Bogdan
b9a28f243e Bump version to 1.7.3 2023-07-16 08:14:24 +03:00
Bogdan
146e7ca7b6 Use HelpTexts for sync levels in applications 2023-07-16 07:03:58 +03:00
Bogdan
1488fb7570 Revert "Fixed: Ensure translations are fetched before loading app"
This reverts commit 0fc52ae16f.
2023-07-16 04:07:54 +03:00
Mark McDowall
0fc52ae16f Fixed: Ensure translations are fetched before loading app
(cherry picked from commit ad2721dc55f3233e4c299babe5744418bc530418)
2023-07-16 02:21:39 +03:00
Mark McDowall
5218bea705 Use named keys for apply tags help text
(cherry picked from commit c1f8c7b17ba5775a0f6f76cebc3173e03124d000)
2023-07-16 02:11:34 +03:00
Bogdan
ac33330c7c Fix selection input in QueryParameterModal 2023-07-15 18:20:59 +03:00
Bogdan
041a7c571f Translate url type for indexer description 2023-07-15 18:00:52 +03:00
Bogdan
5d73c6aa91 Update webpack, eslint and core-js 2023-07-15 17:34:54 +03:00
Bogdan
ef9a3a4f2a Fixed: (AvistaZ) Allow search by episode 2023-07-15 17:34:28 +03:00
Bogdan
3ce3f8acdd Fixed: (Apps) Lower the severity for common messages 2023-07-13 06:21:05 +03:00
Bogdan
9bac2992b5 Fixed: (UI) Show available indexers count in Add Indexer 2023-07-13 00:37:57 +03:00
Bogdan
4a88b70f40 Show the correct total of releases when selecting 2023-07-13 00:30:12 +03:00
Bogdan
c9b1d0d958 Fixed: (API) Prevent search failed exception when using non-interactive search 2023-07-12 04:40:17 +03:00
Bogdan
a5b5e7a3a5 Fixed: (UI) Prevent passing NaN values to search API when using invalid ids 2023-07-12 04:34:30 +03:00
Bogdan
376202e2af Fixed: (BTN) Prevent NullRef when Result.Torrents is null 2023-07-11 04:53:43 +03:00
Servarr
6b698b33be Automated API Docs update [skip ci] 2023-07-10 19:23:30 +03:00
Bogdan
1706728230 New: Bulk Manage Applications, Download Clients
Co-authored-by: Qstick <qstick@gmail.com>
2023-07-10 19:17:46 +03:00
Bogdan
cb520b2264 Bump version to 1.7.2 2023-07-09 14:59:01 +03:00
ricci2511
193335e2a8 New: Add support for search through url query params 2023-07-09 01:19:05 +03:00
Servarr
1c98727cf3 Automated API Docs update [skip ci] 2023-07-08 19:19:02 +03:00
Bogdan
ab5b321385 New: (UI) Add priority to Indexer Editor 2023-07-08 19:12:54 +03:00
Bogdan
96340909f1 Add translations to SearchFooter 2023-07-08 18:16:02 +03:00
Bogdan
bd6a37dc8c Fixed: (UI) Regain jump to character functionality for search releases 2023-07-08 17:02:01 +03:00
Bogdan
a663cebada Check indexer health checks on bulk updates 2023-07-08 03:52:21 +03:00
Bogdan
2ce5618499 Improve indexer multiple select functionality 2023-07-08 03:13:41 +03:00
Bogdan
94c91d4c3f Fix recursive call in translate() 2023-07-08 03:10:51 +03:00
Bogdan
79fbb2d0d7 New: (UI) Show advanced settings toggle in application modal content 2023-07-07 17:51:12 +03:00
Bogdan
e2e52746bb Fix repeat search when limits are empty 2023-07-07 17:26:56 +03:00
Bogdan
21cc96d683 Fixed: (History) Save limit and offset in history data 2023-07-07 16:21:20 +03:00
Bogdan
e68b45636e Minor refactoring in TorrentsCSV 2023-07-07 13:25:53 +03:00
Servarr
ce68fe4105 Automated API Docs update [skip ci] 2023-07-06 01:29:07 +03:00
Bogdan
712404ddca Show download client field only when download clients are set 2023-07-06 01:07:32 +03:00
ricci2511
826828e8ec New: Add download client per indexer setting 2023-07-06 01:07:32 +03:00
Bogdan
252740519f Remove unused prop in Stats 2023-07-06 00:39:33 +03:00
Bogdan
062fd77e1b Fixed: (UI) Prevent search results clearing when using header search with enter key 2023-07-06 00:17:16 +03:00
Bogdan
6769055b6b Fixed: (TorrentPotato) Allow use of custom APIs 2023-07-06 00:07:50 +03:00
Taloth Saldono
90e92c0b66 Ensure mousetrap instance exists in unbindShortcut
(cherry picked from commit 930742ae2c69a530afe60f76a5824f2722540df8)
2023-07-05 23:02:22 +03:00
Bogdan
7eac11f57a Fixed: (UI) Change default search results sorting to age 2023-07-05 16:52:39 +03:00
Bogdan
02a3c1b224 Align ProwlarrErrorPipeline with upstream 2023-07-04 23:51:10 +03:00
Bogdan
57efa6d0b1 Add Find() to BasicRepository 2023-07-04 22:38:52 +03:00
Qstick
cee52147bc Add package to Sentry release to ensure apps don't mix 2023-07-04 12:21:00 -05:00
Bogdan
a1abcd6c93 Fixed: (History) Reduce History Cleanup Days to 30 2023-07-04 06:56:13 +03:00
Bogdan
18e2757d37 Allow templating in JSON rows selector in Cardigann 2023-07-03 22:45:04 +03:00
Bogdan
8790a6f06a New: (HttpClient) Add HTTP/2 support 2023-07-03 18:55:13 +03:00
Bogdan
4fafdb2cd2 Add x265 categories for Movies and TV in Newznab 2023-07-03 18:54:34 +03:00
Bogdan
bfc06fc8bc Bump version to 1.7.1 2023-07-02 12:01:07 +03:00
Bogdan
9f4f6a5726 Add missing translation for query type 2023-06-29 17:42:59 +03:00
Bogdan
d9ace9a862 Fixed: (Stats) Exclude cached queries from average elapsed time 2023-06-29 16:55:46 +03:00
Bogdan
95691c7476 New: Show query type in history 2023-06-29 16:25:49 +03:00
Bogdan
90f2020e59 Fixed: Misaligned table border in history 2023-06-29 16:08:23 +03:00
Bogdan
6afa1dc8ba Fixed: (Cardigann) Don't check for captcha when captcha answer is empty 2023-06-29 14:43:11 +03:00
Bogdan
e8139f2a5b Fixed: (PornoLab) Moved to YML for Cardigann 2023-06-28 17:56:01 +03:00
Bogdan
45328db2c7 Add close reason to label actions 2023-06-28 15:25:36 +03:00
Bogdan
e55d6b827a Add ContentSummary to HDBits requests 2023-06-27 13:19:57 +03:00
Bogdan
34cd68fa07 Add ContentSummary to BeyondHD requests 2023-06-27 13:19:57 +03:00
Bogdan
aed3f9f887 Create overload for ToJson for Formatting 2023-06-27 13:19:57 +03:00
Bogdan
6880e67507 Fixed: (Apps) Ensure validation for test connection 2023-06-27 06:52:59 +03:00
Bogdan
e0e1b1494e Exclude RSS history events in migration 2023-06-27 05:20:44 +03:00
Bogdan
20df31919d Check for event type to prevent multiple runs on the same row 2023-06-26 20:49:15 +03:00
Bogdan
8785fe02e8 Execute update queries only for certain rows in migration 34 2023-06-26 18:29:14 +03:00
Bogdan
b2b877a8c3 Fix: (UI) Maintain search type and parameters on repeat search 2023-06-26 15:08:31 +03:00
Bogdan
0de302ad48 Don't save empty data in history service 2023-06-26 15:08:31 +03:00
Bogdan
06391489cf Fixed: (Apps) Use forceSave=true to avoid validation warnings 2023-06-26 10:58:14 +03:00
Qstick
8fcceb0702 Bump version to 1.7.0 2023-06-25 20:35:32 -05:00
Bogdan
f20319fff1 Bump version to 1.6.3 2023-06-25 19:15:06 +03:00
Bogdan
20bcc00662 Fix apprise server url migration 2023-06-25 08:38:39 +03:00
Bogdan
c4af3e746f Add more trace logs related info to bug_report.yml [skip ci]
Co-authored-by: Bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-06-24 08:38:50 +03:00
Bogdan
660a162b7e Fixed: (Cardigann) Throw exception only when all download selectors fail 2023-06-23 11:18:14 +03:00
Bogdan
20a3cad7fb Add indexer id in logs for invalid dates in Cardigann definitions 2023-06-23 10:41:25 +03:00
Bogdan
77fe3f78fe Fixed: (Cardigann) Skip to next download selector when max redirects reached
Fixes #578
2023-06-22 17:01:25 +03:00
Bogdan
d777cb8e29 Fixed: (API) Prevent NullRef when searching empty query with a non-default type 2023-06-22 10:36:53 +03:00
Bogdan
15e7cc7ea8 New: (UI) Show indexer categories in info modal 2023-06-20 13:23:06 +03:00
Shivam Dua
04cf061275 Fixed: (UI) Add New Indexer button on search page when no indexers are present
Add missing listeners and components to make add indexer button work on
search page when no indexers are present
2023-06-20 07:33:34 +03:00
Bogdan
d4cdeac69a Fixed: (Cardigann) Definitions with category mapping Other to use 8000 (Other) 2023-06-20 07:21:35 +03:00
Bogdan
e60fe05ee0 Revert "Fix typo botton to bottom"
This reverts commit e2e65627ee.
2023-06-20 05:20:26 +03:00
Bogdan
9a4c23797a Display error when search failed due to all indexers being disabled 2023-06-20 03:05:55 +03:00
Bogdan
acfdb5bae3 New: (UI) Show disabled indexers as disabled options in search page 2023-06-20 03:05:55 +03:00
Bogdan
e2e65627ee Fix typo botton to bottom 2023-06-19 14:31:37 +03:00
Bogdan
4b8906ea62 Cleanup redundant DownloadProtocol in indexers 2023-06-19 04:26:45 +03:00
Bogdan
f0c5d8ceea Minor refactoring in Cardigann definition 2023-06-19 04:08:01 +03:00
Bogdan
427802a50e Update status translations for Indexer index 2023-06-18 15:46:43 +03:00
Bogdan
0c9eae244a Add skip ci to API docs update commit 2023-06-18 15:45:04 +03:00
Bogdan
75ff2f41d3 Update description for freeleech only in BakaBT 2023-06-18 09:37:33 +03:00
Bakerboy448
d1ba208243 Fixed: (HttpIndexerBase) Better HTTP error handling 2023-06-18 08:15:23 +03:00
Bogdan
4e03ebadc4 New: (UI) Add filter by categories in add indexer modal
Fixes #872
Closes #1731
2023-06-18 08:14:39 +03:00
Bogdan
0155ff60fd Map Cardigann capabilities from meta definition 2023-06-18 08:14:35 +03:00
Bogdan
f0915638f3 New: (Apps) Sync Anime Standard Search with Sonarr
Fixes #998
Closes #1732
2023-06-18 07:05:08 +03:00
Bogdan
56eb58aed1 Bump version to 1.6.2 2023-06-18 07:01:38 +03:00
Bogdan
8a891d07cf Test eligibility of the first request in AvistazBase 2023-06-17 14:22:57 +03:00
Bogdan
40a932cd28 Improved page loading errors 2023-06-17 03:36:40 +03:00
Mark McDowall
4a81630073 Fixed: Clearing logs not updating UI once complete
(cherry picked from commit 56b3acddc9f50f59c78c03ca072fe802752b88a7)
2023-06-17 02:27:45 +03:00
Bogdan
0ff0fe2e68 Prevent NullRef when deleting missing backups 2023-06-17 02:08:40 +03:00
Bogdan
51e33740b0 Update import path in CategoryLabel 2023-06-17 01:08:06 +03:00
Bogdan
119164f729 Show indexer privacy in search results 2023-06-16 05:23:07 +03:00
Bogdan
ef0f8e25fd Sort limits in IndexerCapabilities 2023-06-16 05:23:07 +03:00
Bogdan
d21debe77f Convert to 'using' declaration in Housekeeping Tasks 2023-06-16 02:40:47 +03:00
Bogdan
a3ccc3d0cf Close database connections in housekeeping tasks 2023-06-16 02:40:39 +03:00
Bogdan
46d930e903 Apply template text to switch cases in Cardigann 2023-06-16 00:06:11 +03:00
Bogdan
4561859c2b Fixed: (UI) Case-insensitive sorting for add indexer modal 2023-06-14 10:03:02 +03:00
Bogdan
83166fb0b5 Allow array of string as value in EnhancedSelectInput 2023-06-14 07:11:50 +03:00
Bogdan
b98f9a945d Fix use of TmdbId in NewznabRequestGenerator 2023-06-14 04:11:26 +03:00
Bogdan
e658e3fe48 Fixed: (Cardigann) Skip duplicated GET requests 2023-06-12 03:58:02 +03:00
Bogdan
9042525f22 Bump version to 1.6.1 2023-06-11 09:33:46 +03:00
Bogdan
7b551a0af1 Update Anidub description 2023-06-11 07:42:41 +03:00
Bogdan
31c2917bad Fixed: (Indexers) Allow RSS searches in HttpIndexerBase 2023-06-11 03:25:00 +03:00
727 changed files with 17523 additions and 8705 deletions

View File

@@ -1,5 +1,5 @@
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']
body:
- type: checkboxes
@@ -74,7 +74,7 @@ body:
- type: checkboxes
attributes:
label: Trace Logs have been provided as applicable. Reports may be closed if the required logs are not provided.
description: Trace logs are generally required for all bug reports
description: Trace logs are generally required for all bug reports and contain `trace`. Info logs are invalid for bug reports and do not contain `debug` nor `trace`
options:
- label: I have followed the steps in the wiki link above and provided the required trace logs that are relevant and show this issue.
- label: I have read and followed the steps in the wiki link above and provided the required trace logs - the logs contain `trace` - that are relevant and show this issue.
required: true

View File

@@ -6,6 +6,3 @@ contact_links:
- name: Support via Discord
url: https://prowlarr.com/discord
about: Chat with users and devs on support and setup related topics.
- name: Support via Reddit
url: https://reddit.com/r/prowlarr
about: Discuss and search thru support topics.

View File

@@ -4,9 +4,9 @@
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://prowlarr.com/discord)
or [Subreddit](https://reddit.com/r/prowlarr)
to be a support request. Please hop over onto our [Discord](https://prowlarr.com/discord).
close: true
close-reason: 'not planned'
'Type: Indexer Request':
comment: >
@@ -14,6 +14,7 @@
for bug reports and feature requests. However, this issue appears
to be a indexer request. Please use our Indexer request [site](https://requests.prowlarr.com/)
close: true
close-reason: 'not planned'
'Status: Logs Needed':
comment: >

View File

@@ -2,7 +2,7 @@
[![Build Status](https://dev.azure.com/Prowlarr/Prowlarr/_apis/build/status/Prowlarr.Prowlarr?branchName=develop)](https://dev.azure.com/Prowlarr/Prowlarr/_build/latest?definitionId=1&branchName=develop)
[![Translated](https://translate.servarr.com/widgets/servarr/-/prowlarr/svg-badge.svg)](https://translate.servarr.com/engage/prowlarr/?utm_source=widget)
[![Docker Pulls](https://img.shields.io/docker/pulls/hotio/prowlarr.svg)](https://wiki.servarr.com/prowlarr/installation#docker)
[![Docker Pulls](https://img.shields.io/docker/pulls/hotio/prowlarr.svg)](https://wiki.servarr.com/prowlarr/installation/docker)
![Github Downloads](https://img.shields.io/github/downloads/Prowlarr/Prowlarr/total.svg)
[![Backers on Open Collective](https://opencollective.com/Prowlarr/backers/badge.svg)](#backers)
[![Sponsors on Open Collective](https://opencollective.com/Prowlarr/sponsors/badge.svg)](#sponsors)
@@ -29,7 +29,6 @@ Prowlarr is an indexer manager/proxy built on the popular \*arr .net/reactjs bas
[![Wiki](https://img.shields.io/badge/servarr-wiki-181717.svg?maxAge=60)](https://wiki.servarr.com/prowlarr)
[![Discord](https://img.shields.io/badge/discord-chat-7289DA.svg?maxAge=60)](https://prowlarr.com/discord)
[![Reddit](https://img.shields.io/badge/reddit-discussion-FF4500.svg?maxAge=60)](https://www.reddit.com/r/Prowlarr)
Note: GitHub Issues are for Bugs and Feature Requests Only

View File

@@ -9,15 +9,15 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '1.6.0'
majorVersion: '1.11.0'
minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.408'
dotnetVersion: '6.0.417'
nodeVersion: '16.X'
innoVersion: '6.2.0'
nodeVersion: '16.x'
windowsImage: 'windows-2022'
linuxImage: 'ubuntu-20.04'
macImage: 'macOS-11'
@@ -27,6 +27,10 @@ trigger:
include:
- develop
- master
paths:
exclude:
- .github
- src/Prowlarr.Api.*/openapi.json
pr:
branches:
@@ -34,8 +38,9 @@ pr:
- develop
paths:
exclude:
- .github
- src/NzbDrone.Core/Localization/Core
- src/Prowlarr.API.*/openapi.json
- src/Prowlarr.Api.*/openapi.json
stages:
- stage: Setup
@@ -349,7 +354,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create FreeBSD Core Core tar
displayName: Create freebsd-x64 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Prowlarr.$(buildName).freebsd-core-x64.tar.gz'
archiveType: 'tar'
@@ -362,7 +367,7 @@ stages:
- bash: |
echo "Uploading source maps to sentry"
curl -sL https://sentry.io/get-cli/ | bash
RELEASENAME="${PROWLARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
RELEASENAME="Prowlarr@${PROWLARRVERSION}-${BUILD_SOURCEBRANCHNAME}"
sentry-cli releases new --finalize -p prowlarr -p prowlarr-ui -p prowlarr-update "${RELEASENAME}"
sentry-cli releases -p prowlarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite
sentry-cli releases set-commits --auto "${RELEASENAME}"
@@ -528,8 +533,8 @@ stages:
testRunTitle: '$(testName) Unit Tests'
failTaskOnFailedTests: true
- job: Unit_LinuxCore_Postgres
displayName: Unit Native LinuxCore with Postgres Database
- job: Unit_LinuxCore_Postgres14
displayName: Unit Native LinuxCore with Postgres14 Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
@@ -565,6 +570,7 @@ stages:
-e POSTGRES_PASSWORD=prowlarr \
-e POSTGRES_USER=prowlarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:14
displayName: Start postgres
- bash: |
@@ -577,7 +583,60 @@ stages:
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'LinuxCore Postgres Unit Tests'
testRunTitle: 'LinuxCore Postgres14 Unit Tests'
failTaskOnFailedTests: true
- job: Unit_LinuxCore_Postgres15
displayName: Unit Native LinuxCore with Postgres15 Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Prowlarr.*.linux-core-x64.tar.gz'
artifactName: linux-x64-tests
Prowlarr__Postgres__Host: 'localhost'
Prowlarr__Postgres__Port: '5432'
Prowlarr__Postgres__User: 'prowlarr'
Prowlarr__Postgres__Password: 'prowlarr'
pool:
vmImage: ${{ variables.linuxImage }}
timeoutInMinutes: 10
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: $(artifactName)
targetPath: $(testsFolder)
- bash: find ${TESTSFOLDER} -name "Prowlarr.Test.Dummy" -exec chmod a+x {} \;
displayName: Make Test Dummy Executable
condition: and(succeeded(), ne(variables['osName'], 'Windows'))
- bash: |
docker run -d --name=postgres15 \
-e POSTGRES_PASSWORD=prowlarr \
-e POSTGRES_USER=prowlarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:15
displayName: Start postgres
- bash: |
chmod a+x ${TESTSFOLDER}/test.sh
ls -lR ${TESTSFOLDER}
${TESTSFOLDER}/test.sh Linux Unit Test
displayName: Run Tests
- task: PublishTestResults@2
displayName: Publish Test Results
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'LinuxCore Postgres15 Unit Tests'
failTaskOnFailedTests: true
- stage: Integration
@@ -663,8 +722,8 @@ stages:
failTaskOnFailedTests: true
displayName: Publish Test Results
- job: Integration_LinuxCore_Postgres
displayName: Integration Native LinuxCore with Postgres Database
- job: Integration_LinuxCore_Postgres14
displayName: Integration Native LinuxCore with Postgres14 Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
@@ -710,6 +769,7 @@ stages:
-e POSTGRES_PASSWORD=prowlarr \
-e POSTGRES_USER=prowlarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:14
displayName: Start postgres
- bash: |
@@ -720,7 +780,70 @@ stages:
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'Integration LinuxCore Postgres Database Integration Tests'
testRunTitle: 'Integration LinuxCore Postgres14 Database Integration Tests'
failTaskOnFailedTests: true
displayName: Publish Test Results
- job: Integration_LinuxCore_Postgres15
displayName: Integration Native LinuxCore with Postgres Database
dependsOn: Prepare
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Prowlarr.*.linux-core-x64.tar.gz'
Prowlarr__Postgres__Host: 'localhost'
Prowlarr__Postgres__Port: '5432'
Prowlarr__Postgres__User: 'prowlarr'
Prowlarr__Postgres__Password: 'prowlarr'
pool:
vmImage: ${{ variables.linuxImage }}
steps:
- task: UseDotNet@2
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'linux-x64-tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
inputs:
buildType: 'current'
artifactName: Packages
itemPattern: '**/$(pattern)'
targetPath: $(Build.ArtifactStagingDirectory)
- task: ExtractFiles@1
inputs:
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
displayName: Extract Package
- bash: |
mkdir -p ./bin/
cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Prowlarr/. ./bin/
displayName: Move Package Contents
- bash: |
docker run -d --name=postgres15 \
-e POSTGRES_PASSWORD=prowlarr \
-e POSTGRES_USER=prowlarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:15
displayName: Start postgres
- bash: |
chmod a+x ${TESTSFOLDER}/test.sh
${TESTSFOLDER}/test.sh Linux Integration Test
displayName: Run Integration Tests
- task: PublishTestResults@2
inputs:
testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml'
testRunTitle: 'Integration LinuxCore Postgres15 Database Integration Tests'
failTaskOnFailedTests: true
displayName: Publish Test Results

View File

@@ -392,22 +392,21 @@ then
fi
fi
if [ "$FRONTEND" = "YES" ];
if [[ "$LINT" = "YES" || "$FRONTEND" = "YES" ]];
then
YarnInstall
RunWebpack
fi
if [ "$LINT" = "YES" ];
then
if [ -z "$FRONTEND" ];
then
YarnInstall
fi
LintUI
fi
if [ "$FRONTEND" = "YES" ];
then
RunWebpack
fi
if [ "$PACKAGES" = "YES" ];
then
UpdateVersionNumber

View File

@@ -26,7 +26,8 @@ module.exports = {
globals: {
expect: false,
chai: false,
sinon: false
sinon: false,
JSX: true
},
parserOptions: {

View File

@@ -4,14 +4,14 @@ module.exports = {
plugins: [
// Stage 1
'@babel/plugin-proposal-export-default-from',
['@babel/plugin-proposal-optional-chaining', { loose }],
['@babel/plugin-proposal-nullish-coalescing-operator', { loose }],
['@babel/plugin-transform-optional-chaining', { loose }],
['@babel/plugin-transform-nullish-coalescing-operator', { loose }],
// Stage 2
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-transform-export-namespace-from',
// Stage 3
['@babel/plugin-proposal-class-properties', { loose }],
['@babel/plugin-transform-class-properties', { loose }],
'@babel/plugin-syntax-dynamic-import'
],
env: {

View File

@@ -35,7 +35,7 @@ module.exports = (env) => {
},
entry: {
index: 'index.js'
index: 'index.ts'
},
resolve: {
@@ -65,23 +65,23 @@ module.exports = (env) => {
output: {
path: distFolder,
publicPath: '/',
filename: '[name].js',
filename: '[name]-[contenthash].js',
sourceMapFilename: '[file].map'
},
optimization: {
moduleIds: 'deterministic',
chunkIds: 'named',
splitChunks: {
chunks: 'initial',
name: 'vendors'
}
chunkIds: isProduction ? 'deterministic' : 'named'
},
performance: {
hints: false
},
experiments: {
topLevelAwait: true
},
plugins: [
new webpack.DefinePlugin({
__DEV__: !isProduction,
@@ -89,13 +89,15 @@ module.exports = (env) => {
}),
new MiniCssExtractPlugin({
filename: 'Content/styles.css'
filename: 'Content/styles.css',
chunkFilename: 'Content/[id]-[chunkhash].css'
}),
new HtmlWebpackPlugin({
template: 'frontend/src/index.ejs',
filename: 'index.html',
publicPath: '/'
publicPath: '/',
inject: false
}),
new FileManagerPlugin({

View File

@@ -5,9 +5,9 @@ import NotFound from 'Components/NotFound';
import Switch from 'Components/Router/Switch';
import HistoryConnector from 'History/HistoryConnector';
import IndexerIndex from 'Indexer/Index/IndexerIndex';
import StatsConnector from 'Indexer/Stats/StatsConnector';
import IndexerStats from 'Indexer/Stats/IndexerStats';
import SearchIndexConnector from 'Search/SearchIndexConnector';
import ApplicationSettingsConnector from 'Settings/Applications/ApplicationSettingsConnector';
import ApplicationSettings from 'Settings/Applications/ApplicationSettings';
import DevelopmentSettingsConnector from 'Settings/Development/DevelopmentSettingsConnector';
import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
import GeneralSettingsConnector from 'Settings/General/GeneralSettingsConnector';
@@ -60,7 +60,7 @@ function AppRoutes(props) {
<Route
path="/indexers/stats"
component={StatsConnector}
component={IndexerStats}
/>
{/*
@@ -98,7 +98,7 @@ function AppRoutes(props) {
<Route
path="/settings/applications"
component={ApplicationSettingsConnector}
component={ApplicationSettings}
/>
<Route

View File

@@ -1,6 +1,7 @@
.version {
margin: 0 3px;
font-weight: bold;
font-family: var(--defaultFontFamily);
}
.maintenance {

View File

@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
@@ -64,12 +65,12 @@ function AppUpdatedModalContent(props) {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Prowlarr Updated
{translate('AppUpdated')}
</ModalHeader>
<ModalBody>
<div>
Version <span className={styles.version}>{version}</span> of Prowlarr has been installed, in order to get the latest changes you'll need to reload Prowlarr.
<InlineMarkdown data={translate('AppUpdatedVersion', { version })} blockClassName={styles.version} />
</div>
{
@@ -77,16 +78,14 @@ function AppUpdatedModalContent(props) {
<div>
{
!update.changes &&
<div className={styles.maintenance}>
{translate('MaintenanceRelease')}
</div>
<div className={styles.maintenance}>{translate('MaintenanceRelease')}</div>
}
{
!!update.changes &&
<div>
<div className={styles.changes}>
What's new?
{translate('WhatsNew')}
</div>
<UpdateChanges
@@ -113,14 +112,14 @@ function AppUpdatedModalContent(props) {
<Button
onPress={onSeeChangesPress}
>
Recent Changes
{translate('RecentChanges')}
</Button>
<Button
kind={kinds.PRIMARY}
onPress={onModalClose}
>
Reload
{translate('Reload')}
</Button>
</ModalFooter>
</ModalContent>

View File

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

View File

@@ -0,0 +1,48 @@
import SortDirection from 'Helpers/Props/SortDirection';
export interface Error {
responseJSON: {
message: string;
};
}
export interface AppSectionDeleteState {
isDeleting: boolean;
deleteError: Error;
}
export interface AppSectionSaveState {
isSaving: boolean;
saveError: Error;
}
export interface PagedAppSectionState {
pageSize: number;
}
export interface AppSectionSchemaState<T> {
isSchemaFetching: boolean;
isSchemaPopulated: boolean;
schemaError: Error;
schema: {
items: T[];
};
}
export interface AppSectionItemState<T> {
isFetching: boolean;
isPopulated: boolean;
error: Error;
item: T;
}
interface AppSectionState<T> {
isFetching: boolean;
isPopulated: boolean;
error: Error;
items: T[];
sortKey: string;
sortDirection: SortDirection;
}
export default AppSectionState;

View File

@@ -0,0 +1,58 @@
import CommandAppState from './CommandAppState';
import HistoryAppState from './HistoryAppState';
import IndexerAppState, {
IndexerHistoryAppState,
IndexerIndexAppState,
IndexerStatusAppState,
} from './IndexerAppState';
import IndexerStatsAppState from './IndexerStatsAppState';
import SettingsAppState from './SettingsAppState';
import SystemAppState from './SystemAppState';
import TagsAppState from './TagsAppState';
interface FilterBuilderPropOption {
id: string;
name: string;
}
export interface FilterBuilderProp<T> {
name: string;
label: string;
type: string;
valueType?: string;
optionsSelector?: (items: T[]) => FilterBuilderPropOption[];
}
export interface PropertyFilter {
key: string;
value: boolean | string | number | string[] | number[];
type: string;
}
export interface Filter {
key: string;
label: string;
filers: PropertyFilter[];
}
export interface CustomFilter {
id: number;
type: string;
label: string;
filers: PropertyFilter[];
}
interface AppState {
commands: CommandAppState;
history: HistoryAppState;
indexerHistory: IndexerHistoryAppState;
indexerIndex: IndexerIndexAppState;
indexerStats: IndexerStatsAppState;
indexerStatus: IndexerStatusAppState;
indexers: IndexerAppState;
settings: SettingsAppState;
system: SystemAppState;
tags: TagsAppState;
}
export default AppState;

View File

@@ -0,0 +1,8 @@
import { CustomFilter } from './AppState';
interface ClientSideCollectionAppState {
totalItems: number;
customFilters: CustomFilter[];
}
export default ClientSideCollectionAppState;

View File

@@ -0,0 +1,6 @@
import AppSectionState from 'App/State/AppSectionState';
import Command from 'Commands/Command';
export type CommandAppState = AppSectionState<Command>;
export default CommandAppState;

View File

@@ -0,0 +1,10 @@
import AppSectionState from 'App/State/AppSectionState';
import Column from 'Components/Table/Column';
import History from 'typings/History';
interface HistoryAppState extends AppSectionState<History> {
pageSize: number;
columns: Column[];
}
export default HistoryAppState;

View File

@@ -0,0 +1,40 @@
import Column from 'Components/Table/Column';
import SortDirection from 'Helpers/Props/SortDirection';
import Indexer, { IndexerStatus } from 'Indexer/Indexer';
import History from 'typings/History';
import AppSectionState, {
AppSectionDeleteState,
AppSectionSaveState,
} from './AppSectionState';
import { Filter, FilterBuilderProp } from './AppState';
export interface IndexerIndexAppState {
isTestingAll: boolean;
sortKey: string;
sortDirection: SortDirection;
secondarySortKey: string;
secondarySortDirection: SortDirection;
view: string;
tableOptions: {
showSearchAction: boolean;
};
selectedFilterKey: string;
filterBuilderProps: FilterBuilderProp<Indexer>[];
filters: Filter[];
columns: Column[];
}
interface IndexerAppState
extends AppSectionState<Indexer>,
AppSectionDeleteState,
AppSectionSaveState {
itemMap: Record<number, number>;
}
export type IndexerStatusAppState = AppSectionState<IndexerStatus>;
export type IndexerHistoryAppState = AppSectionState<History>;
export default IndexerAppState;

View File

@@ -0,0 +1,13 @@
import { AppSectionItemState } from 'App/State/AppSectionState';
import { Filter, FilterBuilderProp } from 'App/State/AppState';
import Indexer from 'Indexer/Indexer';
import { IndexerStats } from 'typings/IndexerStats';
export interface IndexerStatsAppState
extends AppSectionItemState<IndexerStats> {
filterBuilderProps: FilterBuilderProp<Indexer>[];
selectedFilterKey: string;
filters: Filter[];
}
export default IndexerStatsAppState;

View File

@@ -0,0 +1,10 @@
import AppSectionState, {
AppSectionDeleteState,
} from 'App/State/AppSectionState';
import Release from 'typings/Release';
interface ReleaseAppState
extends AppSectionState<Release>,
AppSectionDeleteState {}
export default ReleaseAppState;

View File

@@ -0,0 +1,42 @@
import AppSectionState, {
AppSectionDeleteState,
AppSectionItemState,
AppSectionSaveState,
} from 'App/State/AppSectionState';
import Application from 'typings/Application';
import DownloadClient from 'typings/DownloadClient';
import Notification from 'typings/Notification';
import { UiSettings } from 'typings/UiSettings';
export interface AppProfileAppState
extends AppSectionState<Application>,
AppSectionDeleteState,
AppSectionSaveState {}
export interface ApplicationAppState
extends AppSectionState<Application>,
AppSectionDeleteState,
AppSectionSaveState {
isTestingAll: boolean;
}
export interface DownloadClientAppState
extends AppSectionState<DownloadClient>,
AppSectionDeleteState,
AppSectionSaveState {}
export interface NotificationAppState
extends AppSectionState<Notification>,
AppSectionDeleteState {}
export type UiSettingsAppState = AppSectionItemState<UiSettings>;
interface SettingsAppState {
appProfiles: AppProfileAppState;
applications: ApplicationAppState;
downloadClients: DownloadClientAppState;
notifications: NotificationAppState;
ui: UiSettingsAppState;
}
export default SettingsAppState;

View File

@@ -0,0 +1,10 @@
import SystemStatus from 'typings/SystemStatus';
import { AppSectionItemState } from './AppSectionState';
export type SystemStatusAppState = AppSectionItemState<SystemStatus>;
interface SystemAppState {
status: SystemStatusAppState;
}
export default SystemAppState;

View File

@@ -0,0 +1,28 @@
import ModelBase from 'App/ModelBase';
import AppSectionState, {
AppSectionDeleteState,
AppSectionSaveState,
} from 'App/State/AppSectionState';
export interface Tag extends ModelBase {
label: string;
}
export interface TagDetail extends ModelBase {
label: string;
applicationIds: number[];
indexerIds: number[];
indexerProxyIds: number[];
notificationIds: number[];
}
export interface TagDetailAppState
extends AppSectionState<TagDetail>,
AppSectionDeleteState,
AppSectionSaveState {}
interface TagsAppState extends AppSectionState<Tag>, AppSectionDeleteState {
details: TagDetailAppState;
}
export default TagsAppState;

View File

@@ -0,0 +1,37 @@
import ModelBase from 'App/ModelBase';
export interface CommandBody {
sendUpdatesToClient: boolean;
updateScheduledTask: boolean;
completionMessage: string;
requiresDiskAccess: boolean;
isExclusive: boolean;
isLongRunning: boolean;
name: string;
lastExecutionTime: string;
lastStartTime: string;
trigger: string;
suppressMessages: boolean;
seriesId?: number;
}
interface Command extends ModelBase {
name: string;
commandName: string;
message: string;
body: CommandBody;
priority: string;
status: string;
result: string;
queued: string;
started: string;
ended: string;
duration: string;
trigger: string;
stateChangeTime: string;
sendUpdatesToClient: boolean;
updateScheduledTask: boolean;
lastExecutionTime: string;
}
export default Command;

View File

@@ -2,6 +2,7 @@ import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { kinds } from 'Helpers/Props';
import { defaultFontFamily } from 'Styles/Variables/fonts';
function getColors(kind) {
@@ -39,7 +40,15 @@ class BarChart extends Component {
plugins: {
title: {
display: true,
text: this.props.title
align: 'start',
text: this.props.title,
padding: {
bottom: 30
},
font: {
size: 14,
family: defaultFontFamily
}
},
legend: {
display: this.props.legend

View File

@@ -1,6 +1,7 @@
import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { defaultFontFamily } from 'Styles/Variables/fonts';
function getColors(kind) {
@@ -22,7 +23,15 @@ class DoughnutChart extends Component {
plugins: {
title: {
display: true,
text: this.props.title
align: 'start',
text: this.props.title,
padding: {
bottom: 30
},
font: {
size: 14,
family: defaultFontFamily
}
},
legend: {
position: 'bottom'

View File

@@ -1,6 +1,7 @@
import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { defaultFontFamily } from 'Styles/Variables/fonts';
function getColors(index) {
@@ -36,7 +37,15 @@ class StackedBarChart extends Component {
plugins: {
title: {
display: true,
text: this.props.title
align: 'start',
text: this.props.title,
padding: {
bottom: 30
},
font: {
size: 14,
family: defaultFontFamily
}
}
}
},

View File

@@ -23,7 +23,9 @@ function ErrorBoundaryError(props: ErrorBoundaryErrorProps) {
info,
} = props;
const [detailedError, setDetailedError] = useState(null);
const [detailedError, setDetailedError] = useState<
StackTrace.StackFrame[] | null
>(null);
useEffect(() => {
if (error) {

View File

@@ -20,12 +20,12 @@ import styles from './FileBrowserModalContent.css';
const columns = [
{
name: 'type',
label: translate('Type'),
label: () => translate('Type'),
isVisible: true
},
{
name: 'name',
label: translate('Name'),
label: () => translate('Name'),
isVisible: true
}
];

View File

@@ -198,11 +198,13 @@ class FilterBuilderRow extends Component {
const selectedFilterBuilderProp = this.selectedFilterBuilderProp;
const keyOptions = filterBuilderProps.map((availablePropFilter) => {
const { name, label } = availablePropFilter;
return {
key: availablePropFilter.name,
value: availablePropFilter.label
key: name,
value: typeof label === 'function' ? label() : label
};
});
}).sort((a, b) => a.value.localeCompare(b.value));
const ValueComponent = getRowValueConnector(selectedFilterBuilderProp);

View File

@@ -9,13 +9,13 @@ import FilterBuilderRowValue from './FilterBuilderRowValue';
function createMapStateToProps() {
return createSelector(
(state) => state.indexers,
(qualityProfiles) => {
(indexers) => {
const {
isFetching,
isPopulated,
error,
items
} = qualityProfiles;
} = indexers;
const tagList = items.map((item) => {
return {

View File

@@ -3,9 +3,24 @@ import translate from 'Utilities/String/translate';
import FilterBuilderRowValue from './FilterBuilderRowValue';
const privacyTypes = [
{ id: 'public', name: translate('Public') },
{ id: 'private', name: translate('Private') },
{ id: 'semiPrivate', name: translate('SemiPrivate') }
{
id: 'public',
get name() {
return translate('Public');
}
},
{
id: 'private',
get name() {
return translate('Private');
}
},
{
id: 'semiPrivate',
get name() {
return translate('SemiPrivate');
}
}
];
function PrivacyFilterBuilderRowValue(props) {

View File

@@ -5,6 +5,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
import sortByName from 'Utilities/Array/sortByName';
import translate from 'Utilities/String/translate';
import SelectInput from './SelectInput';
function createMapStateToProps() {
@@ -23,7 +24,7 @@ function createMapStateToProps() {
if (includeNoChange) {
values.unshift({
key: 'noChange',
value: 'No Change',
value: translate('NoChange'),
disabled: true
});
}

View File

@@ -0,0 +1,98 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { fetchDownloadClients } from 'Store/Actions/settingsActions';
import sortByName from 'Utilities/Array/sortByName';
import EnhancedSelectInput from './EnhancedSelectInput';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.downloadClients,
(state, { includeAny }) => includeAny,
(state, { protocol }) => protocol,
(downloadClients, includeAny, protocolFilter) => {
const {
isFetching,
isPopulated,
error,
items
} = downloadClients;
const values = items
.filter((downloadClient) => downloadClient.protocol === protocolFilter)
.sort(sortByName)
.map((downloadClient) => ({
key: downloadClient.id,
value: downloadClient.name
}));
if (includeAny) {
values.unshift({
key: 0,
value: '(Any)'
});
}
return {
isFetching,
isPopulated,
error,
values
};
}
);
}
const mapDispatchToProps = {
dispatchFetchDownloadClients: fetchDownloadClients
};
class DownloadClientSelectInputConnector extends Component {
//
// Lifecycle
componentDidMount() {
if (!this.props.isPopulated) {
this.props.dispatchFetchDownloadClients();
}
}
//
// Listeners
onChange = ({ name, value }) => {
this.props.onChange({ name, value: parseInt(value) });
};
//
// Render
render() {
return (
<EnhancedSelectInput
{...this.props}
onChange={this.onChange}
/>
);
}
}
DownloadClientSelectInputConnector.propTypes = {
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
values: PropTypes.arrayOf(PropTypes.object).isRequired,
includeAny: PropTypes.bool.isRequired,
onChange: PropTypes.func.isRequired,
dispatchFetchDownloadClients: PropTypes.func.isRequired
};
DownloadClientSelectInputConnector.defaultProps = {
includeAny: false,
protocol: 'torrent'
};
export default connect(createMapStateToProps, mapDispatchToProps)(DownloadClientSelectInputConnector);

View File

@@ -578,7 +578,7 @@ EnhancedSelectInput.propTypes = {
className: PropTypes.string,
disabledClassName: PropTypes.string,
name: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.number)]).isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf(PropTypes.number)]).isRequired,
values: PropTypes.arrayOf(PropTypes.object).isRequired,
isDisabled: PropTypes.bool.isRequired,
isFetching: PropTypes.bool.isRequired,

View File

@@ -9,6 +9,10 @@
&:hover {
background-color: var(--inputHoverBackgroundColor);
}
&.isDisabled {
cursor: not-allowed;
}
}
.optionCheck {

View File

@@ -10,6 +10,7 @@ import CaptchaInputConnector from './CaptchaInputConnector';
import CardigannCaptchaInputConnector from './CardigannCaptchaInputConnector';
import CheckInput from './CheckInput';
import DeviceInputConnector from './DeviceInputConnector';
import DownloadClientSelectInputConnector from './DownloadClientSelectInputConnector';
import EnhancedSelectInput from './EnhancedSelectInput';
import EnhancedSelectInputConnector from './EnhancedSelectInputConnector';
import FormInputHelpText from './FormInputHelpText';
@@ -72,6 +73,9 @@ function getComponent(type) {
case inputTypes.CATEGORY_SELECT:
return NewznabCategorySelectInputConnector;
case inputTypes.DOWNLOAD_CLIENT_SELECT:
return DownloadClientSelectInputConnector;
case inputTypes.INDEXER_FLAGS_SELECT:
return IndexerFlagsSelectInputConnector;
@@ -258,12 +262,15 @@ FormInputGroup.propTypes = {
values: PropTypes.arrayOf(PropTypes.any),
type: PropTypes.string.isRequired,
kind: PropTypes.oneOf(kinds.all),
min: PropTypes.number,
max: PropTypes.number,
unit: PropTypes.string,
buttons: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
helpText: PropTypes.string,
helpTexts: PropTypes.arrayOf(PropTypes.string),
helpTextWarning: PropTypes.string,
helpLink: PropTypes.string,
autoFocus: PropTypes.bool,
includeNoChange: PropTypes.bool,
includeNoChangeDisabled: PropTypes.bool,
selectedValueOptions: PropTypes.object,

View File

@@ -2,8 +2,10 @@
display: flex;
justify-content: flex-end;
margin-right: $formLabelRightMarginWidth;
padding-top: 8px;
min-height: 35px;
text-align: end;
font-weight: bold;
line-height: 35px;
}
.hasError {

View File

@@ -33,11 +33,11 @@ function HintedSelectInputOption(props) {
isMobile && styles.isMobile
)}
>
<div>{value}</div>
<div>{typeof value === 'function' ? value() : value}</div>
{
hint != null &&
<div className={styles.hintText}>
<div className={styles.hintText} title={hint}>
{hint}
</div>
}
@@ -48,7 +48,7 @@ function HintedSelectInputOption(props) {
HintedSelectInputOption.propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
value: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
hint: PropTypes.node,
depth: PropTypes.number,
isSelected: PropTypes.bool.isRequired,

View File

@@ -24,7 +24,7 @@ function HintedSelectInputSelectedValue(props) {
>
<div className={styles.valueText}>
{
isMultiSelect &&
isMultiSelect ?
value.map((key, index) => {
const v = valuesMap[key];
return (
@@ -32,26 +32,28 @@ function HintedSelectInputSelectedValue(props) {
{v ? v.value : key}
</Label>
);
})
}) :
null
}
{
!isMultiSelect && value
isMultiSelect ? null : value
}
</div>
{
hint != null && includeHint &&
hint != null && includeHint ?
<div className={styles.hintText}>
{hint}
</div>
</div> :
null
}
</EnhancedSelectInputSelectedValue>
);
}
HintedSelectInputSelectedValue.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number]))]).isRequired,
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number]))]).isRequired,
values: PropTypes.arrayOf(PropTypes.object).isRequired,
hint: PropTypes.string,
isMultiSelect: PropTypes.bool.isRequired,

View File

@@ -1,18 +1,20 @@
import _ from 'lodash';
import { groupBy, map } from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
import sortByName from 'Utilities/Array/sortByName';
import titleCase from 'Utilities/String/titleCase';
import EnhancedSelectInput from './EnhancedSelectInput';
function createMapStateToProps() {
return createSelector(
(state, { value }) => value,
(state) => state.indexers,
createSortedSectionSelector('indexers', sortByName),
(value, indexers) => {
const values = [];
const groupedIndexers = _(indexers.items).groupBy((x) => x.protocol).map((val, key) => ({ protocol: key, indexers: val })).value();
const groupedIndexers = map(groupBy(indexers.items, 'protocol'), (val, key) => ({ protocol: key, indexers: val }));
groupedIndexers.forEach((element) => {
values.push({
@@ -21,10 +23,12 @@ function createMapStateToProps() {
});
if (element.indexers && element.indexers.length > 0) {
element.indexers.forEach((subCat) => {
element.indexers.forEach((indexer) => {
values.push({
key: subCat.id,
value: subCat.name,
key: indexer.id,
value: indexer.name,
hint: `(${indexer.id})`,
isDisabled: !indexer.enable,
parentKey: element.protocol === 'usenet' ? -1 : -2
});
});
@@ -49,7 +53,6 @@ class IndexersSelectInputConnector extends Component {
// Render
render() {
return (
<EnhancedSelectInput
{...this.props}

View File

@@ -0,0 +1,13 @@
.message {
composes: alert from '~Components/Alert.css';
a {
color: var(--linkColor);
text-decoration: none;
&:hover {
color: var(--linkHoverColor);
text-decoration: underline;
}
}
}

View File

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

View File

@@ -1,5 +1,8 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
import { kinds } from 'Helpers/Props';
import styles from './InfoInput.css';
class InfoInput extends Component {
@@ -7,12 +10,15 @@ class InfoInput extends Component {
// Render
render() {
const {
value
} = this.props;
const { value } = this.props;
return (
<span dangerouslySetInnerHTML={{ __html: value }} />
<Alert
kind={kinds.INFO}
className={styles.message}
>
<span dangerouslySetInnerHTML={{ __html: value }} />
</Alert>
);
}
}

View File

@@ -10,7 +10,7 @@ function parseValue(props, value) {
} = props;
if (value == null || value === '') {
return min;
return null;
}
let newValue = isFloat ? parseFloat(value) : parseInt(value);
@@ -41,7 +41,7 @@ class NumberInput extends Component {
componentDidUpdate(prevProps, prevState) {
const { value } = this.props;
if (value !== prevProps.value && !this.state.isFocused) {
if (!isNaN(value) && value !== prevProps.value && !this.state.isFocused) {
this.setState({
value: value == null ? '' : value.toString()
});

View File

@@ -68,6 +68,7 @@ class PathInputConnector extends Component {
}
PathInputConnector.propTypes = {
...PathInput.props,
includeFiles: PropTypes.bool.isRequired,
dispatchFetchPaths: PropTypes.func.isRequired,
dispatchClearPaths: PropTypes.func.isRequired

View File

@@ -61,7 +61,7 @@ class SelectInput extends Component {
value={key}
{...otherOptionProps}
>
{optionValue}
{typeof optionValue === 'function' ? optionValue() : optionValue}
</option>
);
})
@@ -75,7 +75,7 @@ SelectInput.propTypes = {
className: PropTypes.string,
disabledClassName: PropTypes.string,
name: PropTypes.string.isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.func]).isRequired,
values: PropTypes.arrayOf(PropTypes.object).isRequired,
isDisabled: PropTypes.bool,
hasError: PropTypes.bool,

View File

@@ -41,7 +41,7 @@ class Icon extends PureComponent {
return (
<span
className={containerClassName}
title={title}
title={typeof title === 'function' ? title() : title}
>
{icon}
</span>
@@ -58,7 +58,7 @@ Icon.propTypes = {
name: PropTypes.object.isRequired,
kind: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
title: PropTypes.string,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
isSpinning: PropTypes.bool.isRequired,
fixedWidth: PropTypes.bool.isRequired
};

View File

@@ -1,98 +0,0 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import styles from './Link.css';
class Link extends Component {
//
// Listeners
onClick = (event) => {
const {
isDisabled,
onPress
} = this.props;
if (!isDisabled && onPress) {
onPress(event);
}
};
//
// Render
render() {
const {
className,
component,
to,
target,
isDisabled,
noRouter,
onPress,
...otherProps
} = this.props;
const linkProps = { target };
let el = component;
if (to) {
if ((/\w+?:\/\//).test(to)) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_blank';
linkProps.rel = 'noreferrer';
} else if (noRouter) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_self';
} else {
el = RouterLink;
linkProps.to = `${window.Prowlarr.urlBase}/${to.replace(/^\//, '')}`;
linkProps.target = target;
}
}
if (el === 'button' || el === 'input') {
linkProps.type = otherProps.type || 'button';
linkProps.disabled = isDisabled;
}
linkProps.className = classNames(
className,
styles.link,
to && styles.to,
isDisabled && 'isDisabled'
);
const props = {
...otherProps,
...linkProps
};
props.onClick = this.onClick;
return (
React.createElement(el, props)
);
}
}
Link.propTypes = {
className: PropTypes.string,
component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
to: PropTypes.string,
target: PropTypes.string,
isDisabled: PropTypes.bool,
noRouter: PropTypes.bool,
onPress: PropTypes.func
};
Link.defaultProps = {
component: 'button',
noRouter: false
};
export default Link;

View File

@@ -0,0 +1,96 @@
import classNames from 'classnames';
import React, {
ComponentClass,
FunctionComponent,
SyntheticEvent,
useCallback,
} from 'react';
import { Link as RouterLink } from 'react-router-dom';
import styles from './Link.css';
interface ReactRouterLinkProps {
to?: string;
}
export interface LinkProps extends React.HTMLProps<HTMLAnchorElement> {
className?: string;
component?:
| string
| FunctionComponent<LinkProps>
| ComponentClass<LinkProps, unknown>;
to?: string;
target?: string;
isDisabled?: boolean;
noRouter?: boolean;
onPress?(event: SyntheticEvent): void;
}
function Link(props: LinkProps) {
const {
className,
component = 'button',
to,
target,
type,
isDisabled,
noRouter = false,
onPress,
...otherProps
} = props;
const onClick = useCallback(
(event: SyntheticEvent) => {
if (!isDisabled && onPress) {
onPress(event);
}
},
[isDisabled, onPress]
);
const linkProps: React.HTMLProps<HTMLAnchorElement> & ReactRouterLinkProps = {
target,
};
let el = component;
if (to) {
if (/\w+?:\/\//.test(to)) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_blank';
linkProps.rel = 'noreferrer';
} else if (noRouter) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_self';
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
el = RouterLink;
linkProps.to = `${window.Prowlarr.urlBase}/${to.replace(/^\//, '')}`;
linkProps.target = target;
}
}
if (el === 'button' || el === 'input') {
linkProps.type = type || 'button';
linkProps.disabled = isDisabled;
}
linkProps.className = classNames(
className,
styles.link,
to && styles.to,
isDisabled && 'isDisabled'
);
const elementProps = {
...otherProps,
type,
...linkProps,
};
elementProps.onClick = onClick;
return React.createElement(el, elementProps);
}
export default Link;

View File

@@ -97,6 +97,7 @@ class SpinnerErrorButton extends Component {
render() {
const {
kind,
isSpinning,
error,
children,
@@ -112,7 +113,7 @@ class SpinnerErrorButton extends Component {
const showIcon = wasSuccessful || hasWarning || hasError;
let iconName = icons.CHECK;
let iconKind = kinds.SUCCESS;
let iconKind = kind === kinds.PRIMARY ? kinds.DEFAULT : kinds.SUCCESS;
if (hasWarning) {
iconName = icons.WARNING;
@@ -126,6 +127,7 @@ class SpinnerErrorButton extends Component {
return (
<SpinnerButton
kind={kind}
isSpinning={isSpinning}
{...otherProps}
>
@@ -154,6 +156,7 @@ class SpinnerErrorButton extends Component {
}
SpinnerErrorButton.propTypes = {
kind: PropTypes.oneOf(kinds.all),
isSpinning: PropTypes.bool.isRequired,
error: PropTypes.object,
children: PropTypes.node.isRequired

View File

@@ -10,27 +10,55 @@ class InlineMarkdown extends Component {
render() {
const {
className,
data
data,
blockClassName
} = this.props;
// For now only replace links
// For now only replace links or code blocks (not both)
const markdownBlocks = [];
if (data) {
const regex = RegExp(/\[(.+?)\]\((.+?)\)/g);
const linkRegex = RegExp(/\[(.+?)\]\((.+?)\)/g);
let endIndex = 0;
let match = null;
while ((match = regex.exec(data)) !== null) {
while ((match = linkRegex.exec(data)) !== null) {
if (match.index > endIndex) {
markdownBlocks.push(data.substr(endIndex, match.index - endIndex));
}
markdownBlocks.push(<Link key={match.index} to={match[2]}>{match[1]}</Link>);
endIndex = match.index + match[0].length;
}
if (endIndex !== data.length) {
if (endIndex !== data.length && markdownBlocks.length > 0) {
markdownBlocks.push(data.substr(endIndex, data.length - endIndex));
}
const codeRegex = RegExp(/(?=`)`(?!`)[^`]*(?=`)`(?!`)/g);
endIndex = 0;
match = null;
let matchedCode = false;
while ((match = codeRegex.exec(data)) !== null) {
matchedCode = true;
if (match.index > endIndex) {
markdownBlocks.push(data.substr(endIndex, match.index - endIndex));
}
markdownBlocks.push(<code key={`code-${match.index}`} className={blockClassName ?? null}>{match[0].substring(1, match[0].length - 1)}</code>);
endIndex = match.index + match[0].length;
}
if (endIndex !== data.length && markdownBlocks.length > 0 && matchedCode) {
markdownBlocks.push(data.substr(endIndex, data.length - endIndex));
}
if (markdownBlocks.length === 0) {
markdownBlocks.push(data);
}
}
return <span className={className}>{markdownBlocks}</span>;
@@ -39,7 +67,8 @@ class InlineMarkdown extends Component {
InlineMarkdown.propTypes = {
className: PropTypes.string,
data: PropTypes.string
data: PropTypes.string,
blockClassName: PropTypes.string
};
export default InlineMarkdown;

View File

@@ -33,7 +33,7 @@ class FilterMenuContent extends Component {
selectedFilterKey={selectedFilterKey}
onPress={onFilterSelect}
>
{filter.label}
{typeof filter.label === 'function' ? filter.label() : filter.label}
</FilterMenuItem>
);
})

View File

@@ -3,6 +3,7 @@ import React from 'react';
import Icon from 'Components/Icon';
import Link from 'Components/Link/Link';
import { icons } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './ModalContent.css';
function ModalContent(props) {
@@ -28,6 +29,7 @@ function ModalContent(props) {
<Icon
name={icons.CLOSE}
size={18}
title={translate('Close')}
/>
</Link>
}

View File

@@ -7,6 +7,7 @@ function ErrorPage(props) {
const {
version,
isLocalStorageSupported,
translationsError,
indexersError,
indexerStatusError,
indexerCategoriesError,
@@ -21,6 +22,8 @@ function ErrorPage(props) {
if (!isLocalStorageSupported) {
errorMessage = 'Local Storage is not supported or disabled. A plugin or private browsing may have disabled it.';
} else if (translationsError) {
errorMessage = getErrorMessage(translationsError, 'Failed to load translations from API');
} else if (indexersError) {
errorMessage = getErrorMessage(indexersError, 'Failed to load indexers from API');
} else if (indexerStatusError) {
@@ -55,6 +58,7 @@ function ErrorPage(props) {
ErrorPage.propTypes = {
version: PropTypes.string.isRequired,
isLocalStorageSupported: PropTypes.bool.isRequired,
translationsError: PropTypes.object,
indexersError: PropTypes.object,
indexerStatusError: PropTypes.object,
indexerCategoriesError: PropTypes.object,

View File

@@ -78,6 +78,7 @@ class PageHeader extends Component {
aria-label="Donate"
to="https://prowlarr.com/donate"
size={14}
title={translate('Donate')}
/>
<IconButton
className={styles.translate}

View File

@@ -24,6 +24,7 @@ function PageHeaderActionsMenu(props) {
<MenuButton className={styles.menuButton} aria-label="Menu Button">
<Icon
name={icons.INTERACTIVE}
title={translate('Menu')}
/>
</MenuButton>

View File

@@ -3,7 +3,7 @@ import React, { Component } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { createSelector } from 'reselect';
import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
import { fetchTranslations, saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
import { fetchIndexers } from 'Store/Actions/indexerActions';
import { fetchIndexerStatus } from 'Store/Actions/indexerStatusActions';
@@ -54,6 +54,7 @@ const selectIsPopulated = createSelector(
(state) => state.indexerStatus.isPopulated,
(state) => state.settings.indexerCategories.isPopulated,
(state) => state.system.status.isPopulated,
(state) => state.app.translations.isPopulated,
(
customFiltersIsPopulated,
tagsIsPopulated,
@@ -63,7 +64,8 @@ const selectIsPopulated = createSelector(
indexersIsPopulated,
indexerStatusIsPopulated,
indexerCategoriesIsPopulated,
systemStatusIsPopulated
systemStatusIsPopulated,
translationsIsPopulated
) => {
return (
customFiltersIsPopulated &&
@@ -74,7 +76,8 @@ const selectIsPopulated = createSelector(
indexersIsPopulated &&
indexerStatusIsPopulated &&
indexerCategoriesIsPopulated &&
systemStatusIsPopulated
systemStatusIsPopulated &&
translationsIsPopulated
);
}
);
@@ -89,6 +92,7 @@ const selectErrors = createSelector(
(state) => state.indexerStatus.error,
(state) => state.settings.indexerCategories.error,
(state) => state.system.status.error,
(state) => state.app.translations.error,
(
customFiltersError,
tagsError,
@@ -98,7 +102,8 @@ const selectErrors = createSelector(
indexersError,
indexerStatusError,
indexerCategoriesError,
systemStatusError
systemStatusError,
translationsError
) => {
const hasError = !!(
customFiltersError ||
@@ -109,7 +114,8 @@ const selectErrors = createSelector(
indexersError ||
indexerStatusError ||
indexerCategoriesError ||
systemStatusError
systemStatusError ||
translationsError
);
return {
@@ -122,7 +128,8 @@ const selectErrors = createSelector(
indexersError,
indexerStatusError,
indexerCategoriesError,
systemStatusError
systemStatusError,
translationsError
};
}
);
@@ -184,6 +191,9 @@ function createMapDispatchToProps(dispatch, props) {
dispatchFetchStatus() {
dispatch(fetchStatus());
},
dispatchFetchTranslations() {
dispatch(fetchTranslations());
},
onResize(dimensions) {
dispatch(saveDimensions(dimensions));
},
@@ -217,6 +227,7 @@ class PageConnector extends Component {
this.props.dispatchFetchUISettings();
this.props.dispatchFetchGeneralSettings();
this.props.dispatchFetchStatus();
this.props.dispatchFetchTranslations();
}
}
@@ -242,6 +253,7 @@ class PageConnector extends Component {
dispatchFetchUISettings,
dispatchFetchGeneralSettings,
dispatchFetchStatus,
dispatchFetchTranslations,
...otherProps
} = this.props;
@@ -282,6 +294,7 @@ PageConnector.propTypes = {
dispatchFetchUISettings: PropTypes.func.isRequired,
dispatchFetchGeneralSettings: PropTypes.func.isRequired,
dispatchFetchStatus: PropTypes.func.isRequired,
dispatchFetchTranslations: PropTypes.func.isRequired,
onSidebarVisibleChange: PropTypes.func.isRequired
};

View File

@@ -1,22 +1,19 @@
import React, { forwardRef, ReactNode, useCallback } from 'react';
import Scroller from 'Components/Scroller/Scroller';
import React, { ForwardedRef, forwardRef, ReactNode, useCallback } from 'react';
import Scroller, { OnScroll } from 'Components/Scroller/Scroller';
import ScrollDirection from 'Helpers/Props/ScrollDirection';
import { isLocked } from 'Utilities/scrollLock';
import styles from './PageContentBody.css';
interface PageContentBodyProps {
className: string;
innerClassName: string;
className?: string;
innerClassName?: string;
children: ReactNode;
initialScrollTop?: number;
onScroll?: (payload) => void;
onScroll?: (payload: OnScroll) => void;
}
const PageContentBody = forwardRef(
(
props: PageContentBodyProps,
ref: React.MutableRefObject<HTMLDivElement>
) => {
(props: PageContentBodyProps, ref: ForwardedRef<HTMLDivElement>) => {
const {
className = styles.contentBody,
innerClassName = styles.innerContentBody,
@@ -26,7 +23,7 @@ const PageContentBody = forwardRef(
} = props;
const onScrollWrapper = useCallback(
(payload) => {
(payload: OnScroll) => {
if (onScroll && !isLocked()) {
onScroll(payload);
}

View File

@@ -1,4 +1,5 @@
.jumpBar {
z-index: $pageJumpBarZIndex;
display: flex;
align-content: stretch;
align-items: stretch;

View File

@@ -1,6 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
import Alert from 'Components/Alert';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import { kinds } from 'Helpers/Props';
function PageSectionContent(props) {
const {
@@ -17,7 +19,7 @@ function PageSectionContent(props) {
);
} else if (!isFetching && !!error) {
return (
<div>{errorMessage}</div>
<Alert kind={kinds.DANGER}>{errorMessage}</Alert>
);
} else if (isPopulated && !error) {
return (

View File

@@ -20,12 +20,12 @@ const SIDEBAR_WIDTH = parseInt(dimensions.sidebarWidth);
const links = [
{
iconName: icons.MOVIE_CONTINUING,
title: translate('Indexers'),
title: () => translate('Indexers'),
to: '/',
alias: '/indexers',
children: [
{
title: translate('Stats'),
title: () => translate('Stats'),
to: '/indexers/stats'
}
]
@@ -33,47 +33,47 @@ const links = [
{
iconName: icons.SEARCH,
title: translate('Search'),
title: () => translate('Search'),
to: '/search'
},
{
iconName: icons.ACTIVITY,
title: translate('History'),
title: () => translate('History'),
to: '/history'
},
{
iconName: icons.SETTINGS,
title: translate('Settings'),
title: () => translate('Settings'),
to: '/settings',
children: [
{
title: translate('Indexers'),
title: () => translate('Indexers'),
to: '/settings/indexers'
},
{
title: translate('Apps'),
title: () => translate('Apps'),
to: '/settings/applications'
},
{
title: translate('DownloadClients'),
title: () => translate('DownloadClients'),
to: '/settings/downloadclients'
},
{
title: translate('Connect'),
title: () => translate('Connect'),
to: '/settings/connect'
},
{
title: translate('Tags'),
title: () => translate('Tags'),
to: '/settings/tags'
},
{
title: translate('General'),
title: () => translate('General'),
to: '/settings/general'
},
{
title: translate('UI'),
title: () => translate('UI'),
to: '/settings/ui'
}
]
@@ -81,32 +81,32 @@ const links = [
{
iconName: icons.SYSTEM,
title: translate('System'),
title: () => translate('System'),
to: '/system/status',
children: [
{
title: translate('Status'),
title: () => translate('Status'),
to: '/system/status',
statusComponent: HealthStatusConnector
},
{
title: translate('Tasks'),
title: () => translate('Tasks'),
to: '/system/tasks'
},
{
title: translate('Backup'),
title: () => translate('Backup'),
to: '/system/backup'
},
{
title: translate('Updates'),
title: () => translate('Updates'),
to: '/system/updates'
},
{
title: translate('Events'),
title: () => translate('Events'),
to: '/system/events'
},
{
title: translate('LogFiles'),
title: () => translate('LogFiles'),
to: '/system/logs/files'
}
]

View File

@@ -64,7 +64,7 @@ class PageSidebarItem extends Component {
}
<span className={isChildItem ? styles.noIcon : null}>
{title}
{typeof title === 'function' ? title() : title}
</span>
{
@@ -88,7 +88,7 @@ class PageSidebarItem extends Component {
PageSidebarItem.propTypes = {
iconName: PropTypes.object,
title: PropTypes.string.isRequired,
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
to: PropTypes.string.isRequired,
isActive: PropTypes.bool,
isActiveParent: PropTypes.bool,

View File

@@ -1,9 +1,21 @@
import classNames from 'classnames';
import { throttle } from 'lodash';
import React, { forwardRef, ReactNode, useEffect, useRef } from 'react';
import React, {
ForwardedRef,
forwardRef,
MutableRefObject,
ReactNode,
useEffect,
useRef,
} from 'react';
import ScrollDirection from 'Helpers/Props/ScrollDirection';
import styles from './Scroller.css';
export interface OnScroll {
scrollLeft: number;
scrollTop: number;
}
interface ScrollerProps {
className?: string;
scrollDirection?: ScrollDirection;
@@ -12,11 +24,11 @@ interface ScrollerProps {
scrollTop?: number;
initialScrollTop?: number;
children?: ReactNode;
onScroll?: (payload) => void;
onScroll?: (payload: OnScroll) => void;
}
const Scroller = forwardRef(
(props: ScrollerProps, ref: React.MutableRefObject<HTMLDivElement>) => {
(props: ScrollerProps, ref: ForwardedRef<HTMLDivElement>) => {
const {
className,
autoFocus = false,
@@ -30,7 +42,7 @@ const Scroller = forwardRef(
} = props;
const internalRef = useRef();
const currentRef = ref ?? internalRef;
const currentRef = (ref as MutableRefObject<HTMLDivElement>) ?? internalRef;
useEffect(
() => {

View File

@@ -1,58 +1,66 @@
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import React from 'react';
import { useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import formatDateTime from 'Utilities/Date/formatDateTime';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
import TableRowCell from './TableRowCell';
import styles from './RelativeDateCell.css';
class RelativeDateCell extends PureComponent {
function createRelativeDateCellSelector() {
return createSelector(createUISettingsSelector(), (uiSettings) => {
return {
showRelativeDates: uiSettings.showRelativeDates,
shortDateFormat: uiSettings.shortDateFormat,
longDateFormat: uiSettings.longDateFormat,
timeFormat: uiSettings.timeFormat
};
});
}
function RelativeDateCell(props) {
//
// Render
render() {
const {
className,
date,
includeSeconds,
showRelativeDates,
shortDateFormat,
longDateFormat,
timeFormat,
component: Component,
dispatch,
...otherProps
} = this.props;
const {
className,
date,
includeSeconds,
component: Component,
dispatch,
...otherProps
} = props;
if (!date) {
return (
<Component
className={className}
{...otherProps}
/>
);
}
const { showRelativeDates, shortDateFormat, longDateFormat, timeFormat } =
useSelector(createRelativeDateCellSelector());
return (
<Component
className={className}
title={formatDateTime(date, longDateFormat, timeFormat, { includeSeconds, includeRelativeDay: !showRelativeDates })}
{...otherProps}
>
{getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds, timeForToday: true })}
</Component>
);
if (!date) {
return <Component className={className} {...otherProps} />;
}
return (
<Component
className={className}
title={formatDateTime(date, longDateFormat, timeFormat, {
includeSeconds,
includeRelativeDay: !showRelativeDates
})}
{...otherProps}
>
{getRelativeDate(date, shortDateFormat, showRelativeDates, {
timeFormat,
includeSeconds,
timeForToday: true
})}
</Component>
);
}
RelativeDateCell.propTypes = {
className: PropTypes.string.isRequired,
date: PropTypes.string,
includeSeconds: PropTypes.bool.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
component: PropTypes.elementType,
dispatch: PropTypes.func
};

View File

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

View File

@@ -1,25 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import Link from 'Components/Link/Link';
import TableRowCell from './TableRowCell';
import styles from './TableRowCellButton.css';
function TableRowCellButton({ className, ...otherProps }) {
return (
<Link
className={className}
component={TableRowCell}
{...otherProps}
/>
);
}
TableRowCellButton.propTypes = {
className: PropTypes.string.isRequired
};
TableRowCellButton.defaultProps = {
className: styles.cell
};
export default TableRowCellButton;

View File

@@ -0,0 +1,19 @@
import React, { ReactNode } from 'react';
import Link, { LinkProps } from 'Components/Link/Link';
import TableRowCell from './TableRowCell';
import styles from './TableRowCellButton.css';
interface TableRowCellButtonProps extends LinkProps {
className?: string;
children: ReactNode;
}
function TableRowCellButton(props: TableRowCellButtonProps) {
const { className = styles.cell, ...otherProps } = props;
return (
<Link className={className} component={TableRowCell} {...otherProps} />
);
}
export default TableRowCellButton;

View File

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

View File

@@ -1,8 +1,12 @@
import React from 'react';
type PropertyFunction<T> = () => T;
interface Column {
name: string;
label: string;
columnLabel: string;
isSortable: boolean;
label: string | PropertyFunction<string> | React.ReactNode;
columnLabel?: string;
isSortable?: boolean;
isVisible: boolean;
isModifiable?: boolean;
}

View File

@@ -107,7 +107,7 @@ function Table(props) {
{...getTableHeaderCellProps(otherProps)}
{...column}
>
{column.label}
{typeof column.label === 'function' ? column.label() : column.label}
</TableHeaderCell>
);
})
@@ -121,6 +121,7 @@ function Table(props) {
}
Table.propTypes = {
...TableHeaderCell.props,
className: PropTypes.string,
horizontalScroll: PropTypes.bool.isRequired,
selectAll: PropTypes.bool.isRequired,

View File

@@ -30,6 +30,7 @@ class TableHeaderCell extends Component {
const {
className,
name,
label,
columnLabel,
isSortable,
isVisible,
@@ -53,7 +54,8 @@ class TableHeaderCell extends Component {
{...otherProps}
component="th"
className={className}
title={columnLabel}
label={typeof label === 'function' ? label() : label}
title={typeof columnLabel === 'function' ? columnLabel() : columnLabel}
onPress={this.onPress}
>
{children}
@@ -77,7 +79,8 @@ class TableHeaderCell extends Component {
TableHeaderCell.propTypes = {
className: PropTypes.string,
name: PropTypes.string.isRequired,
columnLabel: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.node]),
columnLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
isSortable: PropTypes.bool,
isVisible: PropTypes.bool,
isModifiable: PropTypes.bool,

View File

@@ -35,7 +35,7 @@ function TableOptionsColumn(props) {
isDisabled={isModifiable === false}
onChange={onVisibleChange}
/>
{label}
{typeof label === 'function' ? label() : label}
</label>
{
@@ -56,7 +56,7 @@ function TableOptionsColumn(props) {
TableOptionsColumn.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
isVisible: PropTypes.bool.isRequired,
isModifiable: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,

View File

@@ -112,7 +112,7 @@ class TableOptionsColumnDragSource extends Component {
<TableOptionsColumn
name={name}
label={label}
label={typeof label === 'function' ? label() : label}
isVisible={isVisible}
isModifiable={isModifiable}
index={index}
@@ -138,7 +138,7 @@ class TableOptionsColumnDragSource extends Component {
TableOptionsColumnDragSource.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired,
isVisible: PropTypes.bool.isRequired,
isModifiable: PropTypes.bool.isRequired,
index: PropTypes.number.isRequired,

View File

@@ -192,7 +192,7 @@ class TableOptionsModal extends Component {
<TableOptionsColumnDragSource
key={name}
name={name}
label={label || columnLabel}
label={columnLabel || label}
isVisible={isVisible}
isModifiable={true}
index={index}
@@ -210,7 +210,7 @@ class TableOptionsModal extends Component {
<TableOptionsColumn
key={name}
name={name}
label={label || columnLabel}
label={columnLabel || label}
isVisible={isVisible}
index={index}
isModifiable={false}

View File

@@ -39,7 +39,8 @@ class VirtualTable extends Component {
super(props, context);
this.state = {
width: 0
width: 0,
scrollRestored: false
};
this._grid = null;
@@ -48,20 +49,25 @@ class VirtualTable extends Component {
componentDidUpdate(prevProps, prevState) {
const {
items,
scrollIndex
scrollIndex,
scrollTop
} = this.props;
const {
width
width,
scrollRestored
} = this.state;
if (this._grid &&
(prevState.width !== width ||
hasDifferentItemsOrOrder(prevProps.items, items))) {
if (this._grid && (prevState.width !== width || hasDifferentItemsOrOrder(prevProps.items, items))) {
// recomputeGridSize also forces Grid to discard its cache of rendered cells
this._grid.recomputeGridSize();
}
if (this._grid && scrollTop !== undefined && scrollTop !== 0 && !scrollRestored) {
this.setState({ scrollRestored: true });
this._grid.scrollToPosition({ scrollTop });
}
if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) {
this._grid.scrollToCell({
rowIndex: scrollIndex,
@@ -98,6 +104,7 @@ class VirtualTable extends Component {
focusScroller,
header,
headerHeight,
rowHeight,
rowRenderer,
...otherProps
} = this.props;
@@ -141,6 +148,7 @@ class VirtualTable extends Component {
{header}
<div ref={registerChild}>
<Grid
{...otherProps}
ref={this.setGridRef}
autoContainerWidth={true}
autoHeight={true}
@@ -148,7 +156,7 @@ class VirtualTable extends Component {
width={width}
height={height}
headerHeight={height - headerHeight}
rowHeight={ROW_HEIGHT}
rowHeight={rowHeight}
rowCount={items.length}
columnCount={1}
columnWidth={width}
@@ -162,7 +170,6 @@ class VirtualTable extends Component {
className={styles.tableBodyContainer}
style={gridStyle}
containerStyle={containerStyle}
{...otherProps}
/>
</div>
</Scroller>
@@ -180,16 +187,19 @@ VirtualTable.propTypes = {
className: PropTypes.string.isRequired,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
scrollIndex: PropTypes.number,
scrollTop: PropTypes.number,
scroller: PropTypes.instanceOf(Element).isRequired,
focusScroller: PropTypes.bool.isRequired,
header: PropTypes.node.isRequired,
headerHeight: PropTypes.number.isRequired,
rowRenderer: PropTypes.func.isRequired
rowRenderer: PropTypes.func.isRequired,
rowHeight: PropTypes.number.isRequired
};
VirtualTable.defaultProps = {
className: styles.tableContainer,
headerHeight: 38,
rowHeight: ROW_HEIGHT,
focusScroller: true
};

View File

@@ -6,37 +6,51 @@ import translate from 'Utilities/String/translate';
export const shortcuts = {
OPEN_KEYBOARD_SHORTCUTS_MODAL: {
key: '?',
name: translate('OpenThisModal')
get name() {
return translate('OpenThisModal');
}
},
CLOSE_MODAL: {
key: 'Esc',
name: translate('CloseCurrentModal')
get name() {
return translate('CloseCurrentModal');
}
},
ACCEPT_CONFIRM_MODAL: {
key: 'Enter',
name: translate('AcceptConfirmationModal')
get name() {
return translate('AcceptConfirmationModal');
}
},
MOVIE_SEARCH_INPUT: {
key: 's',
name: translate('FocusSearchBox')
get name() {
return translate('FocusSearchBox');
}
},
SAVE_SETTINGS: {
key: 'mod+s',
name: translate('SaveSettings')
get name() {
return translate('SaveSettings');
}
},
SCROLL_TOP: {
key: 'mod+home',
name: translate('MovieIndexScrollTop')
get name() {
return translate('MovieIndexScrollTop');
}
},
SCROLL_BOTTOM: {
key: 'mod+end',
name: translate('MovieIndexScrollBottom')
get name() {
return translate('MovieIndexScrollBottom');
}
}
};
@@ -67,8 +81,10 @@ function keyboardShortcuts(WrappedComponent) {
};
unbindShortcut = (key) => {
delete this._mousetrapBindings[key];
this._mousetrap.unbind(key);
if (this._mousetrap != null) {
delete this._mousetrapBindings[key];
this._mousetrap.unbind(key);
}
};
unbindAllShortcuts = () => {

View File

@@ -1,24 +1,30 @@
import PropTypes from 'prop-types';
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import scrollPositions from 'Store/scrollPositions';
function withScrollPosition(WrappedComponent, scrollPositionKey) {
function ScrollPosition(props) {
interface WrappedComponentProps {
initialScrollTop: number;
}
interface ScrollPositionProps {
history: RouteComponentProps['history'];
location: RouteComponentProps['location'];
match: RouteComponentProps['match'];
}
function withScrollPosition(
WrappedComponent: React.FC<WrappedComponentProps>,
scrollPositionKey: string
) {
function ScrollPosition(props: ScrollPositionProps) {
const { history } = props;
const initialScrollTop =
history.action === 'POP' ||
(history.location.state && history.location.state.restoreScrollPosition)
? scrollPositions[scrollPositionKey]
: 0;
history.action === 'POP' ? scrollPositions[scrollPositionKey] : 0;
return <WrappedComponent {...props} initialScrollTop={initialScrollTop} />;
}
ScrollPosition.propTypes = {
history: PropTypes.object.isRequired,
};
return ScrollPosition;
}

View File

@@ -11,7 +11,7 @@ import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import { authenticationMethodOptions, authenticationRequiredOptions, authenticationRequiredWarning } from 'Settings/General/SecuritySettings';
import { authenticationMethodOptions, authenticationRequiredOptions } from 'Settings/General/SecuritySettings';
import translate from 'Utilities/String/translate';
import styles from './AuthenticationRequiredModalContent.css';
@@ -34,7 +34,8 @@ function AuthenticationRequiredModalContent(props) {
authenticationMethod,
authenticationRequired,
username,
password
password,
passwordConfirmation
} = settings;
const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none';
@@ -63,71 +64,75 @@ function AuthenticationRequiredModalContent(props) {
className={styles.authRequiredAlert}
kind={kinds.WARNING}
>
{authenticationRequiredWarning}
{translate('AuthenticationRequiredWarning')}
</Alert>
{
isPopulated && !error ?
<div>
<FormGroup>
<FormLabel>{translate('Authentication')}</FormLabel>
<FormLabel>{translate('AuthenticationMethod')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText')}
helpTextWarning={authenticationMethod.value === 'none' ? translate('AuthenticationMethodHelpTextWarning') : undefined}
helpLink="https://wiki.servarr.com/prowlarr/faq#forced-authentication"
onChange={onInputChange}
{...authenticationMethod}
/>
</FormGroup>
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
<FormGroup>
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationRequired"
values={authenticationRequiredOptions}
helpText={translate('AuthenticationRequiredHelpText')}
onChange={onInputChange}
{...authenticationRequired}
/>
</FormGroup> :
null
}
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationRequired"
values={authenticationRequiredOptions}
helpText={translate('AuthenticationRequiredHelpText')}
onChange={onInputChange}
{...authenticationRequired}
/>
</FormGroup>
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Username')}</FormLabel>
<FormGroup>
<FormLabel>{translate('Username')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="username"
onChange={onInputChange}
{...username}
/>
</FormGroup> :
null
}
<FormInputGroup
type={inputTypes.TEXT}
name="username"
onChange={onInputChange}
helpTextWarning={username?.value ? undefined : translate('AuthenticationRequiredUsernameHelpTextWarning')}
{...username}
/>
</FormGroup>
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Password')}</FormLabel>
<FormGroup>
<FormLabel>{translate('Password')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="password"
onChange={onInputChange}
{...password}
/>
</FormGroup> :
null
}
<FormInputGroup
type={inputTypes.PASSWORD}
name="password"
onChange={onInputChange}
helpTextWarning={password?.value ? undefined : translate('AuthenticationRequiredPasswordHelpTextWarning')}
{...password}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="passwordConfirmation"
onChange={onInputChange}
helpTextWarning={passwordConfirmation?.value ? undefined : translate('AuthenticationRequiredPasswordConfirmationHelpTextWarning')}
{...passwordConfirmation}
/>
</FormGroup>
</div> :
null
}

View File

@@ -0,0 +1,11 @@
import { useEffect, useRef } from 'react';
export default function usePrevious<T>(value: T): T | undefined {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}

View File

@@ -72,8 +72,10 @@ import {
faLanguage as fasLanguage,
faLaptop as fasLaptop,
faLevelUpAlt as fasLevelUpAlt,
faListCheck as fasListCheck,
faLocationArrow as fasLocationArrow,
faLock as fasLock,
faMagnet as fasMagnet,
faMedkit as fasMedkit,
faMinus as fasMinus,
faMusic as fasMusic,
@@ -180,6 +182,8 @@ export const INTERACTIVE = fasUser;
export const KEYBOARD = farKeyboard;
export const LOCK = fasLock;
export const LOGOUT = fasSignOutAlt;
export const MAGNET = fasMagnet;
export const MANAGE = fasListCheck;
export const MEDIA_INFO = farFileInvoice;
export const MISSING = fasExclamationTriangle;
export const MONITORED = fasBookmark;

View File

@@ -9,6 +9,8 @@ export const KEY_VALUE_LIST = 'keyValueList';
export const INFO = 'info';
export const MOVIE_MONITORED_SELECT = 'movieMonitoredSelect';
export const CATEGORY_SELECT = 'newznabCategorySelect';
export const DOWNLOAD_CLIENT_SELECT = 'downloadClientSelect';
export const FLOAT = 'float';
export const NUMBER = 'number';
export const OAUTH = 'oauth';
export const PASSWORD = 'password';
@@ -34,6 +36,7 @@ export const all = [
INFO,
MOVIE_MONITORED_SELECT,
CATEGORY_SELECT,
FLOAT,
NUMBER,
OAUTH,
PASSWORD,

View File

@@ -18,6 +18,8 @@ function HistoryDetails(props) {
query,
queryResults,
categories,
limit,
offset,
source,
url
} = data;
@@ -31,43 +33,66 @@ function HistoryDetails(props) {
/>
{
!!indexer &&
indexer ?
<DescriptionListItem
title={translate('Indexer')}
data={indexer.name}
/>
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('QueryResults')}
data={queryResults ? queryResults : '-'}
/>
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('Categories')}
data={categories ? categories : '-'}
/>
/> :
null
}
{
!!data &&
limit ?
<DescriptionListItem
title={translate('Limit')}
data={limit}
/> :
null
}
{
offset ?
<DescriptionListItem
title={translate('Offset')}
data={offset}
/> :
null
}
{
data ?
<DescriptionListItem
title={translate('Source')}
data={source}
/>
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('Url')}
data={url ? <Link to={url}>{translate('Link')}</Link> : '-'}
/>
/> :
null
}
</DescriptionList>
);
@@ -76,42 +101,46 @@ function HistoryDetails(props) {
if (eventType === 'releaseGrabbed') {
const {
source,
title,
grabTitle,
url
} = data;
return (
<DescriptionList>
{
!!indexer &&
indexer ?
<DescriptionListItem
title={translate('Indexer')}
data={indexer.name}
/>
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('Source')}
data={source ? source : '-'}
/>
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('Title')}
data={title ? title : '-'}
/>
title={translate('GrabTitle')}
data={grabTitle ? grabTitle : '-'}
/> :
null
}
{
!!data &&
data ?
<DescriptionListItem
title={translate('Url')}
data={url ? <Link to={url}>{translate('Link')}</Link> : '-'}
/>
/> :
null
}
</DescriptionList>
);
@@ -124,11 +153,12 @@ function HistoryDetails(props) {
title={translate('Auth')}
>
{
!!indexer &&
indexer ?
<DescriptionListItem
title={translate('Indexer')}
data={indexer.name}
/>
/> :
null
}
</DescriptionList>
);

View File

@@ -1,5 +0,0 @@
.markAsFailedButton {
composes: button from '~Components/Link/Button.css';
margin-right: auto;
}

View File

@@ -1,16 +1,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import Button from 'Components/Link/Button';
import SpinnerButton from 'Components/Link/SpinnerButton';
import Modal from 'Components/Modal/Modal';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import HistoryDetails from './HistoryDetails';
import styles from './HistoryDetailsModal.css';
function getHeaderTitle(eventType) {
switch (eventType) {
@@ -33,10 +30,8 @@ function HistoryDetailsModal(props) {
eventType,
indexer,
data,
isMarkingAsFailed,
shortDateFormat,
timeFormat,
onMarkAsFailedPress,
onModalClose
} = props;
@@ -61,18 +56,6 @@ function HistoryDetailsModal(props) {
</ModalBody>
<ModalFooter>
{
eventType === 'grabbed' &&
<SpinnerButton
className={styles.markAsFailedButton}
kind={kinds.DANGER}
isSpinning={isMarkingAsFailed}
onPress={onMarkAsFailedPress}
>
Mark as Failed
</SpinnerButton>
}
<Button
onPress={onModalClose}
>
@@ -89,10 +72,8 @@ HistoryDetailsModal.propTypes = {
eventType: PropTypes.string.isRequired,
indexer: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
isMarkingAsFailed: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
onMarkAsFailedPress: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
import ConfirmModal from 'Components/Modal/ConfirmModal';
@@ -121,9 +122,9 @@ class History extends Component {
{
!isFetchingAny && hasError &&
<div>
<Alert kind={kinds.DANGER}>
{translate('UnableToLoadHistory')}
</div>
</Alert>
}
{
@@ -131,9 +132,9 @@ class History extends Component {
// wait for the episodes to populate because they are never coming.
isPopulated && !hasError && !items.length &&
<div>
No history found
</div>
<Alert kind={kinds.INFO}>
{translate('NoHistoryFound')}
</Alert>
}
{

View File

@@ -62,6 +62,7 @@ class HistoryOptions extends Component {
<FormInputGroup
type={inputTypes.NUMBER}
name="historyCleanupDays"
unit={translate('days')}
value={historyCleanupDays}
helpText={translate('HistoryCleanupDaysHelpText')}
helpTextWarning={translate('HistoryCleanupDaysHelpTextWarning')}

View File

@@ -26,9 +26,7 @@
width: 70px;
}
.parameters {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
.parametersContent {
display: flex;
flex-wrap: wrap;
}

View File

@@ -6,7 +6,7 @@ interface CssExports {
'details': string;
'elapsedTime': string;
'indexer': string;
'parameters': string;
'parametersContent': string;
'query': string;
'releaseGroup': string;
'source': string;

View File

@@ -1,17 +1,94 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import RelativeDateCell from 'Components/Table/Cells/RelativeDateCell';
import TableRowCell from 'Components/Table/Cells/TableRowCell';
import TableRow from 'Components/Table/TableRow';
import { icons } from 'Helpers/Props';
import { icons, kinds } from 'Helpers/Props';
import CapabilitiesLabel from 'Indexer/Index/Table/CapabilitiesLabel';
import translate from 'Utilities/String/translate';
import HistoryDetailsModal from './Details/HistoryDetailsModal';
import * as historyDataTypes from './historyDataTypes';
import HistoryEventTypeCell from './HistoryEventTypeCell';
import HistoryRowParameter from './HistoryRowParameter';
import styles from './HistoryRow.css';
export const historyParameters = [
{ key: historyDataTypes.IMDB_ID, title: 'IMDb' },
{ key: historyDataTypes.TMDB_ID, title: 'TMDb' },
{ key: historyDataTypes.TVDB_ID, title: 'TVDb' },
{ key: historyDataTypes.TRAKT_ID, title: 'Trakt' },
{ key: historyDataTypes.R_ID, title: 'TvRage' },
{ key: historyDataTypes.TVMAZE_ID, title: 'TvMaze' },
{
key: historyDataTypes.SEASON,
get title() {
return translate('Season');
}
},
{
key: historyDataTypes.EPISODE,
get title() {
return translate('Episode');
}
},
{
key: historyDataTypes.ARTIST,
get title() {
return translate('Artist');
}
},
{
key: historyDataTypes.ALBUM,
get title() {
return translate('Album');
}
},
{
key: historyDataTypes.LABEL,
get title() {
return translate('Label');
}
},
{
key: historyDataTypes.TRACK,
get title() {
return translate('Track');
}
},
{
key: historyDataTypes.YEAR,
get title() {
return translate('Year');
}
},
{
key: historyDataTypes.GENRE,
get title() {
return translate('Genre');
}
},
{
key: historyDataTypes.AUTHOR,
get title() {
return translate('Author');
}
},
{
key: historyDataTypes.TITLE,
get title() {
return translate('Title');
}
},
{
key: historyDataTypes.PUBLISHER,
get title() {
return translate('Publisher');
}
}
];
class HistoryRow extends Component {
//
@@ -44,15 +121,52 @@ class HistoryRow extends Component {
data
} = this.props;
const { query, queryType, limit, offset } = data;
let searchQuery = query;
let categories = [];
if (data.categories) {
categories = data.categories.split(',').map((item) => {
return parseInt(item);
});
categories = data.categories.split(',').map((item) => parseInt(item));
}
this.props.onSearchPress(data.query, indexer.id, categories);
const searchParams = [
historyDataTypes.IMDB_ID,
historyDataTypes.TMDB_ID,
historyDataTypes.TVDB_ID,
historyDataTypes.TRAKT_ID,
historyDataTypes.R_ID,
historyDataTypes.TVMAZE_ID,
historyDataTypes.SEASON,
historyDataTypes.EPISODE,
historyDataTypes.ARTIST,
historyDataTypes.ALBUM,
historyDataTypes.LABEL,
historyDataTypes.TRACK,
historyDataTypes.YEAR,
historyDataTypes.GENRE,
historyDataTypes.AUTHOR,
historyDataTypes.TITLE,
historyDataTypes.PUBLISHER
]
.reduce((acc, key) => {
if (key in data && data[key].length > 0) {
const value = data[key];
acc.push({ key, value });
}
return acc;
}, [])
.map((item) => `{${item.key}:${item.value}}`)
.join('')
;
if (searchParams.length > 0) {
searchQuery += `${searchParams}`;
}
this.props.onSearchPress(searchQuery, indexer.id, categories, queryType, parseInt(limit), parseInt(offset));
};
onDetailsPress = () => {
@@ -84,6 +198,8 @@ class HistoryRow extends Component {
return null;
}
const parameters = historyParameters.filter((parameter) => parameter.key in data && data[parameter.key]);
return (
<TableRow>
{
@@ -133,162 +249,19 @@ class HistoryRow extends Component {
if (name === 'parameters') {
return (
<TableRowCell
key={name}
className={styles.parameters}
>
{
data.imdbId ?
<HistoryRowParameter
title='IMDb'
value={data.imdbId}
/> :
null
}
{
data.tmdbId ?
<HistoryRowParameter
title='TMDb'
value={data.tmdbId}
/> :
null
}
{
data.tvdbId ?
<HistoryRowParameter
title='TVDb'
value={data.tvdbId}
/> :
null
}
{
data.traktId ?
<HistoryRowParameter
title='Trakt'
value={data.traktId}
/> :
null
}
{
data.rId ?
<HistoryRowParameter
title='TvRage'
value={data.rId}
/> :
null
}
{
data.tvMazeId ?
<HistoryRowParameter
title='TvMaze'
value={data.tvMazeId}
/> :
null
}
{
data.season ?
<HistoryRowParameter
title={translate('Season')}
value={data.season}
/> :
null
}
{
data.episode ?
<HistoryRowParameter
title={translate('Episode')}
value={data.episode}
/> :
null
}
{
data.artist ?
<HistoryRowParameter
title={translate('Artist')}
value={data.artist}
/> :
null
}
{
data.album ?
<HistoryRowParameter
title={translate('Album')}
value={data.album}
/> :
null
}
{
data.label ?
<HistoryRowParameter
title={translate('Label')}
value={data.label}
/> :
null
}
{
data.track ?
<HistoryRowParameter
title={translate('Track')}
value={data.track}
/> :
null
}
{
data.year ?
<HistoryRowParameter
title={translate('Year')}
value={data.year}
/> :
null
}
{
data.genre ?
<HistoryRowParameter
title={translate('Genre')}
value={data.genre}
/> :
null
}
{
data.author ?
<HistoryRowParameter
title={translate('Author')}
value={data.author}
/> :
null
}
{
data.bookTitle ?
<HistoryRowParameter
title={translate('Book')}
value={data.bookTitle}
/> :
null
}
{
data.publisher ?
<HistoryRowParameter
title={translate('Publisher')}
value={data.publisher}
/> :
null
}
<TableRowCell key={name}>
<div className={styles.parametersContent}>
{parameters.map((parameter) => {
return (
<HistoryRowParameter
key={parameter.key}
title={parameter.title}
value={data[parameter.key]}
/>
);
}
)}
</div>
</TableRowCell>
);
}
@@ -300,8 +273,25 @@ class HistoryRow extends Component {
className={styles.indexer}
>
{
data.title ?
data.title :
data.grabTitle ?
data.grabTitle :
null
}
</TableRowCell>
);
}
if (name === 'queryType') {
return (
<TableRowCell
key={name}
className={styles.query}
>
{
data.queryType ?
<Label kind={kinds.INFO}>
{data.queryType}
</Label> :
null
}
</TableRowCell>
@@ -363,7 +353,7 @@ class HistoryRow extends Component {
if (name === 'date') {
return (
<RelativeDateCellConnector
<RelativeDateCell
key={name}
date={date}
className={styles.date}
@@ -377,6 +367,12 @@ class HistoryRow extends Component {
key={name}
className={styles.details}
>
<IconButton
name={icons.INFO}
onPress={this.onDetailsPress}
title={translate('HistoryDetails')}
/>
{
eventType === 'indexerQuery' ?
<IconButton
@@ -386,11 +382,6 @@ class HistoryRow extends Component {
/> :
null
}
<IconButton
name={icons.INFO}
onPress={this.onDetailsPress}
title={translate('HistoryDetails')}
/>
</TableRowCell>
);
}

View File

@@ -1,4 +1,5 @@
import { push } from 'connected-react-router';
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
@@ -48,8 +49,15 @@ class HistoryRowConnector extends Component {
//
// Listeners
onSearchPress = (term, indexerId, categories) => {
this.props.setSearchDefault({ searchQuery: term, searchIndexerIds: [indexerId], searchCategories: categories });
onSearchPress = (query, indexerId, categories, type, limit, offset) => {
this.props.setSearchDefault(_.pickBy({
searchQuery: query,
searchIndexerIds: [indexerId],
searchCategories: categories,
searchType: type,
searchLimit: limit,
searchOffset: offset
}));
this.props.push(`${window.Prowlarr.urlBase}/search`);
};

View File

@@ -1,43 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import styles from './HistoryRowParameter.css';
class HistoryRowParameter extends Component {
//
// Render
render() {
const {
title,
value
} = this.props;
return (
<div className={styles.parameter}>
<div className={styles.info}>
<span>
{
title
}
</span>
</div>
<div
className={styles.value}
>
{
value
}
</div>
</div>
);
}
}
HistoryRowParameter.propTypes = {
title: PropTypes.string.isRequired,
value: PropTypes.string.isRequired
};
export default HistoryRowParameter;

View File

@@ -0,0 +1,44 @@
import React from 'react';
import Link from 'Components/Link/Link';
import styles from './HistoryRowParameter.css';
interface HistoryRowParameterProps {
title: string;
value: string;
}
function HistoryRowParameter(props: HistoryRowParameterProps) {
const { title, value } = props;
const type = title.toLowerCase();
let link = null;
if (type === 'imdb') {
link = <Link to={`https://imdb.com/title/${value}/`}>{value}</Link>;
} else if (type === 'tmdb') {
link = (
<Link to={`https://www.themoviedb.org/movie/${value}`}>{value}</Link>
);
} else if (type === 'tvdb') {
link = (
<Link to={`https://www.thetvdb.com/?tab=series&id=${value}`}>
{value}
</Link>
);
} else if (type === 'tvmaze') {
link = <Link to={`https://www.tvmaze.com/shows/${value}/_`}>{value}</Link>;
}
return (
<div className={styles.parameter}>
<div className={styles.info}>
<span>{title}</span>
</div>
<div className={styles.value}>{link ? link : value}</div>
</div>
);
}
export default HistoryRowParameter;

View File

@@ -0,0 +1,17 @@
export const IMDB_ID = 'imdbId';
export const TMDB_ID = 'tmdbId';
export const TVDB_ID = 'tvdbId';
export const TRAKT_ID = 'traktId';
export const R_ID = 'rId';
export const TVMAZE_ID = 'tvMazeId';
export const SEASON = 'season';
export const EPISODE = 'episode';
export const ARTIST = 'artist';
export const ALBUM = 'album';
export const LABEL = 'label';
export const TRACK = 'track';
export const YEAR = 'year';
export const GENRE = 'genre';
export const AUTHOR = 'author';
export const TITLE = 'title';
export const PUBLISHER = 'publisher';

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import AddIndexerModalContentConnector from './AddIndexerModalContentConnector';
import styles from './AddIndexerModal.css';
@@ -8,6 +9,7 @@ function AddIndexerModal({ isOpen, onModalClose, onSelectIndexer, ...otherProps
return (
<Modal
isOpen={isOpen}
size={sizes.EXTRA_LARGE}
onModalClose={onModalClose}
className={styles.modal}
>

View File

@@ -52,17 +52,22 @@
}
@media only screen and (max-width: $breakpointSmall) {
.filterInput {
margin-bottom: 5px;
}
.alert {
display: none;
}
.filterRow {
flex-direction: column;
display: block;
margin-bottom: 10px;
}
.filterContainer {
margin-right: 0;
margin-bottom: 12px;
margin-bottom: 5px;
}
.scroller {
@@ -71,3 +76,30 @@
margin-left: -30px;
}
}
@media only screen and (min-width: $breakpointSmall) {
.filterContainer {
max-width: 50%;
}
}
.modalFooter {
composes: modalFooter from '~Components/Modal/ModalFooter.css';
justify-content: space-between;
}
.available {
font-weight: bold;
}
@media only screen and (max-width: $breakpointExtraSmall) {
.modalFooter {
flex-direction: column;
gap: 10px;
}
.available {
display: none;
}
}

View File

@@ -2,12 +2,14 @@
// Please do not change this file!
interface CssExports {
'alert': string;
'available': string;
'filterContainer': string;
'filterInput': string;
'filterLabel': string;
'filterRow': string;
'indexers': string;
'modalBody': string;
'modalFooter': string;
'scroller': string;
}
export const cssExports: CssExports;

View File

@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
import EnhancedSelectInput from 'Components/Form/EnhancedSelectInput';
import NewznabCategorySelectInputConnector from 'Components/Form/NewznabCategorySelectInputConnector';
import TextInput from 'Components/Form/TextInput';
import Button from 'Components/Link/Button';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
@@ -15,39 +16,45 @@ import TableBody from 'Components/Table/TableBody';
import { kinds, scrollDirections } from 'Helpers/Props';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import translate from 'Utilities/String/translate';
import SelectIndexerRowConnector from './SelectIndexerRowConnector';
import SelectIndexerRow from './SelectIndexerRow';
import styles from './AddIndexerModalContent.css';
const columns = [
{
name: 'protocol',
label: translate('Protocol'),
label: () => translate('Protocol'),
isSortable: true,
isVisible: true
},
{
name: 'name',
label: translate('Name'),
name: 'sortName',
label: () => translate('Name'),
isSortable: true,
isVisible: true
},
{
name: 'language',
label: translate('Language'),
label: () => translate('Language'),
isSortable: true,
isVisible: true
},
{
name: 'description',
label: translate('Description'),
label: () => translate('Description'),
isSortable: false,
isVisible: true
},
{
name: 'privacy',
label: translate('Privacy'),
label: () => translate('Privacy'),
isSortable: true,
isVisible: true
},
{
name: 'categories',
label: () => translate('Categories'),
isSortable: false,
isVisible: true
}
];
@@ -65,15 +72,21 @@ const protocols = [
const privacyLevels = [
{
key: 'private',
value: translate('Private')
get value() {
return translate('Private');
}
},
{
key: 'semiPrivate',
value: translate('SemiPrivate')
get value() {
return translate('SemiPrivate');
}
},
{
key: 'public',
value: translate('Public')
get value() {
return translate('Public');
}
}
];
@@ -89,7 +102,8 @@ class AddIndexerModalContent extends Component {
filter: '',
filterProtocols: [],
filterLanguages: [],
filterPrivacyLevels: []
filterPrivacyLevels: [],
filterCategories: []
};
}
@@ -121,7 +135,13 @@ class AddIndexerModalContent extends Component {
.map((language) => ({ key: language, value: language }));
const filteredIndexers = indexers.filter((indexer) => {
const { filter, filterProtocols, filterLanguages, filterPrivacyLevels } = this.state;
const {
filter,
filterProtocols,
filterLanguages,
filterPrivacyLevels,
filterCategories
} = this.state;
if (!indexer.name.toLowerCase().includes(filter.toLocaleLowerCase()) && !indexer.description.toLowerCase().includes(filter.toLocaleLowerCase())) {
return false;
@@ -139,6 +159,18 @@ class AddIndexerModalContent extends Component {
return false;
}
if (filterCategories.length) {
const { categories = [] } = indexer.capabilities || {};
const flat = ({ id, subCategories = [] }) => [id, ...subCategories.flatMap(flat)];
const flatCategories = categories
.filter((item) => item.id < 100000)
.flatMap(flat);
if (!filterCategories.every((item) => flatCategories.includes(item))) {
return false;
}
}
return true;
});
@@ -165,7 +197,7 @@ class AddIndexerModalContent extends Component {
<div className={styles.filterRow}>
<div className={styles.filterContainer}>
<label className={styles.filterLabel}>Protocol</label>
<label className={styles.filterLabel}>{translate('Protocol')}</label>
<EnhancedSelectInput
name="indexerProtocols"
value={this.state.filterProtocols}
@@ -175,7 +207,7 @@ class AddIndexerModalContent extends Component {
</div>
<div className={styles.filterContainer}>
<label className={styles.filterLabel}>Language</label>
<label className={styles.filterLabel}>{translate('Language')}</label>
<EnhancedSelectInput
name="indexerLanguages"
value={this.state.filterLanguages}
@@ -185,7 +217,7 @@ class AddIndexerModalContent extends Component {
</div>
<div className={styles.filterContainer}>
<label className={styles.filterLabel}>Privacy</label>
<label className={styles.filterLabel}>{translate('Privacy')}</label>
<EnhancedSelectInput
name="indexerPrivacyLevels"
value={this.state.filterPrivacyLevels}
@@ -193,6 +225,15 @@ class AddIndexerModalContent extends Component {
onChange={({ value }) => this.setState({ filterPrivacyLevels: value })}
/>
</div>
<div className={styles.filterContainer}>
<label className={styles.filterLabel}>{translate('Categories')}</label>
<NewznabCategorySelectInputConnector
name="indexerCategories"
value={this.state.filterCategories}
onChange={({ value }) => this.setState({ filterCategories: value })}
/>
</div>
</div>
<Alert
@@ -212,7 +253,7 @@ class AddIndexerModalContent extends Component {
isFetching ? <LoadingIndicator /> : null
}
{
error ? <div>{errorMessage}</div> : null
error ? <Alert kind={kinds.DANGER}>{errorMessage}</Alert> : null
}
{
isPopulated && !!indexers.length ?
@@ -225,9 +266,10 @@ class AddIndexerModalContent extends Component {
<TableBody>
{
filteredIndexers.map((indexer) => (
<SelectIndexerRowConnector
<SelectIndexerRow
key={`${indexer.implementation}-${indexer.name}`}
implementation={indexer.implementation}
implementationName={indexer.implementationName}
{...indexer}
onIndexerSelect={onIndexerSelect}
/>
@@ -237,15 +279,30 @@ class AddIndexerModalContent extends Component {
</Table> :
null
}
{
isPopulated && !!indexers.length && !filteredIndexers.length ?
<Alert
kind={kinds.WARNING}
>
{translate('NoIndexersFound')}
</Alert> :
null
}
</Scroller>
</ModalBody>
<ModalFooter>
<Button
onPress={onModalClose}
>
{translate('Close')}
</Button>
<ModalFooter className={styles.modalFooter}>
<div className={styles.available}>
{
isPopulated ?
translate('CountIndexersAvailable', { count: filteredIndexers.length }) :
null
}
</div>
<div>
<Button onPress={onModalClose}>{translate('Close')}</Button>
</div>
</ModalFooter>
</ModalContent>
);

View File

@@ -1,15 +1,18 @@
import { some } from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { fetchIndexerSchema, selectIndexerSchema, setIndexerSchemaSort } from 'Store/Actions/indexerActions';
import createAllIndexersSelector from 'Store/Selectors/createAllIndexersSelector';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import AddIndexerModalContent from './AddIndexerModalContent';
function createMapStateToProps() {
return createSelector(
createClientSideCollectionSelector('indexers.schema'),
(indexers) => {
createAllIndexersSelector(),
(indexers, allIndexers) => {
const {
isFetching,
isPopulated,
@@ -19,11 +22,19 @@ function createMapStateToProps() {
sortKey
} = indexers;
const indexerList = items.map((item) => {
const { definitionName } = item;
return {
...item,
isExistingIndexer: some(allIndexers, { definitionName })
};
});
return {
isFetching,
isPopulated,
error,
indexers: items,
indexers: indexerList,
sortKey,
sortDirection
};
@@ -49,8 +60,8 @@ class AddIndexerModalContentConnector extends Component {
//
// Listeners
onIndexerSelect = ({ implementation, name }) => {
this.props.selectIndexerSchema({ implementation, name });
onIndexerSelect = ({ implementation, implementationName, name }) => {
this.props.selectIndexerSchema({ implementation, implementationName, name });
this.props.onSelectIndexer();
};

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