Commit 020485c9 authored by delanoe's avatar delanoe

Merge remote-tracking branch 'origin/romain-new' into unstable-new

parents f9c19e0c eecabef5
......@@ -5,7 +5,6 @@
* To display another list name, add a new class under this
*/
.MAPLIST {
color: black;
/* green */
......@@ -16,8 +15,9 @@
.MAINLIST {
color: black;
/* background-color: rgba(60, 118, 61, 0.5); */
/* orange */
background-color: orange;
/* background-color: rgba(60, 118, 61, 0.5); */
cursor: pointer;
}
......@@ -36,6 +36,47 @@
cursor: pointer;
}
.inlay {
border-radius: .8em;
padding: 0 .5em;
margin: 0 .2em;
}
.words-panel > .tab-content {
font-size: 80%;
border-left: 1px solid #aaa;
border-right: 1px solid #aaa;
border-bottom: 1px solid #aaa;
padding: 1em ;
margin-right: 1px;
min-height: 22em ; /* needs to be bigger than .words-list */
}
#addfreengram {
padding: 3em .5em .2em .5em ;
}
.nav-pills.activelists >li>a {
padding:10px 1px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
border-top: 1px solid #ddd;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #aaa;
}
.nav-pills.activelists > li.active > a,
.nav-pills.activelists > li.active > a:focus,
.nav-pills.activelists > li.active > a:hover {
background-color: #337ab7;
border-top: 1px solid #aaa;
border-left: 1px solid #aaa;
border-right: 1px solid #aaa;
border-bottom: none ;
}
.delete-keyword, .occurrences {
vertical-align: super;
......@@ -83,6 +124,7 @@
.words-list {
margin-bottom: 5px;
min-height: 17em ;
}
.keyword-text {
......
......@@ -22,7 +22,7 @@
* Main function
* GET the document node and all its ngrams
*/
window.annotationsApp.run(function ($rootScope) {
window.annotationsApp.run(function ($rootScope, NgramListHttpService) {
// ex: projects/1/corpora/2/documents/9/
// ex: projects/1/corpora/2/documents/9/focus=2677 (to highlight ngram 2677 more)
var path = window.location.pathname.match(/\/projects\/(.*)\/corpora\/(.*)\/documents\/(.*)\/(?:focus=([0-9,]+))?/);
......@@ -40,8 +40,22 @@
$rootScope.focusNgrams = []
// -------------------------------
// shared toolbox (functions useful for several modules) -------------------
$rootScope.mafonction = function (bidule) {console.warn(bidule)}
$rootScope.refresh = function() {
// Refresh the annotations
NgramListHttpService.get(
{'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId},
function(data) {
$rootScope.annotations = data[$rootScope.corpusId.toString()][$rootScope.docId.toString()];
$rootScope.refreshDisplay();
},
function(data) {
console.error("unable to refresh the list of ngrams");
}
);
}
// chained recursion to do several AJAX actions and then a callback (eg refresh)
$rootScope.makeChainedCalls =
......
......@@ -88,6 +88,8 @@
function toggleMenu(context, annotation) {
$timeout(function() {
$scope.$apply(function() {
$scope.menuItems = []; // init empty menu
var mainlist_id = $rootScope.listIds.MAINLIST;
var stoplist_id = $rootScope.listIds.STOPLIST;
var maplist_id = $rootScope.listIds.MAPLIST;
......@@ -128,9 +130,11 @@
// NB: remember that shown mainlist items are actually main 'without map'
// otherwise the menu for mainlist items can hide the menu for map items
if ($rootScope.lists[annotation.list_id] == "MAPLIST") {
var sourceList = $rootScope.lists[annotation.list_id]
$scope.menuItems.push({
if ( sourceList == "MAPLIST") {
$scope.menuItems = [
{
// "tgtListName" is just used to render the GUI explanation
'tgtListName': 'STOPLIST',
// crudCalls is an array of rest/DB actions
......@@ -143,18 +147,20 @@
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':stoplist_id, 'ngramIdList': targetId} }
]
});
$scope.menuItems.push({
},
{
'tgtListName': 'MAINLIST',
'crudCalls':[
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
'params' : {'listId':maplist_id, 'ngramIdList': targetId} }
]
});
}
];
}
else if ($rootScope.lists[annotation.list_id] == "MAINLIST") {
$scope.menuItems.push({
else if (sourceList == "MAINLIST") {
$scope.menuItems = [
{
'tgtListName': "STOPLIST",
'crudCalls':[
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
......@@ -162,18 +168,20 @@
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':stoplist_id, 'ngramIdList': targetId} }
]
});
$scope.menuItems.push({
},
{
'tgtListName': "MAPLIST",
'crudCalls':[
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':maplist_id, 'ngramIdList': targetId} }
]
});
}
];
}
else if ($rootScope.lists[annotation.list_id] == "STOPLIST") {
$scope.menuItems.push({
else if (sourceList == "STOPLIST") {
$scope.menuItems = [
{
'tgtListName': "MAINLIST",
'crudCalls':[
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
......@@ -181,8 +189,8 @@
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':mainlist_id, 'ngramIdList': targetId} }
]
});
$scope.menuItems.push({
},
{
'tgtListName': "MAPLIST",
'crudCalls':[
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
......@@ -192,7 +200,8 @@
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':maplist_id, 'ngramIdList': targetId} }
]
});
}
];
}
// show the menu
......@@ -305,28 +314,13 @@
* (1 intention => list of actions => MainApiChangeNgramHttpService CRUDs)
* post/delete
*/
$scope.onMenuClick = function($event, crudCalls) {
$scope.onMenuClick = function($event, todoCrudCalls) {
// console.warn('in onMenuClick')
// console.warn('item.crudCalls', crudCalls)
var lastCallback = function() {
// Refresh the annotationss
NgramListHttpService.get(
{'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId},
function(data) {
$rootScope.annotations = data[$rootScope.corpusId.toString()][$rootScope.docId.toString()];
$rootScope.refreshDisplay();
},
function(data) {
console.error("unable to refresh the list of ngrams");
}
);
}
// run the loop by calling the initial recursion step
$rootScope.makeChainedCalls(0, crudCalls, lastCallback)
// syntax: (step_to_run, list_of_steps, lastCallback)
$rootScope.makeChainedCalls(0, todoCrudCalls, $rootScope.refresh)
// syntax: (step_to_run_first, list_of_steps, lastCallback)
// hide the highlighted text and the menu element
$(".text-panel").removeClass("selection");
......
......@@ -21,89 +21,37 @@
if (listName == 'MAPLIST') {
crudActions = [
["delete", thisListId]
// only 'remove' is needed here
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
'params' : {'listId':thisListId, 'ngramIdList': thisNgramId} }
]
}
else if (listName == 'MAINLIST') {
crudActions = [
["delete", thisListId],
["put", $rootScope.listIds.STOPLIST],
// remove
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
'params' : {'listId':thisListId, 'ngramIdList': thisNgramId} },
// consequence: add to opposite list
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':$rootScope.listIds.STOPLIST, 'ngramIdList': thisNgramId} }
]
}
else if (listName == 'STOPLIST') {
crudActions = [
["delete", thisListId],
["put", $rootScope.listIds.MAINLIST],
]
// remove
{'service': MainApiChangeNgramHttpService, 'action': 'delete',
'params' : {'listId':thisListId, 'ngramIdList': thisNgramId} },
// consequence: add to opposite list
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':$rootScope.listIds.MAINLIST, 'ngramIdList': thisNgramId} }
]
}
// console.log(crudActions)
// using recursion to make chained calls,
// todo factorize with highlight.js
var lastCallback = function() {
// Refresh the annotationss
NgramListHttpService.get(
{'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId},
function(data) {
// $rootScope.annotations
// ----------------------
// is the union of all lists, one being later "active"
// (then used for left-side flatlist AND inline annots)
$rootScope.annotations = data[$rootScope.corpusId.toString()][$rootScope.docId.toString()];
// TODO £NEW : lookup obj[list_id][term_text] = {terminfo}
// $rootScope.lookup =
$rootScope.refreshDisplay();
},
function(data) {
console.error("unable to refresh the list of ngrams");
}
);
}
// chained recursion to do several actions then callback (eg refresh)
function makeChainedCalls (i, listOfActions, finalCallback) {
// each action couple has 2 elts
var action = listOfActions[i][0]
var listId = listOfActions[i][1]
MainApiChangeNgramHttpService[action](
{'listId': listId,
'ngramIdList': thisNgramId},
// on success
function(data) {
// case NEXT
// ----
// when chained actions
if (listOfActions.length > i+1) {
// console.log("calling next action ("+(i+1)+")")
// ==============================================
makeChainedCalls(i+1, listOfActions, finalCallback)
// ==============================================
}
// case LAST
// ------
// when last action
else {
finalCallback()
}
},
// on error
function(data) {
console.error("unable to edit the Ngram \""+ngramText+"\""
+"(ngramId "+ngramId+")"+"at crud no "+i
+" ("+action+" on list "+listId+")");
}
);
}
// run the loop by calling the initial recursion step
makeChainedCalls(0, crudActions, lastCallback)
$rootScope.makeChainedCalls(0, crudActions, $rootScope.refresh)
};
}]);
......@@ -155,8 +103,8 @@
/*
* Add a new NGram from the user input in the extra-text list
*/
$scope.onListSubmit = function ($event, listId) {
var inputEltId = "#"+ listId +"-input";
$scope.onListSubmit = function ($event, tgtListId) {
var inputEltId = "#"+ tgtListId +"-input";
if ($event.keyCode !== undefined && $event.keyCode != 13) return;
var value = angular.element(inputEltId).val().trim();
......@@ -170,11 +118,11 @@
// TODO £NEW : lookup obj[list_id][term_text] = {terminfo}
// // $rootScope.lookup =
console.log('looking for "' + value + '" in list:' + listId)
console.log('looking for "' + value + '" in list:' + tgtListId)
var already_in_list = false ;
angular.forEach($rootScope.annotations, function(annot,i) {
// console.log(i + ' => ' + annot.text + ',' + annot.list_id) ;
if (value == annot.text && listId == annot.list_id) {
if (value == annot.text && tgtListId == annot.list_id) {
console.log('the term "' + value + '" was already present in list')
// no creation
already_in_list = true ;
......@@ -184,64 +132,46 @@
if (already_in_list) { return ; }
// ---------------------------------------------------------------
// AddNgram
// --------
// creation will return an ngramId
// (checks if there's a preexisting ngramId for this value
// otherwise creates a new one and indexes the ngram in corpus)
MainApiAddNgramHttpService.put(
{
// text <=> str to create the new ngram
'text': value,
'corpusId': $rootScope.corpusId
},
// on AddNgram success
function(data) {
var newNgramId = data.id
console.log("OK created new ngram for '"+value+"' with id: "+newNgramId)
// ChangeNgram
// -----------
// add to listId after creation
// TODO: if maplist => also add to miam
MainApiChangeNgramHttpService["put"](
{
'listId': listId,
'ngramIdList': newNgramId
},
// on ChangeNgram success
function(data) {
// Refresh the annotations (was broken: TODO FIX)
console.warn("refresh attempt");
angular.element(inputEltId).val(""); // what for ???
NgramListHttpService.get(
{
'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId
},
// on refresh success
function(data) {
$rootScope.annotations = data[$rootScope.corpusId.toString()][$rootScope.docId.toString()];
$rootScope.refreshDisplay();
},
// on refresh error
function(data) {
console.error("unable to get the list of ngrams");
}
);
},
// on ChangeNgram error
function(data) {
console.error("unable to edit the Ngram"+ngramId+") on list "+listId+")");
}
);
},
// on AddNgram error
function(data) {
angular.element(inputEltId).parent().addClass("has-error");
console.error("error adding Ngram "+ value);
}
);
var tgtListName = $rootScope.lists[tgtListId]
// alert("ADDING TO listId: " + tgtListId +"\n listName: "+ tgtListName)
var crudCallsToMake = []
switch (tgtListName) {
case "STOPLIST":
crudCallsToMake = [
{'service': MainApiAddNgramHttpService, 'action': 'put',
'params' : {'ngramStr':value, corpusId: $rootScope.corpusId},
'dataPropertiesToCache': ['id'] },
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':tgtListId, 'ngramIdList': {'fromCache': 'id'} } }
];
break;
case "MAINLIST":
crudCallsToMake = [
{'service': MainApiAddNgramHttpService, 'action': 'put',
'params' : {'ngramStr':value, corpusId: $rootScope.corpusId},
'dataPropertiesToCache': ['id'] },
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':tgtListId, 'ngramIdList': {'fromCache': 'id'} } }
];
break;
case "MAPLIST":
crudCallsToMake = [
{'service': MainApiAddNgramHttpService, 'action': 'put',
'params' : {'ngramStr':value, corpusId: $rootScope.corpusId},
'dataPropertiesToCache': ['id'] },
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':$rootScope.listIds.MAINLIST, 'ngramIdList': {'fromCache': 'id'} } },
{'service': MainApiChangeNgramHttpService, 'action': 'put',
'params' : {'listId':tgtListId, 'ngramIdList': {'fromCache': 'id'} } }
];
break;
}
// run the ajax calls in a recursive loop by calling the step n° 0
$rootScope.makeChainedCalls(0, crudCallsToMake, $rootScope.refresh)
}; // onListSubmit
}]);
......
......@@ -36,9 +36,11 @@
</select>
</h5>
<div class="row spacer"></div>
<ul class="nav nav-pills nav-justified">
<ul class="nav nav-pills nav-justified activelists">
<li ng-repeat="(listId, listName) in activeLists" ng-class="{active: $first == true}">
<a href="#tab-{[{listId}]}" data-toggle="tab">{[{listName}]}</a>
<a href="#tab-{[{listId}]}" data-toggle="tab">
<span class="{[{listName}]} inlay">{[{listName}]}</span>
</a>
</li>
</ul>
</div>
......@@ -60,12 +62,11 @@
<li ng-class="{'disabled': currentListPage >= totalListPages(listId) - 1}"><a ng-click="nextListPage()" class="glyphicon glyphicon-forward"></a></li>
</ul>
</nav>
<!--
<div class="form-group" ng-controller="NgramInputController">
<input autosave="search" maxlength="240" placeholder="Add any text" type="text" class="form-control" id="{[{listId}]}-input" ng-keypress="onListSubmit($event, listId)">
<button type="submit" class="form-control btn btn-default btn-primary" ng-click="onListSubmit($event, listId)">Add to {[{listName}]}</button>
<div id="addfreengram" class="form-group" ng-controller="NgramInputController">
<label for="{[{listId}]}-input">Add a free term to <span class="{[{listName}]} inlay">{[{listName}]}</span>:</label>
<input autosave="search" maxlength="240" placeholder="Any text" type="text" class="form-control" id="{[{listId}]}-input" ng-keypress="onListSubmit($event, listId)">
<button type="submit" class="form-control btn btn-default" ng-click="onListSubmit($event, listId)">Create &amp; add</button>
</div>
-->
</div>
</div>
</div>
......
......@@ -1413,13 +1413,6 @@ $("#Clean_All").click(function(){
// $("#Clean_All, #Save_All").attr( "disabled", "disabled" );
});
$("#Save_All").click(function(){
SaveLocalChanges()
});
$("#Save_All_Bottom").click(function(){
SaveLocalChanges()
});
// find all the consequences of changes from MAP => MAIN
// -----------------------------------------------------
......@@ -2310,23 +2303,36 @@ function isNumeric(n) {
// (it can only go back OFF with a save action via page reload)
function toggleNeedSave() {
var icons = $(".needsaveicon")
var boxes = $('.savediv')
var topButton = $('#ImportListOrSaveAll')
var botButton = $('#Save_All_Bottom')
// change the status icons
$(".needsaveicon").removeClass("glyphicon-floppy-saved");
$(".needsaveicon").addClass("glyphicon-floppy-remove");
$(".needsaveicon").css("color","red");
$(".needsaveicon").css("font-size","120%");
icons.removeClass("glyphicon-floppy-saved");
icons.removeClass("glyphicon-import");
icons.addClass("glyphicon-exclamation-sign");
icons.css("color","red");
icons.css("font-size","120%");
// give new text to the hybrid save/import button
topButton.html("<b>Save all changes</b>")
// save_divs get a new tooltip title
$('.savediv').prop('title', "Click to save all changes to DB")
boxes.prop('title', "Click to save all changes to DB")
// activate the buttons
$('#Save_All').prop('disabled', false) ;
$('#Save_All').removeClass("btn-muted");
$('#Save_All').addClass("btn-success");
topButton.prop('disabled', false) ;
topButton.removeClass("btn-warning");
topButton.addClass("btn-success");
botButton.prop('disabled', false) ;
botButton.removeClass("btn-muted");
botButton.addClass("btn-success");
$('#Save_All_Bottom').prop('disabled', false) ;
$('#Save_All_Bottom').removeClass("btn-muted");
$('#Save_All_Bottom').addClass("btn-success");
// bind the onclick events (it also replaces the default import onclick for the hybrid button)
topButton.attr("onclick","SaveLocalChanges()");
botButton.attr("onclick","SaveLocalChanges()");
// toggle the global var ON
_NeedSave = true
......
......@@ -126,19 +126,11 @@ em {
</center>
</h2>
<div class="savediv pull-left" style="margin-top:1.5em;padding-right:1em;" title="No changes to save">
<!-- need save status -->
<span class="needsaveicon glyphicon glyphicon-floppy-saved"></span>
&nbsp;
<!-- save button -->
<button id="Save_All" class="btn btn-muted" disabled style="font-size:120%">
<b>Save all changes</b>
</button>
<br/>
<br/>
<!-- import icon -->
<span class="glyphicon glyphicon-import"></span>
<!-- save/import icon -->
<span class="needsaveicon glyphicon glyphicon-import"></span>
&nbsp;
<button id="ImportList" class="btn btn-warning" style="font-size:120%"
<!-- save/import button -->
<button id="ImportListOrSaveAll" class="btn btn-warning" style="font-size:120%"
onclick="$('#csvimport').modal('show');">
<b>Import a Termlist</b>
</button>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment