Commit c74a8774 authored by delanoe's avatar delanoe

Merge remote-tracking branch 'origin/romain-testing' into testing

parents 5cc4fa3a a94986db
...@@ -22,8 +22,15 @@ _node_available_types = NODETYPES ...@@ -22,8 +22,15 @@ _node_available_types = NODETYPES
def _query_nodes(request, node_id=None): def _query_nodes(request, node_id=None):
user = cache.User[request.user.id]
if request.user.id is None:
raise TypeError("This API request must come from an authenticated user.")
else:
# we query among the nodes that belong to this user
user = cache.User[request.user.id]
# parameters validation # parameters validation
# fixme: this validation does not allow custom keys in url (eg '?name=' for rename action)
parameters = get_parameters(request) parameters = get_parameters(request)
parameters = validate(parameters, {'type': dict, 'items': { parameters = validate(parameters, {'type': dict, 'items': {
'formated': {'type': str, 'required' : False, 'default': 'json'}, 'formated': {'type': str, 'required' : False, 'default': 'json'},
...@@ -255,7 +262,7 @@ class NodeListHaving(APIView): ...@@ -255,7 +262,7 @@ class NodeListHaving(APIView):
class NodeResource(APIView): class NodeResource(APIView):
# TODO either real authentification test or remove check on user.id # contains a check on user.id (within _query_nodes)
def get(self, request, node_id): def get(self, request, node_id):
parameters, query, count = _query_nodes(request, node_id) parameters, query, count = _query_nodes(request, node_id)
if not len(query): if not len(query):
...@@ -265,6 +272,7 @@ class NodeResource(APIView): ...@@ -265,6 +272,7 @@ class NodeResource(APIView):
field: getattr(node, field) for field in parameters['fields'] field: getattr(node, field) for field in parameters['fields']
}) })
# contains a check on user.id (within _query_nodes)
def delete(self, request, node_id): def delete(self, request, node_id):
parameters, query, count = _query_nodes(request, node_id) parameters, query, count = _query_nodes(request, node_id)
if not len(query): if not len(query):
...@@ -275,6 +283,46 @@ class NodeResource(APIView): ...@@ -275,6 +283,46 @@ class NodeResource(APIView):
session.commit() session.commit()
return JsonHttpResponse({'deleted': result.rowcount}) return JsonHttpResponse({'deleted': result.rowcount})
def post(self, request, node_id):
"""
For the moment, only used to rename a node
params in request.GET:
none (not allowed by _query_nodes validation)
params in request.DATA:
["name": the_new_name_str]
TODO 1 factorize with .projects.ProjectView.put and .post (thx c24b)
TODO 2 allow other changes than name
"""
# contains a check on user.id (within _query_nodes)
parameters, query, count = _query_nodes(request, node_id)
the_node = query.pop()
# retrieve the name
if 'name' in request.data:
new_name = request.data['name']
else:
return JsonHttpResponse({
"detail":"A 'name' parameter is required in data payload"
}, 400)
# check for conflicts
other = session.query(Node).filter(Node.name == new_name).count()
if other > 0:
return JsonHttpResponse({
"detail":"A node with this name already exists"
}, 409)
# normal case: do the renaming
else:
setattr(the_node, 'name', new_name)
session.commit()
return JsonHttpResponse({
'renamed': new_name
}, 200)
class CorpusFavorites(APIView): class CorpusFavorites(APIView):
......
...@@ -64,6 +64,9 @@ var Resource = function(url_path) { ...@@ -64,6 +64,9 @@ var Resource = function(url_path) {
success: callback success: callback
}); });
}; };
// TODO allow also POST with params
// TODO this.post function(id, criteria OR params, callback)
// change an item // change an item
this.change = this.update = function(id, callback) { this.change = this.update = function(id, callback) {
$.ajax({ $.ajax({
......
var coocId = null ;
var coocName = null ;
var graphNameBox = document.getElementById("graph-name")
var changeNameText = 'type name here'
// initial tests
var coocIdMatch = window.location.search.match(/cooc_id=(\d+)/)
if (! coocIdMatch) {
console.error("could not find cooc_id in url (this graph is not saved in DB yet): can't show the rename input")
$('#graph-rename').remove()
}
else {
// we got a real COOCCURRENCES node
coocId = parseInt(coocIdMatch.pop())
// check if has a name already
garganrest.nodes.get(coocId, testName)
}
// HELPER FUNCTIONS
// ----------------
function testName(jsonNode) {
var aName = jsonNode.name
// names like "GRAPH EXPLORER COOC (in:4885)" are default so counted as null
if (! aName || aName.match(/^GRAPH EXPLORER COOC/)) {
// there's no real name => leave the page editable
coocName = null
}
else {
// we got a real name => just fill it in the page
coocName = aName
showName(coocName, graphNameBox)
}
console.warn('coocName for this graph:', coocName)
}
function makeEditable(textElement, callback) {
var newInput = '<input id="graphname-edit" type="text"'
newInput += ' value="'+changeNameText+'"';
newInput += ' onfocus="return cleanInput(this)"';
newInput += ' onblur="return refillInput(this)"';
newInput += ' onkeypress="return checkEnterKey(event,submitName,this)"';
newInput += '></input>';
textElement.innerHTML = newInput
}
function cleanInput(inputElement) {
if (inputElement.value == changeNameText) {inputElement.value = ''}
}
function refillInput(inputElement) {
if (inputElement.value == '') {inputElement.value = changeNameText}
}
// binding for the input submitting
function checkEnterKey(e, callback, element) {
if(e.which == 13) { callback(element) }
}
function submitName(inputElement) {
console.warn ("renaming: using coocId =", coocId)
var newName = inputElement.value
// the element where we'll show the response
var messagePopBox = document.getElementById("handmade-popover")
var messagePopTxt = document.getElementById("handmade-popover-content")
messagePopBox.classList.remove("hide")
messagePopTxt.innerHTML = "Submitting..."
var myData = new FormData();
myData.append("name", newName)
console.log("myData.get('name')",myData.get('name'))
$.ajax({
url: '/api/nodes/' + coocId ,
type: 'POST',
contentType: false,
processData: false,
data: myData,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(result) {
messagePopTxt.innerHTML = '<h5 style="margin:.3em 0 0 0">OK saved !</h5>'
showName(newName, graphNameBox)
setTimeout(function(){messagePopBox.classList += ' hide'}, 2000);
},
error: function(result) {
messagePopTxt.innerHTML = '<span style="color:red">Error:</span>'
messagePopTxt.innerHTML += '<i>'+result.statusText+'</i>'
if (result.status == 409) {
messagePopTxt.innerHTML += '<br/>(name is already taken!)'
}
setTimeout(function(){messagePopBox.classList += ' hide'}, 2000); }
});
}
function showName(nameStr, target) {
target.innerHTML = '"'+nameStr+'"'
}
...@@ -29,3 +29,25 @@ ...@@ -29,3 +29,25 @@
/* glyphicons are always rendered too high within bootstrap buttons */ /* glyphicons are always rendered too high within bootstrap buttons */
vertical-align:middle vertical-align:middle
} }
/* graph name => editable input => submitName() => minimsg */
.editable {
color: grey ;
}
#graphname-edit {
color: white;
background-color: transparent;
border: none;
max-width: 8em;
}
.minimsg {
font-size: .7em ;
padding: 7p0x 9px;
}
.minimsg * {
line-height: 100%;
}
...@@ -23,25 +23,26 @@ ...@@ -23,25 +23,26 @@
<div id="graph_{{cooc.id}}"> <div id="graph_{{cooc.id}}">
<div class="row"> <div class="row">
<div class="col-md-1 content"></div> <div class="col-md-1 content"></div>
<div class="col-md-5 content"> <div class="col-md-5 content">
<li> <li>
<h5>{{cooc.name}}</h5>
{{cooc.date}} {{cooc.date}}
{% for key, value in coocs_count.items %} {% for key, value in coocs_count.items %}
{% if key == cooc.id %} {% if key == cooc.id %}
{% if value > 0 %} {% if value > 0 %}
<ul> <ul>
<!-- <li>{{cooc.id}}</li> --!> <!-- <li>{{cooc.id}}</li> -->
<li>From: {% if not cooc.hyperdata.start %} begin of corpus {% else %} {{cooc.hyperdata.start}} {% endif %} <li>From: {% if not cooc.hyperdata.start %} begin of corpus {% else %} {{cooc.hyperdata.start}} {% endif %}
, To: {% if not cooc.hyperdata.end %} end of corpus {% else %} {{cooc.hyperdata.end}} {% endif %} , To: {% if not cooc.hyperdata.end %} end of corpus {% else %} {{cooc.hyperdata.end}} {% endif %}
</li> </li>
<li> {{ value }} nodes with distances: <li> {{ value }} nodes with distances:
<ul> <ul>
<li> <li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5"> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
Conditional Conditional
</a> </a>
(with bridgeness (with bridgeness
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=10">10</a> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=10">10</a>
...@@ -49,10 +50,10 @@ ...@@ -49,10 +50,10 @@
or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=30">30</a> or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=30">30</a>
) )
</li> </li>
<li> <li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5"> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
Distributional Distributional
</a> </a>
(with bridgeness (with bridgeness
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=10">10</a> <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=10">10</a>
...@@ -62,13 +63,13 @@ ...@@ -62,13 +63,13 @@
</li> </li>
</ul> </ul>
</ul> </ul>
{% else %} {% else %}
<!-- <!--
<br> Processing (wait and reload the page) <br> Processing (wait and reload the page)
!--> !-->
<div class="progress"> <div class="progress">
<div class=" progress-bar progress-bar-striped active" <div class=" progress-bar progress-bar-striped active"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 70%"> role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 70%">
<span> <span>
Processing (wait and reload the page) Processing (wait and reload the page)
......
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
<script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script> <script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<link rel="stylesheet" type="text/css" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}"> <link rel="stylesheet" type="text/css" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/menu.css"%}"/> <link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/menu.css"%}"/>
{% block css %} {% block css %}
{% endblock %} {% endblock %}
</head> </head>
<body> <body>
...@@ -45,8 +47,26 @@ ...@@ -45,8 +47,26 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
</ul>
{% if view == "graph" %}
<li id="graph-rename" style="padding:15">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
<span id="graph-name" class="editable" ondblclick="makeEditable(this)">
Name your graph
</span>
</li>
<li style="padding:15">
<button class="hide" onclick="submitName(this)"></button>
<!-- £TODO put styles in a separate css file -->
<div id="handmade-popover" class="hide popover right" style="height: 42px; top:4px; min-width:100px; width:135px; display:block">
<div class="arrow"></div>
<div id="handmade-popover-content" class="minimsg popover-content">
Submitting...
</div>
</div>
</li>
{% endif %}
</ul>
<ul class="nav pull-right"> <ul class="nav pull-right">
<li class="dropdown"> <li class="dropdown">
<a href="#" role="button" class="dropdown-toggle navbar-text" data-toggle="dropdown" title="That is your username"> <a href="#" role="button" class="dropdown-toggle navbar-text" data-toggle="dropdown" title="That is your username">
...@@ -104,7 +124,7 @@ ...@@ -104,7 +124,7 @@
<span class="glyphicon glyphicon-user" aria-hidden="true"></span> <span class="glyphicon glyphicon-user" aria-hidden="true"></span>
</a> </a>
</li> </li>
--!> -->
{% for state in corpus.hyperdata.statuses %} {% for state in corpus.hyperdata.statuses %}
{% if state.action == "Workflow" %} {% if state.action == "Workflow" %}
...@@ -151,7 +171,7 @@ ...@@ -151,7 +171,7 @@
<a type="button" class="btn btn-default {% if view == 'analytics' %} active {% endif %}" <a type="button" class="btn btn-default {% if view == 'analytics' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/analytics'" onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/analytics'"
data-target='#' href='#'> data-target='#' href='#'>
<span class="glyphicon glyphicon-signal" aria-hidden="true"></span> <span class="glyphicon glyphicon-signal" aria-hidden="true"></span>
Analytics Analytics
</a> </a>
...@@ -298,6 +318,7 @@ ...@@ -298,6 +318,7 @@
<script type="text/javascript" src="{% static "lib/bootstrap/3.2.0/bootstrap.min.js" %}"></script> <script type="text/javascript" src="{% static "lib/bootstrap/3.2.0/bootstrap.min.js" %}"></script>
<script type="text/javascript"> <script type="text/javascript">
// initializes the popover elements with jquery
$(function () { $("[data-toggle='popover']").popover({ $(function () { $("[data-toggle='popover']").popover({
html: true, html: true,
title: function() { title: function() {
...@@ -346,8 +367,15 @@ ...@@ -346,8 +367,15 @@
{% if view == "graph" %}
<!-- garganrest could be used here to update node's names if we add POST -->
<script type="text/javascript" src="{% static "lib/gargantext/garganrest.js" %}"></script>
<!-- Graph renaming (load after garganrest)-->
<script type="text/javascript" src="{% static "lib/gargantext/graph_renamer.js" %}"></script>
{% endif %}
{% if debug == False %} {% if debug == False %}
<!-- Piwik --> <!-- Piwik -->
<script type="text/javascript"> <script type="text/javascript">
var _paq = _paq || []; var _paq = _paq || [];
......
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