From dd016e97810e226bfe2f3ff4e9295297629061ea Mon Sep 17 00:00:00 2001 From: Elias <elias@stupeflix.com> Date: Sat, 27 Jun 2015 16:24:31 +0200 Subject: [PATCH] Annotations : refactored lists, generic lists now --- annotations/static/annotations/app.css | 42 +- annotations/static/annotations/app.js | 385 ++++++++++-------- .../static/annotations/keyword_tpl.html | 6 +- .../static/annotations/selection_tpl.html | 9 +- annotations/templates/annotations/main.html | 61 ++- annotations/views.py | 6 +- 6 files changed, 267 insertions(+), 242 deletions(-) diff --git a/annotations/static/annotations/app.css b/annotations/static/annotations/app.css index 2433f49b..98aa0972 100644 --- a/annotations/static/annotations/app.css +++ b/annotations/static/annotations/app.css @@ -1,5 +1,21 @@ /* app css stylesheet */ +/* +* Class names corresponding to server-side list names +* To display another list name, please add a new class under this +*/ +.MiamList { + color: black; + background-color: rgba(60, 118, 61, 0.5); + cursor: pointer; +} + +.StopList { + color: black; + background-color: rgba(169, 68, 66, 0.2); + cursor: pointer; +} + .delete-keyword, .occurrences { vertical-align: super; font-size: 70%; @@ -27,27 +43,9 @@ border-bottom: none; } -.miamword { - color: black; - background-color: rgba(60, 118, 61, 0.5); - cursor: pointer; -} - -.stopword { - color: black; - background-color: rgba(169, 68, 66, 0.2); - cursor: pointer; -} - -.global-stopword { - color: black; - background-color: rgba(169, 68, 66, 0.05); - cursor: pointer; -} - .main-panel, .text-panel, .words-panel { height: 800px; - margin: 10px 0px; + margin: 10px 0; } .text-panel { @@ -59,11 +57,7 @@ height: 250px; } -.keyword-container { - /*display: inline-block;*/ -} - -.keyword { +.keyword-text { word-break: break-all; } diff --git a/annotations/static/annotations/app.js b/annotations/static/annotations/app.js index 1492d3cd..eabffca6 100644 --- a/annotations/static/annotations/app.js +++ b/annotations/static/annotations/app.js @@ -10,6 +10,9 @@ $interpolateProvider.endSymbol('}]}'); }); + /* + * Template of the ngram element displayed in the flat lists (called "extra-text") + */ window.annotationsApp.directive('keywordTemplate', function () { return { templateUrl: function ($element, $attributes) { @@ -18,6 +21,9 @@ }; }); + /* + * For ngram elements displayed in the flat lists (called "extra-text") + */ window.annotationsApp.controller('ExtraAnnotationController', ['$scope', '$rootScope', '$element', 'NgramHttpService', function ($scope, $rootScope, $element, NgramHttpService) { @@ -34,9 +40,12 @@ } }); }); - } + }; }]); + /* + * For mouse selection on the text + */ window.annotationsApp.controller('AnnotationController', ['$scope', '$rootScope', '$element', function ($scope, $rootScope, $element) { @@ -57,14 +66,9 @@ }; }]); - window.annotationsApp.directive('selectionTemplate', function () { - return { - templateUrl: function ($element, $attributes) { - return S + 'annotations/selection_tpl.html'; - } - }; - }); - + /* + * Controller of the menu over the current mouse selection + */ window.annotationsApp.controller('AnnotationMenuController', ['$scope', '$rootScope', '$element', '$timeout', 'NgramHttpService', function ($scope, $rootScope, $element, $timeout, NgramHttpService) { @@ -87,9 +91,12 @@ } return false; } - + // we only need one singleton at a time var selection = getSelected(); + /* + * When mouse selection is started, we highlight it + */ function toggleSelectionHighlight(text) { if (text.trim() !== "") { $(".text-panel").addClass("selection"); @@ -98,53 +105,68 @@ } } + /* + * Dynamically construct the selection menu scope + */ function toggleMenu(context, annotation) { $timeout(function() { $scope.$apply(function() { + var miamlist_id = _.invert($rootScope.activeLists).MiamList; + var stoplist_id = _.invert($rootScope.activeLists).StopList; + // variable used in onClick + $scope.selection_text = angular.copy(annotation); if (angular.isObject(annotation)) { - $scope.level = angular.copy(annotation.level || 'global'); - $scope.category = $rootScope.lists[annotation.list_id].toLowerCase(); - $scope.listId = angular.copy(annotation.list_id); - // used in onClick - $scope.selection_text = angular.copy(annotation); - - if ($scope.category == "miamlist") { - $scope.local_miamlist = false; - $scope.global_stoplist = true; - $scope.local_stoplist = true; - } else if ($scope.category == "stoplist") { - - if ($scope.level == "local") { - $scope.local_stoplist = false; - $scope.global_stoplist = true; + // existing ngram + // Delete from the current list + $scope.menuItems = [ + { + 'action': 'delete', + 'listId': annotation.list_id, + 'verb': 'Delete from', + 'listName': $rootScope.lists[annotation.list_id] } - if ($scope.level == "global") { - $scope.global_stoplist = false; - $scope.local_stoplist = true; - } - $scope.local_miamlist = true; + ]; + if ($rootScope.lists[annotation.list_id] == "MiamList") { + // Add to the alternative list + $scope.menuItems.push({ + 'action': 'post', + 'listId': stoplist_id, + 'verb': 'Add to', + 'listName': $rootScope.lists[stoplist_id] + }); + } else if ($rootScope.lists[annotation.list_id] == "StopList") { + // Add to the alternative list + $scope.menuItems.push({ + 'action': 'post', + 'listId': miamlist_id, + 'verb': 'Add to', + 'listName': $rootScope.lists[miamlist_id] + }); } - // show menu + // show the menu $element.fadeIn(100); - } - else if (annotation.trim() !== "") { - $scope.selection_text = angular.copy(annotation); - $scope.level = "New Ngram from selection"; - $scope.category = null; - $scope.local_miamlist = true; - $scope.local_stoplist = true; - $scope.global_stoplist = true; - // show menu + } else if (annotation.trim() !== "") { + // new ngram + $scope.menuItems = [ + { + 'action': 'post', + 'listId': miamlist_id, + 'verb': 'Add to', + 'listName': $rootScope.activeLists[miamlist_id] + } + ]; + // show the menu $element.fadeIn(100); } else { - // close menu + $scope.menuItems = []; + // close the menu $element.fadeOut(100); } }); }); } - var elt = $(".text-panel")[0]; + var pos = $(".text-panel").position(); function positionElement(context, x, y) { @@ -157,18 +179,26 @@ positionElement(null, e.pageX, e.pageY); } - // TODO is mousedown necessary ? - $(".text-panel").mousedown(function(){ - $(".text-panel").mousemove(positionMenu); + /* + * Dynamically position the menu + */ + $(".text-container").mousedown(function(){ + $(".text-container").mousemove(positionMenu); }); - $(".text-panel").mouseup(function(){ - $(".text-panel").unbind("mousemove", positionMenu); + /* + * Finish positioning the menu then display the menu + */ + $(".text-container").mouseup(function(){ + $(".text-container").unbind("mousemove", positionMenu); toggleSelectionHighlight(selection.toString().trim()); toggleMenu(null, selection.toString().trim()); }); - $(".text-panel").delegate(':not("#selection")', "click", function(e) { + /* + * Toggle the menu when clicking on an existing ngram keyword + */ + $(".text-container").delegate(':not("#selection")', "click", function(e) { if ($(e.target).hasClass("keyword-inline")) return; positionMenu(e); toggleSelectionHighlight(selection.toString().trim()); @@ -178,7 +208,10 @@ $rootScope.$on("positionAnnotationMenu", positionElement); $rootScope.$on("toggleAnnotationMenu", toggleMenu); - $scope.onClick = function($event, action, listId, level) { + /* + * Menu click action + */ + $scope.onMenuClick = function($event, action, listId) { if (angular.isObject($scope.selection_text)) { // delete from the current list NgramHttpService[action]({ @@ -204,43 +237,63 @@ $rootScope.annotations.push(data); }); } - // hide selection highlighted text and the menu + // hide the highlighted text the the menu $(".text-panel").removeClass("selection"); $element.fadeOut(100); }; } ]); + /* + * Text highlighting controller + */ window.annotationsApp.controller('IntraTextController', ['$scope', '$rootScope', '$compile', 'NgramHttpService', function ($scope, $rootScope, $compile, NgramHttpService) { - $scope.extra_stoplist = []; - $scope.extra_miamlist = []; - $scope.currentStopPage = 0; - $scope.currentMiamPage = 0; + $scope.extraNgramList = {}; + $scope.currentListPage = angular.forEach($rootScope.activeLists, function(name, id) { + this[id] = 0; + }, {}); + $scope.pageSize = 15; var counter = 0; /* - * Replace the text by and html template + * Replace the text by an html template for ngram keywords */ - function replaceTextByTemplate(text, annotation, template, pattern, lists) { + function replaceTextByTemplate(text, ngram, template, pattern, lists) { return text.replace(pattern, function(matched) { var tpl = angular.element(template); tpl.append(matched); - tpl.attr('title', annotation.tooltip_content); - tpl.attr('uuid', annotation.uuid); - - if ('MiamList' == lists[annotation.list_id]) tpl.addClass("miamword"); - if ('StopList' == lists[annotation.list_id]) tpl.addClass("stopword"); - //if (annotation.category == 'stoplist' && annotation.level == 'global') tpl.addClass("global-stopword"); - + tpl.attr('title', ngram.tooltip_content); + tpl.attr('uuid', ngram.uuid); + /* + * Add CSS class depending on the list the ngram is into + * FIXME Lists names and css classes are fixed, can do better + */ + tpl.addClass(ngram.listName); return tpl.get(0).outerHTML; }); } - function compileText(annotations, fullText, abstractText, $rootScope) { + /* + * Sorts annotations on the number of words + * Required for overlapping ngrams + */ + function lengthSort(listitems, valuekey) { + listitems.sort(function(a, b) { + var compA = a[valuekey].split(" ").length; + var compB = b[valuekey].split(" ").length; + return (compA > compB) ? -1 : (compA <= compB) ? 1 : 0; + }); + return listitems; + } + /* + * Match and replace Ngram into the text + */ + function compileNgramsHtml(annotations, textMapping, $rootScope) { + // TODO remove debug counter counter = 0; var templateBegin = "<span ng-controller='AnnotationController' ng-click='onClick($event)' class='keyword-inline'>"; var templateBeginRegexp = "<span ng-controller='AnnotationController' ng-click='onClick\(\$event\)' class='keyword-inline'>"; @@ -251,97 +304,93 @@ var startPattern = "\\b((?:"+templateBeginRegexp+")*"; var middlePattern = "(?:<\/span>)*\\s(?:"+templateBeginRegexp+")*"; var endPattern = "(?:<\/span>)*)\\b"; - /* - * Sorts annotations on the number of words - */ - function lengthSort(listitems, valuekey) { - listitems.sort(function(a, b) { - var compA = a[valuekey].split(" ").length; - var compB = b[valuekey].split(" ").length; - return (compA > compB) ? -1 : (compA <= compB) ? 1 : 0; - }); - return listitems; - } - var sortedSizeAnnotations = lengthSort(annotations, "text"); - var extra_stoplist = [], - extra_miamlist = []; + var sortedSizeAnnotations = lengthSort(annotations, "text"), + + extraNgramList = angular.copy($scope.extraNgramList); + + extraNgramList = angular.forEach(extraNgramList, function(name, id) { + extraNgramList[id] = []; + }); + _.each(sortedSizeAnnotations, function (annotation) { - // TODO better split to manage two-words with minus sign - annotation.category = $rootScope.lists[annotation.list_id].toLowerCase(); + // exclude ngrams that are into inactive lists + if ($rootScope.activeLists[annotation.list_id] === undefined) return; + // used to setup css class + annotation.listName = $rootScope.lists[annotation.list_id]; + // regexps var words = annotation.text.split(" "); var pattern = new RegExp(startPattern + words.join(middlePattern) + endPattern, 'gmi'); var textRegexp = new RegExp("\\b"+annotation.text+"\\b", 'igm'); + var isDisplayedIntraText = false; + // highlight text as html + angular.forEach(textMapping, function(text, eltId) { + if (pattern.test(text) === true) { + textMapping[eltId] = replaceTextByTemplate(text, annotation, template, pattern, $rootScope.lists); + // TODO remove debug + counter++; + isDisplayedIntraText = true; + } + }); - if (pattern.test(fullText) === true) { - fullText = replaceTextByTemplate(fullText, annotation, template, pattern, $rootScope.lists); - // TODO remove debug - counter++; - } else if (pattern.test(abstractText) === true) { - abstractText = replaceTextByTemplate(abstractText, annotation, template, pattern, $rootScope.lists); - counter++; - } else if (!textRegexp.test($rootScope.full_text) && !textRegexp.test($rootScope.abstract_text)) { - if (annotation.category == "stoplist") { - // Deactivated stoplist for the moment - // if ($.inArray(annotation.uuid, $scope.extra_stoplist.map(function (item) { - // return item.uuid; - // })) == -1) { - // extra_stoplist = lengthSort(extra_stoplist.concat(annotation), "text"); - // } - } else if (annotation.category == "miamlist") { - if ($.inArray(annotation.uuid, $scope.extra_miamlist.map(function (item) { - return item.uuid; - })) == -1) { - extra_miamlist = lengthSort(extra_miamlist.concat(annotation), "text"); - } + if (!isDisplayedIntraText) { + // add extra-text ngrams that are not already displayed + if ($.inArray(annotation.uuid, extraNgramList[annotation.list_id].map(function (item) { + return item.uuid; + })) == -1) { + // push the ngram and sort + extraNgramList[annotation.list_id] = lengthSort(extraNgramList[annotation.list_id].concat(annotation), "text"); } } }); - $scope.extra_stoplist = extra_stoplist; - $scope.extra_miamlist = extra_miamlist; - - return { - 'fullTextHtml': fullText, - 'abstractTextHtml': abstractText - }; + // update extraNgramList + $scope.extraNgramList = extraNgramList; + // return the object of element ID with the corresponding HTML + return textMapping; } + /* + * Listen changes on the ngram data + */ $rootScope.$watchCollection('annotations', function (newValue, oldValue) { if ($rootScope.annotations === undefined) return; if (angular.equals(newValue, oldValue)) return; - $rootScope.miamListId = _.invert($rootScope.lists)['MiamList']; - $rootScope.stopListId = _.invert($rootScope.lists)['StopList']; - - $scope.extra_stoplist = []; - $scope.extra_miamlist = []; - - var result = compileText( + // initialize extraNgramList + $scope.extraNgramList = angular.copy($rootScope.activeLists); + $scope.extraNgramList = angular.forEach($scope.extraNgramList, function(name, id) { + $scope.extraNgramList[id] = []; + }); + /* + * Transform text into HTML with higlighted ngrams + */ + var result = compileNgramsHtml( $rootScope.annotations, - angular.copy($rootScope.full_text), - angular.copy($rootScope.abstract_text), + { + '#full-text': angular.copy($rootScope.full_text), + '#abstract-text': angular.copy($rootScope.abstract_text), + '#title': angular.copy($rootScope.title) + }, $rootScope ); - - $.each($rootScope.annotations, function(index, element) { - if (element.list_id == $rootScope.stopListId) { - $scope.extra_stoplist.push(element); - } else if (element.list_id == $rootScope.miamListId) { - $scope.extra_miamlist.push(element); - } + // inject highlighted HTML + angular.forEach(result, function(html, eltId) { + angular.element(eltId).html(html); }); - - angular.element('#full-text').html(result.fullTextHtml); - angular.element('#abstract-text').html(result.abstractTextHtml); - + // inject one Angular controller on every highlighted text element angular.element('.text-container').find('[ng-controller=AnnotationController]').each(function(idx, elt) { angular.element(elt).replaceWith($compile(elt)($rootScope.$new(true))); }); }); - function submitNewAnnotation($event, inputEltId, listId) { + /* + * Add a new NGram from the free user input in the extra-text list + */ + $scope.onListSubmit = function ($event, listId) { + var inputEltId = "#"+ listId +"-input"; if ($event.keyCode !== undefined && $event.keyCode != 13) return; + var value = $(inputEltId).val().trim(); if (value === "") return; @@ -350,47 +399,42 @@ 'listId': listId, 'ngramId': 'new' }, - {'annotation' : {'text': value}}, + { + 'annotation' : {'text': value} + }, function(data) { // on success if (data) { $rootScope.annotations.push(data); + $(inputEltId).val(""); + } else { + $(inputEltId).addClass("error"); } - }); - - $(inputEltId).val(""); - } - - $scope.onMiamlistSubmit = function ($event) { - submitNewAnnotation($event, "#miamlist-input", _.invert($rootScope.lists)['MiamList']); - }; - // TODO refactor - $scope.onStoplistSubmit = function ($event) { - submitNewAnnotation($event, "#stoplist-input", _.invert($rootScope.lists)['MiamList']); - }; - $scope.numStopPages = function () { - if ($scope.extra_stoplist === undefined) return 0; - return Math.ceil($scope.extra_stoplist.length / $scope.pageSize); - }; - $scope.numMiamPages = function () { - if ($scope.extra_miamlist === undefined) return 0; - return Math.ceil($scope.extra_miamlist.length / $scope.pageSize); - }; - $scope.nextMiamPage = function() { - $scope.currentMiamPage = $scope.currentMiamPage + 1; + }, function(data) { + // on error + $(inputEltId).addClass("error"); + } + ); }; - $scope.previousMiamPage = function() { - $scope.currentMiamPage = $scope.currentMiamPage - 1; + + $scope.totalListPages = function (listId) { + if ($scope.extraNgramList[listId] === undefined) return 0; + return Math.ceil($scope.extraNgramList[listId].length / $scope.pageSize); }; - $scope.nextStopPage = function() { - $scope.currentStopPage = $scope.currentStopPage + 1; + + $scope.nextListPage = function(listId) { + $scope.currentListPage[listId] = $scope.currentListPage[listId] + 1; }; - $scope.previousStopPage = function() { - $scope.currentStopPage = $scope.currentStopPage - 1; + + $scope.previousListPage = function(list) { + $scope.currentListPage[listId] = $scope.currentListPage[listId] - 1; }; } ]); + /* + * Filter used in Ngram flat lists pagination (extra-text panel) + */ window.annotationsApp.filter('startFrom', function () { return function (input, start) { if (input === undefined) return; @@ -405,28 +449,32 @@ $rootScope.documentResource = DocumentHttpService.get( {'docId': $rootScope.docId}, function(data, responseHeaders) { - $scope.title = data.title; + $scope.authors = data.authors; $scope.journal = data.journal; $scope.publication_date = data.publication_date; - // TODO this data have to be deleted //$scope.current_page_number = data.current_page_number; //$scope.last_page_number = data.last_page_number; - // put in rootScope because used by many components + $rootScope.title = data.title; $rootScope.docId = data.id; $rootScope.full_text = data.full_text; $rootScope.abstract_text = data.abstract_text; - // GET the annotations - // TODO + // GET the annotationss $rootScope.annotationsResource = NgramListHttpService.get( - {'corpusId': $rootScope.corpusId, 'docId': $rootScope.docId} + { + 'corpusId': $rootScope.corpusId, + 'docId': $rootScope.docId + } ).$promise.then(function(data) { $rootScope.annotations = data[$rootScope.corpusId.toString()][$rootScope.docId.toString()]; - $rootScope.lists = data[$rootScope.corpusId.toString()]['lists']; + $rootScope.lists = data[$rootScope.corpusId.toString()].lists; + // TODO active list selection controller + $rootScope.activeLists = $rootScope.lists; + $rootScope.mainListId = _.invert($rootScope.activeLists).MiamList; }); }); - // TODO setup pagination client-side + // TODO setup article pagination $scope.onPreviousClick = function () { DocumentHttpService.get($scope.docId - 1); }; @@ -435,8 +483,11 @@ }; }]); + /* + * Main function + * GET the document node and all its ngrams + */ window.annotationsApp.run(function ($rootScope) { - /* GET the document node and all the annotations in the list associated */ var path = window.location.pathname.match(/\/project\/(.*)\/corpus\/(.*)\/document\/(.*)\//); $rootScope.projectId = path[1]; $rootScope.corpusId = path[2]; diff --git a/annotations/static/annotations/keyword_tpl.html b/annotations/static/annotations/keyword_tpl.html index 07180369..b96a5121 100644 --- a/annotations/static/annotations/keyword_tpl.html +++ b/annotations/static/annotations/keyword_tpl.html @@ -1,5 +1,3 @@ -<span ng-if="keyword.category == 'miamlist'" ng-click='onDeleteClick()' class="delete-keyword" data-keyword-id="{[{keyword.uuid}]}" data-keyword-text="{[{keyword.text}]}" data-keyword-category="miamlist">×</span> -<span ng-if="keyword.category == 'miamlist'" data-toggle="tooltip" class="keyword miamword">{[{keyword.text}]}</span> -<span ng-if="keyword.category == 'stoplist'" ng-click='onDeleteClick()' class="delete-keyword" data-keyword-id="{[{keyword.uuid}]}" data-keyword-text="{[{keyword.text}]}" data-keyword-category="stoplist">×</span> -<span ng-if="keyword.category == 'stoplist'" data-toggle="tooltip" class="keyword stopword">{[{keyword.text}]}</span> +<span ng-click='onDeleteClick()' class="delete-keyword">×</span> +<span data-toggle="tooltip" class="keyword-text {[{keyword.listName}]}">{[{keyword.text}]}</span> <span class="occurrences" data-keyword-id="{[{keyword.uuid}]}">{[{keyword.occurrences}]}</span> diff --git a/annotations/static/annotations/selection_tpl.html b/annotations/static/annotations/selection_tpl.html index 71432a61..308065dc 100644 --- a/annotations/static/annotations/selection_tpl.html +++ b/annotations/static/annotations/selection_tpl.html @@ -1,10 +1,3 @@ <ul class="noselection"> - <li class="miamword" ng-if="local_miamlist === true" ng-click="onClick($event, 'post', miamListId, 'local')">add to miam-list</li> - <li class="miamword" ng-if="local_miamlist === false" ng-click="onClick($event, 'delete', miamListId, 'local')">remove from miam-list</li> - - <li class="stopword" ng-if="local_stoplist === true" ng-click="onClick($event, 'post', stopListId, 'local')">add to stop-list</li> - <li class="stopword" ng-if="local_stoplist === false" ng-click="onClick($event, 'delete', stopListId, 'local')">remove from stop-list</li> - - <!--<li class="stopword" ng-if="global_stoplist === true" ng-click="onClick($event, 'post', 'stoplist', 'global')">add to global stop-list</li> - <li class="stopword" ng-if="global_stoplist === false" ng-click="onClick($event, 'delete', 'stoplist', 'global')">remove from global stop-list</li>--> + <li ng-repeat="item in menuItems" class="{[{item.listName}]}" ng-click="onMenuClick($event, item.action, item.listId)">{[{item.verb}]} {[{item.listName}]}</li> </ul> diff --git a/annotations/templates/annotations/main.html b/annotations/templates/annotations/main.html index 74cfed88..9d8fe5a6 100644 --- a/annotations/templates/annotations/main.html +++ b/annotations/templates/annotations/main.html @@ -9,8 +9,8 @@ <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <title>Gargantext corpus annotations editor</title> - <meta name="description" content=""> + <title>Gargantext article editor</title> + <meta name="description" content="Gargantext"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="{% static 'bower_components/bootstrap/dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'bower_components/angular/angular-csp.css' %}"> @@ -18,51 +18,36 @@ <script src="{% static 'bower_components/jquery/dist/jquery.min.js' %}"></script> </head> <body> - <!-- TODO integrate this later into the corpus.html django template --> + <!-- TODO integrate this later into the any other django template --> <div id="annotationsApp"> <div class="container-fluid"> <div class="row-fluid main-panel" ng-controller="IntraTextController"> <div class="col-md-4 col-xs-4 tabbable words-panel"> <ul class="nav nav-pills nav-justified"> - <li class="active"><a href="#tab1" data-toggle="tab">Miamwords</a></li> - <li><a href="#tab2" data-toggle="tab">Stopwords</a></li> + <li ng-repeat="(listId, listName) in activeLists" ng-class="{active: $first == true}"> + <a href="#tab-{[{listId}]}" data-toggle="tab">{[{listName}]}</a> + </li> </ul> <div class="tab-content"> - <div class="tab-pane active" id="tab1"> - <div ng-if="extra_miamlist.length == 0" class="alert alert-info" role="alert">No extra text miam-word yet</div> - <ul class="list-group words-list"> + <div ng-class="{active: $first == true}" class="tab-pane" ng-repeat="(listId, listName) in activeLists" id="tab-{[{listId}]}"> + <div ng-if="extraNgramList[listId].length == 0" class="alert alert-info" role="alert">No Ngram in {[{listName}]} yet</div> - <li ng-repeat="keyword in extra_miamlist | startFrom:currentMiamPage*pageSize | limitTo:pageSize" class="list-group-item"> - <div ng-controller="ExtraAnnotationController" keyword-template class="keyword-container"></div> - </li> - </ul> - <nav ng-class="{invisible: numMiamPages() - 1 == 0}" class="clearfix"> - <ul class="pagination pagination-s pull-right words-pagination"> - <li ng-class="{disabled: currentMiamPage == 0}"><a ng-click="previousMiamPage()" class="glyphicon glyphicon-backward"></a></li> - <li ng-class="{disabled: currentMiamPage >= numMiamPages()-1}"><a ng-click="nextMiamPage()" class="glyphicon glyphicon-forward"></a></li> - </ul> - </nav> - <div class="form-group"> - <input type="text" class="form-control" id="miamlist-input" ng-keypress="onMiamlistSubmit($event)"> - <button type="submit" class="btn btn-default btn-primary" ng-click="onMiamlistSubmit($event)">Add</button> - </div> - </div> - <div class="tab-pane" id="tab2"> - <div ng-if="extra_stoplist.length == 0" class="alert alert-info" role="alert">No extra text stop-word yet</div> <ul class="list-group words-list"> - <li ng-repeat="keyword in extra_stoplist | startFrom:currentStopPage*pageSize | limitTo:pageSize" class="list-group-item"> + <li ng-repeat="keyword in extraNgramList[listId] | startFrom:currentListPage[listId]*pageSize | limitTo:pageSize" class="list-group-item"> <div ng-controller="ExtraAnnotationController" keyword-template class="keyword-container"></div> </li> </ul> - <nav ng-class="{invisible: numStopPages() - 1 == 0}" class="clearfix"> + + <nav ng-class="{invisible: totalListPages(listId) - 1 == 0}" class="clearfix"> <ul class="pagination pagination-s pull-right words-pagination"> - <li ng-class="{disabled: currentStopPage == 0}"><a ng-click="previousMiamPage()" class="glyphicon glyphicon-backward"></a></li> - <li ng-class="{disabled: currentStopPage >= numStopPages()-1}"><a ng-click="nextStopPage()" class="glyphicon glyphicon-forward"></a></li> + <li ng-class="{disabled: currentListPage[listId] == 0}"><a ng-click="previousListPage(listId)" class="glyphicon glyphicon-backward"></a></li> + <li ng-class="{disabled: currentListPage[listId] >= totalListPages(listId)-1}"><a ng-click="nextListPage(listId)" class="glyphicon glyphicon-forward"></a></li> </ul> </nav> + <div class="form-group"> - <input type="text" class="form-control" id="stoplist-input" ng-keypress="onStoplistSubmit($event)"> - <button type="submit" class="btn btn-default btn-primary" ng-click="onStoplistSubmit($event)">Add</button> + <input type="text" class="form-control" id="{[{ listId }]}-input" ng-keypress="onListSubmit($event, listId)"> + <button type="submit" class="btn btn-default btn-primary" ng-click="onListSubmit($event, listId)">Add to {[{listName}]}</button> </div> </div> </div> @@ -70,7 +55,7 @@ <div class="col-md-8 col-xs-8 text-panel" ng-controller="DocController" id="document"> <div class="row-fluid clearfix"> <div class="col-md-7 col-xs-7"> - <h3>{[{title}]}</h3> + <h3 class="text-container" id="title">{[{title}]}</h3> </div> <div class="col-md-5 col-xs-5"> <nav> @@ -90,17 +75,21 @@ </div> <h4 ng-if="abstract_text != null">Abstract</h4> <p id="abstract-text" class="text-container"> - <div ng-if="abstract_text == null" class="alert alert-info" role="alert">No abstract text</div> + <div ng-if="abstract_text == null" class="alert alert-info" role="alert">Empty abstract text</div> </p> <h4 ng-if="full_text != null">Full Article</h4> <p id="full-text" class="text-container"> - <div ng-if="full_text == null" class="alert alert-info" role="alert">No full text</div> + <div ng-if="full_text == null" class="alert alert-info" role="alert">Empty full text</div> </p> </div> </div> <!-- end of the main row --> </div> - <!-- this menu is over the text --> - <div ng-controller="AnnotationMenuController" id="selection" class="selection-menu" selection-template></div> + <!-- this menu is over the text on mouse selection --> + <div ng-controller="AnnotationMenuController" id="selection" class="selection-menu"> + <ul class="noselection"> + <li ng-repeat="item in menuItems" class="{[{item.listName}]}" ng-click="onMenuClick($event, item.action, item.listId)">{[{item.verb}]} {[{item.listName}]}</li> + </ul> + </div> </div> <!--[if lt IE 7]> <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> diff --git a/annotations/views.py b/annotations/views.py index cd485bd5..b07e360b 100644 --- a/annotations/views.py +++ b/annotations/views.py @@ -40,15 +40,15 @@ class NgramList(APIView): """Get All for a doc id""" corpus_id = int(corpus_id) doc_id = int(doc_id) - lists = dict() + lists = {} for list_type in ['MiamList', 'StopList']: - list_id = list() + list_id = listIds(user_id=request.user.id, corpus_id=int(corpus_id), typeList=list_type) lists["%s" % list_id[0][0]] = list_type # ngrams of list_id of corpus_id: doc_ngram_list = listNgramIds(corpus_id=corpus_id, doc_id=doc_id, user_id=request.user.id) - #doc_ngram_list = [(1, 'miam', 2, 1931), (2, 'stop', 2, 1932), (3, 'Potassium channels', 4, 1931)] + doc_ngram_list = [(1, 'miam', 2, 1931), (2, 'stop', 2, 1932), (3, 'Potassium channels', 4, 1931)] data = { '%s' % corpus_id : { '%s' % doc_id : [ -- 2.21.0