Select Git revision
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
app.js 7.61 KiB
/******************************************************************************
* Vipra Application
* Main application file
******************************************************************************/
/* globals angular, $, Vipra, ReconnectingWebSocket, Alerter */
(function() {
"use strict";
var app = angular.module('vipra.app', [
'ngResource',
'ngSanitize',
'ngAnimate',
'ui.router',
'cfp.hotkeys',
'nya.bootstrap.select',
'angulartics',
'angulartics.google.analytics',
'vipra.controllers',
'vipra.directives',
'vipra.factories',
'vipra.templates'
]);
app.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', '$httpProvider',
function($locationProvider, $stateProvider, $urlRouterProvider, $httpProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
// states
$stateProvider.state('index', {
url: '/?q',
templateUrl: 'html/index.html',
controller: 'IndexController',
reloadOnSearch: false
});
$stateProvider.state('about', {
url: '/about',
templateUrl: 'html/about.html',
controller: 'AboutController'
});
$stateProvider.state('network', {
url: '/network?type&id',
templateUrl: 'html/network.html',
controller: 'NetworkController'
});
$stateProvider.state('explorer', {
url: '/explorer',
templateUrl: 'html/explorer.html',
controller: 'ExplorerController'
});
// states: articles
$stateProvider.state('articles', {
url: '/articles?p',
templateUrl: 'html/articles/index.html',
controller: 'ArticlesIndexController',
reloadOnSearch: false
});
$stateProvider.state('articles.show', {
url: '/:id',
templateUrl: 'html/articles/show.html',
controller: 'ArticlesShowController'
});
// states: topics
$stateProvider.state('topics', {
url: '/topics?p',
templateUrl: 'html/topics/index.html',
controller: 'TopicsIndexController',
reloadOnSearch: false
});
$stateProvider.state('topics.show', {
url: '/:id',
templateUrl: 'html/topics/show.html',
controller: 'TopicsShowController'
});
$stateProvider.state('topics.show.articles', {
url: '/articles',
templateUrl: 'html/topics/articles.html',
controller: 'TopicsArticlesController'
});
// states: words
$stateProvider.state('words', {
url: '/words?p',
templateUrl: 'html/words/index.html',
controller: 'WordsIndexController'
});
$stateProvider.state('words.show', {
url: '/:id',
templateUrl: 'html/words/show.html',
controller: 'WordsShowController'
});
$stateProvider.state('words.show.topics', {
url: '/topics',
templateUrl: 'html/words/topics.html',
controller: 'WordsTopicsController'
});
$stateProvider.state('words.show.articles', {
url: '/articles',
templateUrl: 'html/words/articles.html',
controller: 'WordsArticlesController'
});
// states: entities
$stateProvider.state('entities', {
url: '/entities?p',
templateUrl: 'html/entities/index.html',
controller: 'EntitiesIndexController'
});
$stateProvider.state('entities.show', {
url: '/:id',
templateUrl: 'html/entities/show.html',
controller: 'EntitiesShowController'
});
$stateProvider.state('entities.show.articles', {
url: '/articles',
templateUrl: 'html/entities/articles.html',
controller: 'EntitiesArticlesController'
});
// states: errors
$stateProvider.state('error', {
url: '/{code:[4-5][0-9]{2}}',
templateUrl: 'html/error.html',
controller: 'ErrorsController'
});
// http interceptors
$httpProvider.interceptors.push(function($q, $rootScope) {
var requestIncrement = function(config) {
$rootScope.loading.requests = ++$rootScope.loading.requests || 1;
$rootScope.loading[config.method] = ++$rootScope.loading[config.method] || 1;
$rootScope.loading.any = true;
};
var requestDecrement = function(config) {
$rootScope.loading.requests = Math.max(--$rootScope.loading.requests, 0);
$rootScope.loading[config.method] = Math.max(--$rootScope.loading[config.method], 0);
$rootScope.loading.any = $rootScope.loading.requests > 0;
};
return {
request: function(config) {
requestIncrement(config);
return config;
},
requestError: function(rejection) {
requestDecrement(rejection.config);
return $q.reject(rejection);
},
response: function(response) {
requestDecrement(response.config);
return response;
},
responseError: function(rejection) {
requestDecrement(rejection.config);
if(rejection.status === -1) {
// backend unavailable
$rootScope.fatal = 'Backend unavailable';
} else if (rejection.data) {
if (angular.isArray(rejection.data)) {
for (var i = 0; i < rejection.data.length; i++) {
var rd = rejection.data[i];
Alerter.showDanger(rd.title, rd.detail);
}
} else {
Alerter.showDanger(rejection.data.title, rejection.data.detail);
}
}
return $q.reject(rejection);
}
};
});
Alerter.setSettings({
prepend: false,
merge: true
}, {
fadeAfter: 0
});
}
]);
app.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.loading = {};
$rootScope.Vipra = window.Vipra;
$rootScope.$on('$stateChangeError', function() {
$state.transitionTo('error', {
code: 404
}, {
location: 'replace'
});
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState) {
$rootScope.oldState = fromState;
$rootScope.state = toState;
Alerter.removeAlerts();
});
$rootScope.$on('$stateChangeStart', function() {
$rootScope.alerts = [];
});
$rootScope.handleWSMessage = function(data) {
Alerter.showInfo(null, data.message, {fadeAfter: 7000});
};
$rootScope.showMessage = function(msg) {
Alerter.showInfo(null, msg, {fadeAfter: 7000});
};
var socket = new ReconnectingWebSocket(Vipra.getWSURL(), null, {
reconnectInterval: 10000
});
socket.onmessage = function(event) {
try {
var data = JSON.parse(event.data);
$rootScope.$apply(function() {
$rootScope.handleWSMessage(data);
});
} catch(e) {
$rootScope.$apply(function() {
$rootScope.showMessage(event.data);
});
}
};
}]);
$(document).on('change', '.btn-file :file', function() {
var input = $(this),
numFiles = input.get(0).files ? input.get(0).files.length : 1,
label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
input.trigger('fileselect', [numFiles, label]);
});
$(document).ready(function() {
$('.btn-file :file').on('fileselect', function(event, numFiles, label) {
var input = $(this).parents('.input-group').find(':text'),
log = numFiles > 1 ? numFiles + ' files selected' : label;
if (input.length) {
input.val(log);
}
});
});
})();