Commit a77ea0cf authored by Romain Loth's avatar Romain Loth

Update/delete possible for terms table (TODO: groupings)

parent e8bde84e
...@@ -35,8 +35,7 @@ from sqlalchemy.ext.mutable import MutableDict, MutableList ...@@ -35,8 +35,7 @@ from sqlalchemy.ext.mutable import MutableDict, MutableList
# useful for queries # useful for queries
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from sqlalchemy import func from sqlalchemy import func, desc
# bulk insertions # bulk insertions
......
"""
API views for advanced operations on ngrams and ngramlists
-----------------------------------------------------------
- retrieve several lists together ("family")
- retrieve detailed list infos (ngram_id, term strings, scores...)
- modify NodeNgram lists (PUT/DEL an ngram to a MAINLIST OR MAPLIST...)
"""
from gargantext.util.http import APIView, get_parameters, JsonHttpResponse,\ from gargantext.util.http import APIView, get_parameters, JsonHttpResponse,\
ValidationException ValidationException, Http404
from gargantext.util.db import session, aliased from gargantext.util.db import session, aliased, desc
from gargantext.util.db_cache import cache from gargantext.util.db_cache import cache
from gargantext.models import Ngram, NodeNgram, NodeNodeNgram from gargantext.models import Ngram, NodeNgram, NodeNodeNgram
from gargantext.util.lists import Translations from gargantext.util.lists import UnweightedList, Translations
from sqlalchemy import desc
# from gargantext.constants import *
# from gargantext.util.validation import validate
# from collections import defaultdict
def _query_list(list_id, def _query_list(list_id,
...@@ -64,6 +68,116 @@ class List(APIView): ...@@ -64,6 +68,116 @@ class List(APIView):
""" """
pass pass
class ListChange(APIView):
"""
Any ngram action on standard NodeNgram lists (MAIN, MAP, STOP)
USAGE EXEMPLE:
HOST/api/ngramlists/change?list=42&ngrams=1,2,3,4,5
vvvvvv ||||||
old list vvvvvv
to modify new list items
| |
v v
2 x UnweightedLists: self.base_list self.change_list
We use DEL/PUT HTTP methods to differentiate the 2 basic rm/add actions
They rely only on inline parameters (no need for payload data)
No chained effects: eg removing from MAPLIST will not remove
automatically from associated MAINLIST
NB: request.user is also checked for current authentication status
"""
def initial(self, request):
"""
Before dispatching to put(), delete()...
1) Checks current user authentication to prevent remote DB manipulation
2) Prepares self.list_objects from params
"""
if not request.user.is_authenticated():
raise Http404()
# can't use return in initial() (although 401 maybe better than 404)
# can't use @requires_auth because of positional 'self' within class
# get validated params
self.params = get_parameters(request)
(self.base_list, self.change_list) = ListChange._validate(self.params)
def put(self, request):
"""
Adds one or more ngrams to a list.
"""
# union of items ----------------------------
new_list = self.base_list + self.change_list
# -------------------------------------------
# save
new_list.save(self.base_list.id)
return JsonHttpResponse({
'parameters': self.params,
'count_added': len(new_list.items) - len(self.base_list.items),
}, 201)
def delete(self, request):
"""
Removes one or more ngrams from a list.
"""
# removal (set difference) ------------------
new_list = self.base_list - self.change_list
# -------------------------------------------
# save
new_list.save(self.base_list.id)
return JsonHttpResponse({
'parameters': self.params,
'count_removed': len(self.base_list.items) - len(new_list.items),
}, 200)
@staticmethod
def _validate(params):
"""
Checks "list" and "ngrams" parameters for their:
- presence
- type
These two parameters are mandatory for any ListChange methods.
ngrams are also converted to an UnweightedList object for easy add/remove
"""
if 'list' not in params:
raise ValidationException('The route /api/ngramlists/change requires a "list" \
parameter, for instance /api/ngramlists/change?list_id=42')
if 'ngrams' not in params:
raise ValidationException('The route /api/ngramlists/change requires an "ngrams"\
parameter, for instance /api/ngramlists/change?ngrams=1,2,3,4')
# 2 x retrieval => 2 x UnweightedLists
# ------------------------------------
base_list_id = None
try:
base_list_id = int(params['list'])
# UnweightedList retrieved by id
base_list = UnweightedList(base_list_id)
except:
raise ValidationException('The "list" parameter requires an existing list id.')
change_ngram_ids = []
try:
change_ngram_ids = [int(n) for n in params['ngrams'].split(',')]
# UnweightedList created from items
change_list = UnweightedList(change_ngram_ids)
except:
raise ValidationException('The "ngrams" parameter requires one or more ngram_ids separated by comma')
return(base_list, change_list)
class ListFamily(APIView): class ListFamily(APIView):
""" """
Compact combination of *multiple* list info Compact combination of *multiple* list info
...@@ -78,14 +192,14 @@ class ListFamily(APIView): ...@@ -78,14 +192,14 @@ class ListFamily(APIView):
USAGE EXEMPLES USAGE EXEMPLES
HOST/api/ngramlists/family?corpus=2 HOST/api/ngramlists/family?corpus=2
HOST/api/ngramlists/family?corpus=2&glance=10 HOST/api/ngramlists/family?corpus=2&head=10
HOST/api/ngramlists/family?mainlist=91&scoring=94 HOST/api/ngramlists/family?mainlist=91&scoring=94
HOST/api/ngramlists/family?mainlist=91&scoring=94&glance=10 HOST/api/ngramlists/family?mainlist=91&scoring=94&head=10
HOST/api/ngramlists/family?mainlist=91&stoplist=90&scoring=94 HOST/api/ngramlists/family?mainlist=91&stoplist=90&scoring=94
etc. etc.
REST Parameters: REST Parameters:
"glance=20" "head=20"
use pagination to only load the k top ngrams of the mainlist use pagination to only load the k top ngrams of the mainlist
(useful for fast loading of terms view) (useful for fast loading of terms view)
"corpus=ID" "corpus=ID"
...@@ -100,10 +214,10 @@ class ListFamily(APIView): ...@@ -100,10 +214,10 @@ class ListFamily(APIView):
parameters = get_parameters(request) parameters = get_parameters(request)
glance_limit = None glance_limit = None
mainlist = None mainlist_id = None
scores_id = None scores_id = None
groups_id = None groups_id = None
secondary_lists = {'maplist':None, 'stoplist':None} other_list_ids = {'maplist':None, 'stoplist':None}
# 1) retrieve a mainlist_id and other lists # 1) retrieve a mainlist_id and other lists
########################################## ##########################################
...@@ -119,22 +233,22 @@ class ListFamily(APIView): ...@@ -119,22 +233,22 @@ class ListFamily(APIView):
else: else:
scores_id = corpus.children('OCCURRENCES').first().id scores_id = corpus.children('OCCURRENCES').first().id
# retrieve the family of lists that have corpus as parent # retrieve the family of lists that have corpus as parent
mainlist = corpus.children('MAINLIST').first().id, mainlist_id = corpus.children('MAINLIST').first().id
groups_id = corpus.children('GROUPLIST').first().id groups_id = corpus.children('GROUPLIST').first().id
secondary_lists['stoplist'] = corpus.children('STOPLIST').first().id other_list_ids['stoplist'] = corpus.children('STOPLIST').first().id
secondary_lists['maplist'] = corpus.children('MAPLIST').first().id, other_list_ids['maplist'] = corpus.children('MAPLIST').first().id
# custom request: refers to each list individually # custom request: refers to each list individually
# ------------------------------------------------- # -------------------------------------------------
elif "mainlist" in parameters and "scoring" in parameters: elif "mainlist" in parameters and "scoring" in parameters:
mainlist = parameters['mainlist'] mainlist_id = parameters['mainlist']
scores_id = parameters['scoring'] scores_id = parameters['scoring']
groups_id = None groups_id = None
if 'groups' in parameters: if 'groups' in parameters:
groups_id = parameters['scoring'] groups_id = parameters['scoring']
for k in ['stoplist', 'maplist']: for k in ['stoplist', 'maplist']:
if k in parameters: if k in parameters:
secondary_lists[k] = parameters[k] other_list_ids[k] = parameters[k]
# or request has an error # or request has an error
# ----------------------- # -----------------------
...@@ -149,21 +263,22 @@ class ListFamily(APIView): ...@@ -149,21 +263,22 @@ class ListFamily(APIView):
ngraminfo = {} # ngram details sorted per ngram id ngraminfo = {} # ngram details sorted per ngram id
linkinfo = {} # ngram groups sorted per ngram id linkinfo = {} # ngram groups sorted per ngram id
listmembers = {} # ngram ids sorted per list name listmembers = {} # ngram ids sorted per list name
if "glance" in parameters: if "head" in parameters:
# glance <=> only mainlist AND only k top ngrams # head <=> only mainlist AND only k top ngrams
glance_limit = int(parameters['glance']) glance_limit = int(parameters['head'])
mainlist_query = _query_list(mainlist, details=True, mainlist_query = _query_list(mainlist_id, details=True,
pagination_limit = glance_limit, pagination_limit = glance_limit,
scoring_metric_id= scores_id) scoring_metric_id= scores_id)
else: else:
# infos for all ngrams # infos for all ngrams
mainlist_query = _query_list(mainlist, details=True, mainlist_query = _query_list(mainlist_id, details=True,
scoring_metric_id= scores_id) scoring_metric_id= scores_id)
# and for the other lists (stop and map) # and for the other lists (stop and map)
for li in secondary_lists: for li in other_list_ids:
li_elts = _query_list(secondary_lists[li], details=False li_elts = _query_list(other_list_ids[li], details=False
).all() ).all()
listmembers[li] = {ng[0]:True for ng in li_elts} # simple array of ngram_ids
listmembers[li] = [ng[0] for ng in li_elts]
# and the groupings # and the groupings
if groups_id: if groups_id:
...@@ -171,7 +286,6 @@ class ListFamily(APIView): ...@@ -171,7 +286,6 @@ class ListFamily(APIView):
linkinfo = links.groups linkinfo = links.groups
# the output form # the output form
ngraminfo = {}
for ng in mainlist_query.all(): for ng in mainlist_query.all():
ng_id = ng[0] ng_id = ng[0]
# id => [term, weight] # id => [term, weight]
...@@ -180,5 +294,12 @@ class ListFamily(APIView): ...@@ -180,5 +294,12 @@ class ListFamily(APIView):
return JsonHttpResponse({ return JsonHttpResponse({
'ngraminfos' : ngraminfo, 'ngraminfos' : ngraminfo,
'listmembers' : listmembers, 'listmembers' : listmembers,
'links' : linkinfo 'links' : linkinfo,
'nodeids' : {
'mainlist': mainlist_id,
'maplist' : other_list_ids['maplist'],
'stoplist': other_list_ids['stoplist'],
'groups': groups_id,
'scores': scores_id,
}
}) })
...@@ -10,16 +10,18 @@ urlpatterns = [ ...@@ -10,16 +10,18 @@ urlpatterns = [
url(r'^nodes/(\d+)/facets$', nodes.CorpusFacet.as_view()), url(r'^nodes/(\d+)/facets$', nodes.CorpusFacet.as_view()),
# get a list of ngram_ids or ngram_infos by list_id # add or remove ngram from a list
# # ex: add <=> PUT ngramlists/change?list=42&ngrams=1,2
# url(r'^ngramlists/(\d+)$', ngramlists.List.as_view()), # rm <=> DEL ngramlists/change?list=42&ngrams=1,2
url(r'^ngramlists/change$', ngramlists.ListChange.as_view()),
# entire combination of lists from a corpus # get entire combination of lists from a corpus
# (or any combination of lists that go together : # (or any combination of lists that go together :
# - a mainlist # - a mainlist
# - an optional stoplist # - an optional stoplist
# - an optional maplist # - an optional maplist
# - an optional grouplist # - an optional grouplist)
# aka lexical model
url(r'^ngramlists/family$', ngramlists.ListFamily.as_view()), url(r'^ngramlists/family$', ngramlists.ListFamily.as_view()),
] ]
...@@ -318,8 +318,8 @@ function Final_UpdateTable( action ) { ...@@ -318,8 +318,8 @@ function Final_UpdateTable( action ) {
// debug // debug
console.log("\nFUN Final_UpdateTable()") console.log("\nFUN Final_UpdateTable()")
console.log("AjaxRecords") // console.log("AjaxRecords")
console.log(AjaxRecords) // console.log(AjaxRecords)
// (1) Identifying if the button is collapsed: // (1) Identifying if the button is collapsed:
var isCollapsed=false; var isCollapsed=false;
...@@ -346,9 +346,8 @@ function Final_UpdateTable( action ) { ...@@ -346,9 +346,8 @@ function Final_UpdateTable( action ) {
var dataini = (TheBuffer[0])?TheBuffer[0]:oldest; var dataini = (TheBuffer[0])?TheBuffer[0]:oldest;
var datafin = (TheBuffer[1])?TheBuffer[1]:latest; var datafin = (TheBuffer[1])?TheBuffer[1]:latest;
pr("show me the pubs of the selected period") pr("show me the pubs of the selected score range")
pr("\tfrom ["+dataini+"] to ["+datafin+"]") pr("\tfrom ["+dataini+"] to ["+datafin+"]")
pr("\tfrom ["+oldest+"] to ["+latest+"]")
TimeRange = [] TimeRange = []
for (var i in AjaxRecords) { for (var i in AjaxRecords) {
...@@ -557,7 +556,7 @@ function transformContent(rec_id) { ...@@ -557,7 +556,7 @@ function transformContent(rec_id) {
result["ngramId"] = ngram_info["id"] ; result["ngramId"] = ngram_info["id"] ;
// uncomment if column state (here and in Main_test) // uncomment if column state (here and in Main_test)
result["state"] = AjaxRecords[rec_id].state // result["state"] = AjaxRecords[rec_id].state
// ------------------------------------------- // -------------------------------------------
// check box state columns 'will_be_map' and 'will_be_stop' // check box state columns 'will_be_map' and 'will_be_stop'
...@@ -870,16 +869,16 @@ function SaveLocalChanges() { ...@@ -870,16 +869,16 @@ function SaveLocalChanges() {
} }
// [ = = = = / For deleting subforms = = = = ] // [ = = = = / For deleting subforms = = = = ]
console.log(" = = = = = = = = = == ") // console.log(" = = = = = = = = = == ")
console.log("FlagsBuffer:") // console.log("FlagsBuffer:")
console.log(JSON.stringify(FlagsBuffer)) // console.log(JSON.stringify(FlagsBuffer))
var nodes_2del = Object.keys(FlagsBuffer["delete"]).map(Number) var nodes_2del = Object.keys(FlagsBuffer["delete"]).map(Number) // main => stop
var nodes_2keep = Object.keys(FlagsBuffer["keep"]).map(Number) var nodes_2keep = Object.keys(FlagsBuffer["keep"]).map(Number) // ??? stop => main ???
var nodes_2group = $.extend({}, FlagsBuffer["group"]) var nodes_2group = $.extend({}, FlagsBuffer["group"])
var nodes_2inmap = $.extend({}, FlagsBuffer["inmap"]) var nodes_2inmap = $.extend({}, FlagsBuffer["inmap"]) // add to map
var nodes_2outmap = $.extend({}, FlagsBuffer["outmap"]) var nodes_2outmap = $.extend({}, FlagsBuffer["outmap"]) // remove from map
// console.log("") // console.log("")
// console.log("") // console.log("")
...@@ -896,8 +895,12 @@ function SaveLocalChanges() { ...@@ -896,8 +895,12 @@ function SaveLocalChanges() {
// console.log("") // console.log("")
// console.log("") // console.log("")
var list_id = $("#list_id").val() // retrieve node_ids from hidden input
var corpus_id = getIDFromURL( "corpora" ) var mainlist_id = $("#mainlist_id").val()
var maplist_id = $("#maplist_id" ).val()
var stoplist_id = $("#stoplist_id" ).val()
// var corpus_id = getIDFromURL( "corpora" )
$("#stoplist_content").html() $("#stoplist_content").html()
...@@ -906,15 +909,59 @@ function SaveLocalChanges() { ...@@ -906,15 +909,59 @@ function SaveLocalChanges() {
// }); // });
$("#Save_All").append('<img width="8%" src="/static/img/ajax-loader.gif"></img>') $("#Save_All").append('<img width="8%" src="/static/img/ajax-loader.gif"></img>')
CRUD( corpus_id , "/group" , [] , nodes_2group , "PUT" , function(result) {
CRUD( corpus_id , "/keep" , [] , nodes_2inmap , "PUT" , function(result) { // chained CRUD calls
CRUD( corpus_id , "/keep" , [] , nodes_2outmap , "DELETE" , function(result) { CRUD_1_AddMap()
CRUD( list_id , "" , nodes_2del , [] , "DELETE", function(result) {
window.location.reload() // add some ngrams to maplist
}); function CRUD_1_AddMap() {
}); CRUD( maplist_id , Object.keys(nodes_2inmap), "PUT" , function(success) {
}); if (success) {
}); CRUD_2_RmMap() // chained AJAX 1 -> 2
}
else {
console.warn('CRUD error on ngrams add to maplist ('+maplist_id+')')
}
});
}
// remove some ngrams from maplist
function CRUD_2_RmMap() {
CRUD( maplist_id , Object.keys(nodes_2outmap), "DELETE" , function(success) {
if (success) {
CRUD_3_AddStopRmMain() // chained AJAX 2 -> 3
}
else {
console.warn('CRUD error on ngrams remove from maplist ('+maplist_id+')')
}
});
}
// 2 operations going together: add ngrams to stoplist and remove them from mainlist
function CRUD_3_AddStopRmMain() {
CRUD( stoplist_id , nodes_2del, "PUT" , function(success) {
if (success) {
// console.log("OK CRUD 3a add stop")
CRUD( mainlist_id , nodes_2del, "DELETE" , function(success) {
if (success) {
// console.log("OK CRUD 3b rm main")
CRUD_4() // chained AJAX 3 -> 4
}
else {
console.warn('CRUD error on ngrams remove from mainlist ('+mainlist_id+')')
}
});
}
else {
console.warn('CRUD error on ngrams add to stoplist ('+stoplist_id+')')
}
});
}
// TODO add to groups
function CRUD_4() {
window.location.reload() // refresh whole page if all OK
}
} }
...@@ -938,37 +985,40 @@ $("#Save_All").click(function(){ ...@@ -938,37 +985,40 @@ $("#Save_All").click(function(){
SaveLocalChanges() SaveLocalChanges()
}); });
// For lists, all http-requests // For list modifications (add/delete), all http-requests
function CRUD( parent_id , action , nodes , args , http_method , callback) { function CRUD( list_id , ngram_ids , http_method , callback) {
var the_url = window.location.origin+"/api/node/"+parent_id+"/ngrams"+action+"/"+nodes.join("+"); // ngramlists/change?node_id=42&ngram_ids=1,2
the_url = the_url.replace(/\/$/, ""); //remove trailing slash var the_url = window.location.origin+"/api/ngramlists/change?list="+list_id+"&ngrams="+ngram_ids.join(",");
// debug // debug
// console.log("CRUD AJAX => URL: " + the_url + " (" + http_method + ")") // console.log("starting CRUD AJAX => URL: " + the_url + " (" + http_method + ")")
if(nodes.length>0 || Object.keys(args).length>0) { if(ngram_ids.length>0) {
$.ajax({ $.ajax({
method: http_method, method: http_method,
url: the_url, url: the_url,
data: args, // data: args, // currently all data explicitly in the url (like a GET)
beforeSend: function(xhr) { beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken")); xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
}, },
success: function(data){ success: function(data){
console.log(http_method + " ok!!") console.log("-- CRUD ----------")
console.log(nodes) console.log(http_method + " ok!!")
console.log(data) console.log(JSON.stringify(data))
callback(true); console.log("------------------")
}, callback(true);
error: function(result) { },
console.log("Data not found in #Save_All"); error: function(result) {
console.log(result) console.log("-- CRUD ----------")
callback(false); console.log("Data not found in #Save_All");
} console.log(result)
}); console.log("------------------")
callback(false);
} else callback(false); }
} });
} else callback(true);
}
...@@ -1003,6 +1053,13 @@ function Main_test( data , initial , search_filter) { ...@@ -1003,6 +1053,13 @@ function Main_test( data , initial , search_filter) {
console.log(" = = = = / MAIN_TEST: = = = = ") console.log(" = = = = / MAIN_TEST: = = = = ")
console.log("") console.log("")
// Expected infos in "data.ngrams" should have the form:
// { "1": { id: "1", name: "réalité", score: 36 },
// "9": { id: "9", name: "pdg", score: 116 },
// "10": { id:"10", name: "infrastructure", score: 12 } etc. }
// (see filling of rec_info below)
// console.log(data.ngrams)
var DistributionDict = {} var DistributionDict = {}
for(var i in DistributionDict) for(var i in DistributionDict)
...@@ -1032,7 +1089,7 @@ function Main_test( data , initial , search_filter) { ...@@ -1032,7 +1089,7 @@ function Main_test( data , initial , search_filter) {
div_table += "\t"+"\t"+'<th data-dynatable-column="ngramId" style="background-color:grey">ngramId</th>'+"\n"; div_table += "\t"+"\t"+'<th data-dynatable-column="ngramId" style="background-color:grey">ngramId</th>'+"\n";
// uncomment for column stateId (here and in transformContent) // uncomment for column stateId (here and in transformContent)
div_table += "\t"+"\t"+'<th data-dynatable-column="state" style="background-color:grey">State</th>'+"\n" ; // div_table += "\t"+"\t"+'<th data-dynatable-column="state" style="background-color:grey">State</th>'+"\n" ;
div_table += "\t"+"\t"+'<th data-dynatable-column="name">Terms</th>'+"\n"; div_table += "\t"+"\t"+'<th data-dynatable-column="name">Terms</th>'+"\n";
div_table += "\t"+"\t"+'<th id="score_column_id" data-dynatable-sorts="score" data-dynatable-column="score">Score</th>'+"\n"; div_table += "\t"+"\t"+'<th id="score_column_id" data-dynatable-sorts="score" data-dynatable-column="score">Score</th>'+"\n";
...@@ -1089,15 +1146,14 @@ function Main_test( data , initial , search_filter) { ...@@ -1089,15 +1146,14 @@ function Main_test( data , initial , search_filter) {
$("#stats").html(div_stats) $("#stats").html(div_stats)
AjaxRecords = {} AjaxRecords = {}
console.log("data.ngrams")
console.log(data.ngrams)
for(var id in data.ngrams) { for(var id in data.ngrams) {
// console.log(i) // console.log(i)
// console.log(data.ngrams[i]) // console.log(data.ngrams[i])
var le_ngram = data.ngrams[id] ; var le_ngram = data.ngrams[id] ;
var node_info = { var rec_info = {
"id" : le_ngram.id, "id" : le_ngram.id,
"name": le_ngram.name, "name": le_ngram.name,
"score": le_ngram.score, "score": le_ngram.score,
...@@ -1112,14 +1168,14 @@ function Main_test( data , initial , search_filter) { ...@@ -1112,14 +1168,14 @@ function Main_test( data , initial , search_filter) {
"will_be_map": null, "will_be_map": null,
"will_be_stop": null "will_be_stop": null
} }
// AjaxRecords.push(node_info) // AjaxRecords.push(rec_info)
AjaxRecords[id] = node_info AjaxRecords[id] = rec_info
if ( ! DistributionDict[node_info.score] ) DistributionDict[node_info.score] = 0; if ( ! DistributionDict[rec_info.score] ) DistributionDict[rec_info.score] = 0;
DistributionDict[node_info.score]++; DistributionDict[rec_info.score]++;
} }
console.log(FirstScore) // console.log(FirstScore)
// console.log("The Distribution!:") // console.log("The Distribution!:")
// console.log(Distribution) // console.log(Distribution)
...@@ -1418,8 +1474,17 @@ GET_(new_url, function(res) { ...@@ -1418,8 +1474,17 @@ GET_(new_url, function(res) {
"nb_ngrams":Object.keys(main_ngrams_objects).length, "nb_ngrams":Object.keys(main_ngrams_objects).length,
} }
} ; } ;
NGrams["map"] = res.listmembers.maplist ; // map & stop: 2x(array of ids) ==> 2x(lookup hash)
NGrams["stop"] = res.listmembers.stoplist ; // TODO use simpler struct NGrams["map"] = {} ;
for (var i in res.listmembers.maplist) {
var map_ng_id = res.listmembers.maplist[i] ;
NGrams["map"][map_ng_id] = true ;
}
NGrams["stop"] = {} ;
for (var i in res.listmembers.stoplist) {
var stop_ng_id = res.listmembers.stoplist[i] ;
NGrams["stop"][stop_ng_id] = true ;
}
NGrams["group"] = {"links" : res.links , "nodes" : {}}; NGrams["group"] = {"links" : res.links , "nodes" : {}};
for (var parent_ng_id in res.links) { for (var parent_ng_id in res.links) {
NGrams["group"]["nodes"][parent_ng_id] = false ; NGrams["group"]["nodes"][parent_ng_id] = false ;
...@@ -1429,8 +1494,15 @@ GET_(new_url, function(res) { ...@@ -1429,8 +1494,15 @@ GET_(new_url, function(res) {
} }
} }
} }
console.log('after init NGrams["main"].ngrams') // console.log('after init NGrams["main"].ngrams')
console.log(NGrams["main"].ngrams) // console.log(NGrams["main"].ngrams)
// cache all DB node_ids
$("input#mainlist_id").val(res.nodeids['mainlist'])
$("input#maplist_id" ).val(res.nodeids['maplist'])
$("input#stoplist_id").val(res.nodeids['stoplist'])
$("input#groups_id").val(res.nodeids['groups'])
$("input#scores_id").val(res.nodeids['scores'])
AfterAjax() ; AfterAjax() ;
}); });
...@@ -1537,8 +1609,8 @@ function AfterAjax() { ...@@ -1537,8 +1609,8 @@ function AfterAjax() {
// console.log('NGrams["group"]["nodes"]') // console.log('NGrams["group"]["nodes"]')
// console.log( NGrams["group"]["nodes"] ) // console.log( NGrams["group"]["nodes"] )
console.log('after subforms deletion NGrams["main"].ngrams') // console.log('after subforms deletion NGrams["main"].ngrams')
console.log(NGrams["main"].ngrams) // console.log(NGrams["main"].ngrams)
// initialize state of maplist items // initialize state of maplist items
if( Object.keys(NGrams["map"]).length>0 ) { if( Object.keys(NGrams["map"]).length>0 ) {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
<div class="row"> <div class="row">
<div id="monthly-move-chart"> <div id="monthly-move-chart">
<center> <center>
Select a time range in the chart with blue bars to zoom in Select a score/frequency range in the chart with blue bars to zoom in
<p align="center"> <p align="center">
<a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a> <a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a>
<a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a></p> <a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a></p>
...@@ -41,7 +41,12 @@ ...@@ -41,7 +41,12 @@
<br> <br>
</div> </div>
<input type="hidden" id="list_id" value="{{ list_id }}"></input> <!-- (values set by js) caching our DB ids (handy for list update commands) -->
<input type="hidden" id="mainlist_id" value=""></input>
<input type="hidden" id="maplist_id" value=""></input>
<input type="hidden" id="stoplist_id" value=""></input>
<input type="hidden" id="groups_id" value=""></input>
<input type="hidden" id="scores_id" value=""></input>
<div class="row"> <div class="row">
<div class="panel panel-default"> <div class="panel panel-default">
......
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