Bind any collection to SignalR with a single call.
This commit is contained in:
parent
87a5dc7869
commit
a6aba16902
|
@ -121,6 +121,7 @@
|
||||||
<Compile Include="REST\RestResource.cs" />
|
<Compile Include="REST\RestResource.cs" />
|
||||||
<Compile Include="RootFolders\RootFolderModule.cs" />
|
<Compile Include="RootFolders\RootFolderModule.cs" />
|
||||||
<Compile Include="RootFolders\RootFolderResource.cs" />
|
<Compile Include="RootFolders\RootFolderResource.cs" />
|
||||||
|
<Compile Include="RootFolders\RootFolderConnection.cs" />
|
||||||
<Compile Include="Seasons\SeasonModule.cs" />
|
<Compile Include="Seasons\SeasonModule.cs" />
|
||||||
<Compile Include="Series\SeriesConnection.cs" />
|
<Compile Include="Series\SeriesConnection.cs" />
|
||||||
<Compile Include="Series\SeriesResource.cs" />
|
<Compile Include="Series\SeriesResource.cs" />
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
<Compile Include="Resolvers\QualityTypesToIntResolver.cs" />
|
<Compile Include="Resolvers\QualityTypesToIntResolver.cs" />
|
||||||
<Compile Include="Config\SettingsModule.cs" />
|
<Compile Include="Config\SettingsModule.cs" />
|
||||||
<Compile Include="SignalR\BasicResourceConnection.cs" />
|
<Compile Include="SignalR\BasicResourceConnection.cs" />
|
||||||
|
<Compile Include="SignalR\Serializer.cs" />
|
||||||
<Compile Include="SignalR\SignalrDependencyResolver.cs" />
|
<Compile Include="SignalR\SignalrDependencyResolver.cs" />
|
||||||
<Compile Include="SignalR\NzbDronePersistentConnection.cs" />
|
<Compile Include="SignalR\NzbDronePersistentConnection.cs" />
|
||||||
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
using NzbDrone.Api.SignalR;
|
||||||
|
using NzbDrone.Core.RootFolders;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.RootFolders
|
||||||
|
{
|
||||||
|
public class RootFolderConnection : BasicResourceConnection<RootFolder>
|
||||||
|
{
|
||||||
|
public override string Resource
|
||||||
|
{
|
||||||
|
get { return "RootFolder"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.SignalR;
|
using Microsoft.AspNet.SignalR;
|
||||||
|
using Microsoft.AspNet.SignalR.Infrastructure;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
@ -14,6 +15,7 @@ namespace NzbDrone.Api.SignalR
|
||||||
{
|
{
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
|
||||||
public BasicResourceConnection()
|
public BasicResourceConnection()
|
||||||
{
|
{
|
||||||
_logger = LogManager.GetCurrentClassLogger();
|
_logger = LogManager.GetCurrentClassLogger();
|
||||||
|
@ -33,7 +35,8 @@ namespace NzbDrone.Api.SignalR
|
||||||
|
|
||||||
public void HandleAsync(ModelEvent<T> message)
|
public void HandleAsync(ModelEvent<T> message)
|
||||||
{
|
{
|
||||||
Connection.Broadcast(message);
|
var context =((ConnectionManager)GlobalHost.ConnectionManager).GetConnection(GetType());
|
||||||
|
context.Connection.Broadcast(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNet.SignalR.Json;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.SignalR
|
||||||
|
{
|
||||||
|
public class Serializer : IJsonSerializer
|
||||||
|
{
|
||||||
|
private readonly Common.IJsonSerializer _nzbDroneSerializer;
|
||||||
|
private JsonNetSerializer _signalRSerializer;
|
||||||
|
|
||||||
|
public Serializer(Common.IJsonSerializer nzbDroneSerializer)
|
||||||
|
{
|
||||||
|
_signalRSerializer = new JsonNetSerializer();
|
||||||
|
_nzbDroneSerializer = nzbDroneSerializer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Serialize(object value, TextWriter writer)
|
||||||
|
{
|
||||||
|
if (value.GetType().FullName.StartsWith("NzbDrone"))
|
||||||
|
{
|
||||||
|
_nzbDroneSerializer.Serialize(value, writer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_signalRSerializer.Serialize(value, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Parse(string json, Type targetType)
|
||||||
|
{
|
||||||
|
if (targetType.FullName.StartsWith("NzbDrone"))
|
||||||
|
{
|
||||||
|
return _nzbDroneSerializer.Deserialize(json, targetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _signalRSerializer.Parse(json, targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.SignalR;
|
using Microsoft.AspNet.SignalR;
|
||||||
|
using Microsoft.AspNet.SignalR.Json;
|
||||||
using TinyIoC;
|
using TinyIoC;
|
||||||
|
|
||||||
namespace NzbDrone.Api.SignalR
|
namespace NzbDrone.Api.SignalR
|
||||||
|
@ -13,6 +14,8 @@ namespace NzbDrone.Api.SignalR
|
||||||
public static void Register(TinyIoCContainer container)
|
public static void Register(TinyIoCContainer container)
|
||||||
{
|
{
|
||||||
GlobalHost.DependencyResolver = new SignalrDependencyResolver(container);
|
GlobalHost.DependencyResolver = new SignalrDependencyResolver(container);
|
||||||
|
|
||||||
|
container.Register<IJsonSerializer, Serializer>().AsSingleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SignalrDependencyResolver(TinyIoCContainer container)
|
private SignalrDependencyResolver(TinyIoCContainer container)
|
||||||
|
|
|
@ -9,6 +9,7 @@ namespace NzbDrone.Common
|
||||||
{
|
{
|
||||||
T Deserialize<T>(string json) where T : class, new();
|
T Deserialize<T>(string json) where T : class, new();
|
||||||
string Serialize(object obj);
|
string Serialize(object obj);
|
||||||
|
void Serialize<TModel>(TModel model, TextWriter textWriter);
|
||||||
void Serialize<TModel>(TModel model, Stream outputStream);
|
void Serialize<TModel>(TModel model, Stream outputStream);
|
||||||
object Deserialize(string json, Type type);
|
object Deserialize(string json, Type type);
|
||||||
}
|
}
|
||||||
|
@ -55,13 +56,18 @@ namespace NzbDrone.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Serialize<TModel>(TModel model, Stream outputStream)
|
public void Serialize<TModel>(TModel model, TextWriter outputStream)
|
||||||
{
|
{
|
||||||
var jsonTextWriter = new JsonTextWriter(new StreamWriter(outputStream));
|
var jsonTextWriter = new JsonTextWriter(outputStream);
|
||||||
_jsonNetSerializer.Serialize(jsonTextWriter, model);
|
_jsonNetSerializer.Serialize(jsonTextWriter, model);
|
||||||
jsonTextWriter.Flush();
|
jsonTextWriter.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Serialize<TModel>(TModel model, Stream outputStream)
|
||||||
|
{
|
||||||
|
Serialize(model, new StreamWriter(outputStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -23,7 +23,8 @@ namespace NzbDrone.Owin.MiddleWare
|
||||||
{
|
{
|
||||||
foreach (var nzbDronePersistentConnection in _persistentConnections)
|
foreach (var nzbDronePersistentConnection in _persistentConnections)
|
||||||
{
|
{
|
||||||
appBuilder.MapConnection("signalr/series", nzbDronePersistentConnection.GetType(), new ConnectionConfiguration { EnableCrossDomain = true });
|
var url = string.Format("signalr/{0}", nzbDronePersistentConnection.Resource.Trim('/'));
|
||||||
|
appBuilder.MapConnection(url, nzbDronePersistentConnection.GetType(), new ConnectionConfiguration { EnableCrossDomain = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<w>rootdir</w>
|
<w>rootdir</w>
|
||||||
<w>rootfolder</w>
|
<w>rootfolder</w>
|
||||||
<w>rootfolders</w>
|
<w>rootfolders</w>
|
||||||
|
<w>signalr</w>
|
||||||
<w>thetvdb</w>
|
<w>thetvdb</w>
|
||||||
<w>trakt</w>
|
<w>trakt</w>
|
||||||
<w>tvdb</w>
|
<w>tvdb</w>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="JavaScriptLibraryMappings">
|
<component name="JavaScriptLibraryMappings">
|
||||||
<file url="PROJECT" libraries="{libraries}" />
|
<file url="PROJECT" libraries="{jQuery-1.9.1, libraries}" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
<option passfail="false" />
|
<option passfail="false" />
|
||||||
<option white="false" />
|
<option white="false" />
|
||||||
<option maxerr="50" />
|
<option maxerr="50" />
|
||||||
<option predef="NzbDrone, define, Backbone, _, window,Handlebars, console,require,$,Marionette, Backgrid, jQuery" />
|
<option predef="NzbDrone, define, Backbone, _, window,Handlebars, console,require,$,Marionette, Backgrid, jQuery, signalR" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,12 @@
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.pager.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.pager.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/handlebars.runtime.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/handlebars.runtime.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.bootstrap.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.bootstrap.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.js" />
|
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.modelbinder.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.modelbinder.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.collectionbinder.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/fullcalendar.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/fullcalendar.js" />
|
||||||
|
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.collectionbinder.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/underscore.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/underscore.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/bootstrapSwitch.js" />
|
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/toastr-1.1.5.js" />
|
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/bootstrap.slider.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/bootstrap.slider.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.viewswapper.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.viewswapper.js" />
|
||||||
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.js" />
|
<item url="file://$PROJECT_DIR$/JsLibraries/backbone.js" />
|
||||||
|
@ -26,6 +24,8 @@
|
||||||
</sourceFilesUrls>
|
</sourceFilesUrls>
|
||||||
</properties>
|
</properties>
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
|
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrapSwitch.js" />
|
||||||
|
<root url="file://$PROJECT_DIR$/JsLibraries/toastr-1.1.5.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrap.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrap.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.debug.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.debug.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.js" />
|
||||||
|
@ -34,15 +34,13 @@
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.pager.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.pager.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/handlebars.runtime.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/handlebars.runtime.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.bootstrap.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.bootstrap.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.modelbinder.js" />
|
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/jquery.tablesorter.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/fullcalendar.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.modelbinder.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.collectionbinder.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.collectionbinder.js" />
|
||||||
|
<root url="file://$PROJECT_DIR$/JsLibraries/fullcalendar.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/underscore.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/underscore.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrapSwitch.js" />
|
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrap.slider.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/bootstrap.slider.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/toastr-1.1.5.js" />
|
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.viewswapper.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.marionette.viewswapper.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.js" />
|
||||||
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.mutators.js" />
|
<root url="file://$PROJECT_DIR$/JsLibraries/backbone.mutators.js" />
|
||||||
|
|
|
@ -6,5 +6,5 @@ define(['app', 'AddSeries/RootFolders/RootFolderModel'], function () {
|
||||||
model: NzbDrone.AddSeries.RootFolders.RootFolderModel
|
model: NzbDrone.AddSeries.RootFolders.RootFolderModel
|
||||||
});
|
});
|
||||||
|
|
||||||
return new rootFolderCollection();
|
return new rootFolderCollection().BindSignalR();
|
||||||
});
|
});
|
|
@ -1,7 +1,15 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
(function ($) {
|
|
||||||
|
|
||||||
var connection = $.connection('/signalr/series');
|
Backbone.Collection.prototype.BindSignalR = function (options) {
|
||||||
|
|
||||||
|
if (!options || !options.url) {
|
||||||
|
console.assert(this.url, 'url must be provided or collection must have url');
|
||||||
|
options = {
|
||||||
|
url: this.url.replace('api', 'signalr')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
var _getStatus = function (status) {
|
var _getStatus = function (status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -19,18 +27,21 @@
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var connection = $.connection(options.url);
|
||||||
|
|
||||||
connection.stateChanged(function (change) {
|
connection.stateChanged(function (change) {
|
||||||
|
console.debug('{0} [{1}]'.format(options.url, _getStatus(change.newState)));
|
||||||
console.log('signalR [{0}]'.format(_getStatus(change.newState)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.received(function (data) {
|
connection.received(function () {
|
||||||
console.log(data);
|
self.fetch();
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.error(function (error) {
|
connection.start({ transport: ['longPolling'] });
|
||||||
console.warn(error);
|
|
||||||
});
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
connection.start();
|
|
||||||
})(jQuery);
|
|
Loading…
Reference in New Issue