From 3ae875f3a4b112905f6784a583f105fbd0d3aa64 Mon Sep 17 00:00:00 2001
From: Eike Cochu <eike@cochu.com>
Date: Mon, 4 Apr 2016 00:40:54 +0200
Subject: [PATCH] added entities menu, link, pages, routes, article tab

---
 vipra-ui/app/html/articles/show.html          | 35 +++++++++-
 .../app/html/directives/article-link.html     |  8 +--
 vipra-ui/app/html/directives/entity-link.html |  7 ++
 vipra-ui/app/html/directives/entity-menu.html | 11 +++
 vipra-ui/app/html/entities/articles.html      |  0
 vipra-ui/app/html/entities/index.html         |  0
 vipra-ui/app/html/entities/show.html          |  0
 vipra-ui/app/html/entities/topics.html        |  0
 vipra-ui/app/html/explorer.html               |  4 +-
 vipra-ui/app/html/index.html                  |  2 +-
 vipra-ui/app/html/topics/index.html           | 16 ++---
 vipra-ui/app/js/app.js                        | 26 +++++++
 vipra-ui/app/js/controllers.js                | 70 +++++++++++++++----
 vipra-ui/app/js/directives.js                 | 26 +++++++
 vipra-ui/app/less/app.less                    |  3 +-
 vipra-ui/gulpfile.js                          |  1 +
 16 files changed, 181 insertions(+), 28 deletions(-)
 create mode 100644 vipra-ui/app/html/directives/entity-link.html
 create mode 100644 vipra-ui/app/html/directives/entity-menu.html
 create mode 100644 vipra-ui/app/html/entities/articles.html
 create mode 100644 vipra-ui/app/html/entities/index.html
 create mode 100644 vipra-ui/app/html/entities/show.html
 create mode 100644 vipra-ui/app/html/entities/topics.html

diff --git a/vipra-ui/app/html/articles/show.html b/vipra-ui/app/html/articles/show.html
index fd64d83c..573b548c 100644
--- a/vipra-ui/app/html/articles/show.html
+++ b/vipra-ui/app/html/articles/show.html
@@ -7,6 +7,9 @@
       <li class="active">
         <a data-target=".tab-info" data-toggle="tab"><i class="fa fa-file-text-o"></i></a>
       </li>
+      <li>
+        <a data-target=".tab-entities" data-toggle="tab" bs-tab shown="openTabEntities()">Entities</a>
+      </li>
       <li>
         <a data-target=".tab-words" data-toggle="tab" bs-tab shown="openTabWords()">Words</a>
       </li>
@@ -71,7 +74,7 @@
           </div>
           <div class="col-md-4">
             <h3>Share</h3>
-            <div class="pie-chart" id="topic-share" highcharts="topicShare" style="height: 250px;"></div>
+            <div class="pie-chart" id="topic-share" highcharts="topicShare" style="height: 200px;"></div>
           </div>
         </div>
         <h3>Similar articles</h3>
@@ -95,6 +98,36 @@
         <hr>
         <div class="text-justify" ng-bind-html="::article.text"></div>
       </div>
+      <div role="tabpanel" class="tab-pane tab-entities">
+        <br>
+        <div class="row">
+          <div class="col-md-12">
+            <div class="panel panel-default">
+              <div class="panel-heading">
+                Found <ng-pluralize count="allEntities.length||0" when="{0:'no entities',1:'1 entity',other:'{} unique entities'}"></ng-pluralize> for this article.
+              </div>
+              <table class="table table-bordered table-condensed table-fixed">
+                <thead>
+                  <tr>
+                    <th ng-model="articlesShowModels.entitiesSort" sort-by="entity">Entity</th>
+                  </tr>
+                </thead>
+                <tbody>
+                  <tr ng-repeat="entity in entities | orderBy:articlesShowModels.entitiesSort">
+                    <td>
+                      <entity-link entity="::entity" />
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+              <div class="panel-footer">
+                <ng-pluralize count="entities.length" when="{0:'No entities',1:'First entity',other:'First {} entities'}"></ng-pluralize>.
+                <button class="btn btn-default btn-sm" ng-click="showMoreEntities()" ng-show="entities.length<allEntities.length">Show more</button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
       <div role="tabpanel" class="tab-pane tab-words">
         <br>
         <div class="row">
diff --git a/vipra-ui/app/html/directives/article-link.html b/vipra-ui/app/html/directives/article-link.html
index 96d2a185..9a087e50 100644
--- a/vipra-ui/app/html/directives/article-link.html
+++ b/vipra-ui/app/html/directives/article-link.html
@@ -1,6 +1,6 @@
 <span>
-  <a class="article-link" ui-sref="articles.show({id:article.id})">
-    <span ng-bind="article.title"></span>
-<ng-transclude/>
-</a>
+	<a class="article-link" ui-sref="articles.show({id:article.id})">
+		<span ng-bind="article.title"></span>
+		<ng-transclude/>
+	</a>
 </span>
diff --git a/vipra-ui/app/html/directives/entity-link.html b/vipra-ui/app/html/directives/entity-link.html
new file mode 100644
index 00000000..a54f5363
--- /dev/null
+++ b/vipra-ui/app/html/directives/entity-link.html
@@ -0,0 +1,7 @@
+<span>
+	<entity-menu entity="entity" />
+	<a class="entity-link" ui-sref="entities.show({id:entity.entity})">
+		<span ng-bind="entity.entity"></span>
+		<ng-transclude/>
+	</a>
+</span>
\ No newline at end of file
diff --git a/vipra-ui/app/html/directives/entity-menu.html b/vipra-ui/app/html/directives/entity-menu.html
new file mode 100644
index 00000000..fc02195d
--- /dev/null
+++ b/vipra-ui/app/html/directives/entity-menu.html
@@ -0,0 +1,11 @@
+<div class="dropdown inline-block">
+  <a data-toggle="dropdown">
+    <i class="fa fa-caret-down"></i>
+  </a>
+  <ul class="dropdown-menu" ng-class="{'dropdown-menu-right':dropdownRight}">
+    <li><a ui-sref="entities.show.topics({id:entity.entity})">Topics</a></li>
+    <li><a ui-sref="entities.show.articles({id:entity.entity})">Articles</a></li>
+    <li role="separator" class="divider"></li>
+    <li><a ng-href="{{entity.url}}" target="_blank">DBPedia</a></li>
+  </ul>
+</div>
\ No newline at end of file
diff --git a/vipra-ui/app/html/entities/articles.html b/vipra-ui/app/html/entities/articles.html
new file mode 100644
index 00000000..e69de29b
diff --git a/vipra-ui/app/html/entities/index.html b/vipra-ui/app/html/entities/index.html
new file mode 100644
index 00000000..e69de29b
diff --git a/vipra-ui/app/html/entities/show.html b/vipra-ui/app/html/entities/show.html
new file mode 100644
index 00000000..e69de29b
diff --git a/vipra-ui/app/html/entities/topics.html b/vipra-ui/app/html/entities/topics.html
new file mode 100644
index 00000000..e69de29b
diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html
index 01e44e00..35409e6c 100644
--- a/vipra-ui/app/html/explorer.html
+++ b/vipra-ui/app/html/explorer.html
@@ -34,6 +34,9 @@
           <span class="colorbox" style="background:{{::topic.color}}" bs-popover popover-title="{{topic.name}}" popover-template="partials/topic-popover.html" popover-delay="500"></span>
         </div>
       </li>
+      <li ng-hide="topics.length > 0">
+        <p class="text-muted text-center">No topics</p>
+      </li>
     </ul>
   </div>
   <div class="center message-container">
@@ -62,7 +65,6 @@
         </div>
       </div>
       <div id="topicRelChart" class="chart" highcharts="topicSeq" style="height:500px"></div>
-      <div class="message text-muted" ng-show="!topicsSelected">No topic selected</div>
     </div>
   </div>
 </div>
diff --git a/vipra-ui/app/html/index.html b/vipra-ui/app/html/index.html
index 30b09004..e76878b5 100644
--- a/vipra-ui/app/html/index.html
+++ b/vipra-ui/app/html/index.html
@@ -35,7 +35,7 @@
           <i class="form-control-feedback glyphicon glyphicon-search text-muted"></i>
         </div>
         <span class="input-group-btn">
-          <button class="btn btn-default btn-lg" type="button" title="Advanced" ng-click="advancedSearch=!advancedSearch"><i class="fa fa-chevron-down text-muted"></i></button>
+          <button class="btn btn-default btn-lg" type="button" title="Advanced" ng-click="advancedSearch=!advancedSearch"><i class="fa text-muted" ng-class="{'fa-chevron-down':!advancedSearch,'fa-chevron-up':advancedSearch}"></i></button>
         </span>
       </div>
     </div>
diff --git a/vipra-ui/app/html/topics/index.html b/vipra-ui/app/html/topics/index.html
index 68d726c2..8f05f54e 100644
--- a/vipra-ui/app/html/topics/index.html
+++ b/vipra-ui/app/html/topics/index.html
@@ -10,14 +10,14 @@
         <div class="panel-heading">
           Found
           <ng-pluralize count="topicsTotal||0" when="{0:'no topics',1:'1 topic',other:'{} topics'}"></ng-pluralize> in the database.
-          <span ng-show="topicsTotal">
-          Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="topicsIndexModels.sortkey">
-            <li value="name" class="nya-bs-option"><a>Name</a></li>
-            <li value="created" class="nya-bs-option"><a>Added</a></li>
-          </ol>
-          <sort-dir ng-model="topicsIndexModels.sortdir" />
-        </span>
+          <span ng-show="topicsTotal > 0">
+            Sort by
+            <ol class="nya-bs-select nya-bs-condensed" ng-model="topicsIndexModels.sortkey">
+              <li value="name" class="nya-bs-option"><a>Name</a></li>
+              <li value="created" class="nya-bs-option"><a>Added</a></li>
+            </ol>
+            <sort-dir ng-model="topicsIndexModels.sortdir" />
+          </span>
         </div>
         <table class="table table-hover table-condensed">
           <tbody>
diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js
index 64b34a2d..80e1a674 100644
--- a/vipra-ui/app/js/app.js
+++ b/vipra-ui/app/js/app.js
@@ -114,6 +114,32 @@
         controller: 'WordsArticlesController'
       });
 
+      // states: entities
+
+      $stateProvider.state('entities', {
+        url: '/entities?p',
+        templateUrl: 'html/entities/index.html',
+        controller: 'WordsIndexController'
+      });
+
+      $stateProvider.state('entities.show', {
+        url: '/:id',
+        templateUrl: 'html/entities/show.html',
+        controller: 'WordsShowController'
+      });
+
+      $stateProvider.state('entities.show.topics', {
+        url: '/topics',
+        templateUrl: 'html/entities/topics.html',
+        controller: 'WordsTopicsController'
+      });
+
+      $stateProvider.state('entities.show.articles', {
+        url: '/articles',
+        templateUrl: 'html/entities/articles.html',
+        controller: 'WordsArticlesController'
+      });
+
       // states: errors
 
       $stateProvider.state('error', {
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index b24be9ae..1fc17d66 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -83,6 +83,15 @@
         }
       });
 
+      hotkeys.add({
+        combo: 'i',
+        description: 'Go to index',
+        callback: function() {
+          if ($scope.rootModels.topicModel && $state.current.name !== 'index')
+            $state.transitionTo('index');
+        }
+      });
+
       hotkeys.add({
         combo: 'e',
         description: 'Go to explorer',
@@ -465,6 +474,8 @@
           }
           risingDecayMin = Math.abs(risingDecayMin);
           risingDecayMax = risingDecayMin + Math.abs(risingDecayMax);
+
+          $scope.redrawGraph();
         });
       });
 
@@ -626,7 +637,8 @@
       $scope.articlesShowModels = {
         topicsSort: '-share',
         similarSort: '-share',
-        wordsSort: '-count'
+        wordsSort: '-count',
+        entitiesSort: 'entity'
       };
 
       ArticleFactory.get({
@@ -649,12 +661,14 @@
           $scope.rootModels.topicModel = data.topicModel;
 
         // calculate percentage share
+        var topicShareSeries = [];
+
         if ($scope.article.topics) {
-          var topicShareSeries = [],
-            topics = $scope.article.topics,
+          var topics = $scope.article.topics,
             colors = randomColor({
               count: $scope.article.topics.length
             });
+
           for (var i = 0, d; i < topics.length; i++) {
             d = {
               name: topics[i].topic.name,
@@ -666,16 +680,16 @@
             topicShareSeries.push(d);
             $scope.article.topics[i].color = colors[i];
           }
-
-          $timeout(function() {
-            // highcharts data
-            $scope.topicShare = topicShareChart([{
-              name: 'Topic Share',
-              colorByPoint: true,
-              data: topicShareSeries
-            }]);
-          }, 0);
         }
+
+        $timeout(function() {
+          // highcharts data
+          $scope.topicShare = topicShareChart([{
+            name: 'Topic Share',
+            colorByPoint: true,
+            data: topicShareSeries
+          }]);
+        }, 0);
       });
 
       $scope.$watch('rootModels.topicModel', function(newVal) {
@@ -701,6 +715,24 @@
         $scope.words = $scope.allWords.slice(0, wordsCount);
       };
 
+      $scope.openTabEntities = function() {
+        if($scope.entities) return;
+
+        ArticleFactory.get({
+          id: $stateParams.id,
+          fields: 'entities'
+        }, function(data) {
+          $scope.allEntities = data.entities;
+          $scope.showMoreEntities();
+        });
+      };
+
+      var entitiesCount = 0;
+      $scope.showMoreEntities = function() {
+        entitiesCount += 20;
+        $scope.entities = $scope.allEntities.slice(0, entitiesCount);
+      };
+
       var topicShareChartElement = $('#topic-share');
       $scope.highlightSlice = function(id, toggle) {
         var highcharts = topicShareChartElement.highcharts();
@@ -1188,6 +1220,13 @@
           }
         }
       },
+      noData: {
+        style: {
+          fontSize: "14px",
+          color: "#777",
+          fontWeight: "normal"
+        }
+      },
       series: series
     };
   }
@@ -1219,6 +1258,13 @@
       tooltip: {
         pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
       },
+      noData: {
+        style: {
+          fontSize: "14px",
+          color: "#777",
+          fontWeight: "normal"
+        }
+      },
       series: series
     };
   }
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index ef7b1f8c..78b9736d 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -47,6 +47,18 @@
     };
   }]);
 
+  app.directive('entityLink', [function() {
+    return {
+      scope: {
+        entity: '='
+      },
+      restrict: 'E',
+      replace: true,
+      transclude: true,
+      templateUrl: 'html/directives/entity-link.html'
+    };
+  }]);
+
   app.directive('pagination', [function() {
     return {
       restrict: 'E',
@@ -302,6 +314,20 @@
     };
   }]);
 
+  app.directive('entityMenu', [function() {
+    return {
+      scope: {
+        entity: '=',
+        right: '@'
+      },
+      restrict: 'E',
+      templateUrl: 'html/directives/entity-menu.html',
+      link: function($scope) {
+        $scope.dropdownRight = $scope.right === 'true';
+      }
+    };
+  }]);
+
   app.directive('sortDir', [function() {
     return {
       scope: {
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index ef6b0f4a..3f482be5 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -373,7 +373,8 @@ a:hover {
 }
 
 topic-menu,
-word-menu {
+word-menu,
+entity-menu {
   display: inline-block;
 }
 
diff --git a/vipra-ui/gulpfile.js b/vipra-ui/gulpfile.js
index e6be12b1..ebe1a2b6 100644
--- a/vipra-ui/gulpfile.js
+++ b/vipra-ui/gulpfile.js
@@ -19,6 +19,7 @@ var assets = {
     'bower_components/angular-ui-router/release/angular-ui-router.min.js',
     'bower_components/bootstrap/dist/js/bootstrap.min.js',
     'bower_components/highcharts/highstock.js',
+    'bower_components/highcharts/modules/no-data-to-display.js',
     'bower_components/vis/dist/vis.min.js',
     'bower_components/moment/min/moment-with-locales.min.js',
     'bower_components/nya-bootstrap-select/dist/js/nya-bs-select.min.js',
-- 
GitLab