Commit 911725bf authored by delanoe's avatar delanoe

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

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