diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html index f7b6bad7658a8967c8a969a9af6ece9e42625a06..f6f84ae38371b98669b99d7b4a9d2f0b8c7ebe6f 100644 --- a/vipra-ui/app/html/explorer.html +++ b/vipra-ui/app/html/explorer.html @@ -1,6 +1,6 @@ -<div class="fullsize navpadding container-fluid explorer" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'explorer'"> - <div class="row row-50"> - <div class="sidebar"> +<div class="fullsize navpadding explorer" ng-cloak ng-hide="!rootModels.topicModel || state.name !== 'explorer'" id="outer"> + <div class="ui-layout-center no-padding no-border" id="upper"> + <div class="ui-layout-west explorer-sidebar no-border"> <div class="btn-group btn-group-justified" role="group" aria-label="..."> <a tabindex="0" class="btn btn-sm btn-default" ng-click="checkTopics(true)" title="Select all topics">All</a> <a tabindex="0" class="btn btn-sm btn-default" ng-click="checkTopics(false)" title="Deselect all topics">None</a> @@ -43,37 +43,35 @@ </li> </ul> </div> - <div class="center"> - <div class="wrapper"> - <div class="topbar"> - <small>Values:</small> - <div class="btn-group"> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'absolute'">Absolute</a> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'relative'">Relative</a> - </div> - - <small>Chart:</small> - <div class="btn-group"> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'areaspline'">Area</a> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'spline'">Line</a> - </div> - - <small>Stacking:</small> - <div class="btn-group"> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'none'">None</a> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'normal'">Value</a> - <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'percent'">Percent</a> - </div> - <div class="pull-right"> - <a tabindex="0" class="btn btn-sm btn-default" ng-click="resetZoom()" ng-show="topicsSelected" ng-cloak>Reset zoom</a> - </div> + <div class="ui-layout-center no-padding no-border"> + <div class="topbar"> + <small>Values:</small> + <div class="btn-group"> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'absolute'">Absolute</a> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'relative'">Relative</a> + </div> + + <small>Chart:</small> + <div class="btn-group"> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'areaspline'">Area</a> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'spline'">Line</a> + </div> + + <small>Stacking:</small> + <div class="btn-group"> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'none'">None</a> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'normal'">Value</a> + <a tabindex="0" class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'percent'">Percent</a> + </div> + <div class="pull-right"> + <a tabindex="0" class="btn btn-sm btn-default" ng-click="resetZoom()" ng-show="topicsSelected" ng-cloak>Reset zoom</a> </div> - <div id="topicRelChart" class="chart" highcharts="topicSeq" style="height:500px"></div> </div> + <div id="topicRelChart" class="chart" highcharts="topicSeq" style="height:500px"></div> </div> </div> - <div class="row row-50"> - <div class="sidebar"> + <div class="ui-layout-south no-padding no-border" id="lower"> + <div class="ui-layout-west explorer-sidebar no-border"> <ul class="list-unstyled item-choice no-offset"> <li ng-repeat="topic in selectedTopics = (topics | filter:{selected: true} | filter:search | orderBy:explorerModels.sorttopics:explorerModels.sortdir)" ng-mouseenter="highlightSeries(topic.id, true)" ng-mouseleave="highlightSeries(topic.id, false)" ng-class="{active:explorerModels.activeTopic.id===topic.id}" class="pointer text-muted"> <div class="radio radio-condensed"> @@ -93,54 +91,52 @@ </li> </ul> </div> - <div class="center"> - <div class="wrapper"> - <div class="topbar tabs"> - <ul class="nav nav-tabs" role="tablist"> - <li class="active"> - <a data-target=".tab-evolution" data-toggle="tab" bs-tab>Word Evolution</a> - </li> - <li> - <a data-target=".tab-articles" data-toggle="tab" bs-tab>Articles</a> - </li> - </ul> + <div class="ui-layout-center no-padding no-border"> + <div class="topbar tabs"> + <ul class="nav nav-tabs" role="tablist"> + <li class="active"> + <a data-target=".tab-evolution" data-toggle="tab" bs-tab>Word Evolution</a> + </li> + <li> + <a data-target=".tab-articles" data-toggle="tab" bs-tab>Articles</a> + </li> + </ul> + </div> + <div class="tab-content fullsize"> + <div role="tabpanel" class="tab-pane active tab-evolution"> + <word-evolution chart-id="wordEvoChart" topic="explorerModels.activeTopic"/> </div> - <div class="tab-content fullsize"> - <div role="tabpanel" class="tab-pane active tab-evolution"> - <word-evolution topic="explorerModels.activeTopic"/> - </div> - <div role="tabpanel" class="tab-pane tab-articles auto-overflow"> - <div class="panel panel-default"> - <div class="topbar"> - <small>Sequence:</small> - <sequence-dropdown ng-model="explorerModels.activeSequence" sequences="explorerModels.activeTopic.sequences"></sequence-dropdown> - <button class="btn btn-sm btn-default" ng-click="clearSequence()" ng-disabled="!explorerModels.activeSequence">Clear</button> - </div> - <table class="table table-bordered table-condensed table-fixed"> - <thead> - <tr> - <th ng-model="explorerModels.articlesSort" sort-by="title">Article</th> - </tr> - </thead> - <tbody> - <tr ng-repeat="article in articles | orderBy:explorerModels.articlesSort"> - <td> - <article-link article="::article" /> - </td> - </tr> - <tr ng-show="loadingArticles"> - <td>Loading...</td> - </tr> - <tr ng-show="!loadingArticles&&!articles.length"> - <td>No Articles</td> - </tr> - </tbody> - </table> - <div class="panel-footer"> - <ng-pluralize count="articles.length" when="{0:'No articles',1:'First entity',other:'First {} articles'}"></ng-pluralize> - <button class="btn btn-default btn-sm" ng-click="showMoreArticles()" ng-show="articles.length<articlesTotal" ng-cloak>Show more</button> - <button class="btn btn-default btn-sm" ng-click="showAllArticles()" ng-show="articles.length<articlesTotal" ng-cloak>Show all</button> - </div> + <div role="tabpanel" class="tab-pane tab-articles auto-overflow"> + <div class="panel panel-default"> + <div class="topbar"> + <small>Sequence:</small> + <sequence-dropdown ng-model="explorerModels.activeSequence" sequences="explorerModels.activeTopic.sequences"></sequence-dropdown> + <button class="btn btn-sm btn-default" ng-click="clearSequence()" ng-disabled="!explorerModels.activeSequence">Clear</button> + </div> + <table class="table table-bordered table-condensed table-fixed"> + <thead> + <tr> + <th ng-model="explorerModels.articlesSort" sort-by="title">Article</th> + </tr> + </thead> + <tbody> + <tr ng-repeat="article in articles | orderBy:explorerModels.articlesSort"> + <td> + <article-link article="::article" /> + </td> + </tr> + <tr ng-show="loadingArticles"> + <td>Loading...</td> + </tr> + <tr ng-show="!loadingArticles&&!articles.length"> + <td>No Articles</td> + </tr> + </tbody> + </table> + <div class="panel-footer"> + <ng-pluralize count="articles.length" when="{0:'No articles',1:'First entity',other:'First {} articles'}"></ng-pluralize> + <button class="btn btn-default btn-sm" ng-click="showMoreArticles()" ng-show="articles.length<articlesTotal" ng-cloak>Show more</button> + <button class="btn btn-default btn-sm" ng-click="showAllArticles()" ng-show="articles.length<articlesTotal" ng-cloak>Show all</button> </div> </div> </div> diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js index 590242e0699cccbfca6f0b215679d43c7551280e..31e0a483faab4d1daa916a9bc25ab59fb69146d0 100644 --- a/vipra-ui/app/js/controllers.js +++ b/vipra-ui/app/js/controllers.js @@ -669,6 +669,38 @@ if (!$scope.rootModels.topicModel) $scope.chooseTopicModel(); + $scope.reflowCharts = function() { + var topicHC = $('#topicRelChart').highcharts(); + if (topicHC) topicHC.reflow(); + var wordHC = $('#wordEvoChart').highcharts(); + if (wordHC) wordHC.reflow(); + }; + + $timeout(function() { + $('#outer').layout({ + applyDefaultStyles: true, + south__size: '50%' + }); + $('#upper').layout({ + applyDefaultStyles: true, + center__onresize: function() { + $scope.reflowCharts(); + }, + west: { + size: 250 + } + }); + $('#lower').layout({ + applyDefaultStyles: true, + center__onresize: function() { + $scope.reflowCharts(); + }, + west: { + size: 250 + } + }); + }); + var avgMax = 0, varMax = 0, fallingMax = 0, @@ -792,10 +824,9 @@ return (percent * 100) + '%'; }; - var topicRelChartElement = $('#topicRelChart'); $scope.highlightSeries = function(id, toggle) { if (!$scope.topicsSelected) return; - var highcharts = topicRelChartElement.highcharts(); + var highcharts = $('#topicRelChart').highcharts(); if (!highcharts) return; var series = highcharts.get(id); if (!series) return; @@ -814,7 +845,7 @@ $scope.resetZoom = function() { if (!$scope.topicsSelected) return; - var highcharts = topicRelChartElement.highcharts(); + var highcharts = $('#topicRelChart').highcharts(); if (!highcharts) return; highcharts.xAxis[0].setExtremes(null, null); @@ -840,7 +871,7 @@ delete $scope.explorerModels.activeSequence; delete $scope.articles; - var selectedPoints = topicRelChartElement.highcharts().getSelectedPoints(); + var selectedPoints = $('#topicRelChart').highcharts().getSelectedPoints(); for(var i = 0; i < selectedPoints.length; i++) { selectedPoints[i].select(false); } @@ -1204,10 +1235,9 @@ }], 'Topic Relevance', $scope.topicsShowModels.relChartstyle); }; - var topicRelChartElement = $('#topicRelChart'); $scope.resetRelZoom = function() { if (!$scope.topic) return; - var highcharts = topicRelChartElement.highcharts(); + var highcharts = $('#topicRelChart').highcharts(); if (!highcharts) return; highcharts.xAxis[0].setExtremes(null, null); @@ -1667,7 +1697,7 @@ app.controller('WordEvolutionController', ['$scope', function($scope) { - $scope.chartId = Vipra.randomId(); + $scope.chartId = $scope.chartId || Vipra.randomId(); $scope.wordSeqstyle = 'absolute'; $scope.wordChartstyle = 'spline'; diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js index 6b79e4408b8f019596da9533ac6b9b58730ebf8e..7d0db883fdce180a0c2c81e0ae32e74b9f5c2f73 100644 --- a/vipra-ui/app/js/directives.js +++ b/vipra-ui/app/js/directives.js @@ -498,7 +498,8 @@ app.directive('wordEvolution', [function() { return { scope: { - topic: '=' + topic: '=', + chartId: '@' }, replace: true, controller: 'WordEvolutionController', diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less index a08f5295fa2ff765c9e56d981f7c9ddf2ae8df00..45677f85598dcb1b0f0686df5e318a790684cde7 100644 --- a/vipra-ui/app/less/app.less +++ b/vipra-ui/app/less/app.less @@ -327,6 +327,10 @@ a:hover { } } +.explorer-sidebar { + background: @bar-color !important; + padding: @sidebar-padding !important; +} .sidebar { background: @bar-color; padding: @sidebar-padding; @@ -686,15 +690,6 @@ entity-menu { } } -.row-50 { - height: 50%; - position: relative; - - & + & { - border-top: 1px solid #888; - } -} - .excerpt { padding-top: 10px; color: #555; @@ -927,6 +922,14 @@ entity-menu { } } +.no-border { + border: 0 !important; +} + +.no-padding { + padding: 0 !important; +} + @keyframes spin { 100% { -webkit-transform: rotateY(360deg); diff --git a/vipra-ui/gulpfile.js b/vipra-ui/gulpfile.js index 28223ec704fb022461bd78ba4cf1ce07d1d7139b..4a08eb00a6b0433172ac07bede3bda384ce44077 100644 --- a/vipra-ui/gulpfile.js +++ b/vipra-ui/gulpfile.js @@ -13,6 +13,10 @@ var gulp = require('gulp'), var assets = { js: [ 'bower_components/jquery/dist/jquery.min.js', + 'bower_components/jquery-ui/ui/core.js', + 'bower_components/jquery-ui/ui/widget.js', + 'bower_components/jquery-ui/ui/mouse.js', + 'bower_components/jquery-ui/ui/draggable.js', 'bower_components/angular/angular.min.js', 'bower_components/angular-resource/angular-resource.min.js', 'bower_components/angular-sanitize/angular-sanitize.min.js', @@ -30,7 +34,8 @@ var assets = { 'bower_components/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js', 'bower_components/reconnectingWebsocket/reconnecting-websocket.min.js', 'bower_components/angulartics/dist/angulartics.min.js', - 'bower_components/angulartics-google-analytics/dist/angulartics-google-analytics.min.js' + 'bower_components/angulartics-google-analytics/dist/angulartics-google-analytics.min.js', + 'bower_components/jquery-layout/source/stable/jquery.layout.min.js' ], css: [ 'bower_components/bootstrap/dist/css/bootstrap.min.css',