From 459301e6ee0f64737a7b04e770b98243d16a8999 Mon Sep 17 00:00:00 2001 From: Eike Cochu <eike@cochu.com> Date: Tue, 24 May 2016 22:56:59 +0200 Subject: [PATCH] multiple fixes fixed frontpage article name ellipsis tried to fix empty word issue with reuters (untested) fixed frontpage transparent menubar unreadable search results when scrolling fixed frontpage search results too close to each other temporarily disabled advanced search until date function is working added load more button to frontpage added article menu added article menu to article link fixed articles sort in explorer added series name to chart tooltipcs fixed reloading network nodes on reselect network limited all requests to 50 --- .../de/vipra/cmd/file/FilebaseWordIndex.java | 8 +++-- .../java/de/vipra/cmd/text/ProcessedText.java | 7 +++- .../app/html/directives/article-link.html | 23 ++++++------ .../app/html/directives/article-menu.html | 10 ++++++ vipra-ui/app/html/explorer.html | 2 +- vipra-ui/app/html/index.html | 17 +++++---- vipra-ui/app/js/controllers.js | 36 +++++++++++++------ vipra-ui/app/js/directives.js | 18 +++++++++- vipra-ui/app/less/app.less | 22 ++++-------- 9 files changed, 92 insertions(+), 51 deletions(-) create mode 100644 vipra-ui/app/html/directives/article-menu.html diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/file/FilebaseWordIndex.java b/vipra-cmd/src/main/java/de/vipra/cmd/file/FilebaseWordIndex.java index 11a199fe..51bb48cc 100644 --- a/vipra-cmd/src/main/java/de/vipra/cmd/file/FilebaseWordIndex.java +++ b/vipra-cmd/src/main/java/de/vipra/cmd/file/FilebaseWordIndex.java @@ -53,9 +53,11 @@ public class FilebaseWordIndex implements Iterable<String> { public String transform(final String[] words, final boolean dbInsert) { final CountMap<String> countMap = new CountMap<>(); for (final String word : words) { - countMap.count(word); - if (dbInsert) - newWords.add(word); + if (!word.trim().isEmpty()) { + countMap.count(word); + if (dbInsert) + newWords.add(word); + } } final StringBuilder sb = new StringBuilder(); diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java b/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java index 3564c6c2..65d93b95 100644 --- a/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java +++ b/vipra-cmd/src/main/java/de/vipra/cmd/text/ProcessedText.java @@ -18,7 +18,12 @@ public class ProcessedText { private final List<ArticleWord> articleWords; public ProcessedText(final String text, final long wordCount) { - words = text.toLowerCase().trim().split("\\s+"); + final String[] allWords = text.toLowerCase().trim().split("\\s+"); + final List<String> wordList = new ArrayList<>(allWords.length); + for (final String word : allWords) + if (!word.trim().isEmpty()) + wordList.add(word); + words = wordList.toArray(new String[allWords.length]); originalWordCount = wordCount; reducedWordCount = words.length; reductionRatio = 1 - ((double) reducedWordCount / wordCount); diff --git a/vipra-ui/app/html/directives/article-link.html b/vipra-ui/app/html/directives/article-link.html index 13791ba6..6bf36a2e 100644 --- a/vipra-ui/app/html/directives/article-link.html +++ b/vipra-ui/app/html/directives/article-link.html @@ -1,11 +1,14 @@ -<div class="link-wrapper"> - <a class="article-link" ui-sref="articles.show({id:article.id})"> - <span ng-bind="article.title"></span> - <ng-transclude/> - </a> - <div class="pull-right"> - <i class="fa text-muted pointer" ng-class="{'fa-chevron-down':!excerptShown, 'fa-chevron-up':excerptShown}" ng-click="toggleExcerpt()" ng-if="::showExcerpt"></i> - <span class="badge" ng-bind="::article.topicsCount" ng-attr-title="{{::article.topicsCount}} topic(s)" ng-if="::showBadge"></span> - </div> +<div class="link-wrapper" ng-attr-title="{{::article.title}}"> + <span class="ellipsis menu-padding"> + <a class="article-link" ui-sref="articles.show({id:article.id})"> + <span ng-bind="article.title"></span> + <ng-transclude/> + </a> + <div class="pull-right article-dropdown"> + <i class="fa text-muted pointer" ng-class="{'fa-chevron-down':!excerptShown, 'fa-chevron-up':excerptShown}" ng-click="toggleExcerpt()" ng-if="::showExcerpt"></i> + <span class="badge" ng-bind="::article.topicsCount" ng-attr-title="{{::article.topicsCount}} topic(s)" ng-if="::showBadge"></span> + </div> + </span> + <article-menu class="menu-button" article="article" ng-if="::showMenu" /> <div ng-bind="excerpt" ng-if="excerptShown" class="excerpt"></div> -</div> +</div> \ No newline at end of file diff --git a/vipra-ui/app/html/directives/article-menu.html b/vipra-ui/app/html/directives/article-menu.html new file mode 100644 index 00000000..ec69dd6c --- /dev/null +++ b/vipra-ui/app/html/directives/article-menu.html @@ -0,0 +1,10 @@ +<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="articles.show({id:article.id})">Show</a></li> + <li role="separator" class="divider"></li> + <li><a ui-sref="network({type:'topics',id:article.id})">Network</a></li> + </ul> +</div> \ No newline at end of file diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html index 963d0126..ef29ffe7 100644 --- a/vipra-ui/app/html/explorer.html +++ b/vipra-ui/app/html/explorer.html @@ -116,7 +116,7 @@ <table class="table table-bordered table-condensed table-fixed"> <thead> <tr> - <th ng-model="explorerModels.articlesSort" sort-by="article.title">Article</th> + <th ng-model="explorerModels.articlesSort" sort-by="title">Article</th> </tr> </thead> <tbody> diff --git a/vipra-ui/app/html/index.html b/vipra-ui/app/html/index.html index ea7d9d91..2cca09e3 100644 --- a/vipra-ui/app/html/index.html +++ b/vipra-ui/app/html/index.html @@ -8,18 +8,18 @@ </div> <div class="row row-spaced"> <div class="col-md-12"> - <div class="input-group"> + <div ng-class="{'input-group':advancedSearchEnabled}"> <div class="form-group has-feedback"> <input type="text" class="form-control input-lg" placeholder="Search..." ng-model="search" ng-model-options="{debounce:500}" id="searchBox"> <i class="form-control-feedback glyphicon glyphicon-search text-muted"></i> </div> - <span class="input-group-btn"> + <span class="input-group-btn" ng-show="advancedSearchEnabled"> <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> </div> - <div class="row row-spaced" ng-show="advancedSearch" ng-cloak> + <div class="row row-spaced" ng-show="advancedSearch&&advancedSearchEnabled" ng-cloak> <div class="col-md-6 form-horizontal"> <label for="advFromDate" class="col-sm-2 control-label">From</label> <div class="input-group date col-sm-10" id="advFromDate" bs-datetimepicker ng-model="rootModels.advFromDate"> @@ -43,18 +43,14 @@ <div class="col-md-8 text-center"> <h4>Latest articles</h4> <ul class="list-unstyled"> - <li class="ellipsis" ng-repeat="article in latestArticles"> - <article-link article="::article" badge="false" menu="false" excerpt="false"/> - </li> + <article-link article="::article" badge="false" menu="false" excerpt="false" ng-repeat="article in latestArticles"/> </ul> <p class="text-center" ng-if="!latestArticles.length">No articles</p> </div> <div class="col-md-4 text-center"> <h4>Latest topics</h4> <ul class="list-unstyled"> - <li class="ellipsis" ng-repeat="topic in latestTopics"> - <topic-link topic="::topic" badge="false" menu="false"/> - </li> + <topic-link topic="::topic" badge="false" menu="false" ng-repeat="topic in latestTopics"/> </ul> <p class="text-center" ng-if="!latestTopics.length">No topics</p> </div> @@ -96,6 +92,9 @@ </p> </li> </ul> + <div class="text-center" ng-hide="noMoreResults"> + <button class="btn btn-default" ng-click="loadMoreResults()">Load more</button> + </div> </div> </div> </div> diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js index ea0a1d64..43dc465c 100644 --- a/vipra-ui/app/js/controllers.js +++ b/vipra-ui/app/js/controllers.js @@ -179,6 +179,8 @@ if (!$scope.rootModels.topicModel) $scope.chooseTopicModel(); + $scope.searchResultsStep = 10; + $scope.advancedSearchEnabled = false; $scope.search = $stateParams.q || $scope.search; $scope.$watch('rootModels.topicModel', function() { @@ -213,21 +215,29 @@ $scope.goSearch = function() { $scope.searching = true; + $scope.skip = 0; + $scope.searchResults = []; + $scope.loadMoreResults(); + }; + $scope.loadMoreResults = function() { SearchFactory.query({ topicModel: $scope.rootModels.topicModel.id, - limit: 10, + skip: $scope.skip, + limit: $scope.searchResultsStep, query: $scope.search, from: $scope.rootModels.advFromDate ? $scope.rootModels.advFromDate.getTime() : null, to: $scope.rootModels.advToDate ? $scope.rootModels.advToDate.getTime() : null - }, function(data) { + }, function(data, headers) { $scope.searching = false; - $scope.searchResults = data; + $scope.searchResults.push.apply($scope.searchResults, data); + $scope.skip += $scope.searchResultsStep; + $scope.totalResults = headers("V-Total"); + $scope.noMoreResults = data.length < $scope.searchResultsStep; }, function() { $scope.searching = false; }); }; - } ]); @@ -421,8 +431,9 @@ // on node select $scope.select = function(props) { var node = $scope.nodes.get(props.nodes[0]); - if (node) { + if (node && !node.loaded) { node.loader(node, props); + node.loaded = true; $scope.nodes.update(node); } }; @@ -465,7 +476,8 @@ } if ($scope.shown.words) { TopicFactory.get({ - id: node.dbid + id: node.dbid, + limit: 50 }, function(data) { constructor(data.words, wordNode, node, props); }); @@ -476,7 +488,8 @@ if ($scope.shown.articles) { ArticleFactory.query({ word: node.dbid, - topicModel: $scope.rootModels.topicModel.id + topicModel: $scope.rootModels.topicModel.id, + limit: 50 }, function(data) { constructor(data, articleNode, node, props); }); @@ -484,7 +497,8 @@ if ($scope.shown.topics) { TopicFactory.query({ word: node.dbid, - topicModel: $scope.rootModels.topicModel.id + topicModel: $scope.rootModels.topicModel.id, + limit: 50 }, function(data) { constructor(data, topicNode, node, props); }); @@ -493,7 +507,6 @@ // 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 @@ -668,7 +681,8 @@ sortdir: false, seqstyle: 'absolute', chartstyle: 'areaspline', - chartstack: 'none' + chartstack: 'none', + articlesSort: 'title' }; $scope.$watch('rootModels.topicModel', function() { @@ -1700,7 +1714,7 @@ } }, tooltip: { - headerFormat: '', + headerFormat: '<b>{series.name}</b><br>', pointFormat: '{point.x:%Y}: {point.y:.4f}' }, legend: { diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js index ea7f9b94..6b79e440 100644 --- a/vipra-ui/app/js/directives.js +++ b/vipra-ui/app/js/directives.js @@ -51,7 +51,8 @@ scope: { article: '=', excerpt: '@', - badge: '@' + badge: '@', + menu: '@' }, restrict: 'E', replace: true, @@ -60,6 +61,7 @@ link: function($scope) { $scope.showExcerpt = $scope.excerpt !== 'false'; $scope.showBadge = $scope.badge !== 'false'; + $scope.showMenu = $scope.menu !== 'false'; $scope.toggleExcerpt = function() { if (!$scope.excerptShown) { if ($scope.excerpt) { @@ -395,6 +397,20 @@ }; }]); + app.directive('articleMenu', [function() { + return { + scope: { + article: '=', + right: '@' + }, + restrict: 'E', + templateUrl: 'html/directives/article-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 b7da60f8..b7ea8434 100644 --- a/vipra-ui/app/less/app.less +++ b/vipra-ui/app/less/app.less @@ -43,13 +43,8 @@ a:hover { .search-results { padding-top: 15px; - .search-result { - &:not(: last-child) { - margin-bottom: 20px; - } - a { - font-size: 1.5rem; - } + .search-result + .search-result { + margin-top: 25px; } } @@ -802,14 +797,7 @@ entity-menu { .index { .navbar-default { - border-color: rgba(255,255,255,.2); - background: 0; - .navbar-nav>li>a { - color: #555; - &:hover { - background-color: rgba(255,255,255,.2); - } - } + border: 0; } } @@ -906,6 +894,10 @@ entity-menu { position: relative; } +.article-dropdown { + width: 40px; +} + @keyframes spin { 100% { -webkit-transform: rotateY(360deg); -- GitLab