#
# See LICENCE for detail
# Copyright (c) 2014 IRI
#
import json
import logging
from StringIO import StringIO
import urllib
from dateutil.tz import tzutc
from flask import url_for, render_template, request
from flask.ext.admin import Admin, BaseView, expose
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.admin.contrib.sqla.form import AdminModelConverter
from flask.ext.admin.contrib.sqla.filters import BooleanEqualFilter
from flask.ext.admin.model.form import InlineFormAdmin, converts
from jinja2 import Markup
from wtforms import fields
from wtforms.ext.dateutil import fields as dateutil_fields
import config
import database
import models
import utils
from webapp import app
admin = Admin(app)
def build_ldt_url(view, context, model, name):
# `view` is current administrative view
# `context` is instance of jinja2.runtime.Context
# `model` is model instance
# `name` is property name
if not model.project_id \
or not model.categories_json \
or not isinstance(model.categories_json, dict) \
or not getattr(config,'LDT_PLATFORM_BASE_URL',None):
return ''
output = []
for c in model.categories_json.get("categories",[]):
output.append({"name": c["code"] if "code" in c else "","keywords": [ c["label"] ], "color" : c["color"] })
base_url = getattr(config,'LDT_PLATFORM_BASE_URL','') + "/ldt/embediframe/?"
url_query_params = {'project_id': model.project_id,
'polemic': 'all',
'polemic__max_elements': 200,
'createannotation': True,
'createannotation_polemics': False,
'tag_titles': "",
'polemics_list': json.dumps(output, separators=(',',':'))}
url = base_url + urllib.urlencode(url_query_params)
embed = "<iframe src="%s" width="570" height="711" seamless="seamless" frameborder="0"></iframe>" % url
return Markup("<a href=\"%s\" target=\"_blank\">Lien</a> :<br/><input value=\"%s\"/><br/>Code embed :<input value=\"%s\"/>" % (url, url, embed))
def build_sync_form(view, context, model, name):
# `view` is current administrative view
# `context` is instance of jinja2.runtime.Context
# `model` is model instance
# `name` is property name
if not model.project_id \
or not model.start_ts \
or not getattr(config,'LDT_PLATFORM_BASE_URL',None):
return ''
url = url_for('eventsessionview.sync')
return Markup(render_template('admin/sync_form.html', model=model, url=url))
class StartTSField(dateutil_fields.DateTimeField):
def __init__(self, *args, **kwargs):
if 'display_format' not in kwargs:
kwargs['display_format']='iso'
super(StartTSField, self).__init__(*args, **kwargs)
def _value(self):
if self.raw_data:
return ' '.join(self.raw_data)
elif self.display_format == 'iso':
return self.data and self.data.isoformat() or ''
else:
return self.data and self.data.strftime(self.display_format) or ''
def process_formdata(self, valuelist):
super(StartTSField, self).process_formdata(valuelist)
if self.data and self.data.tzinfo is None:
self.data = self.data.replace(tzinfo=tzutc())
class EventView(ModelView):
column_searchable_list = ('code', 'label')
column_list = ('code', 'label', 'start_date', 'active')
column_filters = ('code', 'label', 'start_date', 'active')
form_create_rules = ('code', 'label', 'description', 'start_date')
inline_models = [(models.EventSession, {'form_overrides': { "start_ts": StartTSField, },})]
def __init__(self, session, **kwargs):
super(EventView, self).__init__(models.Event, session, **kwargs)
class DictToJSONField(fields.TextAreaField):
def process_data(self, value):
if value is None:
value = {}
self.data = json.dumps(value, indent=2)
def process_formdata(self, valuelist):
if valuelist:
self.data = json.loads(valuelist[0])
else:
self.data = None
class JsonAdminConverter(AdminModelConverter):
@converts('JSON')
def conv_JSON(self, field_args, **extra):
return DictToJSONField(**field_args)
class EventSessionView(ModelView):
column_default_sort = ( models.Event.code, True)
column_sortable_list = (('event', models.Event.code),)
column_auto_select_related = True
column_list = ('event', 'project_id', 'order', 'categories_json', 'url', 'sync')
column_filters = ('event',)
column_formatters = {
'sync': build_sync_form,
'url': build_ldt_url,
'categories_json': lambda v, c, m, p: json.dumps(m.categories_json)[:80] if m.categories_json else ''
}
form_overrides = { "start_ts": StartTSField, }
form_widget_args = {
'categories_json': {
'rows': 10,
'class': 'input-xlarge'
},
'start_ts': {
'class': 'input-xlarge'
},
'project_id': {
'class': 'input-xlarge'
}
}
model_form_converter=JsonAdminConverter
def __init__(self, session, **kwargs):
super(EventSessionView, self).__init__(models.EventSession, session, **kwargs)
@expose("/sync/",methods=('POST', ))
def sync(self):
event_session = database.db_session.query(models.EventSession).filter_by(id=int(request.form['event_session_id'])).first()
if not event_session:
abort(404)
stream = StringIO()
handler = logging.StreamHandler(stream)
logger = logging.getLogger('sync_logger')
logger.setLevel(logging.DEBUG)
for h in logger.handlers:
logger.removeHandler(h)
logger.addHandler(handler)
sync_args = {
'start_date' : event_session.start_ts,
'duration' : event_session.duration or None,
'events' : [event_session.event.code],
'channels' : [utils.AnnotationsSynchronizer.DEFAULT_ANNOTATION_CHANNEL],
'project_id' : event_session.project_id,
'annot_url' : url_for('annotationapi0.annotationapi', _external=True),
'post_param' : getattr(config, 'SYNC_POST_PARAM', {}),
'base_url' : getattr(config, 'LDT_PLATFORM_BASE_URL', "http://ldt.iri.centrepompidou.fr/ldtplatform/"),
'replace' : True,
'merge' : False,
'batch_size' : 500,
'logger' : logger,
}
error = None
try:
sync = utils.AnnotationsSynchronizer(**sync_args)
sync.export_annotations()
except Exception as e:
error = repr(e) + " - " + str(e)
logs = [ line for line in stream.getvalue().split("\n")]
return self.render('admin/sync_event_session.html', event_session=event_session, sync_args=repr(sync_args), error=error, logs=logs)
admin.add_view(EventView(database.db_session))
admin.add_view(EventSessionView(database.db_session))