diff --git a/frontend/src/Components/SignalRConnector.js b/frontend/src/Components/SignalRConnector.js index db631de6f..365827a2b 100644 --- a/frontend/src/Components/SignalRConnector.js +++ b/frontend/src/Components/SignalRConnector.js @@ -172,7 +172,7 @@ class SignalRConnector extends Component { const status = resource.status; // Both successful and failed commands need to be - // completed, otherwise they spin until they timeout. + // completed, otherwise they spin until they time out. if (status === 'completed' || status === 'failed') { this.props.dispatchFinishCommand(resource); @@ -224,10 +224,58 @@ class SignalRConnector extends Component { repopulatePage('trackFileUpdated'); }; + handleDownloadclient = ({ action, resource }) => { + const section = 'settings.downloadClients'; + + if (action === 'created' || action === 'updated') { + this.props.dispatchUpdateItem({ section, ...resource }); + } else if (action === 'deleted') { + this.props.dispatchRemoveItem({ section, id: resource.id }); + } + }; + handleHealth = () => { this.props.dispatchFetchHealth(); }; + handleImportlist = ({ action, resource }) => { + const section = 'settings.importLists'; + + if (action === 'created' || action === 'updated') { + this.props.dispatchUpdateItem({ section, ...resource }); + } else if (action === 'deleted') { + this.props.dispatchRemoveItem({ section, id: resource.id }); + } + }; + + handleIndexer = ({ action, resource }) => { + const section = 'settings.indexers'; + + if (action === 'created' || action === 'updated') { + this.props.dispatchUpdateItem({ section, ...resource }); + } else if (action === 'deleted') { + this.props.dispatchRemoveItem({ section, id: resource.id }); + } + }; + + handleMetadata = ({ action, resource }) => { + const section = 'settings.metadata'; + + if (action === 'updated') { + this.props.dispatchUpdateItem({ section, ...resource }); + } + }; + + handleNotification = ({ action, resource }) => { + const section = 'settings.notifications'; + + if (action === 'created' || action === 'updated') { + this.props.dispatchUpdateItem({ section, ...resource }); + } else if (action === 'deleted') { + this.props.dispatchRemoveItem({ section, id: resource.id }); + } + }; + handleArtist = (body) => { const action = body.action; const section = 'artist'; diff --git a/src/Lidarr.Api.V1/DownloadClient/DownloadClientController.cs b/src/Lidarr.Api.V1/DownloadClient/DownloadClientController.cs index bc54aa7e0..b1cbb3ab5 100644 --- a/src/Lidarr.Api.V1/DownloadClient/DownloadClientController.cs +++ b/src/Lidarr.Api.V1/DownloadClient/DownloadClientController.cs @@ -1,6 +1,7 @@ using FluentValidation; using Lidarr.Http; using NzbDrone.Core.Download; +using NzbDrone.SignalR; namespace Lidarr.Api.V1.DownloadClient { @@ -10,8 +11,8 @@ public class DownloadClientController : ProviderControllerBase c.Priority).InclusiveBetween(1, 50); } diff --git a/src/Lidarr.Api.V1/ImportLists/ImportListController.cs b/src/Lidarr.Api.V1/ImportLists/ImportListController.cs index ff2ed98db..24a823e58 100644 --- a/src/Lidarr.Api.V1/ImportLists/ImportListController.cs +++ b/src/Lidarr.Api.V1/ImportLists/ImportListController.cs @@ -3,6 +3,7 @@ using NzbDrone.Core.ImportLists; using NzbDrone.Core.Validation; using NzbDrone.Core.Validation.Paths; +using NzbDrone.SignalR; namespace Lidarr.Api.V1.ImportLists { @@ -12,11 +13,12 @@ public class ImportListController : ProviderControllerBase c.RootFolderPath).Cascade(CascadeMode.Stop) .IsValidPath() diff --git a/src/Lidarr.Api.V1/Indexers/IndexerController.cs b/src/Lidarr.Api.V1/Indexers/IndexerController.cs index 2187e2b28..462c68898 100644 --- a/src/Lidarr.Api.V1/Indexers/IndexerController.cs +++ b/src/Lidarr.Api.V1/Indexers/IndexerController.cs @@ -2,6 +2,7 @@ using Lidarr.Http; using NzbDrone.Core.Indexers; using NzbDrone.Core.Validation; +using NzbDrone.SignalR; namespace Lidarr.Api.V1.Indexers { @@ -11,8 +12,10 @@ public class IndexerController : ProviderControllerBase c.Priority).InclusiveBetween(1, 50); SharedValidator.RuleFor(c => c.DownloadClientId).SetValidator(downloadClientExistsValidator); diff --git a/src/Lidarr.Api.V1/Metadata/MetadataController.cs b/src/Lidarr.Api.V1/Metadata/MetadataController.cs index 01e82ad37..4349058b0 100644 --- a/src/Lidarr.Api.V1/Metadata/MetadataController.cs +++ b/src/Lidarr.Api.V1/Metadata/MetadataController.cs @@ -2,6 +2,7 @@ using Lidarr.Http; using Microsoft.AspNetCore.Mvc; using NzbDrone.Core.Extras.Metadata; +using NzbDrone.SignalR; namespace Lidarr.Api.V1.Metadata { @@ -11,8 +12,8 @@ public class MetadataController : ProviderControllerBase : RestController + public abstract class ProviderControllerBase : RestControllerWithSignalR, + IHandle>, + IHandle>, + IHandle> where TProviderDefinition : ProviderDefinition, new() where TProvider : IProvider where TProviderResource : ProviderResource, new() @@ -22,11 +29,13 @@ public abstract class ProviderControllerBase _resourceMapper; private readonly ProviderBulkResourceMapper _bulkResourceMapper; - protected ProviderControllerBase(IProviderFactory providerFactory, string resource, ProviderResourceMapper resourceMapper, ProviderBulkResourceMapper bulkResourceMapper) + : base(signalRBroadcaster) { _providerFactory = providerFactory; _resourceMapper = resourceMapper; @@ -261,6 +270,24 @@ public IActionResult RequestAction(string name, [FromBody] TProviderResource pro return Content(data.ToJson(), "application/json"); } + [NonAction] + public virtual void Handle(ProviderAddedEvent message) + { + BroadcastResourceChange(ModelAction.Created, message.Definition.Id); + } + + [NonAction] + public virtual void Handle(ProviderUpdatedEvent message) + { + BroadcastResourceChange(ModelAction.Updated, message.Definition.Id); + } + + [NonAction] + public virtual void Handle(ProviderDeletedEvent message) + { + BroadcastResourceChange(ModelAction.Deleted, message.ProviderId); + } + protected virtual void Validate(TProviderDefinition definition, bool includeWarnings) { var validationResult = definition.Settings.Validate();