diff --git a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js b/frontend/src/Settings/DownloadClients/DownloadClientSettings.js index 285ec15a0..8eec91d37 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClientSettings.js +++ b/frontend/src/Settings/DownloadClients/DownloadClientSettings.js @@ -86,7 +86,7 @@ class DownloadClientSettings extends Component { /> diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx index e0fffd03d..09961965a 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/Edit/ManageDownloadClientsEditModalContent.tsx @@ -27,9 +27,9 @@ interface ManageDownloadClientsEditModalContentProps { const NO_CHANGE = 'noChange'; const enableOptions = [ - { key: NO_CHANGE, value: 'No Change', disabled: true }, - { key: 'enabled', value: 'Enabled' }, - { key: 'disabled', value: 'Disabled' }, + { key: NO_CHANGE, value: translate('NoChange'), disabled: true }, + { key: 'enabled', value: translate('Enabled') }, + { key: 'disabled', value: translate('Disabled') }, ]; function ManageDownloadClientsEditModalContent( @@ -97,7 +97,9 @@ function ManageDownloadClientsEditModalContent( setRemoveFailedDownloads(value); break; default: - console.warn('EditDownloadClientsModalContent Unknown Input'); + console.warn( + `EditDownloadClientsModalContent Unknown Input: '${name}'` + ); } }, [] @@ -162,9 +164,7 @@ function ManageDownloadClientsEditModalContent(
- {translate('{count} download clients selected', { - count: selectedCount, - })} + {translate('CountDownloadClientsSelected', [selectedCount])}
diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx index da9a81574..cd221d24e 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalContent.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { DownloadClientAppState } from 'App/State/SettingsAppState'; +import Alert from 'Components/Alert'; import Button from 'Components/Link/Button'; import SpinnerButton from 'Components/Link/SpinnerButton'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; @@ -20,6 +21,7 @@ import { import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; import { SelectStateInputProps } from 'typings/props'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; +import translate from 'Utilities/String/translate'; import getSelectedIds from 'Utilities/Table/getSelectedIds'; import ManageDownloadClientsEditModal from './Edit/ManageDownloadClientsEditModal'; import ManageDownloadClientsModalRow from './ManageDownloadClientsModalRow'; @@ -33,37 +35,37 @@ type OnSelectedChangeCallback = React.ComponentProps< const COLUMNS = [ { name: 'name', - label: 'Name', + label: translate('Name'), isSortable: true, isVisible: true, }, { name: 'implementation', - label: 'Implementation', + label: translate('Implementation'), isSortable: true, isVisible: true, }, { name: 'enable', - label: 'Enabled', + label: translate('Enabled'), isSortable: true, isVisible: true, }, { name: 'priority', - label: 'Priority', + label: translate('Priority'), isSortable: true, isVisible: true, }, { name: 'removeCompletedDownloads', - label: 'Remove Completed', + label: translate('RemoveCompleted'), isSortable: true, isVisible: true, }, { name: 'removeFailedDownloads', - label: 'Remove Failed', + label: translate('RemoveFailed'), isSortable: true, isVisible: true, }, @@ -158,17 +160,24 @@ function ManageDownloadClientsModalContent( [items, setSelectState] ); - const errorMessage = getErrorMessage(error, 'Unable to load import lists.'); + const errorMessage = getErrorMessage( + error, + 'Unable to load download clients.' + ); const anySelected = selectedCount > 0; return ( - Manage Import Lists + {translate('ManageDownloadClients')} {isFetching ? : null} {error ?
{errorMessage}
: null} + {isPopulated && !error && !items.length && ( + {translate('NoDownloadClientsFound')} + )} + {isPopulated && !!items.length && !isFetching && !isFetching ? ( - Delete + {translate('Delete')} - Edit + {translate('Edit')} - + diff --git a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalRow.tsx b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalRow.tsx index 34b7946d3..11ab78509 100644 --- a/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalRow.tsx +++ b/frontend/src/Settings/DownloadClients/DownloadClients/Manage/ManageDownloadClientsModalRow.tsx @@ -1,9 +1,12 @@ import React, { useCallback } from 'react'; +import Label from 'Components/Label'; import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; import Column from 'Components/Table/Column'; import TableRow from 'Components/Table/TableRow'; +import { kinds } from 'Helpers/Props'; import { SelectStateInputProps } from 'typings/props'; +import translate from 'Utilities/String/translate'; import styles from './ManageDownloadClientsModalRow.css'; interface ManageDownloadClientsModalRowProps { @@ -58,17 +61,19 @@ function ManageDownloadClientsModalRow( - {enable ? 'Yes' : 'No'} + {priority} - {removeCompletedDownloads ? 'Yes' : 'No'} + {removeCompletedDownloads ? translate('Yes') : translate('No')} - {removeFailedDownloads ? 'Yes' : 'No'} + {removeFailedDownloads ? translate('Yes') : translate('No')} ); diff --git a/frontend/src/Settings/ImportLists/ImportListSettings.js b/frontend/src/Settings/ImportLists/ImportListSettings.js index 9bdf9869c..ef0681ed5 100644 --- a/frontend/src/Settings/ImportLists/ImportListSettings.js +++ b/frontend/src/Settings/ImportLists/ImportListSettings.js @@ -86,7 +86,7 @@ class ImportListSettings extends Component { /> diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx index 1ad110b80..f4d0a3d5a 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/Edit/ManageImportListsEditModalContent.tsx @@ -26,9 +26,9 @@ interface ManageImportListsEditModalContentProps { const NO_CHANGE = 'noChange'; const autoAddOptions = [ - { key: NO_CHANGE, value: 'No Change', disabled: true }, - { key: 'enabled', value: 'Enabled' }, - { key: 'disabled', value: 'Disabled' }, + { key: NO_CHANGE, value: translate('NoChange'), disabled: true }, + { key: 'enabled', value: translate('Enabled') }, + { key: 'disabled', value: translate('Disabled') }, ]; function ManageImportListsEditModalContent( @@ -36,7 +36,7 @@ function ManageImportListsEditModalContent( ) { const { importListIds, onSavePress, onModalClose } = props; - const [enableAuto, setenableAuto] = useState(NO_CHANGE); + const [enableAuto, setEnableAuto] = useState(NO_CHANGE); const [qualityProfileId, setQualityProfileId] = useState( NO_CHANGE ); @@ -72,7 +72,7 @@ function ManageImportListsEditModalContent( ({ name, value }: { name: string; value: string }) => { switch (name) { case 'enableAuto': - setenableAuto(value); + setEnableAuto(value); break; case 'qualityProfileId': setQualityProfileId(value); @@ -81,7 +81,7 @@ function ManageImportListsEditModalContent( setRootFolderPath(value); break; default: - console.warn('EditImportListModalContent Unknown Input'); + console.warn(`EditImportListModalContent Unknown Input: '${name}'`); } }, [] @@ -136,7 +136,7 @@ function ManageImportListsEditModalContent(
- {translate('{count} import lists selected', { count: selectedCount })} + {translate('CountImportListsSelected', [selectedCount])}
diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx index 9d6b2fae1..947c38651 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/ManageImportListsModalContent.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { ImportListAppState } from 'App/State/SettingsAppState'; +import Alert from 'Components/Alert'; import Button from 'Components/Link/Button'; import SpinnerButton from 'Components/Link/SpinnerButton'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; @@ -20,6 +21,7 @@ import { import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector'; import { SelectStateInputProps } from 'typings/props'; import getErrorMessage from 'Utilities/Object/getErrorMessage'; +import translate from 'Utilities/String/translate'; import getSelectedIds from 'Utilities/Table/getSelectedIds'; import ManageImportListsEditModal from './Edit/ManageImportListsEditModal'; import ManageImportListsModalRow from './ManageImportListsModalRow'; @@ -34,37 +36,37 @@ type OnSelectedChangeCallback = React.ComponentProps< const COLUMNS = [ { name: 'name', - label: 'Name', + label: translate('Name'), isSortable: true, isVisible: true, }, { name: 'implementation', - label: 'Implementation', + label: translate('Implementation'), isSortable: true, isVisible: true, }, { name: 'qualityProfileId', - label: 'Quality Profile', + label: translate('QualityProfile'), isSortable: true, isVisible: true, }, { name: 'rootFolderPath', - label: 'Root Folder', + label: translate('RootFolder'), isSortable: true, isVisible: true, }, { name: 'enableAuto', - label: 'Auto Add', + label: translate('AutomaticAdd'), isSortable: true, isVisible: true, }, { name: 'tags', - label: 'Tags', + label: translate('Tags'), isSortable: true, isVisible: true, }, @@ -190,12 +192,16 @@ function ManageImportListsModalContent( return ( - Manage Import Lists + {translate('ManageImportLists')} {isFetching ? : null} {error ?
{errorMessage}
: null} + {isPopulated && !error && !items.length && ( + {translate('NoImportListsFound')} + )} + {isPopulated && !!items.length && !isFetching && !isFetching ? (
- Delete + {translate('Delete')} - Edit + {translate('Edit')} - Set Tags + {translate('SetTags')} - + diff --git a/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx b/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx index ad9ae4652..a39d0ca86 100644 --- a/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx +++ b/frontend/src/Settings/ImportLists/ImportLists/Manage/Tags/TagsModalContent.tsx @@ -17,6 +17,7 @@ import ModalHeader from 'Components/Modal/ModalHeader'; import { inputTypes, kinds, sizes } from 'Helpers/Props'; import createTagsSelector from 'Store/Selectors/createTagsSelector'; import ImportList from 'typings/ImportList'; +import translate from 'Utilities/String/translate'; import styles from './TagsModalContent.css'; interface TagsModalContentProps { @@ -36,7 +37,7 @@ function TagsModalContent(props: TagsModalContentProps) { const [tags, setTags] = useState([]); const [applyTags, setApplyTags] = useState('add'); - const seriesTags = useMemo(() => { + const importListsTags = useMemo(() => { const tags = ids.reduce((acc: number[], id) => { const s = allImportLists.items.find((s: ImportList) => s.id === id); @@ -69,19 +70,19 @@ function TagsModalContent(props: TagsModalContentProps) { }, [tags, applyTags, onApplyTagsPress]); const applyTagsOptions = [ - { key: 'add', value: 'Add' }, - { key: 'remove', value: 'Remove' }, - { key: 'replace', value: 'Replace' }, + { key: 'add', value: translate('Add') }, + { key: 'remove', value: translate('Remove') }, + { key: 'replace', value: translate('Replace') }, ]; return ( - Tags + {translate('Tags')}
- Tags + {translate('Tags')} - Apply Tags + {translate('ApplyTags')} - Result + {translate('Result')}
- {seriesTags.map((id) => { + {importListsTags.map((id) => { const tag = tagList.find((t) => t.id === id); if (!tag) { @@ -127,7 +128,11 @@ function TagsModalContent(props: TagsModalContentProps) { return (
- {enableRss ? translate('Yes') : translate('No')} + - {enableAutomaticSearch ? translate('Yes') : translate('No')} + - {enableInteractiveSearch ? translate('Yes') : translate('No')} + {priority} diff --git a/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx b/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx index 610eac917..3205c071a 100644 --- a/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx +++ b/frontend/src/Settings/Indexers/Indexers/Manage/Tags/TagsModalContent.tsx @@ -37,7 +37,7 @@ function TagsModalContent(props: TagsModalContentProps) { const [tags, setTags] = useState([]); const [applyTags, setApplyTags] = useState('add'); - const seriesTags = useMemo(() => { + const indexersTags = useMemo(() => { const tags = ids.reduce((acc: number[], id) => { const s = allIndexers.items.find((s: Indexer) => s.id === id); @@ -101,10 +101,10 @@ function TagsModalContent(props: TagsModalContentProps) { value={applyTags} values={applyTagsOptions} helpTexts={[ - 'How to apply tags to the selected indexer(s)', - 'Add: Add the tags the existing list of tags', - 'Remove: Remove the entered tags', - 'Replace: Replace the tags with the entered tags (enter no tags to clear all tags)', + translate('ApplyTagsHelpTexts1'), + translate('ApplyTagsHelpTexts2'), + translate('ApplyTagsHelpTexts3'), + translate('ApplyTagsHelpTexts4'), ]} onChange={onApplyTagsChange} /> @@ -114,7 +114,7 @@ function TagsModalContent(props: TagsModalContentProps) { {translate('Result')}
- {seriesTags.map((id) => { + {indexersTags.map((id) => { const tag = tagList.find((t) => t.id === id); if (!tag) { @@ -149,7 +149,7 @@ function TagsModalContent(props: TagsModalContentProps) { return null; } - if (seriesTags.indexOf(id) > -1) { + if (indexersTags.indexOf(id) > -1) { return null; } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index fbae2ddb8..0604438b6 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -71,6 +71,7 @@ "AutoRedownloadFailedHelpText": "Automatically search for and attempt to download a different release", "AutoUnmonitorPreviouslyDownloadedMoviesHelpText": "Movies deleted from the disk are automatically unmonitored in Radarr", "Automatic": "Automatic", + "AutomaticAdd": "Automatic Add", "AutomaticSearch": "Automatic Search", "AvailabilityDelay": "Availability Delay", "AvailabilityDelayHelpText": "Amount of time before or after available date to search for Movie", @@ -161,7 +162,9 @@ "CopyUsingHardlinksHelpTextWarning": "Occasionally, file locks may prevent renaming files that are being seeded. You may temporarily disable seeding and use Radarr's rename function as a work around.", "CouldNotConnectSignalR": "Could not connect to SignalR, UI won't update", "CouldNotFindResults": "Couldn't find any results for '{0}'", - "CountIndexersSelected": "{0} indexers selected", + "CountDownloadClientsSelected": "{0} download client(s) selected", + "CountImportListsSelected": "{0} import list(s) selected", + "CountIndexersSelected": "{0} indexer(s) selected", "CreateEmptyMovieFolders": "Create empty movie folders", "CreateEmptyMovieFoldersHelpText": "Create missing movie folders during disk scan", "CreateGroup": "Create group", @@ -230,6 +233,12 @@ "DeleteRemotePathMappingMessageText": "Are you sure you want to delete this remote path mapping?", "DeleteRestriction": "Delete Restriction", "DeleteRestrictionHelpText": "Are you sure you want to delete this restriction?", + "DeleteSelectedDownloadClients": "Delete Download Client(s)", + "DeleteSelectedDownloadClientsMessageText": "Are you sure you want to delete {0} selected download client(s)?", + "DeleteSelectedImportLists": "Delete Import List(s)", + "DeleteSelectedImportListsMessageText": "Are you sure you want to delete {0} selected import list(s)?", + "DeleteSelectedIndexers": "Delete Indexer(s)", + "DeleteSelectedIndexersMessageText": "Are you sure you want to delete {0} selected indexer(s)?", "DeleteSelectedMovie": "Delete Selected Movie(s)", "DeleteSelectedMovieFiles": "Delete Selected Movie Files", "DeleteSelectedMovieFilesMessage": "Are you sure you want to delete the selected movie files?", @@ -295,6 +304,8 @@ "EditQualityProfile": "Edit Quality Profile", "EditRemotePathMapping": "Edit Remote Path Mapping", "EditRestriction": "Edit Restriction", + "EditSelectedDownloadClients": "Edit Selected Download Clients", + "EditSelectedImportLists": "Edit Selected Import Lists", "EditSelectedIndexers": "Edit Selected Indexers", "EditSelectedMovies": "Edit Selected Movies", "Edition": "Edition", @@ -406,6 +417,7 @@ "Images": "Images", "ImdbRating": "IMDb Rating", "ImdbVotes": "IMDb Votes", + "Implementation": "Implementation", "Import": "Import", "ImportCustomFormat": "Import Custom Format", "ImportErrors": "Import Errors", @@ -514,7 +526,11 @@ "LowerCase": "Lowercase", "MIA": "MIA", "MaintenanceRelease": "Maintenance Release: bug fixes and other improvements. See Github Commit History for more details", + "ManageClients": "Manage Clients", + "ManageDownloadClients": "Manage Download Clients", + "ManageImportLists": "Manage Import Lists", "ManageIndexers": "Manage Indexers", + "ManageLists": "Manage Lists", "Manual": "Manual", "ManualImport": "Manual Import", "ManualImportSelectLanguage": "Manual Import - Select Language", @@ -632,9 +648,12 @@ "NoChange": "No Change", "NoChanges": "No Changes", "NoCollections": "No collections found, to get started you'll want to add a new movie, or import some existing ones", + "NoDownloadClientsFound": "No download clients found", "NoEventsFound": "No events found", "NoHistory": "No history", "NoHistoryBlocklist": "No history blocklist", + "NoImportListsFound": "No import lists found", + "NoIndexersFound": "No indexers found", "NoLeaveIt": "No, Leave It", "NoLimitForAnyRuntime": "No limit for any runtime", "NoLinks": "No Links", diff --git a/src/Radarr.Api.V3/DownloadClient/DownloadClientController.cs b/src/Radarr.Api.V3/DownloadClient/DownloadClientController.cs index e834fc3a8..e83932c62 100644 --- a/src/Radarr.Api.V3/DownloadClient/DownloadClientController.cs +++ b/src/Radarr.Api.V3/DownloadClient/DownloadClientController.cs @@ -6,8 +6,8 @@ namespace Radarr.Api.V3.DownloadClient [V3ApiController] public class DownloadClientController : ProviderControllerBase { - public static readonly DownloadClientResourceMapper ResourceMapper = new DownloadClientResourceMapper(); - public static readonly DownloadClientBulkResourceMapper BulkResourceMapper = new DownloadClientBulkResourceMapper(); + public static readonly DownloadClientResourceMapper ResourceMapper = new (); + public static readonly DownloadClientBulkResourceMapper BulkResourceMapper = new (); public DownloadClientController(IDownloadClientFactory downloadClientFactory) : base(downloadClientFactory, "downloadclient", ResourceMapper, BulkResourceMapper) diff --git a/src/Radarr.Api.V3/ImportLists/ImportListController.cs b/src/Radarr.Api.V3/ImportLists/ImportListController.cs index 3f7306805..1a5e6821a 100644 --- a/src/Radarr.Api.V3/ImportLists/ImportListController.cs +++ b/src/Radarr.Api.V3/ImportLists/ImportListController.cs @@ -9,8 +9,8 @@ namespace Radarr.Api.V3.ImportLists [V3ApiController] public class ImportListController : ProviderControllerBase { - public static readonly ImportListResourceMapper ResourceMapper = new ImportListResourceMapper(); - public static readonly ImportListBulkResourceMapper BulkResourceMapper = new ImportListBulkResourceMapper(); + public static readonly ImportListResourceMapper ResourceMapper = new (); + public static readonly ImportListBulkResourceMapper BulkResourceMapper = new (); public ImportListController(IImportListFactory importListFactory, ProfileExistsValidator profileExistsValidator) : base(importListFactory, "importlist", ResourceMapper, BulkResourceMapper) diff --git a/src/Radarr.Api.V3/Indexers/IndexerController.cs b/src/Radarr.Api.V3/Indexers/IndexerController.cs index f372ea019..c4670b34b 100644 --- a/src/Radarr.Api.V3/Indexers/IndexerController.cs +++ b/src/Radarr.Api.V3/Indexers/IndexerController.cs @@ -6,8 +6,8 @@ namespace Radarr.Api.V3.Indexers [V3ApiController] public class IndexerController : ProviderControllerBase { - public static readonly IndexerResourceMapper ResourceMapper = new IndexerResourceMapper(); - public static readonly IndexerBulkResourceMapper BulkResourceMapper = new IndexerBulkResourceMapper(); + public static readonly IndexerResourceMapper ResourceMapper = new (); + public static readonly IndexerBulkResourceMapper BulkResourceMapper = new (); public IndexerController(IndexerFactory indexerFactory) : base(indexerFactory, "indexer", ResourceMapper, BulkResourceMapper) diff --git a/src/Radarr.Api.V3/Metadata/MetadataController.cs b/src/Radarr.Api.V3/Metadata/MetadataController.cs index f07a8a303..938878d0b 100644 --- a/src/Radarr.Api.V3/Metadata/MetadataController.cs +++ b/src/Radarr.Api.V3/Metadata/MetadataController.cs @@ -1,3 +1,5 @@ +using System; +using Microsoft.AspNetCore.Mvc; using NzbDrone.Core.Extras.Metadata; using Radarr.Http; @@ -6,12 +8,24 @@ namespace Radarr.Api.V3.Metadata [V3ApiController] public class MetadataController : ProviderControllerBase { - public static readonly MetadataResourceMapper ResourceMapper = new MetadataResourceMapper(); - public static readonly MetadataBulkResourceMapper BulkResourceMapper = new MetadataBulkResourceMapper(); + public static readonly MetadataResourceMapper ResourceMapper = new (); + public static readonly MetadataBulkResourceMapper BulkResourceMapper = new (); public MetadataController(IMetadataFactory metadataFactory) : base(metadataFactory, "metadata", ResourceMapper, BulkResourceMapper) { } + + [NonAction] + public override ActionResult UpdateProvider([FromBody] MetadataBulkResource providerResource) + { + throw new NotImplementedException(); + } + + [NonAction] + public override object DeleteProviders([FromBody] MetadataBulkResource resource) + { + throw new NotImplementedException(); + } } } diff --git a/src/Radarr.Api.V3/Movies/MovieEditorResource.cs b/src/Radarr.Api.V3/Movies/MovieEditorResource.cs index e19ffd0e3..d8a82ee81 100644 --- a/src/Radarr.Api.V3/Movies/MovieEditorResource.cs +++ b/src/Radarr.Api.V3/Movies/MovieEditorResource.cs @@ -16,11 +16,4 @@ namespace Radarr.Api.V3.Movies public bool DeleteFiles { get; set; } public bool AddImportExclusion { get; set; } } - - public enum ApplyTags - { - Add, - Remove, - Replace - } } diff --git a/src/Radarr.Api.V3/Notifications/NotificationController.cs b/src/Radarr.Api.V3/Notifications/NotificationController.cs index 610973e9a..310b6f92b 100644 --- a/src/Radarr.Api.V3/Notifications/NotificationController.cs +++ b/src/Radarr.Api.V3/Notifications/NotificationController.cs @@ -1,3 +1,5 @@ +using System; +using Microsoft.AspNetCore.Mvc; using NzbDrone.Core.Notifications; using Radarr.Http; @@ -6,12 +8,24 @@ namespace Radarr.Api.V3.Notifications [V3ApiController] public class NotificationController : ProviderControllerBase { - public static readonly NotificationResourceMapper ResourceMapper = new NotificationResourceMapper(); - public static readonly NotificationBulkResourceMapper BulkResourceMapper = new NotificationBulkResourceMapper(); + public static readonly NotificationResourceMapper ResourceMapper = new (); + public static readonly NotificationBulkResourceMapper BulkResourceMapper = new (); public NotificationController(NotificationFactory notificationFactory) : base(notificationFactory, "notification", ResourceMapper, BulkResourceMapper) { } + + [NonAction] + public override ActionResult UpdateProvider([FromBody] NotificationBulkResource providerResource) + { + throw new NotImplementedException(); + } + + [NonAction] + public override object DeleteProviders([FromBody] NotificationBulkResource resource) + { + throw new NotImplementedException(); + } } } diff --git a/src/Radarr.Api.V3/ProviderBulkResource.cs b/src/Radarr.Api.V3/ProviderBulkResource.cs index 4eb85a604..141898f7f 100644 --- a/src/Radarr.Api.V3/ProviderBulkResource.cs +++ b/src/Radarr.Api.V3/ProviderBulkResource.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using NzbDrone.Core.ThingiProvider; -using Radarr.Api.V3.Movies; namespace Radarr.Api.V3 { @@ -9,6 +8,18 @@ namespace Radarr.Api.V3 public List Ids { get; set; } public List Tags { get; set; } public ApplyTags ApplyTags { get; set; } + + public ProviderBulkResource() + { + Ids = new List(); + } + } + + public enum ApplyTags + { + Add, + Remove, + Replace } public class ProviderBulkResourceMapper diff --git a/src/Radarr.Api.V3/ProviderControllerBase.cs b/src/Radarr.Api.V3/ProviderControllerBase.cs index 0da984749..26c94c480 100644 --- a/src/Radarr.Api.V3/ProviderControllerBase.cs +++ b/src/Radarr.Api.V3/ProviderControllerBase.cs @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Mvc; using NzbDrone.Common.Serializer; using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.Validation; -using Radarr.Api.V3.Movies; using Radarr.Http.REST; using Radarr.Http.REST.Attributes; @@ -103,8 +102,13 @@ namespace Radarr.Api.V3 [HttpPut("bulk")] [Consumes("application/json")] [Produces("application/json")] - public ActionResult UpdateProvider([FromBody] TBulkProviderResource providerResource) + public virtual ActionResult UpdateProvider([FromBody] TBulkProviderResource providerResource) { + if (!providerResource.Ids.Any()) + { + throw new BadRequestException("ids must be provided"); + } + var definitionsToUpdate = _providerFactory.Get(providerResource.Ids).ToList(); foreach (var definition in definitionsToUpdate) @@ -157,7 +161,7 @@ namespace Radarr.Api.V3 [HttpDelete("bulk")] [Consumes("application/json")] - public object DeleteProviders([FromBody] TBulkProviderResource resource) + public virtual object DeleteProviders([FromBody] TBulkProviderResource resource) { _providerFactory.Delete(resource.Ids);