Select Git revision
controllers.js
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
controllers.js 16.09 KiB
/******************************************************************************
* Vipra Application
* Controllers
******************************************************************************/
(function() {
var app = angular.module('vipra.controllers', [
'ui.router',
'vipra.factories'
]);
app.controller('RootController', ['$scope', '$state', function($scope, $state) {
$scope.$state = $state;
}]);
/**
* Index controller
*/
app.controller('IndexController', ['$scope', '$location', 'ArticleFactory', 'TopicFactory', 'WordFactory', 'SearchFactory',
function($scope, $location, ArticleFactory, TopicFactory, WordFactory, SearchFactory) {
$scope.search = $location.search().query;
ArticleFactory.query({limit:Vipra.const.latestItems, sort:'-created'}, function(response) {
$scope.latestArticles = response.data;
});
TopicFactory.query({limit:Vipra.const.latestItems, sort:'-created'}, function(response) {
$scope.latestTopics = response.data;
});
WordFactory.query({limit:Vipra.const.latestItems, sort:'-created'}, function(response) {
$scope.latestWords = response.data;
});
$scope.$watch('search', function() {
if($scope.search) {
$location.search('query', $scope.search);
$scope.searching = true;
SearchFactory.query({limit:Vipra.const.searchResults, query:$scope.search}, function(response) {
$scope.searching = false;
$scope.searchResults = response.data;
$scope.queryTime = response.$queryTime;
});
} else {
$location.search('query', null);
$scope.searchResults = [];
}
});
}]);
/**
* About controller
*/
app.controller('AboutController', ['$scope', 'InfoFactory',
function($scope, InfoFactory) {
InfoFactory.get(function(response) {
$scope.info = response.data;
$scope.buildDate = Vipra.formatDateTime(moment($scope.info.app.builddate, 'YYMMDD_HHmm').toDate());
$scope.startTime = Vipra.formatDateTime(moment($scope.info.vm.starttime, 'x').toDate());
$scope.upTime = moment.duration($scope.info.vm.uptime).humanize();
});
}]);
/**
* Network controller
*/
app.controller('NetworkController', ['$scope', '$state', '$stateParams', '$timeout', 'Store', 'ArticleFactory', 'TopicFactory', 'WordFactory',
function($scope, $state, $stateParams, $timeout, Store, ArticleFactory, TopicFactory, WordFactory) {
var id = 0,
ids = {},
container = $("#visgraph")[0],
edges = {};
$scope.colors = {
articles: '#BBC9D2',
topics: '#DBB234',
words: '#547C65'
};
$scope.nodes = new vis.DataSet();
$scope.edges = new vis.DataSet();
$scope.data = {
nodes: $scope.nodes,
edges: $scope.edges
};
$scope.options = {
nodes: {
font: { size: 14 },
shape: 'dot',
borderWidth: 0
},
edges: {
color: {
highlight: '#f00'
}
},
layout: { randomSeed: 1 },
physics: {
barnesHut: {
springConstant: 0.008,
gravitationalConstant: -3500
}
}
};
var factory;
if($stateParams.type === 'articles')
factory = ArticleFactory;
else if($stateParams.type === 'topics')
factory = TopicFactory;
else if($stateParams.type === 'words')
factory = WordFactory;
else {
console.log('unknown network type');
return;
}
// get root node
factory.get({id: $stateParams.id}, function(response) {
// add root node
if($stateParams.type === 'articles')
$scope.nodes.add([articleNode(response.data)]);
else if($stateParams.type === 'topics')
$scope.nodes.add([topicNode(response.data)]);
else if($stateParams.type === 'words')
$scope.nodes.add([wordNode(response.data)]);
ids[response.data.id] = id;
// create graph
$scope.graph = new vis.Network(container, $scope.data, $scope.options);
$scope.graph.on('selectNode', $scope.select);
$scope.graph.on('doubleClick', $scope.open);
});
var newNode = function(title, type, show, dbid, color, shape) {
ids[dbid] = ++id;
return {
id: id,
title: title,
label: title.multiline(5),
type: type,
show: show,
dbid: dbid,
shape: shape || 'dot',
color: {
background: color,
highlight: { background: color }
}
};
};
var topicNode = function(topic) {
topic = topic.topic || topic;
return newNode(topic.name, 'topic', 'topics.show', topic.id, $scope.colors.topics, 'triangle');
};
var articleNode = function(article) {
return newNode(article.title, 'article', 'articles.show', article.id, $scope.colors.articles, 'square');
};
var wordNode = function(word) {
return newNode(word.id, 'word', 'words.show', word.id, $scope.colors.words);
};
var edgeExists = function(idA, idB) {
if(idB < idA) {
var tmp = idA;
idA = idB;
idB = tmp;
}
return edges.hasOwnProperty(idA + '-' + idB);
};
var addEdge = function(idA, idB) {
if(idB < idA) {
var tmp = idA;
idA = idB;
idB = tmp;
}
edges[idA + '-' + idB] = 1;
};
// construct new nodes
var constructor = function(result, node, key, nodeFunction) {
if(result.data && (!key || result.data[key])) {
var data = key ? result.data[key] : result.data,
newNodes = [],
newEdges = [];
for(var i = 0; i < data.length; i++) {
var current = data[i];
if(ids.hasOwnProperty(current.id)) {
if(edgeExists(ids[current.id], node.id))
continue;
newEdges.push({from:ids[current.id], to:node.id});
addEdge(ids[current.id], node.id);
} else {
newNodes.push(nodeFunction(current));
newEdges.push({from:id, to:node.id});
addEdge(id, node.id);
}
}
if(newNodes.length)
$scope.nodes.add(newNodes);
if(newEdges.length)
$scope.edges.add(newEdges);
}
};
// on node select
var selectTimeout;
$scope.select = function(props) {
$timeout.cancel(selectTimeout);
selectTimeout = $timeout(function() {
var node = $scope.nodes.get(props.nodes[0]);
if(node) {
if(node.type === 'article' && $scope.shown.topics) {
// node is article, load article to get topics
ArticleFactory.get({id:node.dbid}, function(res) {
for(var i = 0; i < res.data.topics.length; i++)
res.data.topics[i] = res.data.topics[i].topic;
constructor(res, node, 'topics', topicNode);
});
} else if(node.type === 'topic') {
// node is topic, load topic to get words and articles
if($scope.shown.words)
TopicFactory.get({id:node.dbid}, function(res) {
constructor(res, node, 'words', wordNode);
});
if($scope.shown.articles)
TopicFactory.articles({id:node.dbid}, function(res) {
constructor(res, node, null, articleNode);
});
} else if(node.type === 'word' && $scope.shown.topics) {
// node is word, load word to get topics
WordFactory.get({id:node.dbid}, function(res) {
constructor(res, node, 'topics', topicNode);
});
}
$scope.nodes.update(node);
}
}, 500);
};
// on node open
$scope.open = function(props) {
$timeout.cancel(selectTimeout);
var node = $scope.nodes.get(props.nodes[0]);
$state.transitionTo(node.show, {id:node.dbid});
};
}]);
/****************************************************************************
* Article Controllers
****************************************************************************/
/**
* Article Index route
*/
app.controller('ArticlesIndexController', ['$scope', '$state', '$stateParams', 'ArticleFactory', 'Store',
function($scope, $state, $stateParams, ArticleFactory, Store) {
$scope.page = Math.max($stateParams.page || 1, 1);
$scope.limit = Vipra.const.pageSize;
$scope.sort = Store('sortarticles') || 'date';
$scope.order = Store('orderarticles') || '';
$scope.reload = function() {
ArticleFactory.query({
skip: ($scope.page-1)*$scope.limit,
limit: $scope.limit,
sort: $scope.order+$scope.sort
}, function(response) {
$scope.articles = response.data;
$scope.articlesMeta = response.meta;
$scope.queryTime = response.$queryTime;
});
};
$scope.changePage = function(page) {
$scope.page = page;
$scope.reload();
};
$scope.reload();
}]);
/**
* Article Show route
*/
app.controller('ArticlesShowController', ['$scope', '$stateParams', 'ArticleFactory',
function($scope, $stateParams, ArticleFactory, testService) {
$scope.topicSort = $scope.topicSort || 'topic.share';
$scope.topicSortRev = typeof $scope.topicSortRev === 'undefined' ? false : $scope.topicSortRev;
ArticleFactory.get({id: $stateParams.id}, function(response) {
$scope.article = response.data;
$scope.article.text = Vipra.createInitial($scope.article.text);
$scope.articleDate = Vipra.formatDate($scope.article.date);
$scope.articleCreated = Vipra.formatDateTime($scope.article.created);
$scope.articleModified = Vipra.formatDateTime($scope.article.modified);
$scope.articleMeta = response.meta;
$scope.queryTime = response.$queryTime;
// calculate percentage share
var topicShareSeries = [],
topics = $scope.article.topics;
for(var i = 0; i < topics.length; i++) {
var share = Vipra.toPercent(topics[i].count / $scope.article.stats.wordCount);
topics[i].share = share;
topicShareSeries.push({name: topics[i].topic.name.ellipsize(20), y: share});
}
// highcharts data
var topicShare = {
chart: { type: 'pie' },
credits: { enabled: false },
plotOptions: {
pie: { allowPointSelect: true }
},
title: { text: '' },
tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' },
series: [{
name: 'Topic Share',
colorByPoint: true,
data: topicShareSeries
}]
};
$scope.topicShare = topicShare;
});
}]);
/****************************************************************************
* Topic Controllers
****************************************************************************/
/**
* Topic Index route
*/
app.controller('TopicsIndexController', ['$scope', '$stateParams', 'Store', 'TopicFactory',
function($scope, $stateParams, Store, TopicFactory) {
$scope.page = Math.max($stateParams.page || 1, 1);
$scope.limit = Vipra.const.pageSize;
$scope.sort = Store('sorttopics') || 'name';
$scope.order = Store('ordertopics') || '';
$scope.reload = function() {
TopicFactory.query({
skip: ($scope.page-1)*$scope.limit,
limit: $scope.limit,
sort: $scope.order+$scope.sort
}, function(response) {
$scope.topics = response.data;
$scope.topicsMeta = response.meta;
$scope.queryTime = response.$queryTime;
});
};
$scope.changePage = function(page) {
$scope.page = page;
$scope.reload();
};
$scope.reload();
}]);
/**
* Topic Show route
*/
app.controller('TopicsShowController', ['$scope', '$stateParams', '$timeout', 'TopicFactory',
function($scope, $stateParams, $timeout, TopicFactory) {
$scope.wordSort = $scope.wordSort || 'likeliness';
$scope.wordSortRev = typeof $scope.wordSortRev === 'undefined' ? true : $scope.wordSortRev;
TopicFactory.get({id: $stateParams.id}, function(response) {
$scope.topic = response.data;
$scope.topicCreated = Vipra.formatDateTime($scope.topic.created);
$scope.topicModified = Vipra.formatDateTime($scope.topic.modified);
$scope.topicMeta = response.meta;
$scope.queryTime = response.$queryTime;
});
$scope.startRename = function() {
$scope.origName = $scope.topic.name;
$scope.isRename = true;
$timeout(function() {
$('#topicName').select();
}, 0);
};
$scope.endRename = function(save) {
delete $scope.renameErrors;
if(save) {
TopicFactory.update({id:$scope.topic.id}, $scope.topic, function(response) {
$scope.topic = response.data;
$scope.isRename = false;
}, function(response) {
if(response.data)
$scope.renameErrors = Vipra.getErrors(response.data.errors);
});
} else {
$scope.isRename = false;
$scope.topic.name = $scope.origName;
}
};
$scope.keyup = function($event) {
if($event.which === 13 || $event.which === 27) {
$scope.endRename($event.which === 13);
$event.preventDefault();
}
};
}]);
/**
* Topic Show Articles route
*/
app.controller('TopicArticlesController', ['$scope', '$stateParams', 'TopicFactory',
function($scope, $stateParams, TopicFactory) {
TopicFactory.articles({id: $stateParams.id}, function(response) {
$scope.articles = response.data;
$scope.queryTime = response.$queryTime;
});
}]);
/****************************************************************************
* Word Controllers
****************************************************************************/
/**
* Word Index route
*/
app.controller('WordsIndexController', ['$scope', '$state', '$stateParams', 'Store', 'WordFactory',
function($scope, $state, $stateParams, Store, WordFactory) {
$scope.page = Math.max($stateParams.page || 1, 1);
$scope.limit = 300;
$scope.sort = Store('sortwords') || 'id';
$scope.order = Store('orderwords') || '';
$scope.reload = function() {
WordFactory.query({
skip: ($scope.page-1)*$scope.limit,
limit: $scope.limit,
sort: $scope.sort,
sort: $scope.order+$scope.sort
}, function(response) {
$scope.words = response.data;
$scope.wordsMeta = response.meta;
$scope.queryTime = response.$queryTime;
});
};
$scope.changePage = function(page) {
$scope.page = page;
$scope.reload();
};
$scope.reload();
}]);
/**
* Word Show route
*/
app.controller('WordsShowController', ['$scope', '$stateParams', 'WordFactory',
function($scope, $stateParams, WordFactory) {
WordFactory.get({id: $stateParams.id}, function(response) {
$scope.word = response.data;
$scope.wordCreated = Vipra.formatDateTime($scope.word.created);
$scope.wordMeta = response.meta;
$scope.queryTime = response.$queryTime;
});
WordFactory.topics({id: $stateParams.id}, function(response) {
$scope.topics = response.data;
});
}]);
/****************************************************************************
* Directive Controllers
****************************************************************************/
/**
* Pagination
*/
app.controller('PaginationController', ['$scope',
function($scope) {
if(!$scope.page)
$scope.page = 1;
$scope.calculatePages = function() {
var pages = [],
max = Math.ceil($scope.total/$scope.limit*1.0),
pad = 4,
start = Math.max($scope.page - pad, 1),
end = Math.min(Math.max($scope.page + pad, start + pad * 2), max);
for(var i = start; i <= end; i++) {
pages.push(i);
}
$scope.pages = pages;
$scope.maxPage = max;
};
$scope.$watchGroup(['total', 'page', 'limit'], function(newVal, oldVal) {
if(!angular.equals(newVal, oldVal)) {
$scope.calculatePages();
}
});
$scope.calculatePages();
var change = $scope.change() || function() {};
$scope.changePage = function(page) {
$scope.page = page;
change(page);
window.scrollTo(0,0);
};
}]);
})();