add event + event session + admin + category json management. Must rebuild database
authorymh <ymh.work@gmail.com>
Sun, 19 Oct 2014 12:52:38 +0200
changeset 42 926f0426ce78
parent 41 69a7e0b101de
child 43 e27c3c1c57f1
add event + event session + admin + category json management. Must rebuild database
annot-server/models.py
annot-server/oscserver.py
annot-server/settings.py.tmpl
annot-server/webapp/__init__.py
annot-server/webapp/templates/pianoroll.html
annot-server/webapp/views.py
annot-server/websockets.py
client/app/annotationclient.html
client/app/app.js
requirements.txt
--- a/annot-server/models.py	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/models.py	Sun Oct 19 12:52:38 2014 +0200
@@ -8,38 +8,28 @@
 import json
 import uuid
 
-from sqlalchemy import Column, Integer, String, DateTime, Table, Index, text
+from sqlalchemy import Column, Integer, String, DateTime, Text, Table, Index, text, ForeignKey
+from sqlalchemy.orm import relationship, backref
 from sqlalchemy.sql import func
 from sqlalchemy.dialects.postgresql import UUID, JSON
 
 from database import Base, engine
 
-#def get_table_create_stmt():
-#    return (
-#        "CREATE TABLE IF NOT EXISTS annotations ( "
-#        "id serial PRIMARY KEY, "
-#        "uuid uuid UNIQUE, "
-#        "created timestamp default (now() at time zone 'utc') NOT NULL, "
-#        "ts timestamptz NOT NULL, "
-#        "event varchar(255) NOT NULL, "
-#        "channel varchar(255) NOT NULL, "
-#        "content json);"
-#    )
 
 class Annotation(Base):
-    __tablename__ = 'annotations'
+    __tablename__ = 'annotation'
 
     id = Column(Integer, primary_key=True, nullable=False)
     uuid = Column(UUID, unique=True, nullable=False)
     created = Column(DateTime, nullable=False, server_default=text("(now() at time zone 'utc')") )
     ts = Column(DateTime(timezone=True), nullable=False)
-    event = Column(String(255), nullable=False)
+    event_code = Column(String(255), ForeignKey('event.code'), nullable=False)
     channel = Column(String(255), nullable=False)
     content = Column(JSON)
 
-Index('idx_event', Annotation.event)
-Index('idx_channel', Annotation.channel)
-Index('idx_ts', Annotation.ts)
+Index('idx_annotation_event', Annotation.event_code)
+Index('idx_annotation_channel', Annotation.channel)
+Index('idx_annotation_ts', Annotation.ts)
 
 
 def insert_annot_async(params, conn):
@@ -59,3 +49,31 @@
     defer.addCallback(lambda _: stmt.params)
 
     return defer
+
+
+class Event(Base):
+    __tablename__ = 'event'
+
+    id = Column(Integer, primary_key=True, nullable=False)
+    code = Column(String(255), unique=True, nullable=False)
+    label = Column(String(2048), nullable=False)
+    description = Column(Text(), nullable=True)
+
+    sessions = relationship("EventSession", order_by="EventSession.order", backref="event")
+
+    def __unicode__(self):
+        return self.code
+
+Index('idx_event_code', Event.code)
+
+class EventSession(Base):
+    __tablename__ = 'event_session'
+
+    id = Column(Integer, primary_key=True, nullable=False)
+    event_id = Column(Integer, ForeignKey(Event.id), nullable=False)
+    project_id = Column(String(2048), nullable=True)
+    order = Column(Integer, nullable=False, default=0)
+    categories_json = Column(JSON, nullable=True)
+
+
+Index('idx_event_session_order', EventSession.order)
--- a/annot-server/oscserver.py	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/oscserver.py	Sun Oct 19 12:52:38 2014 +0200
@@ -37,7 +37,7 @@
 
         params = {
             'ts' : ts,
-            'event': getAddressParts(message.address)[1],
+            'event_code': getAddressParts(message.address)[1],
             'channel' : utils.PIANOROLL_CHANNEL,
             'content' : values
         }
--- a/annot-server/settings.py.tmpl	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/settings.py.tmpl	Sun Oct 19 12:52:38 2014 +0200
@@ -8,5 +8,4 @@
 
 STATIC_URL = '/static'
 STATIC_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)),'static')
-
-from settings import *
+LDT_PLATFORM_BASE_URL = 'http://ldt.iri.centrepompidou.fr/ldtplatform'
--- a/annot-server/webapp/__init__.py	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/webapp/__init__.py	Sun Oct 19 12:52:38 2014 +0200
@@ -18,3 +18,4 @@
 
 import webapp.views
 import webapp.api
+import webapp.admin
--- a/annot-server/webapp/templates/pianoroll.html	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/webapp/templates/pianoroll.html	Sun Oct 19 12:52:38 2014 +0200
@@ -21,7 +21,7 @@
     <div id="canvasContainer"></div>
     <p><a href="#" onclick="clearInterval(moveInterval); clearInterval(verticalLinesInterval); return false;">stop intervals</a> - temps écoulé : <span id="myspan"></span></p>
     <pre id="log"></pre>
-    <script src="/static/js/pixi.js"></script>
-    <script src="/static/js/pianoroll.js"></script>
+    <script src="{{ config['STATIC_URL'] }}js/pixi.js"></script>
+    <script src="{{ config['STATIC_URL'] }}js/pianoroll.js"></script>
 </body>
-</html>
\ No newline at end of file
+</html>
--- a/annot-server/webapp/views.py	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/webapp/views.py	Sun Oct 19 12:52:38 2014 +0200
@@ -3,9 +3,15 @@
 # Copyright (c) 2014 IRI
 #
 
-from flask import render_template, jsonify, request
+import json
+
+from flask import render_template, jsonify, request, abort
+from jinja2 import Markup
+from sqlalchemy.orm import joinedload
 
 from webapp import app
+from database import db_session
+import models
 
 @app.route('/')
 def page_home():
@@ -22,6 +28,32 @@
 def page_annotationclient():
     return render_template('annotationclient.html', logging=True)
 
+@app.route('/annotationclient/<event_code>')
+def page_annotationclient_event_code(event_code):
+    #TODO: check event code + get event session
+    event_query = db_session.query(models.Event).filter(models.Event.code==event_code)
+    event = event_query.one()
+    if not event:
+        abort(404)
+
+    #TODO: See why the relationship management does not work
+    event_session_q = db_session.query(models.EventSession).filter(models.EventSession.event_id==event.id).order_by(models.EventSession.order.desc())
+    event_session = event_session_q.first()
+
+    categories_json = None
+
+    if event_session:
+        categories_json = event_session.categories_json
+
+    if not categories_json:
+        categories_json = None
+
+    return render_template('annotationclient.html',
+        logging = True,
+        event_code = event_code,
+        categories_json = Markup(json.dumps(categories_json).replace('\'','\\\'')) if categories_json else None
+    )
+
 
 @app.route('/pianoroll')
 def page_pianoroll():
--- a/annot-server/websockets.py	Fri Oct 17 17:54:06 2014 +0200
+++ b/annot-server/websockets.py	Sun Oct 19 12:52:38 2014 +0200
@@ -87,7 +87,7 @@
         params_annot = json.loads(msg)
 
         params = {
-            'event': self.event,
+            'event_code': self.event,
             'channel' : utils.ANNOTATION_CHANNEL,
             'content' : params_annot
         }
--- a/client/app/annotationclient.html	Fri Oct 17 17:54:06 2014 +0200
+++ b/client/app/annotationclient.html	Sun Oct 19 12:52:38 2014 +0200
@@ -95,7 +95,9 @@
             {% if logging %}logging: true,{% endif %}
             urls: {
                 dataUrl: "{{ config['STATIC_URL'] }}/data/categories.json"
-            }
+            },
+            categories_json: '{% if categories_json %}{{categories_json}}{% endif %}',
+            {% if event_code %}event_code: "{{event_code}}",{% endif %}
         });
   </script>
 </body>
--- a/client/app/app.js	Fri Oct 17 17:54:06 2014 +0200
+++ b/client/app/app.js	Sun Oct 19 12:52:38 2014 +0200
@@ -18,23 +18,26 @@
             //console.log('dataApi',$resource, context);
             this.dataResource = $resource(context.urls.dataUrl);
         })
-        .service('dataModel', function(dataApi) {
+        .service('dataModel', function(dataApi, context, $q) {
             //console.log('dataModel',this,dataApi);
-            this.data = dataApi.dataResource.get();
+            if(typeof context.categories_json !== 'undefined' && context.categories_json) {
+                this.data = JSON.parse(context.categories_json);
+            }
+            else {
+                this.data = dataApi.dataResource.get();
+            }
         })
         .controller('homeCtrl', function($scope, $location, dataModel, context, $interval){
-            
+
             function getURLParameter(name) {
                 return decodeURI(
                     (new RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
                 );
             }
-            
-            //console.log('homeCtrl 1', $scope, $location, context);
-            //console.log('homeCtrl 2', context);
+
             $scope.data = dataModel.data;
 
-            dataModel.data.$promise.then(function(data) {
+            var process_categories = function(data) {
                 if(typeof data.categories!=='undefined' && data.categories.length>0){
                     var cats = [];
                     var nbCat = data.categories.length;
@@ -49,7 +52,14 @@
                     }
                     $scope.allCatLabels = cats;
                 }
-            });
+            };
+
+            if (typeof dataModel.data.$promise !== 'undefined') {
+                dataModel.data.$promise.then(process_categories);
+            }
+            else {
+                process_categories(dataModel.data);
+            }
 
             $scope.selectedlevel = false;
 
--- a/requirements.txt	Fri Oct 17 17:54:06 2014 +0200
+++ b/requirements.txt	Sun Oct 19 12:52:38 2014 +0200
@@ -1,10 +1,13 @@
 Flask==0.10.1
+Flask-Admin==1.0.8
 Flask-Restless==0.14.2
 Jinja2==2.7.3
 MarkupSafe==0.23
 SQLAlchemy==0.9.8
 Twisted==14.0.2
 Werkzeug==0.9.6
+WTForms==1.0.5
+aniso8601==0.83
 autobahn==0.9.1
 itsdangerous==0.24
 lxml==3.4.0
@@ -14,9 +17,9 @@
 python-dateutil==2.2
 python-mimeparse==0.1.4
 pytz==2014.7
-requests>=2.4.3
+'requests>=2.4.3'
 six==1.8.0
--e hg+https://bitbucket.org/IRI/txosc/get/tip.tar.gz#egg=txosc
+txosc==0.2.0
 txpostgres==1.2.0
 wsgiref==0.1.2
 zope.interface==4.1.1