Commit 0bb4edbc authored by delanoe's avatar delanoe

Merge branch 'romain-refactoring' into merge

parents adcaf50b c3adae17
...@@ -161,3 +161,9 @@ ...@@ -161,3 +161,9 @@
.float-right { .float-right {
float: right; float: right;
} }
.favactive {
/* yellow */
color: #FFF50D;
text-shadow: -1px 0 #777777, 0 1px #777777, 1px 0 #777777, 0 -1px #777777;
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// dataLoading = signal pour afficher wait // dataLoading = signal pour afficher wait
$scope.dataLoading = true ; $scope.dataLoading = true ;
console.log("annotations.document.DocController.DocumentHttpService.get():before") console.log("annotations.document.DocController.DocumentHttpService.get():before")
$rootScope.documentResource = DocumentHttpService.get( $rootScope.documentResource = DocumentHttpService.get(
...@@ -52,12 +52,64 @@ ...@@ -52,12 +52,64 @@
}]); }]);
annotationsAppDocument.controller('DocFavoriteController', annotationsAppDocument.controller('DocFavoriteController',
['$scope', '$rootScope', 'DocumentHttpService', ['$scope', '$rootScope', 'MainApiFavoritesHttpService',
function ($scope, $rootScope, DocumentHttpService) { function ($scope, $rootScope, MainApiFavoritesHttpService) {
$scope.isFavorite = false;
MainApiFavoritesHttpService.get(
{
'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId
},
function(data) {
if (data['favdocs'].length > 0
&& data['favdocs'][0] == $scope.docId) {
$scope.isFavorite = true ;
}
else {
$scope.isFavorite = false ;
}
},
function(data) {
console.error("unable to check if document belongs to favorites");
$scope.isFavorite = false ;
}
) ;
$scope.onStarClick = function($event) { $scope.onStarClick = function($event) {
console.log($scope.isFavorite)
// console.log($scope)
console.log("TODO"); console.log("TODO");
var myAction ;
if (! $scope.isFavorite) {
// PUT api/nodes/574/favorites?docs=576
myAction = MainApiFavoritesHttpService.put
}
else {
// DELETE api/nodes/574/favorites?docs=576
myAction = MainApiFavoritesHttpService.delete
}
// (1) do the action
myAction(
{
'corpusId': $rootScope.corpusId,
'docId': $rootScope.docId
},
// success
function(data) {
// (2) toggle status and refresh
$scope.isFavorite = ! $scope.isFavorite
$rootScope.refreshDisplay();
},
// failure
function(data) {
console.error("unable to change favorite status");
}
);
}; };
$scope.isFavorite = false;
}]); }]);
})(window); })(window);
...@@ -122,4 +122,49 @@ ...@@ -122,4 +122,49 @@
} }
); );
}); });
/*
* MainApiFavoritesHttpService: Check/Add/Del Document in favorites
* ============================
* route: api/nodes/574/favorites?docs=576
* /!\ for this route we reach out of this annotation module
* and send directly to the gargantext api route for favs
* (cross origin request with http protocol scheme)
* ------
*
* exemple:
* --------
* {
* "favdocs": [576] // <== if doc is among favs
* "missing": [] // <== if doc is not in favs
* }
*
*/
http.factory('MainApiFavoritesHttpService', function($resource) {
return $resource(
// adding explicit "http://" b/c this a cross origin request
'http://' + window.GARG_ROOT_URL + "/api/nodes/:corpusId/favorites?docs=:docId",
{
corpusId: '@corpusId',
docId: '@docId'
},
{
get: {
method: 'GET',
params: {corpusId: '@corpusId', docId: '@docId'}
},
put: {
method: 'PUT',
params: {corpusId: '@corpusId', docId: '@docId'}
},
delete: {
method: 'DELETE',
params: {corpusId: '@corpusId', docId: '@docId'}
}
}
);
});
})(window); })(window);
...@@ -58,9 +58,9 @@ ...@@ -58,9 +58,9 @@
<div class="list-selector"> <div class="list-selector">
<h5>Select lists</h5> <h5>Select lists</h5>
<select class="selectpicker" multiple ng-change="activeListsChange()" ng-model="lists" ng-controller="ActiveListsController"> <select class="selectpicker" multiple ng-change="activeListsChange()" ng-model="lists" ng-controller="ActiveListsController">
<option ng-repeat="item in allListsSelect" id="list---{[{item.id}]}">{[{item.label}]}</option> <option ng-repeat="item in allListsSelect" id="list---{[{item.id}]}">{[{item.label}]}</option>
<!-- to disallow unchecking MapList add this into <option> element: ng-disabled="{[{ item.label == 'MapList' }]}" --> <!-- to disallow unchecking MapList add this into <option> element: ng-disabled="{[{ item.label == 'MapList' }]}" -->
</select> </select>
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
</div> </div>
<div class="col-md-2 col-xs-2 clearfix"> <div class="col-md-2 col-xs-2 clearfix">
<button ng-controller="DocFavoriteController" type="button" class="btn btn-default float-right" ng-click="onStarClick($event)"> <button ng-controller="DocFavoriteController" type="button" class="btn btn-default float-right" ng-click="onStarClick($event)">
<span class="glyphicon" ng-class="{'glyphicon-star-empty': isFavorite == false, 'glyphicon-star': isFavorite == true}"></span> <span class="glyphicon" ng-class="{'glyphicon-star-empty': isFavorite == false, 'glyphicon-star favactive': isFavorite == true}"></span>
</button> </button>
<!--<nav> <!--<nav>
<ul class="pager"> <ul class="pager">
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
/* Constants required for annotations app JS to work */ /* Constants required for annotations app JS to work */
window.STATIC_URL = "{% static '' %}"; window.STATIC_URL = "{% static '' %}";
window.ANNOTATION_API_URL = "{{ api_url }}"; window.ANNOTATION_API_URL = "{{ api_url }}";
window.GARG_ROOT_URL = "{{ garg_url }}";
window.NODES_API_URL = "{{ nodes_api_url }}"; window.NODES_API_URL = "{{ nodes_api_url }}";
</script> </script>
<script src="{% static 'annotations/main.js' %}"></script> <script src="{% static 'annotations/main.js' %}"></script>
......
...@@ -5,13 +5,14 @@ from annotations import views ...@@ -5,13 +5,14 @@ from annotations import views
# /!\ urls patterns here are *without* the trailing slash # /!\ urls patterns here are *without* the trailing slash
urlpatterns = [ urlpatterns = [
# json:title,id,authors,journal, # GET [DocumentHttpService]
# json:title,id,authors,journal,
# publication_date # publication_date
# abstract_text,full_text # abstract_text,full_text
url(r'^documents/(?P<doc_id>[0-9]+)$', views.Document.as_view()), # document view url(r'^documents/(?P<doc_id>[0-9]+)$', views.Document.as_view()), # document view
# GET: # GET [NgramListHttpService]
# was : lists ∩ document (ngram_ids intersection if connected to list node_id and doc node_id) # was : lists ∩ document (ngram_ids intersection if connected to list node_id and doc node_id)
# fixed 2016-01: just lists (because document doesn't get updated by POST create cf. ngram.lists.DocNgram filter commented) # fixed 2016-01: just lists (because document doesn't get updated by POST create cf. ngram.lists.DocNgram filter commented)
url(r'^corpora/(?P<corpus_id>[0-9]+)/documents/(?P<doc_id>[0-9]+)$', views.NgramList.as_view()), # the list associated with an ngram url(r'^corpora/(?P<corpus_id>[0-9]+)/documents/(?P<doc_id>[0-9]+)$', views.NgramList.as_view()), # the list associated with an ngram
......
...@@ -30,6 +30,7 @@ def main(request, project_id, corpus_id, document_id): ...@@ -30,6 +30,7 @@ def main(request, project_id, corpus_id, document_id):
return render_to_response('annotations/main.html', { return render_to_response('annotations/main.html', {
# TODO use reverse() # TODO use reverse()
'api_url': urljoin(request.get_host(), '/annotations/'), 'api_url': urljoin(request.get_host(), '/annotations/'),
'garg_url': request.get_host(),
'nodes_api_url': urljoin(request.get_host(), '/api/'), 'nodes_api_url': urljoin(request.get_host(), '/api/'),
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
......
...@@ -229,11 +229,17 @@ class NodeResource(APIView): ...@@ -229,11 +229,17 @@ class NodeResource(APIView):
return JsonHttpResponse({'deleted': result.rowcount}) return JsonHttpResponse({'deleted': result.rowcount})
class CorpusFavorites(APIView): class CorpusFavorites(APIView):
"""Retrieve/update/delete a corpus node's associated favorite docs """Retrieve/update/delete one or several docs from a corpus associated favs
(url: GET /api/nodes/<corpus_id>/favorites) (url: GET /api/nodes/<corpus_id>/favorites)
=> lists all favorites
(url: GET /api/nodes/<corpus_id>/favorites?docs[]=doc1,doc2)
=> checks for each doc if it is in favorites
(url: DEL /api/nodes/<corpus_id>/favorites?docs[]=doc1,doc2) (url: DEL /api/nodes/<corpus_id>/favorites?docs[]=doc1,doc2)
=> removes each doc from favorites
(url: PUT /api/nodes/<corpus_id>/favorites?docs[]=doc1,doc2) (url: PUT /api/nodes/<corpus_id>/favorites?docs[]=doc1,doc2)
=> add each doc to favorites
""" """
def _get_fav_node(self, corpus_id): def _get_fav_node(self, corpus_id):
...@@ -253,25 +259,57 @@ class CorpusFavorites(APIView): ...@@ -253,25 +259,57 @@ class CorpusFavorites(APIView):
else: else:
self.corpus = corpus self.corpus = corpus
fav_node = self.corpus.children('FAVORITES').first() fav_node = self.corpus.children('FAVORITES').first()
return fav_node return fav_node
def get(self, request, corpus_id): def get(self, request, corpus_id):
response = {} """
2 possibilities with/without param
1) GET http://localhost:8000/api/nodes/2/favorites
(returns the full list of fav docs within corpus 2)
2) GET http://localhost:8000/api/nodes/2/favorites?docs=53,54
(will test if docs 53 and 54 are among the favorites of corpus 2)
(returns the intersection of fav docs with [53,54])
"""
fav_node = self._get_fav_node(corpus_id) fav_node = self._get_fav_node(corpus_id)
req_params = validate(
get_parameters(request),
{'docs': list, 'default': ""}
)
response = {}
if fav_node == None: if fav_node == None:
response = { response = {
'warning':'No favorites node is defined for this corpus (\'%s\')' 'warning':'No favorites node is defined for this corpus (\'%s\')'
% self.corpus.name , % self.corpus.name ,
'doc_ids':[] 'favdocs':[]
} }
else: elif 'docs' not in req_params:
# each docnode associated to the favnode of this corpusnode # each docnode associated to the favnode of this corpusnode
q = (session q = (session
.query(NodeNode.node2_id) .query(NodeNode.node2_id)
.filter(NodeNode.node1_id==fav_node.id)) .filter(NodeNode.node1_id==fav_node.id))
doc_ids = [row.node2_id for row in q.all()] all_doc_ids = [row.node2_id for row in q.all()]
response = { response = {
'doc_ids': doc_ids 'favdocs': all_doc_ids
}
else:
nodeids_to_check = [int(did) for did in req_params['docs'].split(',')]
# each docnode from the input list, if it is associated to the favnode
q = (session
.query(NodeNode.node2_id)
.filter(NodeNode.node1_id==fav_node.id)
.filter(NodeNode.node2_id.in_(nodeids_to_check)))
present_doc_ids = [row.node2_id for row in q.all()]
absent_doc_ids = [did for did in nodeids_to_check if did not in present_doc_ids]
response = {
'favdocs': present_doc_ids,
'missing': absent_doc_ids
} }
return JsonHttpResponse(response) return JsonHttpResponse(response)
...@@ -281,66 +319,95 @@ class CorpusFavorites(APIView): ...@@ -281,66 +319,95 @@ class CorpusFavorites(APIView):
DELETE http://localhost:8000/api/nodes/2/favorites?docs=53,54 DELETE http://localhost:8000/api/nodes/2/favorites?docs=53,54
(will delete docs 53 and 54 from the favorites of corpus 2) (will delete docs 53 and 54 from the favorites of corpus 2)
""" """
# if not request.user.is_authenticated(): if not request.user.is_authenticated():
# # can't use @requires_auth because of positional 'self' within class # can't use @requires_auth because of positional 'self' within class
# return HttpResponse('Unauthorized', status=401) return HttpResponse('Unauthorized', status=401)
# user is ok # user is ok
fav_node = self._get_fav_node(corpus_id) fav_node = self._get_fav_node(corpus_id)
req_params = validate(
get_parameters(request),
{'docs': list, 'default': ""}
)
nodeids_to_delete = req_params['docs'].split(',')
# it deletes from favourites but not from DB response = {}
result = session.execute(
delete(NodeNode) if fav_node == None:
.where(NodeNode.node1_id == fav_node.id) response = {
.where(NodeNode.node2_id.in_(nodeids_to_delete)) 'warning':'No favorites node is defined for this corpus (\'%s\')'
) % self.corpus.name ,
session.commit() 'count_removed': 0
return JsonHttpResponse({'count_removed': result.rowcount}) }
else:
req_params = validate(
get_parameters(request),
{'docs': list, 'default': ""}
)
nodeids_to_delete = [int(did) for did in req_params['docs'].split(',')]
# it deletes from favourites but not from DB
result = session.execute(
delete(NodeNode)
.where(NodeNode.node1_id == fav_node.id)
.where(NodeNode.node2_id.in_(nodeids_to_delete))
)
session.commit()
response = {'count_removed': result.rowcount}
return JsonHttpResponse(response)
def put(self, request, corpus_id, check_each_doc=True): def put(self, request, corpus_id, check_each_doc=True):
# if not request.user.is_authenticated(): if not request.user.is_authenticated():
# # can't use @requires_auth because of positional 'self' within class # can't use @requires_auth because of positional 'self' within class
# return HttpResponse('Unauthorized', status=401) return HttpResponse('Unauthorized', status=401)
# user is ok # user is ok
fav_node = self._get_fav_node(corpus_id) fav_node = self._get_fav_node(corpus_id)
req_params = validate(
get_parameters(request),
{'docs': list, 'default': ""}
)
nodeids_to_add = req_params['docs'].split(',')
if check_each_doc:
# verification que ce sont bien des documents du bon corpus
# un peu long => désactiver par défaut ?
known_docs_q = (session
.query(Node.id)
.filter(Node.parent_id==corpus_id)
.filter(Node.typename=='DOCUMENT')
)
lookup = {known_doc.id:True for known_doc in known_docs_q.all()}
rejected_list = []
for doc_node_id in nodeids_to_add:
if (doc_node_id not in lookup):
rejected_list.append(doc_node_id)
if len(rejected_list):
raise ValidationException(
"Error on some requested docs: %s (Only nodes of type 'doc' AND belonging to corpus %i can be added to favorites.)"
% (str(rejected_list), int(corpus_id)))
# add them
bulk_insert(
NodeNode,
('node1_id', 'node2_id', 'score'),
((fav_node.id, doc_node_id, 1.0 ) for doc_node_id in nodeids_to_add)
)
return JsonHttpResponse({'count_added': len(nodeids_to_add)}) response = {}
if fav_node == None:
response = {
'warning':'No favorites node is defined for this corpus (\'%s\')'
% self.corpus.name ,
'count_added':0
}
else:
req_params = validate(
get_parameters(request),
{'docs': list, 'default': ""}
)
nodeids_to_add = [int(did) for did in req_params['docs'].split(',')]
if check_each_doc:
# verification que ce sont bien des documents du bon corpus
# un peu long => désactiver par défaut ?
known_docs_q = (session
.query(Node.id)
.filter(Node.parent_id==corpus_id)
.filter(Node.typename=='DOCUMENT')
)
lookup = {known_doc.id:True for known_doc in known_docs_q.all()}
# debug
# print("lookup hash", lookup)
rejected_list = []
for doc_node_id in nodeids_to_add:
if (doc_node_id not in lookup):
rejected_list.append(doc_node_id)
if len(rejected_list):
raise ValidationException(
"Error on some requested docs: %s (Only nodes of type 'doc' AND belonging to corpus %i can be added to favorites.)"
% (str(rejected_list), int(corpus_id)))
# add them
bulk_insert(
NodeNode,
('node1_id', 'node2_id', 'score'),
((fav_node.id, doc_node_id, 1.0 ) for doc_node_id in nodeids_to_add)
)
# todo count really added (here: counts input param not result)
response = {'count_added': len(nodeids_to_add)}
return JsonHttpResponse(response)
class CorpusFacet(APIView): class CorpusFacet(APIView):
"""Loop through a corpus node's docs => do counts by a hyperdata field """Loop through a corpus node's docs => do counts by a hyperdata field
......
...@@ -143,6 +143,7 @@ var RecDict={}; ...@@ -143,6 +143,7 @@ var RecDict={};
var AjaxRecords = [] var AjaxRecords = []
var Garbage = {} var Garbage = {}
var countByTitles = {} // useful for title duplicates var countByTitles = {} // useful for title duplicates
var favorites = {}
function getRecord(rec_id) { function getRecord(rec_id) {
return MyTable.data('dynatable').settings.dataset.originalRecords[rec_id]; return MyTable.data('dynatable').settings.dataset.originalRecords[rec_id];
...@@ -153,6 +154,39 @@ function getRecords() { ...@@ -153,6 +154,39 @@ function getRecords() {
return MyTable.data('dynatable').settings.dataset.originalRecords; return MyTable.data('dynatable').settings.dataset.originalRecords;
} }
function favstatusToStar (rec_id, boolFavstatus, boolStrike=false){
var starStr = boolFavstatus ? "glyphicon-star" : "glyphicon-star-empty";
var styleStr = boolStrike ? "style='text-decoration:line-through'" : "";
var htmlStr = "<span class='glyphicon "+starStr+"' "+styleStr ;
htmlStr += " onclick='toggleFavstatus("+rec_id+")'" ;
htmlStr += ">" ;
htmlStr += "</span>" ;
return htmlStr
}
function toggleFavstatus (rec_id) {
var doc_id = AjaxRecords[rec_id]["id"]
var statusBefore = AjaxRecords[rec_id]["isFavorite"]
var myHttpAction = statusBefore ? 'DELETE' : 'PUT'
$.ajax({
url: 'http://localhost:8000/api/nodes/'+corpus_id+'/favorites?docs='+doc_id,
type: myHttpAction,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(favdata) {
// it's been toggled in the DB so we toggle locally
if (statusBefore) delete favorites[doc_id]
else favorites[doc_id] = true
AjaxRecords[rec_id]["isFavorite"] = ! statusBefore ;
// and we reprocess table directly (no need for new ajax of other recs)
MyTable.data('dynatable').process();
},
});
}
function transformContent2(rec_id) { function transformContent2(rec_id) {
// pr("\t\ttransformContent2: "+rec_id) // pr("\t\ttransformContent2: "+rec_id)
var elem = AjaxRecords[rec_id]; var elem = AjaxRecords[rec_id];
...@@ -162,12 +196,14 @@ function transformContent2(rec_id) { ...@@ -162,12 +196,14 @@ function transformContent2(rec_id) {
result["id"] = elem["id"] result["id"] = elem["id"]
result["date"] = '<strike>'+elem["date"]+'</strike>' result["date"] = '<strike>'+elem["date"]+'</strike>'
result["docurl"] = '<strike>'+elem["docurl"]+'</strike>' result["docurl"] = '<strike>'+elem["docurl"]+'</strike>'
result["isFavorite"] = favstatusToStar(rec_id, elem["isFavorite"], boolStrike=true)
result["rawtitle"] = elem["rawtitle"] result["rawtitle"] = elem["rawtitle"]
result["del"] = '<input id='+rec_id+' onclick="overRide(this)" type="checkbox" checked/>' result["del"] = '<input id='+rec_id+' onclick="overRide(this)" type="checkbox" checked/>'
} else { } else {
result["id"] = elem["id"] result["id"] = elem["id"]
result["date"] = elem["date"] result["date"] = elem["date"]
result["docurl"] = elem["docurl"] result["docurl"] = elem["docurl"]
result["isFavorite"] = favstatusToStar(rec_id, elem["isFavorite"])
result["rawtitle"] = elem["rawtitle"] result["rawtitle"] = elem["rawtitle"]
result["del"] = '<input id='+rec_id+' onclick="overRide(this)" type="checkbox"/>' result["del"] = '<input id='+rec_id+' onclick="overRide(this)" type="checkbox"/>'
} }
...@@ -269,6 +305,9 @@ function Main_test(Data) { ...@@ -269,6 +305,9 @@ function Main_test(Data) {
div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-calendar"></span> Date</th>'+"\n" div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-calendar"></span> Date</th>'+"\n"
div_table += "\t"+"\t"+'<th data-dynatable-column="docurl">'+"\n" div_table += "\t"+"\t"+'<th data-dynatable-column="docurl">'+"\n"
div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-text-size"></span> Title</th>'+"\n" div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-text-size"></span> Title</th>'+"\n"
div_table += "\t"+"\t"+'<th data-dynatable-column="isFavorite">'+"\n"
div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-star"></span>'+"\n"
div_table += "\t"+"\t"+'</th>'+"\n"
div_table += "\t"+"\t"+'<th data-dynatable-column="del" data-dynatable-no-sort="true">'+"\n" div_table += "\t"+"\t"+'<th data-dynatable-column="del" data-dynatable-no-sort="true">'+"\n"
div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-trash"></span>'+"\n" div_table += "\t"+"\t"+'<span class="glyphicon glyphicon-trash"></span>'+"\n"
div_table += "\t"+"\t"+'</th>'+"\n" div_table += "\t"+"\t"+'</th>'+"\n"
...@@ -445,7 +484,7 @@ function Main_test(Data) { ...@@ -445,7 +484,7 @@ function Main_test(Data) {
}, },
inputs: { inputs: {
// our own search which differentiates title vs abstract queries // our own search which differentiates title vs abstract queries
queries: $('#doubleSearch, #dupFilter') queries: $('#doubleSearch, #docFilter')
}, },
writers: { writers: {
_rowWriter: ulWriter _rowWriter: ulWriter
...@@ -495,14 +534,16 @@ function Main_test(Data) { ...@@ -495,14 +534,16 @@ function Main_test(Data) {
} }
// MyTable.data('dynatable').process(); // MyTable.data('dynatable').process();
// also append another bound filter for duplicates // also append another bound filter for duplicates/favorites
MyTable.data('dynatable').queries MyTable.data('dynatable').queries
.functions['dupFilter'] = function(record,selected) { .functions['docFilter'] = function(record,opt) {
return (selected == 'filter_all')||(countByTitles[record.rawtitle] > 1) if (opt == 'filter_all') return true
else if (opt == 'filter_favs') return favorites[record.id]
else if (opt == 'filter_dupl') return (countByTitles[record.rawtitle] > 1)
} }
// and set this filter's initial status to 'filter_all' // and set this filter's initial status to 'filter_all'
MyTable.data('dynatable').settings.dataset.queries['dupFilter'] = 'filter_all' MyTable.data('dynatable').settings.dataset.queries['docFilter'] = 'filter_all'
MyTable.data('dynatable').sorts.functions["rawtitleSort"] = function testSort (rec1,rec2) { MyTable.data('dynatable').sorts.functions["rawtitleSort"] = function testSort (rec1,rec2) {
...@@ -531,20 +572,20 @@ function Main_test(Data) { ...@@ -531,20 +572,20 @@ function Main_test(Data) {
var dupFlag = false ; var dupFlag = false ;
$("#div-table").on("dynatable:queries:added", function(e, qname, qval) { $("#div-table").on("dynatable:queries:added", function(e, qname, qval) {
if (!dupFlag && qname == 'dupFilter' && qval == "filter_dupl") { if (!dupFlag && qname == 'docFilter' && qval == "filter_dupl") {
MyTable.data('dynatable').queries.remove('dupFilter') MyTable.data('dynatable').queries.remove('docFilter')
// to avoid recursion when we'll call this filter again in 4 lines // to avoid recursion when we'll call this filter again in 4 lines
dupFlag = true ; dupFlag = true ;
// sort alphabetically **before** duplicates filter // sort alphabetically **before** duplicates filter
MyTable.data('dynatable').sorts.clear(); MyTable.data('dynatable').sorts.clear();
MyTable.data('dynatable').sorts.add('rawtitle', -1) // -1 <==> DESC (ASC doesn't work well ?) MyTable.data('dynatable').sorts.add('rawtitle', -1) // -1 <==> DESC (ASC doesn't work well ?)
MyTable.data('dynatable').queries.add('dupFilter', 'filter_dupl') MyTable.data('dynatable').queries.add('docFilter', 'filter_dupl')
MyTable.data('dynatable').process(); MyTable.data('dynatable').process();
} }
}); });
$("#div-table").on("dynatable:queries:removed", function(e, qname) { $("#div-table").on("dynatable:queries:removed", function(e, qname) {
if (qname == 'dupFilter') { if (qname == 'docFilter') {
dupFlag = false ; dupFlag = false ;
} }
}); });
...@@ -556,36 +597,53 @@ $.ajax({ ...@@ -556,36 +597,53 @@ $.ajax({
url: '/api/nodes?types[]=DOCUMENT&pagination_limit=-1&parent_id=' url: '/api/nodes?types[]=DOCUMENT&pagination_limit=-1&parent_id='
+ corpus_id + corpus_id
+'&fields[]=parent_id&fields[]=id&fields[]=name&fields[]=typename&fields[]=hyperdata', +'&fields[]=parent_id&fields[]=id&fields[]=name&fields[]=typename&fields[]=hyperdata',
success: function(data){ success: function(maindata){
$("#content_loader").remove(); // unfortunately favorites info is in a separate request (other nodes)
$.each(data.records, function(i, record){ $.ajax({
var orig_id = parseInt(record.id); url: 'http://localhost:8000/api/nodes/'+corpus_id+'/favorites',
var arr_id = parseInt(i) success: function(favdata){
RecDict[orig_id] = arr_id; // initialize favs lookup
record.rawtitle = record.name; for (var i in favdata['favdocs']) {
doc_id = favdata['favdocs'][i]
// trick to have a clickable title in docurl slot, but could be done in transformContent2 favorites[doc_id] = true ;
record.docurl = '<a target="_blank" href="/projects/' + project_id + '/corpora/'+ corpus_id + '/documents/' + record.id + '">' + record.name + '</a>'; }
record.date = get_node_date(record);
record.del = false;
});
// initialize CountByTitle census // now process the nodes data from 1st request
for (var i in data.records) { $.each(maindata.records, function(i, record){
ourTitle = data.records[i]['rawtitle'] ; var orig_id = parseInt(record.id);
if (countByTitles.hasOwnProperty(ourTitle)) { var arr_id = parseInt(i)
countByTitles[ourTitle] ++ ; RecDict[orig_id] = arr_id;
} record.rawtitle = record.name;
else {
countByTitles[ourTitle] = 1 ;
}
}
AjaxRecords = data.records; // backup-ing in global variable!
var result = Main_test(data.records) record.isFavorite = false ;
if (favorites[orig_id]) {
record.isFavorite = true ;
}
$("#content_loader").remove() // trick to have a clickable title in docurl slot, but could be done in transformContent2
record.docurl = '<a target="_blank" href="/projects/' + project_id + '/corpora/'+ corpus_id + '/documents/' + record.id + '">' + record.name + '</a>';
record.date = get_node_date(record);
record.del = false;
});
console.log( result ) // initialize CountByTitle census
for (var i in maindata.records) {
ourTitle = maindata.records[i]['rawtitle'] ;
if (countByTitles.hasOwnProperty(ourTitle)) {
countByTitles[ourTitle] ++ ;
}
else {
countByTitles[ourTitle] = 1 ;
}
}
AjaxRecords = maindata.records; // backup-ing in global variable!
$("#content_loader").remove();
var result = Main_test(maindata.records)
console.log( result )
},
});
}, },
}); });
...@@ -73,9 +73,10 @@ ...@@ -73,9 +73,10 @@
<input title="Search in Abstracts" id="searchAB" name="searchAB" type="checkbox">AB <input title="Search in Abstracts" id="searchAB" name="searchAB" type="checkbox">AB
</span>&nbsp;&nbsp; </span>&nbsp;&nbsp;
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span> <span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
<select id="dupFilter" name="dupFilter"> <select id="docFilter" name="docFilter">
<option value="filter_all">All</option> <option value="filter_all">All</option>
<option value="filter_dupl">Duplicates by Title</option> <option value="filter_favs">Favorite documents</option>
<option value="filter_dupl">Duplicates by title</option>
</select> </select>
</div> </div>
</div> </div>
......
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