Skip to content
Snippets Groups Projects
Select Git revision
  • master default
  • ember-ui
2 results

controllers.js

Blame
  • user avatar
    Eike Cochu authored
    updated info resource to return more info
    added about page with description, license and infos
    added moment.js to parse info dates and durations
    c42adf28
    History
    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);
          };
       }]);
    
    })();