Commit f04520e7 authored by Mathieu Rodic's avatar Mathieu Rodic

[FEATURE] Charts are now working with AngularJS on `/tests/mvc`

(some features are still to be added)
parent 14034b42
...@@ -223,7 +223,7 @@ class NodesChildrenMetatadata(APIView): ...@@ -223,7 +223,7 @@ class NodesChildrenMetatadata(APIView):
}) })
return JsonHttpResponse({ return JsonHttpResponse({
'collection': collection, 'data': collection,
}) })
...@@ -329,9 +329,9 @@ class NodesChildrenQueries(APIView): ...@@ -329,9 +329,9 @@ class NodesChildrenQueries(APIView):
raise APIException('Unrecognized "type": "%s" in the query\'s "retrieve" parameter. Possible values are: "%s".' % (retrieve['type'], '", "'.join(retrieve_types), ), 400) raise APIException('Unrecognized "type": "%s" in the query\'s "retrieve" parameter. Possible values are: "%s".' % (retrieve['type'], '", "'.join(retrieve_types), ), 400)
if retrieve['type'] == 'fields': if retrieve['type'] == 'fields':
fields_names = ['id'] + list(set(retrieve['list']) - {'id'}) fields_names = ['id'] + retrieve['list'] if 'id' not in retrieve['list'] else retrieve['list']
elif retrieve['type'] == 'aggregates': elif retrieve['type'] == 'aggregates':
fields_names = list(set(retrieve['list'])) fields_names = list(retrieve['list'])
fields_list = [] fields_list = []
for field_name in fields_names: for field_name in fields_names:
...@@ -410,6 +410,9 @@ class NodesChildrenQueries(APIView): ...@@ -410,6 +410,9 @@ class NodesChildrenQueries(APIView):
.join(metadata_alias, metadata_alias.node_id == Node.id) .join(metadata_alias, metadata_alias.node_id == Node.id)
.filter(metadata_alias.metadata_id == metadata.id) .filter(metadata_alias.metadata_id == metadata.id)
) )
# adjust date
if metadata.type == 'datetime':
value = value + '2000-01-01T00:00:00Z'[len(value):]
# filter query # filter query
query = query.filter(operator( query = query.filter(operator(
getattr(metadata_alias, 'value_' + metadata.type), getattr(metadata_alias, 'value_' + metadata.type),
...@@ -493,22 +496,19 @@ class NodesChildrenQueries(APIView): ...@@ -493,22 +496,19 @@ class NodesChildrenQueries(APIView):
class NodesList(APIView): class NodesList(APIView):
def get(self, request): def get(self, request):
query = Node query = (Node
.query(Node.id, Node.name, NodeType.name.label('type'))
.join(NodeType)
)
if 'type' in request.GET: if 'type' in request.GET:
query = query.filter(type__name=request.GET['type']) query = query.filter(NodeType.name == request.GET['type'])
if 'parent' in request.GET: if 'parent' in request.GET:
query = query.filter(parent_id=int(request.GET['parent'])) query = query.filter(Node.parent_id == int(request.GET['parent']))
collection = [] return JsonHttpResponse({'data': [
for child in query.all(): node._asdict()
type_name = child.type.name for node in query.all()
collection.append({ ]})
'id': child.id,
'text': child.name,
'type': type_name,
'children': type_name is not 'Document',
})
return JsonHttpResponse(collection)
class Nodes(APIView): class Nodes(APIView):
...@@ -520,7 +520,7 @@ class Nodes(APIView): ...@@ -520,7 +520,7 @@ class Nodes(APIView):
return JsonHttpResponse({ return JsonHttpResponse({
'id': node.id, 'id': node.id,
'name': node.name, 'name': node.name,
'type': '', # 'type': node.type__name,
'metadata': dict(node.metadata), 'metadata': dict(node.metadata),
}) })
...@@ -570,7 +570,7 @@ class CorpusController: ...@@ -570,7 +570,7 @@ class CorpusController:
format = request.GET.get('format', 'json') format = request.GET.get('format', 'json')
if format == 'json': if format == 'json':
return JsonHttpResponse({ return JsonHttpResponse({
"collection": [{ "data": [{
'terms': row[0], 'terms': row[0],
'occurrences': row[1] 'occurrences': row[1]
} for row in query.all()], } for row in query.all()],
...@@ -583,132 +583,3 @@ class CorpusController: ...@@ -583,132 +583,3 @@ class CorpusController:
raise ValidationError('Unrecognized "format=%s", should be "csv" or "json"' % (format, )) raise ValidationError('Unrecognized "format=%s", should be "csv" or "json"' % (format, ))
@classmethod
def data(cls, request, corpus_id):
# parameters retrieval and validation
corpus = cls.get(corpus_id)
# query building: initialization
columns = []
conditions = []
group = []
order = []
having = []
join_ngrams = False
# query building: parameters
parameters = request.GET.getlist('parameters[]')
for parameter in parameters:
c = len(columns)
parameter_array = parameter.split('.')
if len(parameter_array) != 2:
raise ValidationError('Unrecognized "parameter[]=%s"' % (parameter, ))
origin = parameter_array[0]
key = parameter_array[1]
if origin == "metadata":
columns.append("%s.metadata->'%s' AS c%d" % (Node._meta.db_table, key, c, ))
conditions.append("%s.metadata ? '%s'" % (Node._meta.db_table, key, ))
# conditions.append("c%d IS NOT NULL" % (c, ))
group.append("c%d" % (c, ))
order.append("c%d" % (c, ))
else:
raise ValidationError('Unrecognized type "%s" in "parameter[]=%s"' % (origin, parameter, ))
# query building: mesured value
mesured = request.GET.get('mesured', '')
c = len(columns)
if mesured == "documents.count":
columns.append("COUNT(%s.id) AS c%d " % (Node._meta.db_table, c, ))
elif mesured == "ngrams.count":
columns.append("COUNT(%s.id) AS c%d " % (Ngram._meta.db_table, c, ))
join_ngrams = True
else:
raise ValidationError('The "mesured" parameter should take one of the following values: "documents.count", "ngrams.count"')
# query building: filters
for filter in request.GET.getlist('filters[]', ''):
splitFilter = filter.split('.')
origin = splitFilter[0]
# 127.0.0.1:8000/api/corpus/13410/data
# ?mesured=ngrams.count
# &parameters[]=metadata.publication_date
# &format=json
# &filters[]=ngrams.in.bee,bees
# &filters[]=metadata.language_fullname.eq.English
# &filters[]=metadata.publication_date.gt.1950-01-01
# &filters[]=metadata.publication_date.lt.2000-01-01
# &filters[]=metadata.title.contains.e
if origin == 'ngrams':
if splitFilter[1] == 'in':
ngrams = '.'.join(splitFilter[2:]).split(',')
map(str.strip, ngrams)
map(lambda ngram: ngram.replace("'", "''"), ngrams)
conditions.append(
"%s.terms IN ('%s')" % (Ngram._meta.db_table, "', '".join(ngrams), )
)
join_ngrams = True
elif origin == 'metadata':
key = splitFilter[1].replace("'", "''")
operator = splitFilter[2]
value = '.'.join(splitFilter[3:]).replace("'", "''")
condition = "%s.metadata->'%s' " % (Node._meta.db_table, key, )
if operator == 'contains':
condition += "LIKE '%%%s%%'" % (value, )
else:
condition += {
'eq': '=',
'lt': '<=',
'gt': '>=',
}[operator]
condition += " '%s'" % (value, )
conditions.append(condition)
else:
raise ValidationError('Unrecognized "filter[]=%s"' % (filter, ))
# query building: initializing SQL
sql_0 = ''
sql_1 = '\nSELECT '
sql_2 = '\nFROM %s' % (Node._meta.db_table, )
sql_3 = '\nWHERE (%s.parent_id = %d)' % (Node._meta.db_table, corpus.id, )
# sql_0 = _sql_cte
# sql_1 = '\nSELECT '
# sql_2 = '\nFROM %s\nINNER JOIN cte ON cte."id" = %s.id' % (Node._meta.db_table, Node._meta.db_table, )
# sql_3 = '\nWHERE ((NOT cte.id = \'%d\') AND (\'%d\' = ANY(cte."path")))' % (corpus.id, corpus.id, )
# query building: assembling SQL
sql_1 += ", ".join(columns)
sql_2 += "\nINNER JOIN %s ON %s.id = %s.type_id" % (NodeType._meta.db_table, NodeType._meta.db_table, Node._meta.db_table, )
if join_ngrams:
sql_2 += "\nINNER JOIN %s ON %s.node_id = %s.id" % (Node_Ngram._meta.db_table, Node_Ngram._meta.db_table, Node._meta.db_table, )
sql_2 += "\nINNER JOIN %s ON %s.id = %s.ngram_id" % (Ngram._meta.db_table, Ngram._meta.db_table, Node_Ngram._meta.db_table, )
sql_3 += "\nAND %s.name = 'Document'" % (NodeType._meta.db_table, )
if conditions:
sql_3 += "\nAND (%s)" % (" AND ".join(conditions), )
if group:
sql_3 += "\nGROUP BY %s" % (", ".join(group), )
if order:
sql_3 += "\nORDER BY %s" % (", ".join(order), )
sql = sql_0 + sql_1 + sql_2 + sql_3
# query execution
# return DebugHttpResponse(sql)
cursor = connection.cursor()
cursor.execute(sql)
# response building
format = request.GET.get('format', 'json')
keys = parameters + [mesured]
rows = cursor.fetchall()
if format == 'json':
dimensions = []
for key in keys:
suffix = key.split('_')[-1]
dimensions.append({
'key': key,
'type': 'datetime' if suffix == 'date' else 'numeric'
})
return JsonHttpResponse({
"collection": [
{key: value for key, value in zip(keys, row)}
for row in rows
],
"list": [row for row in rows],
"dimensions" : dimensions
})
elif format == 'csv':
return CsvHttpResponse([keys] + [row for row in rows])
else:
raise ValidationError('Unrecognized "format=%s", should be "csv" or "json"' % (format, ))
...@@ -44,10 +44,10 @@ urlpatterns = patterns('', ...@@ -44,10 +44,10 @@ urlpatterns = patterns('',
url(r'^api/nodes$', gargantext_web.api.NodesList.as_view()), url(r'^api/nodes$', gargantext_web.api.NodesList.as_view()),
url(r'^api/nodes/(\d+)/ngrams$', gargantext_web.api.CorpusController.ngrams), url(r'^api/nodes/(\d+)/ngrams$', gargantext_web.api.CorpusController.ngrams),
url(r'^api/nodes/(\d+)/data$', gargantext_web.api.CorpusController.data),
url(r'^graph-it$', views.graph_it), url(r'^graph-it$', views.graph_it),
url(r'^ngrams$', views.ngrams), url(r'^ngrams$', views.ngrams),
url(r'^tests/mvc$', views.tests_mvc),
) )
......
This diff is collapsed.
This diff is collapsed.
...@@ -222,7 +222,10 @@ ...@@ -222,7 +222,10 @@
<li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets"> <li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets">
<div class="corpus"> <div class="corpus">
<button ng-click="removeDataset($index)" title="remove this dataset">X</button> <button ng-click="removeDataset($index)" title="remove this dataset">X</button>
Documents count in the corpus <select ng-model="mesured" style="background-color:{{ getColor($index, datasets.length) }}">
<option ng-repeat="(key, value) in {'Documents count': 'count', 'Ngrams count': 'ngrams.count'}" value="{{ value }}">{{ key }}</option>
</select>
in the corpus
<select ng-model="corpusId" ng-change="updateEntities()"> <select ng-model="corpusId" ng-change="updateEntities()">
<option ng-repeat="corpus in corpora" value="{{corpus.id}}">{{corpus.name}}</option> <option ng-repeat="corpus in corpora" value="{{corpus.id}}">{{corpus.name}}</option>
</select> </select>
...@@ -256,12 +259,11 @@ ...@@ -256,12 +259,11 @@
</li> </li>
</ul> </ul>
<button ng-click="query()">Refresh results</button> <button class="refresh" ng-click="query()">Refresh results</button>
<button ng-click="addDataset()">Add a dataset...</button> <button class="add" ng-click="addDataset()">Add a dataset...</button>
<hr/> <hr/>
<div class="graph"> <div class="graph">
<linechart data="graph.data" options="graph.options" mode="" width="" height=""></linechart> <linechart data="graph.data" options="graph.options"></linechart>
<!-- <ng-dygraphs ng-if="graph.data.length" data="graph.data" options="graph.options" legend="graph.legend"></ng-dygraphs> -->
</div> </div>
</div> </div>
...@@ -291,7 +293,7 @@ ...@@ -291,7 +293,7 @@
{% endverbatim %} {% endverbatim %}
<script type="text/javascript" src="{% static "js/angular.min.js" %}"></script> <script type="text/javascript" src="{% static "js/angular.min.js" %}"></script>
<script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script>
<script type="text/javascript" src="https://raw.githubusercontent.com/n3-charts/line-chart/master/build/line-chart.min.js"></script> <script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> --> <!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> -->
<script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script> <script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script>
......
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