Updated property edition + cache to "get" method so it doesn't generate as many requests to Github API
--- a/src/catedit/api.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/api.py Tue Nov 25 16:24:37 2014 +0100
@@ -1,6 +1,6 @@
from flask.ext.restful import Resource, fields, Api, reqparse
from flask import request
-from app import app
+from app import app, cache
from models import Category, CategoryManager
from rdflib import Graph, RDF
from utils import *
@@ -20,6 +20,8 @@
class CategoryAPI(Resource):
# returns category cat_id
+ @classmethod
+ @cache.memoize(timeout=600)
def get(self, cat_id=None):
# load file cat_id
# TODO: load list if cat_id=None
@@ -31,9 +33,11 @@
response=[]
for c in cat_manager_instance.list_cat():
response.append(c.cat_graph.serialize(format='turtle'))
+ # print response
return response
# update category cat_id
+ @classmethod
def put(self, cat_id):
args = cat_parser.parse_args()
cat_manager_instance = CategoryManager()
@@ -45,16 +49,27 @@
args["property_predicate"],
args["property_object"]):
if property_object:
- new_property_list.append((property_predicate, property_object))
- # print new_property_list
+ property_object_to_append=property_object
+ # if URIRef category, we must prefix id with namespace
+ if app.config["PROPERTY_LIST"] \
+ [property_predicate] \
+ ["object_type"] == "uriref-category" :
+ property_object_to_append = app.config["ONTOLOGY_NAMESPACE"] \
+ +property_object
+ print property_object_to_append
+ new_property_list.append((property_predicate, property_object_to_append))
+ print new_property_list
c = cat_manager_instance.load_cat(cat_id)
c.edit_category(new_description=args["description"],
new_label=args["label"],
new_other_properties=new_property_list)
cat_manager_instance.save_cat(c, message=args["commit_message"])
+ cache.delete_memoized(CategoryAPI.get,cat_id)
+ cache.delete_memoized(CategoryAPI.get,None)
return c.cat_graph.serialize(format='turtle'), 200
# Maybe not send the whole cat back, see if it's worth it
+ @classmethod
def post(self):
args = cat_parser.parse_args()
property_list = []
@@ -70,11 +85,16 @@
other_properties=property_list)
cat_manager_instance = CategoryManager()
cat_manager_instance.save_cat(c, message=args["commit_message"])
+ cache.delete_memoized("get",cat_id)
+ cache.delete_memoized("get",None)
return c.cat_graph.serialize(format='turtle'), 201
+ @classmethod
def delete(self, cat_id):
cat_manager_instance = CategoryManager()
cat_manager_instance.delete_cat(cat_id)
+ cache.delete_memoized(CategoryAPI.get,cat_id)
+ cache.delete_memoized(CategoryAPI.get,None)
return 204
api.add_resource(CategoryAPI,
--- a/src/catedit/app.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/app.py Tue Nov 25 16:24:37 2014 +0100
@@ -1,5 +1,6 @@
from flask import Flask, session
from flask.ext.github import GitHub
+from flask.ext.cache import Cache
from settings import *
from config import *
from logging import *
@@ -7,6 +8,7 @@
# set up app and database
app = Flask(__name__)
app.config.from_object(appSettings)
+cache = Cache(app, config={"CACHE_TYPE": "simple"})
# app.config.from_object(systemSettings)
github = GitHub(app)
--- a/src/catedit/models.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/models.py Tue Nov 25 16:24:37 2014 +0100
@@ -46,7 +46,9 @@
app.config["PROPERTY_LIST"]
[predicate]
["rdflib_class"],
- Literal(obj)))
+ app.config["PROPERTY_LIST"]
+ [predicate]
+ ["object_rdflib_class"](obj)))
else:
self.cat_graph = graph
@@ -123,7 +125,9 @@
app.config["PROPERTY_LIST"]
[predicate]
["rdflib_class"],
- Literal(obj)))
+ app.config["PROPERTY_LIST"]
+ [predicate]
+ ["object_rdflib_class"](obj)))
"""
@@ -156,6 +160,7 @@
def list_cat(self):
p = app.config["PERSISTENCE_METHOD"]()
cat_serial_list = p.list()
+ # print cat_serial_list
cat_list=[]
for cat_serial in cat_serial_list:
loaded_cat_graph = Graph()
--- a/src/catedit/persistence.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/persistence.py Tue Nov 25 16:24:37 2014 +0100
@@ -137,6 +137,7 @@
+"/contents/"
+app.config["CATEGORIES_PATH"])
filenames_list = [ file["name"] for file in files_in_repo ]
+ # print filenames_list
except GitHubError:
pass
file_content_list=[]
--- a/src/catedit/settings.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/settings.py Tue Nov 25 16:24:37 2014 +0100
@@ -36,25 +36,29 @@
"subClassOf": {
"descriptive_label_fr" : "Sous-classe de",
"descriptive_label_en" : "Subclass of",
+ "object_type" : "uriref-category",
"rdflib_class" : RDFS.subClassOf,
- "rdflib_object" : "uriref",
+ "object_rdflib_class" : URIRef,
},
"value": {
"descriptive_label_fr" : "Valeur",
"descriptive_label_en" : "Value",
+ "object_type" : "literal",
"rdflib_class" : RDF.value,
- "rdflib_object" : "literal",
+ "object_rdflib_class" : Literal,
},
"type": {
"descriptive_label_fr" : "Type",
"descriptive_label_en" : "Type",
+ "object_type" : "uriref-category",
"rdflib_class" : RDF.type,
- "rdflib_object" : "uriref",
+ "object_rdflib_class" : URIRef,
},
"resource": {
"descriptive_label_fr" : "Ressource",
"descriptive_label_en" : "Resource",
+ "object_type" : "uriref-link",
"rdflib_class" : RDFS.Resource,
- "rdflib_object" : "uriref",
+ "object_rdflib_class" : URIRef,
},
}
--- a/src/catedit/static/js/property_functions.js Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/static/js/property_functions.js Tue Nov 25 16:24:37 2014 +0100
@@ -14,57 +14,101 @@
}
},
- addProperty : function(divName, type){
- var selectElement = document.getElementById('property_type_selector');
- var selectedOptionValue = selectElement.options[selectElement.selectedIndex].value;
- var selectedOptionText = selectElement.options[selectElement.selectedIndex].text
- var selectedOptionObject = selectElement.options[selectElement.selectedIndex].label
- var newProperty = document.createElement('div');
- newProperty.setAttribute('id','property_div'+(createdProperties+1));
- newProperty.setAttribute('class','row property-row');
- var optionObjectHTML = "";
- switch(selectedOptionObject) {
- case "literal":
- optionObjectHTML = '<input type="text" id="property_object'+(createdProperties+1)+'" name="property_object" class="form-control col-md-8">';
- break;
- default:
- optionObjectHTML='<span class="glyphicon glyphicon-exclamation-sign"/>'
- }
+ addProperty : function(divToReveal, divToAddFieldsTo){
+ var selectElement = document.getElementById('property_selector');
+ if (selectElement.options[selectElement.selectedIndex].id != "property_type_default") {
+ var selectedOptionValue = selectElement.options[selectElement.selectedIndex].value;
+ var selectedOptionText = selectElement.options[selectElement.selectedIndex].text;
+ var propertyOptionObjectType = selectElement.options[selectElement.selectedIndex].label;
+ var propertyObjectValue = "default: something went wrong"
+ switch(propertyOptionObjectType) {
+ case "literal":
+ propertyObjectValue = document.getElementById('literal-field').value;
+ propertyObjectText = document.getElementById('literal-field').value;
+ break;
+ case "uriref-category":
+ var selectingCatBox = document.getElementById('uriref-category-field');
+ propertyObjectText = selectingCatBox[selectingCatBox.selectedIndex].innerHTML;
+ propertyObjectValue = selectingCatBox.value;
+ break;
+ case "uriref-link":
+ propertyObjectValue = document.getElementById('uriref-link-field').value;
+ propertyObjectText = document.getElementById('uriref-link-field').value;
+ break;
+ default:
+ optionObject='<span class="glyphicon glyphicon-exclamation-sign"/>'
+ }
- var newPropertyHTML = '<div class="form-inline"> \
- <label class="col-md-2">'
- +selectedOptionText+
- '</label> \
- <input type="hidden" id="property_predicate'+(createdProperties+1)+'" name="property_predicate" value="'+selectedOptionValue+'">'
- +optionObjectHTML+
- '<input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty('+(createdProperties+1)+')" value="Supprimer"> \
- </div>';
+ if (((propertyObjectValue != "") && (propertyOptionObjectType == "literal")) ||
+ ((propertyObjectValue != "") && (propertyOptionObjectType == "uriref-link")) ||
+ ((propertyObjectValue != "default") && (propertyOptionObjectType == "uriref-category"))) {
+ var newProperty = document.createElement('tr');
+ newProperty.setAttribute('id','property_tr'+(createdProperties+1));
+ var newPropertyHTML = '<input type="hidden" id="property_predicate'+(createdProperties+1)+'" name="property_predicate" value="'+selectedOptionValue+'"> \
+ <input type="hidden" id="property_object'+(createdProperties+1)+'" name="property_object" value="'+propertyObjectValue+'"> \
+ <td id="predicate_td'+(createdProperties+1)+'"> \
+ <strong>'+selectedOptionText+'</strong> \
+ </td> \
+ <td id="object_td'+(createdProperties+1)+'">'
+ +propertyObjectText+
+ '</td> \
+ <td id="delete_button'+(createdProperties+1)+'"> \
+ <input type="button" id="property_delete_button'+(createdProperties+1)+'" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty('+(createdProperties+1)+',properties)" value="Supprimer"> \
+ </td>';
- newProperty.innerHTML = newPropertyHTML ;
- parentElement=document.getElementById(divName) ;
- parentElement.insertBefore(newProperty, parentElement.firstChild);
- createdProperties++;
- propertyCount++;
- if (propertyCount > 0) {
- document.getElementById(divName).className="visible";
+ newProperty.innerHTML = newPropertyHTML ;
+ parentElement=document.getElementById(divToAddFieldsTo) ;
+ parentElement.insertBefore(newProperty, parentElement.firstChild);
+ createdProperties++;
+ propertyCount++;
+ if (propertyCount > 0) {
+ document.getElementById(divToReveal).className="visible";
+ }
+ }
}
},
- removeProperty : function(index){
+ removeProperty : function(index, divToReveal){
if (propertyCount > 0) {
- divItem=document.getElementById("property_div"+index);
- divItem.parentNode.removeChild(divItem);
- propertyCount--;
- if (propertyCount == 0) {
- document.getElementById(divName).className="hidden";
- }
+ divItem=document.getElementById("property_tr"+index);
+ divItem.parentNode.removeChild(divItem);
+ propertyCount--;
+ if (propertyCount == 0) {
+ document.getElementById(divToReveal).className="hidden";
+ }
}
},
- helloWorld : function() {
- alert('Hello World! -' + propertyCount);
- }
-
+ displayCorrespondingField : function() {
+ propertySelectItem = document.getElementById("property_selector");
+ switch(propertySelectItem[propertySelectItem.selectedIndex].label)
+ {
+ case "property_type_default":
+ document.getElementById("literal-field").className = "hidden form-control";
+ document.getElementById("uriref-category-field").className = "hidden form-control";
+ document.getElementById("uriref-link-field").className = "hidden form-control";
+ break;
+ case "literal":
+ document.getElementById("literal-field").className = "visible form-control";
+ document.getElementById("uriref-category-field").className = "hidden form-control";
+ document.getElementById("uriref-link-field").className = "hidden form-control";
+ break;
+ case "uriref-category":
+ document.getElementById("literal-field").className = "hidden form-control";
+ document.getElementById("uriref-category-field").className = "visible form-control";
+ document.getElementById("uriref-link-field").className = "hidden form-control";
+ break;
+ case "uriref-link":
+ document.getElementById("literal-field").className = "hidden form-control";
+ document.getElementById("uriref-category-field").className = "hidden form-control";
+ document.getElementById("uriref-link-field").className = "visible form-control";
+ break;
+ default:
+ document.getElementById("literal-field").className = "hidden form-control";
+ document.getElementById("uriref-category-field").className = "hidden form-control";
+ document.getElementById("uriref-link-field").className = "hidden form-control";
+ }
+ }
};
}());
--- a/src/catedit/templates/cateditor.html Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/templates/cateditor.html Tue Nov 25 16:24:37 2014 +0100
@@ -42,14 +42,14 @@
<div class="alert alert-warning" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Attention:</span>
- Vous n'avez pas accès en écriture au repository contenant les catégories - Vous ne pourrez pas les modifier
+ Vous n'avez pas accès en écriture au repository contenant les catégories - Vous ne pourrez pas les modifier.
</div>
{% endif %}
{% if not session["user_logged"] %}
<div class="alert alert-warning" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Attention:</span>
- Vous devez être authentifié pour modifier les catégories
+ Vous devez être authentifié pour modifier les catégories.
</div> {% endif %}
{% if form.label.errors or form.description.errors or form.commit_message.errors %}
<div class="alert alert-danger">
@@ -57,7 +57,7 @@
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
Erreur:
</strong>
- vous n'avez pas rempli certains champs obligatoires
+ Vous n'avez pas rempli certains champs obligatoires.
</div>
{% endif %}
<h2>{% if cat_id: %} Edition : <small>Catégorie existante</small>{% else %}Création : <small>Nouvelle catégorie</small>{% endif %}</h2>
@@ -77,37 +77,74 @@
{{ form.description.label }} <br> {{ form.description(size=150, class="form-control", readonly=readonly, placeholder=description_placeholder) }} <br>
<label>Propriétés </label>
<div class="form-inline">
- <input type="button" value="Ajouter propriété" onClick="CatEditScripts.addProperty('properties');" class="btn btn-default" {{ readonly }}>
- <select id="property_type_selector" class="form-control">
- <option value="subClassOf" label="literal">Sous-classe de</option>
- <option value="value" label="literal">Valeur</option>
- <option value="type" label="literal">Type</option>
+ <input type="button" value="Ajouter propriété" onClick="CatEditScripts.addProperty('properties','property_table_body');" class="btn btn-default" {{ readonly }}>
+ <select id="property_selector" class="form-control" onChange="CatEditScripts.displayCorrespondingField();" {{readonly}}>
+ <option label="property_type_default" selected>
+ Liste des propriétés ...
+ </option>
+ {% for predicate in config["PROPERTY_LIST"] %}
+ <option value='{{ predicate }}' label={{ config["PROPERTY_LIST"][predicate]["object_type"] }} >{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</option>
+ {% endfor %}
+ </select>
+ <input type="text" id="literal-field" class="hidden form-control">
+ <input type="text" id="uriref-link-field" placeholder="http://my-example.com" class="hidden form-control">
+ <select id="uriref-category-field" class="hidden form-control">
+ <option value="default" selected> Liste des catégories </option>
+ {% for cat in cat_list %}
+ <option value="{{ cat.cat_id }}"> {{ cat.cat_label }} </option>
+ {% endfor %}
</select>
</div>
- <div id="properties" class="hidden">
- {% set property_count=1 %}
- {% for (predicate, object) in cat_properties %}
- <div id="property_div{{ property_count }}" class="row property-row">
- <div class="form-inline">
- <label class="col-md-2">
- {% if predicate == "subClassOf" %} Sous-classe de
- {% elif predicate == "value" %} Valeur
- {% elif predicate == "type" %} Type
- {% endif %}
- </label>
- <input type="hidden" id="property_predicate{{ property_count }}" name="property_predicate" value={{ predicate }}>
- <input type="text" id="property_object{{ property_count }}" name="property_object" class="form-control col-md-8" value={{ object }}>
- <input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }})" value="Supprimer">
- </div>
+ <div id="properties" class="row hidden">
+ <div class="row">
+ <div class="col-md-6">
+ <br>
+ <table id="property_table" class="table table-condensed">
+ <tbody id="property_table_body">
+ {% set property_count=1 %}
+ {% for (predicate, object) in cat_properties %}
+ <tr id="property_tr{{property_count}}">
+ {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
+ {% for cat in cat_list %}
+ {% if object == config["ONTOLOGY_NAMESPACE"]+cat.cat_id %}
+ <input type="hidden" id="property_predicate{{ property_count }}" name="property_predicate" value="{{predicate}}"/>
+ <input type="hidden" id="property_object{{ property_count }}" name="property_object" value="{{cat.cat_id}}"/>
+ <td id="predicate_td{{ property_count }}">
+ <strong>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</strong>
+ </td>
+ <td id="object_td{{ property_count }}">
+ {{ cat.cat_label }}
+ </td>
+ <td id="delete_button_td{{ property_count }}">
+ <input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties')" value="Supprimer">
+ </td>
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ <input type="hidden" id="property_predicate{{ property_count }}" name="property_predicate" value="{{predicate}}"/>
+ <input type="hidden" id="property_object{{ property_count }}" name="property_object" value="{{object}}"/>
+ <td id="predicate_td{{ property_count }}">
+ <strong>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</strong>
+ </td>
+ <td id="object_td{{ property_count }}">
+ {{ object }}
+ </td>
+ <td id="delete_button_td{{ property_count }}">
+ <input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties')" value="Supprimer">
+ </td>
+ {% endif %}
+ {% set property_count=property_count+1 %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
</div>
- {% set property_count=property_count+1 %}
- {% endfor %}
+ </div>
</div><br>
{{ form.commit_message.label }} <br> {{ form.commit_message(size=150, class="form-control", readonly=readonly, placeholder=description_placeholder) }} <br>
<br><input type="submit" value="Sauvegarder" class="btn btn-default">
</form>
{% if readonly %} </fieldset> {% endif %}
- </div>
<script src="{{ url_for('static', filename='js/property_functions.js') }}" language="Javascript" type="text/javascript"></script>
{% if cat_id %}
<script type=text/javascript>
--- a/src/catedit/templates/catrecap.html Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/templates/catrecap.html Tue Nov 25 16:24:37 2014 +0100
@@ -88,9 +88,19 @@
<dl class="dl-horizontal">
{% if cat.cat_properties|length == 0 %} <dt></dt><dd>Aucune autre propriété</dd>
{% else %}
- {% for (predicate, property) in cat.cat_properties %}
+ {% for (predicate, object) in cat.cat_properties %}
<dt>{{ predicate }}</dt>
- <dd>{{ property }}</dd>
+ <dd>
+ {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
+ {% for cat in cat_list %}
+ {% if object == config["ONTOLOGY_NAMESPACE"]+cat.cat_id %}
+ {{ cat.cat_label }}
+ {% endif %}
+ {% endfor %}
+ {% else %}
+ {{ object }}
+ {% endif %}
+ </dd>
{% endfor %}
{% endif %}
</dl>
--- a/src/catedit/views.py Mon Nov 24 11:05:08 2014 +0100
+++ b/src/catedit/views.py Tue Nov 25 16:24:37 2014 +0100
@@ -24,7 +24,9 @@
# list categories
if delete_cat_id is None:
serialized_cat_list = cat_api_instance.get()
+ # print serialized_cat_list
cat_list = []
+ # print cat_list
for serialized_cat in serialized_cat_list:
cat_rdf_graph = Graph()
cat_rdf_graph.parse(source=StringIO(serialized_cat), format='turtle')
@@ -46,6 +48,19 @@
@app.route('/cateditor/<string:cat_id>', methods=['GET', 'POST'])
def cat_editor(cat_id=None):
cat_api_instance = CategoryAPI()
+
+ serialized_cat_list = cat_api_instance.get()
+ cat_list = []
+ for serialized_cat in serialized_cat_list:
+ cat_rdf_graph = Graph()
+ cat_rdf_graph.parse(source=StringIO(serialized_cat), format='turtle')
+ c = Category(graph=cat_rdf_graph)
+
+ cat_list.append({"cat_label": c.label,
+ "cat_description": c.description,
+ "cat_id": c.cat_id,
+ "cat_properties": c.properties})
+
if cat_id is not None:
catSerial = cat_api_instance.get(cat_id)
@@ -72,7 +87,8 @@
return render_template('cateditor.html',
cat_id=c.cat_id,
cat_properties=c.properties,
- form=cat_form)
+ form=cat_form,
+ cat_list=cat_list)
# PUT + cat_id = Submit edited cat
if cat_form.validate_on_submit():
@@ -82,7 +98,8 @@
return render_template('cateditor.html',
cat_id=cat_id,
cat_properties=c.properties,
- form=cat_form)
+ form=cat_form,
+ cat_list=cat_list)
else:
setattr(NewCategoryMinimalForm,
@@ -99,7 +116,8 @@
# GET seul = Create cat form
if request.method == 'GET':
return render_template('cateditor.html',
- form=cat_form)
+ form=cat_form,
+ cat_list=cat_list)
# POST seul = Submit created cat
if cat_form.validate_on_submit():
@@ -107,7 +125,8 @@
return redirect(url_for('cat_recap'))
else :
return render_template('cateditor.html',
- form=cat_form)
+ form=cat_form,
+ cat_list=cat_list)
@app.route('/catedit-github-login')
def github_login():
@@ -139,6 +158,7 @@
@github.access_token_getter
def token_getter():
if session.get("user_logged",None):
+ print "I made an authentified request"
return session["user_code"]
@app.route('/catedit-logout')
--- a/virtualenv/requirements.txt Mon Nov 24 11:05:08 2014 +0100
+++ b/virtualenv/requirements.txt Tue Nov 25 16:24:37 2014 +0100
@@ -3,4 +3,5 @@
flask-restful
flask-wtf
Github-Flask
+flask-cache
pep8