Skip to content

Instantly share code, notes, and snippets.

@vcardins
Last active February 15, 2016 02:49
Show Gist options
  • Save vcardins/eb9a0499a4f2daad5908 to your computer and use it in GitHub Desktop.
Save vcardins/eb9a0499a4f2daad5908 to your computer and use it in GitHub Desktop.
Angular Realtime Update
(function() {
'use strict';
angular
.module('app.layout')
.run(appRun);
//appRun.$inject = ['routerHelper', 'RealTime', 'Chat'];
/* @ngInject */
function appRun(routerHelper) {
routerHelper.configureStates(getStates(), '/');
}
function getStates() {
return [
{
state: 'app',
abstract: true,
config: {
url: '/',
title: 'Welcome',
/* @ngInject */
onEnter : function(Auth, Chat, RealTime) {
if (Auth.isAuthenticated()) {
RealTime.subscribe();
Chat.subscribe();
}
},
/* @ngInject */
onExit : function(RealTime, Chat) {
RealTime.unSubscribe();
Chat.unSubscribe();
},
views: {
'master@' : {
templateUrl: 'app/layout/views/shell.html',
controller: 'ShellController',
controllerAs: 'vm'
},
'content@app' : {
//templateUrl: 'app/layout/views/layout-one-column.html'
templateUrl: 'app/map/views/layout.html'
},
'side@app': {
template: '<ui-view>'
},
'content@app' : {
//templateUrl: 'app/dashboard/dashboard.html',
//controller: 'Dashboard',
templateUrl: 'app/map/views/map.html',
controller: 'Maps',
controllerAs: 'vm'
},
'topbar@app': {
templateUrl: 'app/layout/views/topbar.html',
controller: 'TopBar',
controllerAs: 'vm'
},
'sidebar@app': {
templateUrl: 'app/layout/views/sidebar.html',
controller: 'SideBar',
controllerAs: 'vm'
}
//'footer@app': {
// templateUrl: 'app/layout/views/footer.html'
//}
}
}
}
];
}
})();
(function() {
'use strict';
angular.module('blocks.realtime').factory('Chat', Chat);
/* @ngInject */
function Chat(SignalR, config) {
return new SignalR(config.signalR.chatHub);
}
}());
(function () {
'use strict';
var core = angular.module('app.core');
var appName = 'ng-meetup',
hosts = {
dev : 'http://ng-meetup.azurewebsites.net/',
staging : 'http://ng-meetup.azurewebsites.net/',
production : 'http://ng-meetup.azurewebsites.net/'
},
storage = {
//dev : 'http://127.0.0.1:10000/devstoreaccount1/',
dev : 'https://ng-meetup-storage.blob.core.windows.net/',
staging : 'http://ng-meetup-staging.blob.core.windows.net/',
production : 'https://ng-meetup-storage.blob.core.windows.net/'
},
env = 'staging',
api = {
host : hosts[env],
signIn : hosts[env] + 'token',
baseUrl : hosts[env] + 'api/',
storage : storage[env],
clientId: 'ng-meetup',
geoLocation : 'http://api.geonames.org/'
};
var config = {
appErrorPrefix: '[Meetup Demo] ',
title: 'Meetup Demo',
description: '',
grantType: 'password',
authStorageType: 'localStorage',
sessionKey: appName + '.auth_data',
api : api,
signalR : {
defaultHub : 'MessagingHub',
chatHub : 'ChatHub'
},
mapCenter :{
latitude: 37.09024,
longitude: -95.712891
},
lockScreenTimeout:120,
defaultRoute : 'app.maps',
version: '1.0.0',
playSounds : true,
name: 'Techsapp Spa',
year: ((new Date()).getFullYear())
};
core.value('config', config);
})();
(function () {
'use strict';
angular
.module('app.data')
.factory('modelRepository', ModelRepository);
function ModelRepository(model, RealTime) {
var baseUrl = 'model', pk = 'id', _cache = true, collection = [];
var me;
function Ctor() {
me = this;
// Exposed data access functions
this.getAll = getAll;
this.store = store;
this.remove = remove;
}
AbstractRepository.extend(Ctor);
(function(){
RealTime.on('Lookup', 'Create', store);
RealTime.on('Lookup', 'Update', store);
RealTime.on('Lookup', 'Delete', remove);
})();
return Ctor;
/* Implementation */
function store (data, fromColl) {
var isPromise = (typeof data.then === 'function');
if (isPromise) {
data.then(function(models) {
store(models);
})
}
else {
if (!angular.isArray(data)) {
var idx = 0;
var model = collection.filter(function(item, i) { idx = i; return item[pk] === data[pk]; });
if (model[0]) {
if (!fromColl) {
collection[idx] = data;
}
} else {
collection.push(data);
me.collection[data.id] = data;
}
} else {
angular.forEach(data, function(model){
store(model, true);
})
}
}
}
function remove (id){
collection.filter(function(item, i) {
if (item.id === parseInt(id)) {
collection.splice(i, 1);
}
});
}
}
})();
(function() {
'use strict';
angular.module('blocks.realtime').factory('RealTime', RealTime);
/* @ngInject */
function RealTime(SignalR, config) {
return new SignalR(config.signalR.defaultHub);
}
}());
(function($) {
'use strict';
angular
.module('blocks.realtime')
.factory('SignalR', SignalRHub);
/* @ngInject */
function SignalRHub($rootScope, Auth, config) {
var connection = $.hubConnection(config.api.host);
var scope = $rootScope.$new();
return signalR;
function signalR(hub) {
var handlers = {};
var _self;
var proxy = connection.createHubProxy(hub);
var _authToken;
var service = {
subscribe: subscribe,
unSubscribe: unSubscribe,
handleEvent: handleEvent,
on: on,
off: off,
invoke: invoke,
listenStatesChanges: listenStatesChanges
};
connection.disconnected(function() {
if (Auth.isAuthenticated()) {
setTimeout(function () { service.subscribe(); }, 1000);
}
});
proxy.on('handleEvent', handleEvent);
return service;
function subscribe(options, logging) {
_authToken = Auth.authToken();
$.signalR.ajaxDefaults.headers = { Authorization: 'Bearer ' + _authToken };
connection.logging = !!logging;
options = options || {};
options.transport = options.transport || 'longPolling';
options.withCredentials = false;
connection.start(options).
done(listenStatesChanges).
fail(console.info);
}
function unSubscribe() {
connection.stop();
proxy = null;
}
function listenStatesChanges(conn) {
_self = this;
var stateConversion = { 0: 'connecting', 1: 'connected', 2: 'reconnecting', 4: 'disconnected' };
function connectionStateChanged(state) {
console.info(hub + ' state change: ' + stateConversion[state.oldState]
+ ' => ' + stateConversion[state.newState]);
}
if (conn) {console.info(hub + ' State: ' + stateConversion[conn.state]);}
connection.stateChanged(connectionStateChanged);
}
function handleEvent(e) {
console.info(e);
var eventHandlers = (handlers[e.module] || {})[e.action] || [];
eventHandlers.forEach(function(fn) {
scope.$apply(function() {
fn(e.data, e.userId);
});
});
}
function on(module, action, fn) {
if (action === undefined) { action = '$undefined'; }
handlers[module] = handlers[module] || {};
handlers[module][action] = handlers[module][action] || [];
handlers[module][action].push(fn);
}
function off(module, action, fn) {
var eventHandlers = (handlers[module] && handlers[module][action]) || [];
if (fn) {
eventHandlers.splice(eventHandlers.indexOf(fn), 1);
} else {
if (eventHandlers[module]) {
eventHandlers[module] = [];
}
}
}
function invoke () {
var len = arguments.length;
var args = Array.prototype.slice.call(arguments);
var callback;
if (len > 1) {
callback = args.pop();
}
proxy.invoke.apply(proxy, args)
.done(function (result) {
if (callback) {
scope.$apply(function () {
callback(result);
});
}
});
}
}
}
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment