# HG changeset patch # User ymh # Date 1368306545 -7200 # Node ID 54ef33bb4065d2a93bd7fc49d22b07335e581677 # Parent 615d19953572cde4631c4cc85d8c1e4f6509edc0# Parent eb9cc63ce7423fe953f6332fd7f28624e5840ef3 Merge with eb9cc63ce7423fe953f6332fd7f28624e5840ef3 diff -r eb9cc63ce742 -r 54ef33bb4065 .hgtags --- a/.hgtags Tue May 07 15:30:41 2013 +0200 +++ b/.hgtags Sat May 11 23:09:05 2013 +0200 @@ -143,10 +143,8 @@ c4d6ddd5f718d1e55441247aa4c4366a5d7be470 V01.43 996bb5b1adbc920f8ecb49f9d7b45f51a8aa3c04 V01.44 62be1eedf90855ab3cef1ab8a9f0c66130638673 V01.45 -ba7783d59d3fbee183ff2bc5ba1e8deed769928d V01.46.1 +e1b6be4d85a47f4cecce2cf6e88ff190301bd8dc V01.46 1db1fa8c8076e791cfeedb8c2eb73d731656e034 V01.46.01 -ba7783d59d3fbee183ff2bc5ba1e8deed769928d V01.46.1 -0000000000000000000000000000000000000000 V01.46.1 65712578e1f3adc7b441f5e853456442de4b7380 V01.46.02 d0fdcae534a9826644e9f15c6a8c7888dad76c02 V01.46.03 5647cbc32e53dafb824583ea8d0cbaf38ff38bb9 V01.46.04 @@ -160,3 +158,7 @@ 9e21c880c3ee2206a9150a46ea865bbc4a7ccccc V01.46.08 8837650d6f629d0582169c6bda8432290a1680b0 V01.46.09 af204bb19efa9dc45d09017968144bfb470acace V01.46.10 +86dbc665226d08c082a559b2c218efcd56105c69 V01.47 +56c6497c0785d20c3c17da90446d030eba3c78f3 V01.48 +e590a85b91cccd905ddd25db54357f4f584e83fa V01.49 + diff -r eb9cc63ce742 -r 54ef33bb4065 .project --- a/.project Tue May 07 15:30:41 2013 +0200 +++ b/.project Sat May 11 23:09:05 2013 +0200 @@ -10,11 +10,6 @@ - - com.aptana.ide.core.unifiedBuilder - - - com.aptana.projects.webnature diff -r eb9cc63ce742 -r 54ef33bb4065 .settings/org.eclipse.core.resources.prefs --- a/.settings/org.eclipse.core.resources.prefs Tue May 07 15:30:41 2013 +0200 +++ b/.settings/org.eclipse.core.resources.prefs Sat May 11 23:09:05 2013 +0200 @@ -1,42 +1,47 @@ -eclipse.preferences.version=1 -encoding//src/ldt/ldt/core/migrations/0001_initial.py=utf-8 -encoding//src/ldt/ldt/core/migrations/0002_auto__del_owner.py=utf-8 -encoding//src/ldt/ldt/indexation/backends/elasticsearch_backend.py=utf-8 -encoding//src/ldt/ldt/indexation/highlighter.py=utf-8 -encoding//src/ldt/ldt/indexation/models.py=utf-8 -encoding//src/ldt/ldt/indexation/query_parser.py=utf-8 -encoding//src/ldt/ldt/indexation/search_indexes.py=utf-8 -encoding//src/ldt/ldt/indexation/tests.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0001_initial.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0002_auto__add_field_media_mimetype_field__chg_field_media_external_src_url.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0003_auto__chg_field_project_owner.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0004_auto__add_field_project_description.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0005_add_permissions.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0006_auto__add_field_media_image.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0007_auto__add_field_content_image__del_field_media_image.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0008_auto__add_field_project_image.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0013_auto__add_field_content_front_project__chg_field_content_last_annotate.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0014_auto__del_annotationstat__chg_field_content_last_annotated.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0015_auto__add_contentstat__del_field_content_last_annotated__del_field_con.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0016_one_to_one_stat_annotation.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0017_correct_image_path.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0018_auto__chg_field_content_iri_id__chg_field_project_ldt_id__chg_field_au.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0019_recalculate_media_hash_src.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0020_auto__add_field_segment_id_hash__chg_field_segment_iri_id__chg_field_s.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0021_recalculate_segment_id_hash_script.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0022_auto__add_unique_media_src_hash__chg_field_segment_cutting_id__chg_fie.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0023_auto__add_field_segment_audio_src__add_field_segment_audio_href.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0024_auto__chg_field_tag_name.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/migrations/0025_chg_site_domain.py=utf-8 -encoding//src/ldt/ldt/ldt_utils/views/json.py=utf-8 -encoding//src/ldt/ldt/management/utils.py=utf-8 -encoding//src/ldt/ldt/test/test_runner.py=utf-8 -encoding//src/ldt/ldt/text/migrations/0001_initial.py=utf-8 -encoding//src/ldt/ldt/user/migrations/0001_initial.py=utf-8 -encoding//src/ldt/ldt/user/migrations/0008_auto__chg_field_groupprofile_image__chg_field_groupprofile_group__chg_.py=utf-8 -encoding//virtualenv/web/env/guardianenv/Lib/site-packages/guardian/migrations/0001_initial.py=utf-8 -encoding/=UTF-8 +#Mon Apr 08 17:07:34 CEST 2013 +eclipse.preferences.version=1 +encoding//src/ldt/ldt/core/migrations/0001_initial.py=utf-8 +encoding//src/ldt/ldt/core/migrations/0002_auto__del_owner.py=utf-8 +encoding//src/ldt/ldt/indexation/backends/elasticsearch_backend.py=utf-8 +encoding//src/ldt/ldt/indexation/highlighter.py=utf-8 +encoding//src/ldt/ldt/indexation/models.py=utf-8 +encoding//src/ldt/ldt/indexation/query_parser.py=utf-8 +encoding//src/ldt/ldt/indexation/search_indexes.py=utf-8 +encoding//src/ldt/ldt/indexation/signals.py=utf-8 +encoding//src/ldt/ldt/indexation/tests.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/events.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0001_initial.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0002_auto__add_field_media_mimetype_field__chg_field_media_external_src_url.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0003_auto__chg_field_project_owner.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0004_auto__add_field_project_description.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0005_add_permissions.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0006_auto__add_field_media_image.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0007_auto__add_field_content_image__del_field_media_image.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0008_auto__add_field_project_image.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0009_auto__chg_field_content_image__chg_field_project_image.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0010_auto__add_annotationstat.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0011_gen_stat_annotation.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0012_auto__add_field_content_last_annotated.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0013_auto__add_field_content_front_project__chg_field_content_last_annotate.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0014_auto__del_annotationstat__chg_field_content_last_annotated.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0015_auto__add_contentstat__del_field_content_last_annotated__del_field_con.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0016_one_to_one_stat_annotation.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0017_correct_image_path.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0018_auto__chg_field_content_iri_id__chg_field_project_ldt_id__chg_field_au.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0019_recalculate_media_hash_src.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0020_auto__add_field_segment_id_hash__chg_field_segment_iri_id__chg_field_s.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0021_recalculate_segment_id_hash_script.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0022_auto__add_unique_media_src_hash__chg_field_segment_cutting_id__chg_fie.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0023_auto__add_field_segment_audio_src__add_field_segment_audio_href.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0024_auto__chg_field_tag_name.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0025_chg_site_domain.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/migrations/0026_set_relative_ldtproject.py=utf-8 +encoding//src/ldt/ldt/ldt_utils/views/json.py=utf-8 +encoding//src/ldt/ldt/management/commands/synciri.py=utf-8 +encoding//src/ldt/ldt/management/utils.py=utf-8 +encoding//src/ldt/ldt/test/test_runner.py=utf-8 +encoding//src/ldt/ldt/text/migrations/0001_initial.py=utf-8 +encoding//src/ldt/ldt/user/migrations/0001_initial.py=utf-8 +encoding//src/ldt/ldt/user/migrations/0008_auto__chg_field_groupprofile_image__chg_field_groupprofile_group__chg_.py=utf-8 +encoding//virtualenv/web/env/guardianenv/Lib/site-packages/guardian/migrations/0001_initial.py=utf-8 +encoding/=UTF-8 diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/__init__.py --- a/src/ldt/ldt/__init__.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/__init__.py Sat May 11 23:09:05 2013 +0200 @@ -1,4 +1,4 @@ -VERSION = (1, 46, 10, "final", 0) +VERSION = (1, 49, 0, "final", 0) def get_version(): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/api/ldt/resources/annotation.py --- a/src/ldt/ldt/api/ldt/resources/annotation.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/api/ldt/resources/annotation.py Sat May 11 23:09:05 2013 +0200 @@ -7,14 +7,16 @@ from tastypie.exceptions import NotFound, BadRequest from tastypie.resources import Resource import logging #@UnresolvedImport +from ldt.ldt_utils.contentindexer import add_segment class AnnotationObject(object): - def __init__(self, id="", project = "", type = "", type_title = "", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}): + def __init__(self, id="", project = "", type = "", type_title = "", ensemble="", media = "", begin = 0, end = 0, content = {"title":"", "description":""}, tags = [], meta = {"creator":"","created":""}): self.id = id self.project = project self.type = type self.type_title = type_title + self.ensemble = ensemble self.media = media self.begin = begin self.end = end @@ -86,25 +88,44 @@ author = meta['creator'] date = meta['created'] # add(media, cutting_id, cutting_title, title, text, tags_list, begin, dur, author, date - type_id, new_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['title'], a['content']['description'], a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href) + type_id, new_id, ensemble_id = adder.add(a['media'], a['type'], a['type_title'], a['content']['title'], a['content']['description'], a['tags'], begin, dur, author, date, None, "2194379", audio_src, audio_href) if not new_id: protect_models() raise BadRequest content = project.contents.get(iri_id=a['media']) - add_annotation_to_stat(content, a['begin'], a['end']) # We update the ids a['type'] = type_id + a['ensemble'] = ensemble_id a['id'] = new_id if not a['content'].has_key('audio') : a['content']['audio'] = {'src':audio_src, 'href':audio_href} + + #add segment + add_segment({ + "project" : project, + "content" : content, + "ensemble_id" : ensemble_id, + "cutting_id" : a['type'], + "element_id" : new_id, + "title" : a['content']['title'], + "abstract" : a['content']['description'], + "tags" : ",".join(a['tags']), + "start_ts" : begin, + "duration" : dur, + "author" : author, + "date" : date, + "audio_src" : audio_src, + "audio_href" : audio_href, + "polemics": adder.get_polemic_syntax(a['content']['title']) + }) # We save the added annotation and reprotect the contents and projects - adder.save() + adder.save(must_reindex=False) protect_models() # We update the AnnotationObject for the returned datas to be correct. - bundle.obj = AnnotationObject(id = a["id"], project = a["project"], type = a["type"], type_title = a["type_title"], media = a["media"], begin = a["begin"], end = a["end"], content = a['content'], tags = a['tags'], meta = a['meta']) + bundle.obj = AnnotationObject(id = a["id"], project = a["project"], type = a["type"], type_title = a["type_title"], ensemble=a['ensemble'], media = a["media"], begin = a["begin"], end = a["end"], content = a['content'], tags = a['tags'], meta = a['meta']) return bundle def get_resource_uri(self, bundle_or_obj): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/api/ldt/resources/content.py --- a/src/ldt/ldt/api/ldt/resources/content.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/api/ldt/resources/content.py Sat May 11 23:09:05 2013 +0200 @@ -26,7 +26,7 @@ class Meta: allowed_methods = ['get'] resource_name = 'contents' - queryset = Content.objects.select_related('front_project').all() + queryset = Content.objects.select_related('front_project','media_obj').all() filtering = { 'tags' : ALL_WITH_RELATIONS, 'title' : ALL, @@ -34,7 +34,7 @@ ordering = ['title', 'creation_date', 'content_creation_date'] def get_object_list(self, request): - return Content.safe_objects.all() + return Content.safe_objects.select_related('front_project', 'media_obj').all() def override_urls(self): # WARNING : in tastypie <= 1.0, override_urls is used instead of prepend_urls. From 1.0.0, prepend_urls will be prefered and override_urls deprecated diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/api/ldt/resources/segment.py --- a/src/ldt/ldt/api/ldt/resources/segment.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/api/ldt/resources/segment.py Sat May 11 23:09:05 2013 +0200 @@ -2,14 +2,16 @@ from django.conf.urls.defaults import url from django.core.paginator import Paginator, InvalidPage from django.db.models import F, Q -from ldt.indexation import get_results_with_context +from ldt.indexation import get_results_list from ldt.ldt_utils.models import Content, Segment from ldt.ldt_utils.segmentserializer import SegmentSerializer from tastypie.constants import ALL -from tastypie.http import HttpNotFound +from tastypie.exceptions import BadRequest, NotFound from tastypie.resources import ModelResource from tastypie.utils import trailing_slash +import logging +logger = logging.getLogger(__name__) class SegmentResource(ModelResource): class Meta: @@ -38,8 +40,9 @@ self.method_check(request, allowed=['get']) # Do the query. search = request.GET.get('q', '') + if search=='': + raise BadRequest('The request needs a search query "q=" parameter.') field = "all" - content_list = None if u'author:' in search.lower() : sub = search[7:] sub = sub.upper() @@ -48,22 +51,25 @@ if sub[-1] != u'"': sub = sub + u'"' search = u'author:' + sub - results = get_results_with_context(field, search, content_list) - all_segments = Segment.objects.filter(element_id__in=[e['element_id'] for e in results]) - paginator = Paginator(all_segments, getattr(settings, 'API_LIMIT_PER_PAGE', 20)) - + + results = get_results_list(field, search, False) + # get_results_list returns a SearchQuerySet, we load_all() to get all real Segment objects + all_segments = results.load_all() + paginator = Paginator(all_segments, request.GET.get("limit") or getattr(settings, 'API_LIMIT_PER_PAGE', 20)) + try: page = paginator.page(int(request.GET.get('page', 1))) except InvalidPage: - raise HttpNotFound("Sorry, no results on that page.") - + raise NotFound("Sorry, no results on that page.") + objects = [] - - for segment in page.object_list: - bundle = self.build_bundle(obj=segment, request=request) + + for search_res in page.object_list: + # search_res is a SearchResult, search_res.object is the real Segment Object thanks to results.load_all() + bundle = self.build_bundle(obj=search_res.object, request=request) bundle = self.full_dehydrate(bundle) objects.append(bundle) - + object_list = { 'objects': objects, } @@ -78,22 +84,22 @@ returns segments about content iri_id between timecodes begin and end """ if not begin: - return HttpNotFound("begin timecode argument is missing.") + raise NotFound("begin timecode argument is missing.") if not end: - return HttpNotFound("end timecode argument is missing.") + raise NotFound("end timecode argument is missing.") begin = int(begin) end = int(end) - content = Content.objects.filter(iri_id=iri_id) + content = Content.objects.filter(iri_id=iri_id).select_related('media_obj', 'stat_annotation') if not content: - return HttpNotFound("Content does not exist or id is not correct.") + raise NotFound("Content does not exist or id is not correct.") content = content[0] segments = Segment.objects.filter(content=content).filter( Q(start_ts__gte=begin, start_ts__lte=end) | # segment starts between begin and end Q(start_ts__gte=begin-F('duration'), start_ts__lte=end-F('duration')) |# segment ends between begin and end Q(start_ts__lte=begin, start_ts__gte=end-F('duration')) # period [begin:end] is included in the segment - ) + ).select_related("project_obj") a = SegmentSerializer(content, segments) return self.create_response(request, a.serialize_to_cinelab()) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/indexation/__init__.py --- a/src/ldt/ldt/indexation/__init__.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/indexation/__init__.py Sat May 11 23:09:05 2013 +0200 @@ -1,5 +1,7 @@ +from .backends import elasticsearch_backend as ldt_elasticsearch_backend from django.conf import settings - +from haystack import connections +from haystack.constants import DEFAULT_ALIAS from haystack.query import SearchQuerySet from ldt.indexation.highlighter import LdtHighlighter as Highlighter from ldt.indexation.query_parser import QueryParser @@ -7,6 +9,7 @@ from ldt.text.models import Annotation import re import sys + def get_results_with_context(field, query, content_list=None, highlight=True): @@ -82,6 +85,62 @@ return results_list +def object_delete(model, **kwargs): + + + kwargs_filter = kwargs.copy() + kwargs_filter.pop('using', None) + + # here we do a poor man transaction management. + # the is no clear transaction management in Haystack. + # therefore, we give priority to the database and delete there first. + # if there is an error there, the index will not be updated. + + objs = list(model.objects.filter(**kwargs_filter)) + + model.objects.filter(**kwargs_filter).delete() + + using = None + if 'using' in kwargs: + using = kwargs.get('using', None) + if not using: + using = DEFAULT_ALIAS + + conn = connections[using] + + if isinstance(conn, ldt_elasticsearch_backend.ElasticsearchSearchEngine): + conn.get_backend().remove(objs, commit=True) + else: + for o in objs: + conn.get_backend().remove(o, commit=True) + +def object_insert(model, object_list, func_key, using = None): + + if not object_list: + return + + model.objects.bulk_create(object_list) + + obj_dict = dict(model.objects.filter(**{func_key+'__in':[getattr(o, func_key) for o in object_list]}).values_list(func_key,"id")) + + for o in object_list: + o.id = obj_dict[getattr(o,func_key)] + + if not using: + using = DEFAULT_ALIAS + + conn = connections[using] + + backend = conn.get_backend() + unified_index = conn.get_unified_index() + + index = unified_index.get_index(model) + + backend.update(index, object_list) + + + + class SimpleSearch(object): def query(self, field, query): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/indexation/backends/elasticsearch_backend.py --- a/src/ldt/ldt/indexation/backends/elasticsearch_backend.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/indexation/backends/elasticsearch_backend.py Sat May 11 23:09:05 2013 +0200 @@ -7,8 +7,21 @@ from django.db.models.loading import get_model from haystack.backends import BaseEngine, SearchResult, elasticsearch_backend from haystack.constants import DJANGO_CT, DJANGO_ID +from haystack.exceptions import MissingDependency +from haystack.utils import get_identifier from ldt.ldt_utils.models import Segment +import collections import datetime +try: + import requests +except ImportError: + raise MissingDependency("The 'elasticsearch' backend requires the installation of 'requests'.") +try: + import pyelasticsearch +except ImportError: + raise MissingDependency("The 'elasticsearch' backend requires the installation of 'pyelasticsearch'. Please refer to the documentation.") + + class ElasticsearchSearchBackend(elasticsearch_backend.ElasticsearchSearchBackend): @@ -110,6 +123,27 @@ 'facets': facets, 'spelling_suggestion': spelling_suggestion, } + + def remove(self, obj_or_string, commit=True): + + if not self.setup_complete: + try: + self.setup() + except (requests.RequestException, pyelasticsearch.ElasticHttpError), e: + if not self.silently_fail: + raise + + self.log.error("Failed to remove document '%s' from Elasticsearch: %s", repr(obj_or_string), e) + return + + if isinstance(obj_or_string, collections.Iterable) and not isinstance(obj_or_string, basestring): + ids = [get_identifier(elt) for elt in obj_or_string] + if not ids: + return + q = {'ids' : {'values' : ids}} + self.conn.delete_by_query(self.index_name, 'modelresult', q) + else: + return super(ElasticsearchSearchBackend, self).remove(obj_or_string, commit=commit) class ElasticsearchSearchEngine(BaseEngine): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/indexation/query_parser.py --- a/src/ldt/ldt/indexation/query_parser.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/indexation/query_parser.py Sat May 11 23:09:05 2013 +0200 @@ -7,10 +7,13 @@ #TODO: unitest for -from whoosh.qparser import SimpleParser, FieldsPlugin, OperatorsPlugin, PhrasePlugin, SingleQuotePlugin, GroupPlugin, PrefixPlugin, GtLtPlugin, RangePlugin -from whoosh.query import Term, And, AndMaybe, Or, AndNot, Not, Phrase, Prefix, TermRange +from django.conf import settings from haystack.query import SQ -from django.conf import settings +from whoosh.qparser import (SimpleParser, FieldsPlugin, OperatorsPlugin, + PhrasePlugin, SingleQuotePlugin, GroupPlugin, PrefixPlugin, GtLtPlugin, + RangePlugin) +from whoosh.query import (Term, And, AndMaybe, Or, AndNot, Not, Phrase, Prefix, + TermRange) HAYSTACK_DEFAULT_OPERATOR = getattr(settings,'HAYSTACK_DEFAULT_OPERATOR','AND') @@ -158,16 +161,16 @@ current_node, current_connector = self.current_node_stack[-1] current_node.add(new_node, current_connector) - def __convert_nb(self, str): + def __convert_nb(self, str_nb): try: - res = int(str) + res = int(str_nb) return res except ValueError: try: - res = float(str) + res = float(str_nb) return res except ValueError: - return str + return str_nb \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/indexation/search_indexes.py --- a/src/ldt/ldt/indexation/search_indexes.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/indexation/search_indexes.py Sat May 11 23:09:05 2013 +0200 @@ -6,10 +6,10 @@ ''' from haystack import indexes -from ldt.ldt_utils.models import Segment +from ldt.ldt_utils.models import Segment from ldt.text.models import Annotation -class SegmentIndex(indexes.RealTimeSearchIndex, indexes.Indexable): +class SegmentIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) iri_id = indexes.CharField(model_attr='iri_id', indexed=False, stored=True) project_id = indexes.CharField(model_attr='project_id', indexed=False, stored=True, null=True) @@ -27,7 +27,7 @@ def get_model(self): return Segment -class AnnotationIndex(indexes.RealTimeSearchIndex, indexes.Indexable): +class AnnotationIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) tags = indexes.CharField(model_attr='tags', indexed=True, stored=False) title = indexes.CharField(model_attr='title', indexed=True, stored=True) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/indexation/signals.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/indexation/signals.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +''' +Created on Feb 22, 2013 + +@author: ymh +''' +from django.db import models +from haystack import signals +from ldt.ldt_utils.models import Segment +from ldt.text.models import Annotation + +class LdtSignalProcessor(signals.BaseSignalProcessor): + + def __connect_signals(self, klass): + models.signals.post_save.connect(self.handle_save, sender=klass) + models.signals.post_delete.connect(self.handle_delete, sender=klass) + + def __disconnect_signals(self, klass): + models.signals.post_save.disconnect(self.handle_save, sender=klass) + models.signals.post_delete.disconnect(self.handle_delete, sender=klass) + + + def setup(self): + self.__connect_signals(Segment) + self.__connect_signals(Annotation) + + + + def teardown(self): + self.__disconnect_signals(Annotation) + self.__disconnect_signals(Segment) + \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/__init__.py --- a/src/ldt/ldt/ldt_utils/__init__.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/__init__.py Sat May 11 23:09:05 2013 +0200 @@ -1,2 +0,0 @@ -#initialize -from ldt.ldt_utils import contentindexer diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/contentindexer.py --- a/src/ldt/ldt/ldt_utils/contentindexer.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/contentindexer.py Sat May 11 23:09:05 2013 +0200 @@ -1,15 +1,16 @@ -from django.db.models.signals import post_save +from StringIO import StringIO from django.dispatch import receiver from ldt import settings +from ldt.indexation import object_delete, object_insert +from ldt.ldt_utils.events import post_project_save from ldt.ldt_utils.models import Segment, Content, Project -from ldt.ldt_utils.stat import update_stat_project +from ldt.ldt_utils.stat import update_stat_project, add_annotation_to_stat from ldt.ldt_utils.utils import reduce_text_node +from ldt.utils.url import request_with_auth from tagging import settings as tagging_settings import logging import lxml.etree #@UnresolvedImport import tagging.utils -from ldt.utils.url import request_with_auth -from StringIO import StringIO logger = logging.getLogger(__name__) @@ -19,8 +20,11 @@ class LdtIndexer(object): - def __init__(self, decoupage_blackList=settings.DECOUPAGE_BLACKLIST): - self.__decoupage_blacklist = decoupage_blackList + def __init__(self, object_list, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None): + self.__object_list = object_list + self.__decoupage_blacklist = decoupage_blackList + self.__callback = callback + self.__segment_cache = [] @Property def decoupage_blacklist(): #@NoSelf @@ -40,7 +44,23 @@ return locals() def index_all(self): - raise NotImplemented + for i,obj in enumerate(self.__object_list): + if self.__callback: + self.__callback(i,obj) + self.index_object(obj) + + + def index_object(self, obj): + + self._do_index_object(obj) + + if self.__segment_cache: + object_insert(Segment, self.__segment_cache, 'id_hash') + self.__segment_cache = [] + + + def _do_index_object(self, obj): + raise NotImplementedError() def index_ensemble(self, ensemble, content, project=None): ensembleId = ensemble.get(u"id", None) @@ -97,7 +117,7 @@ audio_src = audio_node[0].get(u"source", u"") audio_href = audio_node[0].text - seg = Segment(content=content, + seg = Segment.create(content=content, iri_id=content.iri_id, ensemble_id=ensembleId, cutting_id=decoupId, @@ -114,55 +134,41 @@ audio_src=audio_src, audio_href=audio_href) seg.polemics = seg.get_polemic(polemics) - seg.save() + if settings.LDT_INDEXATION_INSERT_BATCH_SIZE < 2: + seg.save() + else: + self.__segment_cache.append(seg) + if not (len(self.__segment_cache)%settings.LDT_INDEXATION_INSERT_BATCH_SIZE): + object_insert(Segment, self.__segment_cache) + self.__segment_cache = [] class ContentIndexer(LdtIndexer): - def __init__(self, contentList, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None): - super(ContentIndexer, self).__init__(decoupage_blackList) - self.__contentList = contentList - self.__callback = callback - - def index_all(self): - for i,content in enumerate(self.__contentList): - if self.__callback: - self.__callback(i,content) - self.index_content(content) - - def index_content(self, content): + def _do_index_object(self, obj): + + content = obj url = content.iri_url() _, file_content = request_with_auth(url) doc = lxml.etree.parse(StringIO(file_content)) #@UndefinedVariable - Segment.objects.filter(iri_id=content.iri_id).delete() #@UndefinedVariable + object_delete(Segment, iri_id=content.iri_id, project_id='') res = doc.xpath("/iri/body/ensembles/ensemble") for ensemble in res: self.index_ensemble(ensemble, content) - + class ProjectIndexer(LdtIndexer): + + def _do_index_object(self, obj): - def __init__(self, projectList, decoupage_blackList=settings.DECOUPAGE_BLACKLIST, callback=None): - super(ProjectIndexer, self).__init__(decoupage_blackList) - self.__projectList = projectList - self.__callback = callback - - def index_all(self): - for i,project in enumerate(self.__projectList): - if self.__callback: - self.__callback(i,project) - - self.index_project(project) - - def index_project(self, project): - + project = obj # pocketfilms.utils.log.debug("Indexing project : "+str(project.iri_id)) doc = lxml.etree.fromstring(project.ldt_encoded) #@UndefinedVariable - Segment.objects.filter(project_obj__ldt_id=project.ldt_id).delete() #@UndefinedVariable + object_delete(Segment, project_obj__ldt_id=project.ldt_id) res = doc.xpath("/iri/annotations/content") @@ -177,14 +183,66 @@ for ensemble in content.getchildren(): self.index_ensemble(ensemble, content_obj, project) -@receiver(post_save, sender=Project) -def index_project(sender, **kwargs): - if settings.AUTO_INDEX_AFTER_SAVE: +@receiver(post_project_save) +def index_project(**kwargs): + must_reindex = kwargs.get("must_reindex", True) + if must_reindex and settings.AUTO_INDEX_AFTER_SAVE: instance = kwargs['instance'] - if instance.state != 2: - Segment.objects.filter(project_obj__ldt_id=instance.ldt_id).delete() #@UndefinedVariable + if instance.state != Project.PUBLISHED: + object_delete(Segment, project_obj__ldt_id=instance.ldt_id) update_stat_project(instance) else: projectIndexer = ProjectIndexer([instance]) projectIndexer.index_all() update_stat_project(instance) + + + +def add_segment(params): + + project = params.get("project",None) + content = params.get("content",None) + ensemble_id = params.get("ensemble_id", "") + cutting_id = params.get("cutting_id", "") + element_id = params.get("element_id", "") + title = params.get("title", "") + abstract = params.get("abstract", "") + tags_str = params.get("tags", "") + start_ts = params.get("start_ts", 0) + duration = params.get("duration", 0) + author = params.get("author", "") + date_str = params.get("date", "") + audio_src = params.get("audio_src", "") + audio_href = params.get("audio_href", "") + polemics = params.get("polemics", "") + + seg = Segment.create(content=content, + iri_id=content.iri_id if content is not None else "", + ensemble_id=ensemble_id, + cutting_id=cutting_id, + element_id=element_id, + tags=tags_str, + title=title, + abstract=abstract, + duration=duration, + author=author, + start_ts=start_ts, + date=date_str, + project_obj=project, + project_id=project.ldt_id if project is not None else "", + audio_src=audio_src, + audio_href=audio_href) + seg.polemics = seg.get_polemic(polemics) + seg.save() + add_annotation_to_stat(seg.content, seg.start_ts, seg.start_ts+seg.duration) + + +def delete_segment(project, project_id, iri_id, ensemble_id, cutting_id, element_id): + + # delete Segment + for seg in Segment.objects.filter(project_id=project_id, iri_id=iri_id, ensemble_id=ensemble_id, cutting_id=cutting_id, element_id=element_id): + seg.delete() + add_annotation_to_stat(seg.content, seg.start_ts, seg.start_ts+seg.duration) + + + \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/events.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/ldt_utils/events.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +''' +Created on Jan 22, 2013 + +@author: ymh +''' +import django.dispatch + +post_project_save = django.dispatch.Signal(["instance","must_reindex"]) \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/fixtures/user_data.json --- a/src/ldt/ldt/ldt_utils/fixtures/user_data.json Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/fixtures/user_data.json Sat May 11 23:09:05 2013 +0200 @@ -17,50 +17,86 @@ } }, { - "pk": 1, - "model": "oauth_provider.resource", + "pk": 7, + "model": "ldt_utils.media", "fields": { - "url": "/api/1.0/text/delete/", - "name": "delete", - "is_readonly": true - } - }, - { - "pk": 2, - "model": "oauth_provider.resource", - "fields": { - "url": "/api/1.0/text/create/", - "name": "create", - "is_readonly": true + "external_permalink": "", + "src_hash": "f4a5afb24467cbf18825ea6b90bc2bcc78e68610d6650625296ae70b2e981d9bad6619a3b4ff22431e74177dcc264ffb0c9471bc625a6229b7cdbeb2e372468f", + "videopath": "", + "update_date": "2012-11-26T15:48:12", + "external_publication_url": "", + "external_src_url": "", + "creator": null, + "creation_date": "2012-11-26T15:48:12", + "media_creation_date": null, + "mimetype_field": "", + "duration": null, + "title": "", + "src": "http://dvvsyrlsr21oz.cloudfront.net/01-Kristina-HD.mp4", + "external_id": "", + "description": "" } }, { - "pk": 3, - "model": "oauth_provider.resource", + "pk": 48, + "model": "ldt_utils.media", "fields": { - "url": "/api/1.0/text/update/", - "name": "update", - "is_readonly": true + "external_permalink": "", + "src_hash": "79d1ada053cae7e6e49329645fc55f7ffb5341112134e70f55ea91b2c3e647e8e319525c6117ccfaea61039bf701a3ed8fd4921ac7bf2ef89e2e2f2233b29898", + "videopath": "", + "update_date": "2012-11-26T16:06:45", + "external_publication_url": "", + "external_src_url": "", + "creator": null, + "creation_date": "2012-11-26T16:06:45", + "media_creation_date": null, + "mimetype_field": "", + "duration": null, + "title": "", + "src": "http://dvvsyrlsr21oz.cloudfront.net/INTERNATIONALE-CHANT_1-HD.mp4", + "external_id": "", + "description": "" } - }, + }, { - "pk": 4, - "model": "oauth_provider.resource", + "pk": 49, + "model": "ldt_utils.media", "fields": { - "url": "", - "name": "all", - "is_readonly": true + "external_permalink": "", + "src_hash": "64460e021df13d4bc558e5672393539241f846065ec48862b89f43aadbcd278bc311c16782f43e68a0c83ed3357d0ca4d2082204bc4169af23985fa420a56bee", + "videopath": "", + "update_date": "2012-11-26T16:07:09", + "external_publication_url": "", + "external_src_url": "", + "creator": null, + "creation_date": "2012-11-26T16:07:09", + "media_creation_date": null, + "mimetype_field": "", + "duration": null, + "title": "", + "src": "http://dvvsyrlsr21oz.cloudfront.net/NIDIEU-CHANT-2-HD.mp4", + "external_id": "", + "description": "" } - }, + }, { - "pk": 1, - "model": "oauth_provider.consumer", + "pk": 50, + "model": "ldt_utils.media", "fields": { - "status": 1, - "name": "example.com", - "secret": "kd94hf93k423kf44", - "user": 2, - "key": "dpf43f3p2l4k3l03", + "external_permalink": "", + "src_hash": "1cfb8cdec8da988eca4992b07f7d1bc4ef5c6a3f0a175c9941646c1e3a0abcd1eae6cae35b575b66738ef272ed87c2814fb9c8db3192d1f43c3fb5d7043db766", + "videopath": "", + "update_date": "2012-11-26T16:07:29", + "external_publication_url": "", + "external_src_url": "", + "creator": null, + "creation_date": "2012-11-26T16:07:29", + "media_creation_date": null, + "mimetype_field": "", + "duration": null, + "title": "", + "src": "http://dvvsyrlsr21oz.cloudfront.net/MARSEILLAISE-CHANT_3-HD.mp4", + "external_id": "", "description": "" } } diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/forms.py --- a/src/ldt/ldt/ldt_utils/forms.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/forms.py Sat May 11 23:09:05 2013 +0200 @@ -84,7 +84,7 @@ class Media: css = { - 'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css') + 'all' : ('admin/css/forms.css', 'admin/css/widgets.css') } class MediaForm(forms.ModelForm): @@ -100,7 +100,7 @@ class Media: css = { - 'all' : ('admin/css/forms.css', 'admin/css/base.css', 'admin/css/widgets.css') + 'all' : ('admin/css/forms.css', 'admin/css/widgets.css') } class GroupAddForm(ShareForm): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/migrations/0026_set_relative_ldtproject.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/ldt_utils/migrations/0026_set_relative_ldtproject.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +from django.core.management import call_command +from south.v2 import DataMigration + + +class Migration(DataMigration): + + def forwards(self, orm): + call_command('setprojectldtiri') + + def backwards(self, orm): + #do nothing + pass + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'ldt_utils.author': { + 'Meta': {'object_name': 'Author'}, + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'firstname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'lastname': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}) + }, + 'ldt_utils.content': { + 'Meta': {'ordering': "['title']", 'object_name': 'Content'}, + 'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Author']", 'symmetrical': 'False', 'blank': 'True'}), + 'content_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'front_project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/contents/content_default_icon.png'", 'max_length': '200'}), + 'iri_id': ('django.db.models.fields.CharField', [], {'default': "u'75d885e1-4446-11e2-a1e1-00161798aedb'", 'unique': 'True', 'max_length': '255'}), + 'iriurl': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'media_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Media']", 'null': 'True', 'blank': 'True'}), + 'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'ldt_utils.contentstat': { + 'Meta': {'object_name': 'ContentStat'}, + 'annotation_volume_str': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'content': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'stat_annotation'", 'unique': 'True', 'to': "orm['ldt_utils.Content']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_annotated': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'nb_annotations': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}), + 'polemics_volume_str': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}) + }, + 'ldt_utils.media': { + 'Meta': {'object_name': 'Media'}, + 'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'external_id': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'external_permalink': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'external_publication_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'external_src_url': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'media_creation_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'mimetype_field': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}), + 'src': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'src_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'update_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'videopath': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}) + }, + 'ldt_utils.project': { + 'Meta': {'ordering': "['title']", 'object_name': 'Project'}, + 'changed_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}), + 'contents': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['ldt_utils.Content']", 'symmetrical': 'False'}), + 'created_by': ('django.db.models.fields.CharField', [], {'max_length': '70'}), + 'creation_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('sorl.thumbnail.fields.ImageField', [], {'default': "'thumbnails/projects/project_default_icon.png'", 'max_length': '200'}), + 'ldt': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'ldt_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'modification_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'state': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'ldt_utils.segment': { + 'Meta': {'object_name': 'Segment'}, + 'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'audio_href': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}), + 'audio_src': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'author': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), + 'content': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Content']"}), + 'cutting_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'date': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'element_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'ensemble_id': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'id_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128', 'blank': 'True'}), + 'iri_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'polemics': ('django.db.models.fields.IntegerField', [], {'default': '0', 'null': 'True', 'blank': 'True'}), + 'project_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'project_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['ldt_utils.Project']", 'null': 'True'}), + 'start_ts': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'tags': ('tagging.fields.TagField', [], {'max_length': '2048', 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['ldt_utils'] + symmetrical = True diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/models.py --- a/src/ldt/ldt/ldt_utils/models.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/models.py Sat May 11 23:09:05 2013 +0200 @@ -24,7 +24,7 @@ import uuid from shutil import move from django.core.files.storage import default_storage -#from ldt.core.models import Document, Owner +from .events import post_project_save class Author(SafeModel): @@ -43,22 +43,20 @@ ) - class MediaManager(SafeManager): def __init__(self): super(MediaManager, self).__init__(check_perm=False) - + def get_by_natural_key(self, src_hash): return self.get(src_hash=src_hash) - class Media(SafeModel): objects = MediaManager() external_id = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_id')) - external_permalink = models.URLField(max_length=1024, verify_exists=False, null=True, blank=True, verbose_name=_('media.external_permalink')) - external_publication_url = models.URLField(max_length=1024, verify_exists=True, null=True, blank=True, verbose_name=_('media.external_publication_url')) + external_permalink = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_permalink')) + external_publication_url = models.URLField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_publication_url')) external_src_url = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('media.external_src_url')) creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('media.creation_date')) media_creation_date = models.DateTimeField(null=True, blank=True, verbose_name=_('media.media_creation_date')) @@ -247,7 +245,7 @@ def get_duration(self): if self.duration is None: - doc = lxml.etree.parse(self.iri_file_path()) + doc = lxml.etree.parse(self.iri_file_path()) #@UndefinedVariable res = doc.xpath("/iri/body/medias/media[@id='video']/video") if len(res) > 0: try: @@ -326,6 +324,10 @@ if not url_utils.is_absolute(res_url): res_url = unicode(web_url) + res_url return res_url + + def relative_iri_url(self): #this function is called when we create a project + res_url = u"ldt/" + unicode(self.iriurl) + return res_url def iri_file_path(self): return os.path.join(os.path.join(os.path.join(settings.MEDIA_ROOT, "ldt"), self.iri_id), os.path.basename(self.iriurl)) @@ -582,17 +584,22 @@ return locals() polemics_volume = property(**polemics_volume()) - - -class Project(Document, SafeModel): +class Project(Document, SafeModel): + + EDITION = 1 + PUBLISHED = 2 + MODERATED = 3 + REJECTED = 4 + DELETED = 5 + STATE_CHOICES = ( - (1, 'edition'), - (2, 'published'), - (3, 'moderated'), - (4, 'rejected'), - (5, 'deleted') + (EDITION, 'edition'), + (PUBLISHED, 'published'), + (MODERATED, 'moderated'), + (REJECTED, 'rejected'), + (DELETED, 'deleted') ) ldt_id = models.CharField(max_length=255, unique=True) ldt = models.TextField(null=True) @@ -628,7 +635,7 @@ def get_description(self, doc=None): if doc is None: - doc = lxml.etree.fromstring(self.ldt) + doc = lxml.etree.fromstring(self.ldt) #@UndefinedVariable res = doc.xpath("/iri/project") if len(res) > 0: @@ -660,7 +667,15 @@ return locals() stream_mode = property(**stream_mode()) - + + def save(self, *args, **kwargs): + + must_reindex = kwargs.pop("must_reindex", True) + super(Project, self).save(*args, **kwargs) + + post_project_save.send(self, instance=self, must_reindex = must_reindex) + + @staticmethod def create_project(user, title, contents, description='', groups=[], set_icon=True, cuttings=[]): # owner = Owner.objects.get(user=user) #@UndefinedVariable @@ -740,7 +755,7 @@ def has_annotations(self): nb_annot = 0 - doc = lxml.etree.fromstring(self.ldt) + doc = lxml.etree.fromstring(self.ldt) #@UndefinedVariable res = doc.xpath("/iri/annotations/content/ensemble/decoupage") for r in res: nb_annot = nb_annot + r.find('elements').__len__() @@ -790,6 +805,11 @@ audio_src = models.CharField(max_length=255, unique=False, null=True, blank=True) audio_href = models.CharField(max_length=512, unique=False, null=True, blank=True) + @classmethod + def create(cls, **kwargs): + seg = cls(**kwargs) + seg.set_hash() + return seg # All combinations of polemic hashtags can be represented by a combination of # 4 bits, 1 if the hashtag is in the tweet, 0 else. We use the order OK, KO, Q, REF @@ -801,7 +821,7 @@ 'Q': set([2,3,6,7,10,11,14,15]), 'REF': set([1,3,5,7,9,11,13,15]), } - + def is_polemic(self, polemic_keyword): # OK, KO, Q, REF if self.polemics in self.mask[polemic_keyword]: return True @@ -818,14 +838,25 @@ return value.pop() + def set_hash(self): + try: + self.id_hash = generate_hash(self.__unicode__()) + except AttributeError: + self.id_hash = None + + def __unicode__(self): + return "/".join(( + unicode(self.project_id if self.project_id is not None else ""), + unicode(self.iri_id if self.iri_id is not None else ""), + unicode(self.ensemble_id if self.ensemble_id is not None else ""), + unicode(self.cutting_id if self.cutting_id is not None else ""), + unicode(self.element_id if self.element_id is not None else "") + )) + def save(self, *args, **kwargs): - self.id_hash = generate_hash(self.__unicode__()) - + self.set_hash() super(Segment, self).save(*args, **kwargs) - - def __unicode__(self): - return "/".join((unicode(self.project_id), unicode(self.iri_id), unicode(self.ensemble_id), unicode(self.cutting_id), unicode(self.element_id))) class Meta: permissions = ( diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/projectserializer.py --- a/src/ldt/ldt/ldt_utils/projectserializer.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/projectserializer.py Sat May 11 23:09:05 2013 +0200 @@ -1,17 +1,17 @@ +from datetime import datetime from django.conf import settings -from datetime import datetime +from django.contrib.contenttypes.models import ContentType from django.utils.datastructures import SortedDict -from ldt.ldt_utils.models import Content +from ldt.ldt_utils.models import Content, User, Project +from ldt.ldt_utils.stat import get_string_from_buckets from ldt.ldt_utils.utils import reduce_text_node -from ldt.ldt_utils.models import User, Project -from ldt.ldt_utils.stat import get_string_from_buckets -from ldt.security.utils import use_forbidden_url import logging import lxml.etree import uuid DATE_FORMATS = ["%d/%m/%Y", "%Y-%m-%d"] +logger = logging.getLogger(__name__) """ Serialize a project object to a cinelab compatible array @@ -40,6 +40,7 @@ def __parse_views(self, display_node_list): + logger.debug("__parse_views start") for display_node in display_node_list: display_id = display_node.get(u"id", None) if not display_id: @@ -90,11 +91,13 @@ new_display['annotation_types'] = [new_display['annotation_types'][0]] self.views_dict[display_id] = new_display - + logger.debug("__parse_views done") def __parse_ensemble(self, ensemble_node, content, cutting_only=None): + + ensemble_id = ensemble_node.attrib[u"id"] + logger.debug("__parse_ensemble %s start" % ensemble_id) - ensemble_id = ensemble_node.attrib[u"id"] ensemble_author = ensemble_node.attrib[u"author"] ensemble_title = ensemble_node.attrib[u"title"] ensemble_description = ensemble_node.attrib[u"abstract"] @@ -280,10 +283,13 @@ if not list_items: new_list["items"] = None self.lists_dict[ensemble_id] = new_list + + logger.debug("__parse_ensemble %s done" % ensemble_id) def __parse_ldt(self): + logger.debug("__parse_ldt start") self.ldt_doc = lxml.etree.fromstring(self.project.ldt_encoded) if self.from_display: @@ -293,20 +299,35 @@ self.__parse_views(self.ldt_doc.xpath(xpath_str)) + #getting all contents at once + contents_iri_id = list( + set(self.ldt_doc.xpath("/iri/medias/media/@id")) | + set(self.ldt_doc.xpath("/iri/annotations/content/@id")) | + (set(self.ldt_doc.xpath('/iri/annotations/content[ensemble/decoupage/@id=\'%s\']/@id' % self.first_cutting)) if self.first_cutting and self.first_cutting not in self.display_cuttings_list else set()) + ) + + logger.debug(contents_iri_id) + + contents = dict([ (c.iri_id, c) for c in Content.objects.filter(iri_id__in=contents_iri_id).select_related('media_obj', 'stat_annotation').prefetch_related("authors")]) + m_cls = ContentType.objects.get(model='media') + m_cls = m_cls.model_class() + medias = dict([ (m.id, m) for m in m_cls.safe_objects.filter(id__in = [c.media_obj.id for c in contents.values() if c.media_obj])]) + + res = self.ldt_doc.xpath("/iri/medias/media") for mediaNode in res: iri_id = mediaNode.attrib[u"id"] if self.from_display and iri_id not in self.display_contents_list: continue - content = Content.objects.get(iri_id=iri_id) #@UndefinedVariable - self.__parse_content(content) + content = contents[iri_id]#Content.objects.get(iri_id=iri_id) #@UndefinedVariable + self.__parse_content(content, medias) res = self.ldt_doc.xpath("/iri/annotations/content") for content_node in res: content_id = content_node.attrib[u"id"] if self.from_display and content_id not in self.display_contents_list: continue - content = Content.objects.get(iri_id=content_id) #@UndefinedVariable + content = contents[content_id]#Content.objects.get(iri_id=content_id) #@UndefinedVariable for ensemble_node in content_node: if ensemble_node.tag != "ensemble" : continue @@ -320,7 +341,7 @@ ensemble_node = cutting_node.xpath('..')[0] content_node = ensemble_node.xpath('..')[0] iri_id = content_node.get("id") - content = Content.objects.get(iri_id=iri_id) + content = contents[iri_id]#Content.objects.get(iri_id=iri_id) self.__parse_ensemble(ensemble_node, content, cutting_only=[cutting_node]) @@ -341,9 +362,11 @@ self.__parse_edits() self.parsed = True + logger.debug("__parse_ldt done") def __parse_edits(self): + logger.debug("__parse_edits start") editings = self.ldt_doc.xpath("/iri/edits/editing") if not editings: return False @@ -378,10 +401,11 @@ } } self.lists_dict[e_id] = new_list - + logger.debug("__parse_edits done") - def __parse_content(self, content): + def __parse_content(self, content, medias): + logger.debug("__parse_content %s start" % content.iri_id) doc = lxml.etree.parse(content.iri_file_path()) authors = content.authors.all() @@ -412,7 +436,7 @@ url = "" meta_item_value = "" - if use_forbidden_url(content): + if content.media_obj and content.media_obj.id not in medias: url = settings.FORBIDDEN_STREAM_URL elif content.videopath: url = content.videopath.rstrip('/') + "/" + content.src @@ -459,15 +483,20 @@ res = doc.xpath("/iri/body/ensembles/ensemble") for ensemble_node in res: self.__parse_ensemble(ensemble_node, content) + + logger.debug("__parse_content %s done" % content.iri_id) def serialize_to_cinelab(self): res = {} - + + logger.debug("serialize_to_cinelab before parse ldt") + if not self.parsed: self.__parse_ldt() + logger.debug("serialize_to_cinelab parse ldt done") project_main_media = "" if len(self.medias_dict) > 0: diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/searchutils.py --- a/src/ldt/ldt/ldt_utils/searchutils.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/searchutils.py Sat May 11 23:09:05 2013 +0200 @@ -3,7 +3,9 @@ from ldt.ldt_utils.utils import LdtUtils from ldt.security.utils import set_forbidden_stream import base64 +import logging +logger = logging.getLogger(__name__) def search_generate_ldt(request, field, query, query_encoded=True): @@ -28,13 +30,21 @@ id_list = ids.keys() projId_list = projIds.keys() typesId_list = typesIds.keys() - - contentList = Content.objects.filter(iri_id__in=id_list) #@UndefinedVariable - projectList = Project.safe_objects.filter(ldt_id__in=projId_list) + + logger.debug("search_generate_ldt : getting content list") + contentList = Content.objects.filter(iri_id__in=id_list).select_related("front_project", "media_obj") #@UndefinedVariable + logger.debug("search_generate_ldt : getting project list") + projectList = Project.safe_objects.filter(ldt_id__in=projId_list) + + ldtgen = LdtUtils() # generate_ldt(contentList, title=u"", author=u"IRI Web", web_url=u"", startSegment=None, projects=None): + logger.debug("search_generate_ldt : generate ldt") doc = ldtgen.generate_ldt(contentList, title=u"Recherche : " + queryStr, projects=projectList, types_id_list=typesId_list) + + logger.debug("search_generate_ldt : set forbidden streams") doc = set_forbidden_stream(doc, request.user) + logger.debug("search_generate_ldt : done") return doc, results \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/segmentserializer.py --- a/src/ldt/ldt/ldt_utils/segmentserializer.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/segmentserializer.py Sat May 11 23:09:05 2013 +0200 @@ -3,9 +3,12 @@ from ldt.ldt_utils.stat import get_string_from_buckets from ldt.security.utils import use_forbidden_url from tagging.utils import parse_tag_input +import logging import lxml.etree import uuid +logger = logging.getLogger(__name__) + DATE_FORMATS = ["%d/%m/%Y", "%Y-%m-%d"] class SegmentSerializer(object): @@ -30,13 +33,11 @@ self.xml_docs = {} - def __get_cutting_title(self, project_id, content_id, ensemble_id, cutting_id): + def __get_cutting_title(self, project_id, content_id, ensemble_id, cutting_id, project): if not self.xml_docs.has_key(project_id): - project = Project.objects.filter(ldt_id=project_id) if not project: return None - project = project[0] doc = lxml.etree.fromstring(project.ldt_encoded) self.xml_docs[project_id] = doc else: @@ -74,7 +75,7 @@ annotation_types = [] for seg in self.segments: - title = self.__get_cutting_title(seg.project_id, seg.iri_id, seg.ensemble_id, seg.cutting_id) + title = self.__get_cutting_title(seg.project_id, seg.iri_id, seg.ensemble_id, seg.cutting_id, seg.project_obj) annotation_types.append({'id': seg.cutting_id, 'title': title}) for a in annotation_types: @@ -98,7 +99,8 @@ url = "" meta_item_value = "" - + + logger.debug("__parse_content start") if use_forbidden_url(self.content): url = settings.FORBIDDEN_STREAM_URL elif self.content.videopath: @@ -107,6 +109,8 @@ else: url = self.content.src + logger.debug("__parse_content url %s " % url) + media = { "http://advene.liris.cnrs.fr/ns/frame_of_reference/ms" : "o=0", "id" : self.content.iri_id, @@ -192,12 +196,16 @@ def serialize_to_cinelab(self): + logger.debug("serialize_to_cinelab start") if not self.segments: return None self.__parse_content() + logger.debug("serialize_to_cinelab parse content done") self.__parse_segments() + logger.debug("serialize_to_cinelab parse segments done") self.__parse_views() + logger.debug("serialize_to_cinelab parse views done") res = {} res['views'] = self.views @@ -207,5 +215,7 @@ res['annotations'] = self.annotations res['annotation-types'] = self.annotation_types + logger.debug("serialize_to_cinelab done") + return res \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/front/front_group.html --- a/src/ldt/ldt/ldt_utils/templates/front/front_group.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/front/front_group.html Sat May 11 23:09:05 2013 +0200 @@ -14,17 +14,17 @@ {% block js_declaration %} {{block.super}} + }); + {% endblock %} {% block body %} diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/front/front_home.html --- a/src/ldt/ldt/ldt_utils/templates/front/front_home.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/front/front_home.html Sat May 11 23:09:05 2013 +0200 @@ -112,7 +112,7 @@ {% thumbnail group.get_profile.image "54x40" format="PNG" crop="center" as im %}{% trans 'group picture' %}{% endthumbnail %}
-
{{ group.user_set.count }}
+
{{ group.nb_users }}

{{group.name}}

{% if group.get_profile.description|striptags|length > 69 %}{{group.get_profile.description|striptags|slice:":69"}}...{% else %}{{group.get_profile.description|striptags}}{% endif %}

diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/create_content.html Sat May 11 23:09:05 2013 +0200 @@ -10,13 +10,12 @@ {{ block.super }} - + + - - {{ content_form.media.js }} {% endblock %} @@ -29,27 +28,58 @@ post_added_params = {"csrfmiddlewaretoken" : "{{csrf_token}}", "{{cookie_name}}" : "{{session_key}}"}; - onCreateContentReady("{% url ldt.ldt_utils.views.content.upload %}", - "{% absstatic 'ldt' %}", - post_added_params, - "{% trans 'Browse' %}", - "{% trans 'File uploaded' %}", - "{% trans 'Please wait, the upload is not finished yet' %}", - "{% trans 'Cancel upload' %", - "{% url ldt.ldt_utils.views.content.remove_temp_file %}", - "{% url ldt.ldt_utils.views.content.get_duration %}"); - + onCreateContentReady("{% url ldt.ldt_utils.views.content.upload %}", + "{% absstatic 'ldt' %}", + post_added_params, + "{% trans 'Browse' %}", + "{% trans 'File uploaded' %}", + "{% trans 'Please wait, the upload is not finished yet' %}", + "{% trans 'Cancel upload' %", + "{% url ldt.ldt_utils.views.content.remove_temp_file %}", + "{% url ldt.ldt_utils.views.content.get_duration %}"); }); // the function stopRKey prevents from the validation of the form if the user tape enter button while entering a field function stopRKey(evt) { var evt = (evt) ? evt : ((event) ? event : null); var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null); if ((evt.keyCode == 13) && (node.type=="text")) {return false;} - } + } document.onkeypress = stopRKey; + chunked_uploads_endpoints = { + upload_url: '{{WEB_URL}}{% url upload %}', + done_url: '{{WEB_URL}}{% url upload_done uuid='00000000-0000-0000-0000-000000000000' %}', + }; + $(function() { + //gets video_url and returns it to the "scr" field + chunked_uploads_video_url = function(video_url) { + $('#id_content-media_input_type').val("create"); + $('#id_media-src').val(video_url); + $('#id_media-src').attr('readOnly', true); + $(".media_fields").hide(); + $("#media_field_create").show(); + $('#upload_url').append(video_url); + }; + + //callback of chunked upload start + chunked_uploads_start = function(){ + }; + + //callback of chunked upload stop + chunked_uploads_stop = function(){ + }; + + //callback of chunked upload error + chunked_uploads_error = function(){ + alert("The upload failed. Please reload the page, and try again."); + }; + + //callback of chunked upload complete + chunked_uploads_complete = function(){ + }; + }); {% endblock %} @@ -60,8 +90,6 @@ {% endblock %} {% block content %} - - {% if media_form.errors %}

{% trans "The operation could not be performed because one or more error(s) occurred.
Please resubmit the media form after making the following changes:" %}

@@ -108,15 +136,14 @@
{{ content_form.media_input_type.errors }}{{ content_form.media_input_type.label_tag }}{{content_form.media_input_type}}
+
- {{ media_form.media_file.errors }} - {% comment %}{{ media_form.media_file.label_tag }}{{media_form.media_file}}{% endcomment %} -
- -
-
+ + {% include "chunked_uploads.html"%}
+
{{ media_form.external_src_url.errors }}{{ media_form.external_src_url.label_tag }}{{ media_form.external_src_url }}
+
{{ media_form.src.errors }}{{ media_form.src.label_tag }}{{ media_form.src }}
@@ -132,7 +159,6 @@ {% endif %} {% include "ldt/ldt_utils/partial/picture.html"%} {% include "ldt/ldt_utils/partial/permissions.html" %} -
@@ -149,4 +175,8 @@
+ + + + {% endblock %} diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_iframe.html Sat May 11 23:09:05 2013 +0200 @@ -70,7 +70,7 @@ }, {% endif %} height: '{{ player_height }}', - autostart: true + autostart: {% if autostart %} true {% else %} false {% endif %} } {% if polemic == 'all' or polemic == 'tweet' %}, { type: "Polemic", diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/embed_popup.html Sat May 11 23:09:05 2013 +0200 @@ -59,16 +59,16 @@ {% block content %}
-

{% trans 'Share the project' %} : {{ project.title }}

-

{% trans "List of the project's contents" %}:
-

    - {% for c in contents %} -
  • {{ c.title }} - {% trans 'Link to the Metadata Player' %} : {% trans 'See' %} - {% trans 'Select' %} :
  • - {% endfor %} -
-

-
{% trans 'project id' %} ({% trans 'Select' %}) :
-
{% trans 'The project in Lignes de Temps' %} : {% trans 'See' %} - {% trans 'Select' %} :
+

{% trans 'Share the project' %} : {{ project.title }}

+

{% trans "List of the project's contents" %}:
+

    + {% for c in contents %} +
  • {{ c.title }} - {% trans 'Link to the Metadata Player' %} : {% trans 'See' %} - {% trans 'Select' %} :
  • + {% endfor %} +
+

+
{% trans 'project id' %} ({% trans 'Select' %}) :
+
{% trans 'The project in Lignes de Temps' %} : {% trans 'See' %} - {% trans 'Select' %} :

@@ -84,7 +84,6 @@
-
@@ -124,6 +123,9 @@ {% trans 'Create your own configuration' %}
+ + Autostart +
CreateAnnotation @@ -228,7 +230,7 @@
- {% trans 'Show Player' %} + {% trans 'Show Player' %}
{% endblock %} - {% analytics %} + {% analytics %} \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/embed_player.html diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/projectslist.html Sat May 11 23:09:05 2013 +0200 @@ -21,20 +21,27 @@ {% url ldt.ldt_utils.views.json.project_json_id project.ldt_id as json_url_id %} {% if is_gecko %} {% else %} {% endif %} @@ -50,9 +57,9 @@ {% ifequal project.state 2 %} - {% trans 'Project published, click to unpublish' %}
+ {% trans 'Project published, click to unpublish' %}
{% else %} - {% trans 'Project not published, click to publish' %} + {% trans 'Project not published, click to publish' %} {% endifequal %} {% thumbnail project.image "50x50" crop="center" format="PNG" as im %}{% empty %} {% endthumbnail %} @@ -60,7 +67,7 @@ {% if project.state == 2 %} {% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }} {% else %} - {% if project.change %} + {% if project.change or project.owner == user %} {% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }} {% else %} {% if show_username %}{{ project.owner.username }} : {% endif %}{{ project.title }} diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html --- a/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/templates/ldt/ldt_utils/partial/publishedprojectslist.html Sat May 11 23:09:05 2013 +0200 @@ -29,7 +29,8 @@ {% trans 'link json by id' %} - + + {% trans 'Project published' %} diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/tests/content_tests.py --- a/src/ldt/ldt/ldt_utils/tests/content_tests.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/tests/content_tests.py Sat May 11 23:09:05 2013 +0200 @@ -5,19 +5,13 @@ Replace these with more appropriate tests for your application. """ -from ldt.test.testcases import OAuthWebTestCase, TestCase from django.conf import settings -from django.test import TestCase -from ldt.ldt_utils.models import User, Project, Content, Media -from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt +from django.utils._os import WindowsError +from ldt.ldt_utils.models import User, Content, Media from ldt.test.client import Client -import lxml.etree -import tempfile -import unittest -import uuid +from ldt.test.testcases import TestCase import logging import os -import exceptions class ContentTest(TestCase): @@ -27,7 +21,7 @@ self.client = Client() User.objects.create_superuser('blop', 'blop@blop.com', 'blop') - client = self.client.login(username='blop', password='blop') + _ = self.client.login(username='blop', password='blop') self.user = User() self.user.username = 'blop' diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/tests/ldt_tests.py --- a/src/ldt/ldt/ldt_utils/tests/ldt_tests.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/tests/ldt_tests.py Sat May 11 23:09:05 2013 +0200 @@ -5,17 +5,15 @@ Replace these with more appropriate tests for your application. """ -from ldt.test.testcases import OAuthWebTestCase, TestCase -from django.conf import settings -from django.test import TestCase -from ldt.ldt_utils.models import User, Project, Content, Media -from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt +from ldt.ldt_utils.models import User, Project, Content +from ldt.ldt_utils.utils import (LdtUtils, LdtAnnotation, create_ldt, + create_empty_iri, copy_ldt) from ldt.test.client import Client +from ldt.test.testcases import TestCase +import base64 import lxml.etree import tempfile -import unittest import uuid -import logging class UtilsTest(TestCase): @@ -25,7 +23,7 @@ self.client = Client() User.objects.create_superuser('blop', 'blop@blop.com', 'blop') - client = self.client.login(username='blop', password='blop') + _ = self.client.login(username='blop', password='blop') self.user = User() self.user.username = 'blop' @@ -77,11 +75,14 @@ self.cont4.iri_id = "id4" self.cont4.save() + search='' + field='all' + query = base64.urlsafe_b64encode(search.encode('utf8')) + self.project.contents.add(self.cont3, self.cont4) - ldoc = self.LU.generate_init([], 'ldt.ldt_utils.views.search_ldt') + ldoc = self.LU.generate_init([field, query], 'ldt.ldt_utils.views.lignesdetemps.search_ldt', 'ldt.ldt_utils.views.lignesdetemps.search_segments') self.assertEqual(ldoc.xpath("/iri/files/init")[0].tag, "init") - self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library") - + self.assertEqual(ldoc.xpath("/iri/files/library")[0].tag, "library") def test_create_ldt(self): self.cont5 = Content(iriurl="id5/iriurl5", duration=111) self.cont5.iri_id = "id5" @@ -97,7 +98,7 @@ ldt = lxml.etree.fromstring(self.project.ldt_encoded) self.assertEqual(ldt.xpath("/iri")[0].tag, "iri") self.assertEqual(ldt.xpath("/iri/project")[0].get("title"), self.project.title) - self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.iri_url()) + self.assertEqual(ldt.xpath("/iri/medias/media")[0].get("src"), self.cont5.relative_iri_url()) self.assertEqual(ldt.xpath("/iri/medias/media")[1].get("id"), self.cont6.iri_id) def test_copy_ldt(self): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/tests/media_tests.py --- a/src/ldt/ldt/ldt_utils/tests/media_tests.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/tests/media_tests.py Sat May 11 23:09:05 2013 +0200 @@ -5,18 +5,9 @@ Replace these with more appropriate tests for your application. """ -from ldt.test.testcases import OAuthWebTestCase, TestCase -from django.conf import settings -from django.test import TestCase -from ldt.ldt_utils.models import User, Project, Content, Media -from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt +from ldt.ldt_utils.models import User, Media from ldt.test.client import Client -from django.core.exceptions import ObjectDoesNotExist -import lxml.etree -import tempfile -import unittest -import uuid -import logging +from ldt.test.testcases import TestCase class MediaTest(TestCase): @@ -26,13 +17,13 @@ self.client = Client() User.objects.create_superuser('blop', 'blop@blop.com', 'blop') - client = self.client.login(username='blop', password='blop') + _ = self.client.login(username='blop', password='blop') self.user = User() self.user.username = 'blop' def test_create_media(self): - self.media1, created = Media.objects.get_or_create(src = "http://www.youtube.com/watch?v=O2G-PEtyKSY") + self.media1, _ = Media.objects.get_or_create(src = "http://www.youtube.com/watch?v=O2G-PEtyKSY") self.media1.id = 1 self.media1.save() diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/tests/project_tests.py --- a/src/ldt/ldt/ldt_utils/tests/project_tests.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/tests/project_tests.py Sat May 11 23:09:05 2013 +0200 @@ -5,17 +5,14 @@ Replace these with more appropriate tests for your application. """ -from ldt.test.testcases import OAuthWebTestCase, TestCase -from django.conf import settings -from django.test import TestCase -from ldt.ldt_utils.models import User, Project, Content, Media -from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt +from django.core.management import call_command +from ldt.ldt_utils.models import User, Project, Content +from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt from ldt.test.client import Client +from ldt.test.testcases import TestCase import lxml.etree -import tempfile -import unittest import uuid -import logging + class ProjectTest(TestCase): @@ -25,14 +22,29 @@ self.client = Client() User.objects.create_superuser('blop', 'blop@blop.com', 'blop') - client = self.client.login(username='blop', password='blop') - + _ = self.client.login(username='blop', password='blop') self.user = User() self.user.username = 'blop' + self.LU = LdtUtils() + self.project = Project(title="titleproj1", owner=self.user) + self.project.ldt = ' CA: prof et admin <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe Reprise de la figure precedente TC: prof et admin Conseil de classe conseil de classe Reprise de la figure precedente Bout a bout 1 ' + self.project.id = "11321" + self.project.ldt_id = str(uuid.uuid1()) + self.project.description = "proj1description" + self.project.save() - def test_create_project(self): + def test_create_project(self): + self.cont1 = Content(iriurl="cont1_id/iriurl1", duration=123) + self.cont1.iri_id = "cont1_id" + self.cont1.save() + + self.cont2 = Content(iriurl="cont2_id/iriurl2", duration=100) + self.cont2.iri_id = "cont2_id" + self.cont2.save() + self.project2 = Project(title="titleproj2", owner=self.user) - self.project2.ldt = ' CA: prof et admin <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe Reprise de la figure precedente TC: prof et admin Conseil de classe conseil de classe Reprise de la figure precedente Bout a bout 1 ' + + self.project2.ldt = self.LU.generate_ldt(Content.objects.all()) self.project2.ldt_id = str(uuid.uuid1()) self.project2.description = "proj2description" self.project2.save() @@ -41,8 +53,12 @@ #test deletion of project without annotation def test_del_project_v1(self): + self.cont3 = Content(iriurl="cont3_id/iriurl3", duration=100) + self.cont3.iri_id = "cont3_id" + self.cont3.save() + self.project3 = Project(title="titleproj3", owner=self.user) - self.project3.ldt = ' CA: prof et admin <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe Reprise de la figure precedente TC: prof et admin Conseil de classe conseil de classe Reprise de la figure precedente Bout a bout 1 ' + self.project3.ldt = self.LU.generate_ldt(Content.objects.all()) self.project3.id = "333" self.project3.ldt_id = str(uuid.uuid1()) self.project3.description = "proj3description" @@ -55,9 +71,12 @@ #test deletion of project with annotations def test_del_project_v2(self): + self.cont4 = Content(iriurl="cont4_id/iriurl4", duration=100) + self.cont4.iri_id = "cont4_id" + self.cont4.save() - self.project4 = Project(title="titleproj3", owner=self.user) - self.project4.ldt = ' CA: prof et admin <abstract/> <audio source=""/> <tags/> </element> <element id="s_0050F043-3AD2-0A7C-6699-D2A03A1EBA02" begin="5052858" dur="124407" author="" date="2010/09/02" color="10053375" src=""> <title>conseil de classe Reprise de la figure precedente TC: prof et admin Conseil de classe conseil de classe Reprise de la figure precedente Bout a bout 1 ' + self.project4 = Project(title="titleproj4", owner=self.user) + self.project4.ldt=self.LU.generate_ldt(Content.objects.all()) self.project4.id = "444" self.project4.ldt_id = str(uuid.uuid1()) self.project4.description = "proj4description" @@ -74,4 +93,76 @@ self.project4.delete() with self.assertRaises(Project.DoesNotExist): - Project.objects.get(ldt_id=self.project4.ldt_id) \ No newline at end of file + Project.objects.get(ldt_id=self.project4.ldt_id) + + def test_clean_database_project(self) : + self.cont5 = Content(iriurl="cont5_id/iriurl5", duration=123) + self.cont5.iri_id = "cont5_id" + self.cont5.save() + + self.cont6 = Content(iriurl="cont6_id/iriurl6", duration=100) + self.cont6.iri_id = "cont6_id" + self.cont6.save() + + self.cont7 = Content(iriurl="cont7_id/iriurl7", duration=100) + self.cont7.iri_id = "cont7_id" + self.cont7.save() + + self.project.contents.add(self.cont5, self.cont6) + + doc = self.LU.generate_ldt(Content.objects.all()) + + #project5 : valid project + self.project5 = Project(title="titleproj5", owner=self.user) + ldt = lxml.etree.tostring(doc, pretty_print = False) + self.project5.ldt = ldt + self.project5.id = "555" + self.project5.ldt_id = str(uuid.uuid1()) + self.project5.description = "proj5description" + self.project5.save() + + #project6 : project with empty ldt + self.project6 = Project(title="titleproj5", owner=self.user) + self.project6.id = "666" + self.project6.ldt_id = str(uuid.uuid1()) + self.project6.description = "proj6description" + self.project6.save() + + #project7 : project with a non-existing media + + self.project7 = Project(title="titleproj7", owner=self.user) + self.project7.id = "777" + self.project7.ldt_id = str(uuid.uuid1()) + self.project7.ldt = '' + self.project7.description = "proj7description" + self.project7.save() + + #project8 : project with multiple medias some valid and some that don't exist + self.project8 = Project(title="titleproj8", owner=self.user) + self.project8.id = "888" + self.project8.ldt_id = str(uuid.uuid1()) + self.project8.ldt = '' + self.project8.description = "proj8description" + self.project8.save() + + #project9 : project without any media + self.project9 = Project(title="titleproj9", owner=self.user) + self.project9.id = "999" + self.project9.ldt_id = str(uuid.uuid1()) + self.project9.ldt = '' + self.project9.description = "proj9description" + self.project9.save() + + call_command('set_projectldtiri') + + with self.assertRaises(Project.DoesNotExist): + Project.objects.get(ldt_id=self.project6.ldt_id) + + with self.assertRaises(Project.DoesNotExist): + Project.objects.get(ldt_id=self.project7.ldt_id) + + with self.assertRaises(Project.DoesNotExist): + Project.objects.get(ldt_id=self.project9.ldt_id) + + self.assertEqual(ldt, self.project5.ldt) + \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/tests/view_tests.py --- a/src/ldt/ldt/ldt_utils/tests/view_tests.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/tests/view_tests.py Sat May 11 23:09:05 2013 +0200 @@ -5,17 +5,8 @@ Replace these with more appropriate tests for your application. """ -from ldt.test.testcases import OAuthWebTestCase, TestCase -from django.conf import settings -from django.test import TestCase -from ldt.ldt_utils.models import User, Project, Content, Media -from ldt.ldt_utils.utils import LdtUtils, LdtAnnotation, create_ldt, create_empty_iri, copy_ldt -from ldt.test.client import Client -import lxml.etree -import tempfile +from ldt.ldt_utils.models import Project, Content import unittest -import uuid -import logging class ViewsTest(unittest.TestCase): def setUp(self): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/urls.py --- a/src/ldt/ldt/ldt_utils/urls.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/urls.py Sat May 11 23:09:05 2013 +0200 @@ -1,4 +1,4 @@ -from django.conf.urls.defaults import patterns, url +from django.conf.urls.defaults import patterns, url, include from ldt.management import test_ldt # Uncomment the next two lines to enable the admin: @@ -28,11 +28,11 @@ url(r'^cljson/idcutting/(?P.*)/(?P.*)$', 'views.json.project_json_cutting_id'), url(r'^rdf/id/(?P.*)$', 'views.rdf.project_annotations_rdf'), url(r'^workspace/?$', "views.workspace.home", name="root-view"), - url(r'^filterprojects/_(?P[\w\%\_\-\+]*?)/(?Ptrue|false)/(?P\d)$', "views.project.projects_filter",), - url(r'^filterprojects/_(?P[\w\%\_\-\+]*?)/(?Ptrue|false)/(?P\d)/(?P.*)$', "views.project.projects_filter",), - url(r'^filtercontents/_(?P[\w\%\_\-\+]*?)/$', "views.content.contents_filter",), - url(r'^filtergroups/_(?P[\w\%\_\-\+]*?)/$', "views.group.groups_filter",), - url(r'filtershare/_(?P[\w\%\_\-\+]*?)/(?Ptrue|false)$', "views.workspace.share_filter"), + url(r'^filterprojects/_(?P[\w \%\_\-\+]*?)/(?Ptrue|false)/(?P\d)$', "views.project.projects_filter",), + url(r'^filterprojects/_(?P[\w \%\_\-\+]*?)/(?Ptrue|false)/(?P\d)/(?P.*)$', "views.project.projects_filter",), + url(r'^filtercontents/_(?P[\w \%\_\-\+]*?)/$', "views.content.contents_filter",), + url(r'^filtergroups/_(?P[\w \%\_\-\+]*?)/$', "views.group.groups_filter",), + url(r'filtershare/_(?P[\w \%\_\-\+]*?)/(?Ptrue|false)$', "views.workspace.share_filter"), url(r'^embedpopup/?$', "views.workspace.popup_embed"), url(r'^embediframe/?$', "views.workspace.iframe_embed", name="embediframe_page"), url(r'^embedldt/(?P.*)$', 'views.lignesdetemps.embed_ldt', name='embed_ldt'), @@ -78,5 +78,5 @@ url(r'^space/upload/$', 'views.content.upload'), url(r'^space/removetempfile/$', 'views.content.remove_temp_file'), url(r'^space/getduration/$', 'views.content.get_duration'), - + url(r'^chunked_uploads/', include('chunked_uploads.urls')), ) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/utils.py --- a/src/ldt/ldt/ldt_utils/utils.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/utils.py Sat May 11 23:09:05 2013 +0200 @@ -8,7 +8,6 @@ import uuid from ldt.utils.url import request_with_auth from ldt.utils.url import absurl_norequest -import logging __BOOLEAN_DICT = { 'false':False, @@ -58,7 +57,7 @@ videopath = unicode(content.videopath) media = lxml.etree.SubElement(medias, "media") media.set(u"id", content.iri_id) - media.set(u"src", content.iri_url(web_url)) + media.set(u"src", content.relative_iri_url()) media.set(u"video", videopath) media.set(u"pict", u"") media.set(u"extra", u"") @@ -277,12 +276,12 @@ tag_node = lxml.etree.SubElement(tags, 'tag') tag_node.text = tag - return cutting_id, id_annotation + return cutting_id, id_annotation, ensemble_id - def save(self): + def save(self, must_reindex=True): if self.to_add: self.project.ldt = lxml.etree.tostring(self.ldtdoc, pretty_print=True) - self.project.save() + self.project.save(must_reindex=must_reindex) def get_polemic_syntax(self, text): polemics = [] @@ -322,7 +321,7 @@ idsel = content.iri_id elementMedia = lxml.etree.SubElement(elementMedias, 'media') elementMedia.set('id', content.iri_id) - elementMedia.set('src', content.iri_url()) + elementMedia.set('src', content.relative_iri_url()) if content.videopath != None : elementMedia.set('video', content.videopath) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/content.py --- a/src/ldt/ldt/ldt_utils/views/content.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/content.py Sat May 11 23:09:05 2013 +0200 @@ -123,7 +123,6 @@ except Exception as inst: - logging.debug("write_content_base : POST error when processing file:" + str(inst)) #@UndefinedVariable form_status = "error" #set error for form if media_input_type == "url": @@ -171,9 +170,8 @@ @transaction.commit_manually def write_content_base(request, iri_id=None): if iri_id: - instance_content = Content.safe_objects.get(iri_id=iri_id) #@UndefinedVariable + instance_content = Content.safe_objects.select_related('media_obj','front_project').get(iri_id=iri_id) #@UndefinedVariable instance_media = instance_content.media_obj - logging.debug("write_content_base : valid form: for instance : media -> " + repr(instance_media) + " content : for instance : " + repr(instance_content)) #@UndefinedVariable else: logging.debug("No iri_id") #@UndefinedVariable instance_content = None @@ -234,7 +232,6 @@ picture_form.cleaned_data["image"]=File(img_temp) except Exception as inst: logging.debug("couldn't download video thumbnail from image_link : " + str(image_link)) - logging.debug("write_content_base : valid form: for instance : " + repr(instance_media) + " -> media " + str(media_valid) + " content : for instance : " + repr(instance_content) + " : " + str(content_valid) + "picture : valid :" +str(picture_valid)) #@UndefinedVariable if media_valid and content_valid and picture_valid: @@ -297,7 +294,7 @@ except Exception, e: transaction.rollback() __, value, traceback = sys.exc_info() - return False, False, False, False, False, e, traceback + return False, False, False, False, False, False, e, traceback else: form_status = 'empty' @@ -326,9 +323,9 @@ except Exception, e: transaction.rollback() __, __, traceback = sys.exc_info() - return False, False, False, False, False, e, traceback + return False, False, False, False, False, False, e, traceback - return content_form, media_form, picture_form, form_status, current_front_project, "", "" + return content_form, media_form, picture_form, form_status, instance_content, current_front_project, "", "" @login_required def write_content(request, iri_id=None): @@ -370,7 +367,7 @@ return render_to_response('ldt/ldt_utils/reset_confirm.html', {'errors':errors, 'message':message, 'title': title}, context_instance=RequestContext(request)) elif submit_action == "reset": #TODO : verifier index de la recherche maj - content = Content.objects.get(iri_id=iri_id) + content = Content.objects.get(iri_id=iri_id).select_related('front_project') project_temp = content.front_project content.create_front_project() content.save() @@ -379,9 +376,9 @@ elif submit_action=="close": return redirect("root-view") else: - content_form, media_form, picture_form, form_status, current_front_project, e, traceback = write_content_base(request, iri_id) + content_form, media_form, picture_form, form_status, content_temp, current_front_project, e, traceback = write_content_base(request, iri_id) if iri_id: - content_temp = Content.objects.get(iri_id=iri_id) + #content_temp = Content.objects.select_related('media_obj').get(iri_id=iri_id) media_temp = content_temp.media_obj if media_temp: member_list, admin_list = get_userlist_model(media_temp, request.user) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/front.py --- a/src/ldt/ldt/ldt_utils/views/front.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/front.py Sat May 11 23:09:05 2013 +0200 @@ -3,6 +3,7 @@ from django.contrib.auth.models import Group, User from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.urlresolvers import reverse +from django.db.models import Count from django.shortcuts import render_to_response from django.template import RequestContext from ldt.ldt_utils.models import Content, Project @@ -13,23 +14,24 @@ from tagging.models import TaggedItem from ldt.utils.url import absstatic +import logging +logger = logging.getLogger(__name__) def front_home(request): # Get the 3 last annotated contents - last_contents = Content.safe_objects.order_by('-stat_annotation__last_annotated').exclude(stat_annotation__nb_annotations=0)[:3] + last_contents = Content.safe_objects.order_by('-stat_annotation__last_annotated').select_related('stat_annotation').exclude(stat_annotation__nb_annotations=0)[:3] # Get the most annotated contents - most_contents = Content.safe_objects.order_by('-stat_annotation__nb_annotations')[:8] + most_contents = Content.safe_objects.order_by('-stat_annotation__nb_annotations').select_related('stat_annotation')[:8] # Get the active groups - active_groups = Group.objects.exclude(name=settings.PUBLIC_GROUP_NAME)[:5] + active_groups = Group.objects.select_related("profile").annotate(nb_users=Count("user")).exclude(name=settings.PUBLIC_GROUP_NAME)[:5] # Get the main tag list front_tags = settings.FRONT_TAG_LIST # Get the all tags list tag_cloud = get_content_tags() - is_gecko = ((request.META['HTTP_USER_AGENT'].lower().find("firefox")) > -1); - + return render_to_response("front/front_home.html", {'last_contents': last_contents, 'most_contents':most_contents, 'active_groups':active_groups, 'front_tags':front_tags, 'tag_cloud': tag_cloud, 'is_gecko': is_gecko}, @@ -48,9 +50,10 @@ 'is_gecko': is_gecko}, context_instance=RequestContext(request)) - @login_required def group_info(request, group_id): + + # Get the active group group = Group.objects.select_related("profile").get(id=group_id) proj_title = request.GET.get("title") # Get the projects for this group @@ -70,7 +73,7 @@ results = paginator.page(page) except (EmptyPage, InvalidPage): results = paginator.page(paginator.num_pages) - + # Group's users users = User.objects.filter(groups__in=[group]).exclude(is_superuser=True) @@ -94,11 +97,11 @@ tag_label = request.GET.get("tag") # Get all the public contents group if tag_label is None : - content_list = Content.safe_objects.all() + content_list = Content.safe_objects.all().select_related('stat_annotation') else : - content_list = TaggedItem.objects.get_by_model(Content.safe_objects.all(), '"'+tag_label+'"') + content_list = TaggedItem.objects.get_by_model(Content.safe_objects.all().select_related('stat_annotation'), '"'+tag_label+'"') else : - content_list = Content.safe_objects.filter(title__icontains=media_title) + content_list = Content.safe_objects.filter(title__icontains=media_title).select_related('stat_annotation') nb = settings.LDT_FRONT_MEDIA_PER_PAGE @@ -187,7 +190,6 @@ content_list = TaggedItem.objects.get_by_model(Content.objects.all(), '"'+content_tag+'"') results, nb, nb_segment = get_search_results(request, search, field, page, content_list) - return render_to_response('front/front_search_results.html', {'results': results, 'nb_results' : nb, 'nb_segment':nb_segment, 'search' : search, 'field': field, 'tag_label':content_tag, 'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code, 'baseurl': baseurl}, context_instance=RequestContext(request)) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/group.py --- a/src/ldt/ldt/ldt_utils/views/group.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/group.py Sat May 11 23:09:05 2013 +0200 @@ -13,8 +13,7 @@ @login_required def get_group_projects_view(request): - - # Get group, user and project_list + grp_id = request.POST["id_group"] project_list = get_group_projects(request.user, grp_id) @@ -31,15 +30,15 @@ # Get group, user and project_list if grp_id == "-1": if exclude_owner: - project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).exclude(owner=user) + project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).exclude(owner=user).select_related("owner") else: - project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False) + project_list = get_objects_for_user(user, 'ldt_utils.view_project', use_groups=False).select_related("owner") else: grp = Group.objects.get(id=grp_id) if exclude_front: - project_list = get_objects_for_group(grp, 'ldt_utils.view_project').exclude(title__startswith='front') + project_list = get_objects_for_group(grp, 'ldt_utils.view_project').exclude(title__startswith='front').select_related("owner") else: - project_list = get_objects_for_group(grp, 'ldt_utils.view_project') + project_list = get_objects_for_group(grp, 'ldt_utils.view_project').select_related("owner") project_list = add_change_attr(user, project_list) return project_list diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/json.py --- a/src/ldt/ldt/ldt_utils/views/json.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/json.py Sat May 11 23:09:05 2013 +0200 @@ -14,6 +14,8 @@ import lxml.etree import logging +logger = logging.getLogger(__name__) + def project_json_id(request, id): @@ -96,7 +98,6 @@ # do we remove annotations from mashup if the have duration=0 ? (yes by default) remove_zero_dur_str = request.REQUEST.get("removezeroduration") remove_zero_dur = True - logging.debug("CC 1 " + str(remove_zero_dur)) if remove_zero_dur_str: remove_zero_dur = {'true': True, 'false': False, "0": False, "1": True}.get(remove_zero_dur_str.lower()) @@ -106,14 +107,23 @@ if s: # We get the projects with all the segments project_xml, results = search_generate_ldt(request, "tags", s, False) + + logger.debug("mashup_by_tag : search_generate_ldt done") + project = Project() project.ldt = lxml.etree.tostring(project_xml, pretty_print=True) # Needed datas for jsonification now = datetime.now() project.modification_date = project.creation_date = now #return HttpResponse(lxml.etree.tostring(project_xml, pretty_print=True), mimetype="text/xml;charset=utf-8") + logger.debug("mashup_by_tag : serialize_to_cinelab prepare") + ps = ProjectJsonSerializer(project, from_contents=False) + logger.debug("mashup_by_tag : serialize_to_cinelab serializer ready") mashup_dict = ps.serialize_to_cinelab() + + logger.debug("mashup_by_tag : serialize_to_cinelab done") + # Now we build the mashup with the good segments (the ones between in and out) if results: tc_in = 0 @@ -178,6 +188,8 @@ cur_out = cur_in + dur if tc_in<=cur_in and cur_out<=tc_out and ((not remove_zero_dur) or (remove_zero_dur and dur>0.0)): mashup_list["items"].append(res["element_id"]) + if mashup_dict["lists"] is None: + mashup_dict["lists"] = [] mashup_dict["lists"].append(mashup_list) # If asked, we remove the annotations not used in the mashup. @@ -202,8 +214,6 @@ json_str = "%s(%s)" % (callback, json_str) resp = HttpResponse(mimetype="application/json; charset=utf-8") - resp['Cache-Control'] = 'no-cache, must-revalidate' - resp['Pragma'] = 'no-cache' resp.write(json_str) return resp diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/lignesdetemps.py --- a/src/ldt/ldt/ldt_utils/views/lignesdetemps.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/lignesdetemps.py Sat May 11 23:09:05 2013 +0200 @@ -4,21 +4,22 @@ from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext +from ldt.indexation import SimpleSearch from ldt.ldt_utils.models import Content, Project, Media +from ldt.ldt_utils.searchutils import search_generate_ldt +from ldt.ldt_utils.stat import update_stat_project from ldt.ldt_utils.utils import LdtUtils, clean_description -from ldt.indexation import SimpleSearch from ldt.security.permissionchecker import check_object_perm_for_user from ldt.security.utils import set_forbidden_stream -from ldt.ldt_utils.stat import update_stat_project -from ldt.ldt_utils.searchutils import search_generate_ldt +from ldt.utils.projectldt_parser import absolute_src_xml, relative_src_xml from ldt.utils.url import absstatic, absurl from ldt.utils.web_url_management import get_web_url import base64 +import logging import lxml.etree -import logging logger = logging.getLogger(__name__) - + def search_index_get(request, field, query): language_code = request.LANGUAGE_CODE[:2] @@ -44,6 +45,7 @@ resp = HttpResponse(mimetype="text/xml") doc, _ = search_generate_ldt(request, field, query) + doc = absolute_src_xml(doc) doc.write(resp, pretty_print=True) return resp @@ -101,7 +103,6 @@ ldtgen = LdtUtils() doc = ldtgen.generate_init([project_id, content_id, ensemble_id, cutting_id, segment_id], 'ldt.ldt_utils.views.lignesdetemps.ldt_segment', 'ldt.ldt_utils.views.lignesdetemps.highlight_segment') - return HttpResponse(lxml.etree.tostring(lxml.etree.ElementTree(doc), pretty_print=True), mimetype="text/xml;charset=utf-8") def highlight_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): @@ -131,6 +132,7 @@ if project_id and project_id != "_" : project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable ldtdoc = lxml.etree.fromstring(project.ldt_encoded) + ldtdoc = absolute_src_xml(ldtdoc) ldtdoc = set_forbidden_stream(ldtdoc, request.user) displays_node = ldtdoc.find("displays") if not displays_node: @@ -176,6 +178,7 @@ } doc = ldtgen.generate_ldt(content_list, "segment : ", author=username, startSegment=start_segment) + doc = absolute_src_xml(doc) doc = set_forbidden_stream(doc, request.user) doc.write(resp, pretty_print=('DEBUG' in dir(settings) and settings.DEBUG)) @@ -184,7 +187,7 @@ @login_required def index_project(request, id, full=False): - + urlStr = absurl(request, "ldt.ldt_utils.views.lignesdetemps.init", args=['ldt_project', id]) posturl = absurl(request, "ldt.ldt_utils.views.lignesdetemps.save_ldt_project") language_code = request.LANGUAGE_CODE[:2] @@ -212,13 +215,12 @@ else: template_path = 'ldt/ldt_utils/init_ldt.html' - return render_to_response(template_path, - {'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code, - 'baseurl': baseurl, 'url': urlStr, 'posturl': posturl, - 'id': id, 'readonly': readonly, 'audio_record_url': audio_record_url}, + return render_to_response(template_path, + {'colorurl': colorurl, 'i18nurl': i18nurl, 'language': language_code, + 'baseurl': baseurl, 'url': urlStr, 'posturl': posturl, + 'id': id, 'readonly': readonly}, context_instance=RequestContext(request)) - - + def embed_ldt(request, id): # Almost identical to index_project but without login_required and less parameters @@ -275,6 +277,7 @@ doc = lxml.etree.fromstring(project.ldt_encoded) doc = set_forbidden_stream(doc, request.user) + doc = absolute_src_xml(doc) resp.write(lxml.etree.tostring(doc, pretty_print=True, xml_declaration=True, encoding="utf-8")) return resp @@ -284,10 +287,12 @@ def save_ldt_project(request): if request.method == "POST": ldt = request.POST['ldt'] - id = request.POST['id'] - ldtproject = Project.safe_objects.select_related().get(ldt_id=id) #@UndefinedVariable - + ldt_id = request.POST['id'] + ldtproject = Project.safe_objects.select_related().get(ldt_id=ldt_id) #@UndefinedVariable + ldtxml=lxml.etree.fromstring(ldt) #save xml ldt + ldt, _, _ = relative_src_xml(ldtxml) + ldt = lxml.etree.tostring(ldt, pretty_print=True) ldtproject.ldt = ldt doc = lxml.etree.fromstring(ldtproject.ldt_encoded) @@ -300,11 +305,11 @@ new_contents = [] result = doc.xpath("/iri/medias/media") for medianode in result: - id = medianode.get("id") - new_contents.append(id) + media_id = medianode.get("id") + new_contents.append(media_id) #Put back the video fied from "forbidden_stream_url" to the video url if medianode.get("video") == settings.FORBIDDEN_STREAM_URL: - content = Content.objects.get(iri_id=id) + content = Content.objects.get(iri_id=media_id) media = Media.objects.get(id=content.media_obj.id) medianode.set('video', media.videopath) ldtproject.ldt = lxml.etree.tostring(doc, pretty_print=True) @@ -325,7 +330,7 @@ if c not in contents_id: content = Content.objects.get(iri_id=c) ldtproject.contents.add(content) - + update_stat_project(ldtproject) #remove html tags added by flash @@ -338,7 +343,7 @@ ldtproject.ldt = lxml.etree.tostring(doc, pretty_print=True) ldtproject.description = new_desc if new_desc else description - + #set a new icon for this project if check_icon_project: ldtproject.set_icon() @@ -349,7 +354,7 @@ ldt = '' new_contents = [] - return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request)) + return render_to_response('ldt/ldt_utils/save_done.html', {'ldt': ldt, 'id':ldt_id, 'title':ldtproject.title, 'contents': new_contents}, context_instance=RequestContext(request)) def index(request, url): @@ -372,6 +377,7 @@ ldtgen = LdtUtils() doc = ldtgen.generate_ldt(contentList, title=contentList[0].title, startSegment=startSegment) doc = set_forbidden_stream(doc, request.user) + doc = absolute_src_xml(doc) doc.write(resp, pretty_print=True) return resp diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/project.py --- a/src/ldt/ldt/ldt_utils/views/project.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/project.py Sat May 11 23:09:05 2013 +0200 @@ -235,21 +235,21 @@ if id_group > 0: # Search inside a group grp = Group.objects.get(id=id_group) project_list = get_objects_for_group(grp, 'ldt_utils.view_project').filter(query) + project_list = add_change_attr(request.user, project_list) elif id_group == -1:# Search inside projects shared with a specific user project_list = get_objects_for_user(request.user, 'ldt_utils.view_project', use_groups=False).exclude(owner=request.user) + project_list = add_change_attr(request.user, project_list) else: # We paginate in these cases : user's project or published if status==2: - project_list = Project.safe_objects.filter(query).exclude(title__startswith='front') + project_list = Project.safe_objects.filter(query).select_related("owner").exclude(title__startswith='front') else: - project_list = Project.safe_objects.filter(query) + project_list = Project.safe_objects.filter(query).select_related("owner") project_nb = float(project_list.count()) #@UndefinedVariable nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE)) project_list = project_list[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable show_username = False - project_list = add_change_attr(request.user, project_list) - if status == 2: url_templ = "ldt/ldt_utils/partial/publishedprojectslist.html" else: @@ -281,7 +281,8 @@ def get_projects_page(num_page, user): project_nb = float(Project.safe_objects.filter(owner=user).count()) #@UndefinedVariable nb_pj_pages = int(math.ceil(project_nb / settings.LDT_MAX_PROJECTS_PER_PAGE)) - project_list = add_change_attr(user, Project.safe_objects.filter(owner=user)[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)]) #@UndefinedVariable + # add_change_attr is not useful because user and project's owner are the same + project_list = Project.safe_objects.filter(owner=user).select_related("owner")[(num_page*settings.LDT_MAX_PROJECTS_PER_PAGE):((num_page+1)*settings.LDT_MAX_PROJECTS_PER_PAGE)] #@UndefinedVariable return project_nb, nb_pj_pages, project_list diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/ldt_utils/views/workspace.py --- a/src/ldt/ldt/ldt_utils/views/workspace.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/ldt_utils/views/workspace.py Sat May 11 23:09:05 2013 +0200 @@ -3,7 +3,9 @@ from django.contrib.auth.models import Group from django.core.paginator import Paginator, InvalidPage, EmptyPage from django.core.urlresolvers import reverse #, resolve -from django.http import HttpResponseForbidden, HttpResponseNotFound, HttpResponseRedirect +from django.db import transaction +from django.http import (HttpResponseForbidden, HttpResponseNotFound, + HttpResponseRedirect) from django.shortcuts import render_to_response from django.template import RequestContext from django.template.loader import render_to_string @@ -12,13 +14,14 @@ from django.utils.translation import ugettext as _ from itertools import groupby from ldt.indexation import get_results_with_context, highlight_documents +from ldt.ldt_utils import contentindexer from ldt.ldt_utils.forms import SearchForm from ldt.ldt_utils.models import Content, Project, Segment from ldt.ldt_utils.projectserializer import ProjectJsonSerializer from ldt.ldt_utils.utils import boolean_convert from ldt.ldt_utils.views.content import get_contents_page, get_content_tags -from ldt.ldt_utils.views.project import get_projects_page, \ - get_published_projects_page +from ldt.ldt_utils.views.project import (get_projects_page, + get_published_projects_page) from ldt.security.utils import add_change_attr, get_userlist from ldt.utils.url import absstatic, absurl from ldt.utils.web_url_management import get_web_url @@ -160,7 +163,10 @@ else: rend_dict["polemic_qColor"] = "036aae" - + if request.GET.has_key("autostart"): + rend_dict["autostart"] = {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("autostart").lower()) + else : + rend_dict["autostart"] = True if request.GET.has_key("createannotation"): rend_dict["createannotation"] = {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("createannotation").lower()) if request.GET.has_key("show_mic_record"): @@ -242,7 +248,7 @@ LANGUAGE_CODE = settings.LANGUAGE_CODE ps = ProjectJsonSerializer(project, from_contents=True, from_display=True) annotations = ps.get_annotations(first_cutting=True) - rend_dict = {'project':project, 'contents':project_contents, 'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode, + rend_dict = {'project':project, 'contents':project_contents, 'json_url':json_url, 'player_id':player_id, 'annotations':annotations, 'ldt_id': ldt_id, 'stream_mode': stream_mode, 'external_url': external_url, 'polemic':False, 'show_mic_record':False, 'annotations_list':False, 'iframe_url':iframe_url, 'WEB_URL':WEB_URL, 'LANGUAGE_CODE':LANGUAGE_CODE} @@ -278,6 +284,7 @@ def search_index(request): language_code = request.LANGUAGE_CODE[:2] nb = 0 + nb_segment=0 results = [] search = '' field = 'all' @@ -313,25 +320,26 @@ results = get_results_with_context(field, search, content_list) all_segments = Segment.objects.filter(element_id__in=[e['element_id'] for e in results]) all_projects = Project.objects.filter(ldt_id__in=[e['project_id'] for e in results], state=2) - all_contents = Content.objects.filter(iri_id__in=[e['iri_id'] for e in results]) + all_contents = Content.objects.filter(iri_id__in=[e['iri_id'] for e in results]).select_related('stat_annotation') viewable_projects_id = [p.ldt_id for p in all_projects] nb_segment=0 complete_results = [] results.sort(key=lambda k: k['iri_id']) for iri_id, item in groupby(results, itemgetter('iri_id')): - content=[] + content=None content_filter = filter(lambda e: e.iri_id == iri_id, all_contents) if len(content_filter)>0: - content = filter(lambda e: e.iri_id == iri_id, all_contents)[0] + content = content_filter[0] if content.description is None: content.description = '' - + if content is None: + continue all_related_segments = list(item) valid_segments = [] for s in all_related_segments: - array_of_segs = [seg for seg in all_segments if seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id'] ] + array_of_segs = [seg for seg in all_segments if (seg.element_id == s['element_id'] and seg.project_id == s['project_id'] and seg.iri_id == s['iri_id'] and seg.cutting_id == s['cutting_id'] and seg.ensemble_id == s['ensemble_id']) ] if len(array_of_segs)>0: segment = array_of_segs[0] @@ -379,6 +387,7 @@ return render_to_response('ldt/ldt_utils/loading.html', context_instance=RequestContext(request)) +@transaction.commit_on_success def delete_segment(request, project_id, content_id, ensemble_id, cutting_id, segment_id): if project_id and project_id != "_" : project = Project.safe_objects.get(ldt_id=project_id) #@UndefinedVariable @@ -395,7 +404,9 @@ el = element[0] el.getparent().remove(el) project.ldt = lxml.etree.tostring(ldtdoc) - project.save() + project.save(must_reindex=False) + contentindexer.delete_segment(project, project_id, content_id, ensemble_id, cutting_id, segment_id) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) else: return HttpResponseNotFound(_("Annotation not found")) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/locale/fr/LC_MESSAGES/django.mo diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/locale/fr/LC_MESSAGES/django.po diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/management/commands/initsitedomain.py --- a/src/ldt/ldt/management/commands/initsitedomain.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/management/commands/initsitedomain.py Sat May 11 23:09:05 2013 +0200 @@ -1,8 +1,5 @@ from django.core.management.base import BaseCommand -from ldt.ldt_utils.models import Content, Project -from ldt.ldt_utils.contentindexer import ContentIndexer, ProjectIndexer from django.conf import settings -from django.db import models from django.contrib.sites.models import Site class Command(BaseCommand): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/management/commands/reindex.py diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/management/commands/setprojectldtiri.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/management/commands/setprojectldtiri.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,33 @@ +from django.core.management.base import BaseCommand +from ldt.ldt_utils.models import Project +from ldt.utils.projectldt_parser import relative_src_xml +import lxml.etree +from ..utils import show_progress + +class Command(BaseCommand): + help = 'set the .iri src in relative url' + + def handle(self, *args, **options): + + writer = None + + project_list = list(Project.objects.all()) + + for i,p in enumerate(project_list): #we check all the project in the database + + writer = show_progress(i+1, len(project_list), "Processing project %s" % p.title, 80, writer) + no_more_media = False + modif = False + try : + iri = lxml.etree.fromstring(p.ldt) + except : + iri = None + p.delete() + if iri is not None : + new_ldt, modif, no_more_media = relative_src_xml(iri) + if modif and not no_more_media: + new_ldt = lxml.etree.tostring(new_ldt, pretty_print=True) + p.ldt= new_ldt #we write the the new xml + p.save(must_reindex=False) + if no_more_media : + p.delete() \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/management/commands/synciri.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/management/commands/synciri.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +''' +Created on Jan 22, 2013 + +@author: ymh +''' + +from django.core.management.base import NoArgsCommand +from ..utils import show_progress +from ldt.ldt_utils.models import Content + +class Command(NoArgsCommand): + + def handle_noargs(self, **options): + + content_list = list(Content.objects.all()) + writer = None + for i,c in enumerate(content_list): + writer = show_progress(i+1, len(content_list), "Processing content %s" % c.title, 80, writer) + c.sync_iri_file() + \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/security/__init__.py --- a/src/ldt/ldt/security/__init__.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/security/__init__.py Sat May 11 23:09:05 2013 +0200 @@ -1,7 +1,7 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.contrib.auth.models import User -from django.core.signals import request_started +from django.core.signals import request_started from ldt.security.permissionchecker import check_object_perm_for_user try: @@ -98,7 +98,7 @@ # use our check_object_perm_for_user instead of not optimized guardian has_perm if self.pk and not check_object_perm_for_user(self, 'change_%s' % cls_name, user): raise AttributeError('User %s is not allowed to change object %s' % (user, self)) - + return func(self, *args, **kwargs) return wrapped return wrapper diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/security/permissionchecker.py diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/security/utils.py --- a/src/ldt/ldt/security/utils.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/security/utils.py Sat May 11 23:09:05 2013 +0200 @@ -5,6 +5,7 @@ from cache import get_cached_userlist, cached_assign from ldt.security import change_security import types + def unprotect_instance(instance): if hasattr(instance, 'old_save'): @@ -27,24 +28,28 @@ cls = ContentType.objects.get(model='content') cls = cls.model_class() + m_cls = ContentType.objects.get(model='media') + m_cls = m_cls.model_class() + + content_ids = xml.xpath('/iri/medias/media/@id') + contents = dict( [(c.iri_id, c) for c in cls.safe_objects.filter(iri_id__in=content_ids).select_related("media_obj")]) + + medias = dict([(m.id,m) for m in m_cls.safe_objects.filter(id__in=[c.media_obj.id for c in contents.values()])]) + for elem in xml.xpath('/iri/medias/media'): - content = cls.safe_objects.filter(iri_id=elem.get('id')) - if content and use_forbidden_url(content[0]) : + content = contents.get(elem.get('id'), None) + if content and (content.media_obj and content.media_obj.id not in medias) : elem.set('video', settings.FORBIDDEN_STREAM_URL) return xml def use_forbidden_url(content): - c_cls = ContentType.objects.get(model='content') - c_cls = c_cls.model_class() m_cls = ContentType.objects.get(model='media') m_cls = m_cls.model_class() - new_content = c_cls.safe_objects.filter(iri_id=content.iri_id) - if new_content: - if new_content[0].media_obj: - media = m_cls.safe_objects.filter(id=new_content[0].media_obj.id) - if not media: - return True + if content.media_obj: + media = m_cls.safe_objects.filter(id=content.media_obj.id) + if not media: + return True return False def add_change_attr(user, obj_list): @@ -54,11 +59,9 @@ """ if len(obj_list) == 0: return [] - model_name = obj_list[0].__class__.__name__.lower() ctype = ContentType.objects.get(model=model_name) cls = ctype.model_class() - # We don't use obj.values_list('pk', flat=True) because the full queryset will be calculated and used after anyway. pk_list = [item.pk for item in obj_list] if model_name in [cls_name.lower() for cls_name in settings.USE_GROUP_PERMISSIONS] or model_name == 'group': @@ -67,13 +70,13 @@ change_list = get_objects_for_user(user, '%s.change_%s' % (cls._meta.app_label, model_name)).filter(pk__in=pk_list) else: to_check = False - + for obj in obj_list: if not to_check or obj in change_list: obj.change = True else: obj.change = False - + return obj_list def assign_perm_to_obj(object, read_list, write_list, owner): diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/settings.py --- a/src/ldt/ldt/settings.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/settings.py Sat May 11 23:09:05 2013 +0200 @@ -10,7 +10,7 @@ #DEFAULT_FROM_EMAIL = "admin@domain.com" #SERVER_EMAIL = "admin@domain.com" -INSTALLED_APPS = ( +INSTALLED_APPS = getattr(settings, 'INSTALLED_APPS', ( 'django_extensions', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -35,9 +35,10 @@ 'guardian', 'sorl.thumbnail', 'tastypie', -) + 'chunked_uploads', +)) -MIDDLEWARE_CLASSES = ( +MIDDLEWARE_CLASSES = getattr(settings, 'MIDDLEWARE_CLASSES', ( 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', @@ -49,7 +50,7 @@ 'django.contrib.messages.middleware.MessageMiddleware', 'django_openid_consumer.middleware.OpenIDMiddleware', 'ldt.ldt_utils.middleware.userprofile.LanguageMiddleware', -) +)) @@ -78,26 +79,27 @@ ACCOUNT_ACTIVATION_DAYS = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', 7) LDT_MEDIA_PREFIX = getattr(settings, 'LDT_MEDIA_PREFIX', MEDIA_URL + 'ldt/') -LDT_MAX_SEARCH_NUMBER = 50 -LDT_MAX_FRAGMENT_PER_SEARCH = 3 -LDT_RESULTS_PER_PAGE = 1 -LDT_JSON_DEFAULT_INDENT = 2 -LDT_MAX_CONTENTS_PER_PAGE = 10 -LDT_MAX_PROJECTS_PER_PAGE = 10 -LDT_FRONT_MEDIA_PER_PAGE = 9 -LDT_FRONT_PROJECTS_PER_PAGE = 12 +LDT_MAX_SEARCH_NUMBER = getattr(settings, 'LDT_MAX_SEARCH_NUMBER', 50) +LDT_MAX_FRAGMENT_PER_SEARCH = getattr(settings, 'LDT_MAX_FRAGMENT_PER_SEARCH', 3) +LDT_RESULTS_PER_PAGE = getattr(settings, 'LDT_RESULTS_PER_PAGE', 1) +LDT_JSON_DEFAULT_INDENT = getattr(settings, 'LDT_JSON_DEFAULT_INDENT', 2) +LDT_MAX_CONTENTS_PER_PAGE = getattr(settings, 'LDT_MAX_CONTENTS_PER_PAGE', 10) +LDT_MAX_PROJECTS_PER_PAGE = getattr(settings, 'LDT_MAX_PROJECTS_PER_PAGE', 10) +LDT_FRONT_MEDIA_PER_PAGE = getattr(settings, 'LDT_FRONT_MEDIA_PER_PAGE', 9) +LDT_FRONT_PROJECTS_PER_PAGE = getattr(settings, 'LDT_FRONT_PROJECTS_PER_PAGE', 12) AUTO_INDEX_AFTER_SAVE = getattr(settings, 'AUTO_INDEX_AFTER_SAVE', True) +LDT_INDEXATION_INSERT_BATCH_SIZE = getattr(settings, 'LDT_INDEXATION_INSERT_BATCH_SIZE', 5000) WEB_VERSION = getattr(settings, 'WEB_VERSION', '') -ANONYOUS_USER_ID = -1 -USE_GROUP_PERMISSIONS = ['Project', 'Content'] -PUBLIC_GROUP_NAME = 'everyone' +ANONYOUS_USER_ID = getattr(settings, 'ANONYMOUS_USER_ID',-1) +USE_GROUP_PERMISSIONS = getattr(settings, 'USE_GROUP_PERMISSIONS', ['Project', 'Content']) +PUBLIC_GROUP_NAME = getattr(settings, 'PUBLIC_GROUP_NAME','everyone') -DEFAULT_CONTENT_ICON = "thumbnails/contents/content_default_icon.png" -DEFAULT_PROJECT_ICON = "thumbnails/projects/project_default_icon.png" -DEFAULT_USER_ICON = "thumbnails/users/user_default_icon.png" -DEFAULT_GROUP_ICON = "thumbnails/groups/group_default_icon.png" +DEFAULT_CONTENT_ICON = getattr(settings, 'DEFAULT_CONTENT_ICON', "thumbnails/contents/content_default_icon.png") +DEFAULT_PROJECT_ICON = getattr(settings, 'DEFAULT_PROJECT_ICON', "thumbnails/projects/project_default_icon.png") +DEFAULT_USER_ICON = getattr(settings, 'DEFAULT_USER_ICON', "thumbnails/users/user_default_icon.png") +DEFAULT_GROUP_ICON = getattr(settings, 'DEFAULT_GROUP_ICON', "thumbnails/groups/group_default_icon.png") # force settings value if(not hasattr(settings, 'MAX_TAG_LENGTH') or getattr(settings, 'MAX_TAG_LENGTH') > 255): @@ -105,9 +107,11 @@ EXTERNAL_STREAM_SRC = getattr(settings, 'EXTERNAL_STREAM_SRC', ['youtube.com', 'dailymotion.com', 'vimeo.com']) -HAYSTACK_CONNECTIONS = { +HAYSTACK_CONNECTIONS = getattr(settings, 'HAYSTACK_CONNECTIONS', { 'default': { 'ENGINE': 'haystack.backends.simple_backend.SimpleEngine', }, -} +}) +HAYSTACK_SIGNAL_PROCESSOR = getattr(settings, 'HAYSTACK_SIGNAL_PROCESSOR', 'ldt.indexation.signals.LdtSignalProcessor') + diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/css/embed_popup.css diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/css/front_group.css --- a/src/ldt/ldt/static/ldt/css/front_group.css Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/static/ldt/css/front_group.css Sat May 11 23:09:05 2013 +0200 @@ -38,9 +38,8 @@ .li_membre_groupe p { margin-left: 45px; } - /* media title search input*/ - #search_title{ +#search_title{ background : url(../img/search.gif) no-repeat; border: none; height: 16px; @@ -52,7 +51,8 @@ background: transparent; margin: 0px 7px 10px 0px; } + #result_pagination { border: 0 none; margin: 5px 0; -} +} \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/css/ldtform.css --- a/src/ldt/ldt/static/ldt/css/ldtform.css Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/static/ldt/css/ldtform.css Sat May 11 23:09:05 2013 +0200 @@ -1,10 +1,26 @@ @charset "UTF-8"; +input, textarea, select, .form-row p { + margin: 2px 0; + padding: 2px 3px; + vertical-align: middle; + font-family: "Lucida Grande", Verdana, Arial, sans-serif; + font-weight: normal; + font-size: 11px; +} + +textarea { + vertical-align: top !important; +} + +input[type=text], input[type=password], textarea, select, .vTextField { + border: 1px solid #ccc; +} body { min-width: 0; } -#add_content, #add_contribution, #add_group { +#add_contribution, #add_group { padding: 10px; } @@ -147,7 +163,7 @@ } #media_fields_div { - width : 338px; + width : 300px; height : 50px; margin-top: 10px 0px; padding-left: 10px; diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/js/embed_popup.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/js/projectscontents.js --- a/src/ldt/ldt/static/ldt/js/projectscontents.js Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/static/ldt/js/projectscontents.js Sat May 11 23:09:05 2013 +0200 @@ -412,17 +412,11 @@ var h = $(element).innerHeight() + 10; var w = $(element).innerWidth() + 10; } - + nm.sizes.minH = h + 10; nm.sizes.minW = w; iframe.height(h); iframe.width(w); - - if ($.browser.mozilla && createcontent) { - $(".nyroModalCont", parent.window.document).height(h+10); - } else { - nm.resize(true); - } } // @@ -438,7 +432,8 @@ $("#close_button").click(function (e) { e.preventDefault(); parent.$.nmTop().close(); - }); + }); + $("#submit_button_write").click(function(e) { $(".submitcontent-loader-content").show(); resize_modal_window($("#add_content"), true); @@ -456,103 +451,22 @@ $('#my_form').bind('submit', function() { window.submit_asked = true; if($('#id_content-media_input_type').val()=="upload"){ - if(window.upload_from_local_done==false){ - // The form has sent but the uploading has not ended. - if($('#upload_progress_info').children().size()>0){ - $('#progress_info').remove(); - } - $('#upload_progress_info').append('

' + wait_label + '.
' + cancel_label + '.

'); - return false; + /*if(chunked_upload_complete == true){ + return true; } else{ - return true; - } + return false; + }*/ + return false; } else{ - //alert("2. " + $('#id_content-media_input_type').val()); return true; } }); - $("#upload_progress_bar").css({ width:"90%", height:"10" }); - $('#media_fields_div').height(80); - - // We init the swfupload object - swfupload = new SWFUpload({ - debug: false, - - upload_url: url_upload, - flash_url: media_prefix+"swf/swfupload.swf", - - post_params: post_added_params, - - button_placeholder_id: "upload_btn", - button_width: "60", - button_height: "16", - button_cursor: SWFUpload.CURSOR.HAND, - button_text : '' + btn_label + '', - button_text_style : ".btnText { font-size: 12; font-family: Arial; }", - - file_types : "*.flv;*.f4v;*.mp4;*.mov;*.mp3", - file_types_description : "Media Files (flv, f4v, mov H264, mp4, mp3)", - file_upload_limit : "1", - file_queue_limit : "1", - - upload_error_handler : uploadError, - upload_start_handler : function(file) { - try { - if($('#upload_progress_info').children().size()>0){ - $('#progress_info').remove(); - } - $('#upload_progress_info').append('

' + cancel_label + '.

'); - } - catch (ex) { - //this.debug(ex); - } - }, - upload_progress_handler : uploadProgress, - upload_success_handler : function() { - try { - if($('#upload_progress_info').children().size()>0){ - $('#progress_info').remove(); - } - $('#upload_progress_info').append('

' + success_label + '.

'); - $("#upload_progress_bar > div").css({ 'background': '#90ffa8' }); - window.upload_from_local_done = true; - // Now that the file is uploaded, we submit the form if asked - if(window.submit_asked==true){ - $('#my_form').submit(); - } - else{ - // We ask the uploaded media's duration - if(window.ask_duration_url){ - $.ajax({ - type: "GET", - url: window.ask_duration_url, - data: "filename="+ $('#id_media-local_file_name').val(), - cache: false, - success: function(data, status, request){ - if(data && data!=""){ - $('#id_content-duration').val(data); - } - } - }); - } - } - } - catch (ex) { - //this.debug(ex); - } - }, - file_queued_handler : displayUploadPath, - file_dialog_complete_handler: function() { - window.submit_asked = false; - this.startUpload(); - } - //upload_complete_handler: function() { this.startUpload(); }, - }); } + function displayUploadPath(file) { try { $('#id_media-local_file_name').val(file.name); @@ -561,62 +475,6 @@ //this.debug(ex); } } -function startLocalUpload(){ - swfupload.startUpload(); -} -function uploadProgress(file, bytesLoaded, bytesTotal) { - try { - var percent = Math.ceil((bytesLoaded / bytesTotal) * 100); - $("#upload_progress_bar").progressbar({ value: percent }); - } - catch (ex) { - //this.debug(ex); - } -} -function cancelSwfUpload(){ - swfupload.cancelUpload(); - if($('#media_field_upload').has($('#cancelupload')).length==0){ - $('#cancelupload').remove(); - } -} -function uploadError(file, errorCode, message) { - try { - if($('#upload_progress_info').children().size()>0){ - $('#progress_info').remove(); - } - switch (errorCode) { - case SWFUpload.UPLOAD_ERROR.HTTP_ERROR: - $('#upload_progress_info').append('

' + "Error Code: HTTP Error, File name: " + file.name + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED: - $('#upload_progress_info').append('

' + "Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.IO_ERROR: - $('#upload_progress_info').append('

' + "Error Code: IO Error, File name: " + file.name + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR: - $('#upload_progress_info').append('

' + "Error Code: Security Error, File name: " + file.name + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED: - $('#upload_progress_info').append('

' + "Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED: - $('#upload_progress_info').append('

' + "Error Code: File Validation Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '

'); - break; - case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED: - $('#upload_progress_info').append('

' + "Error Code: FILE_CANCELLED" + '

'); - break; - case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED: - $('#upload_progress_info').append('

' + "STOPPED" + '

'); - break; - default: - $('#upload_progress_info').append('

' + "unhandled error: File name: " + file.name + ", File size: " + file.size + ", Message: " + message + '

'); - break; - } - } catch (ex) { - //this.debug(ex); - } -} // Test the value of the URL from the form to load a picture in case it is a youtube video function testUrlValue(e){ diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/Annotation.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/AnnotationsList.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/LdtPlayer-core.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/Polemic.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/Segments.js --- a/src/ldt/ldt/static/ldt/metadataplayer/Segments.js Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/static/ldt/metadataplayer/Segments.js Sat May 11 23:09:05 2013 +0200 @@ -102,11 +102,11 @@ var url = (typeof _annotation.url !== "undefined" ? _annotation.url : (document.location.href.replace(/#.*$/,'') + '#id=' + _annotation.id)); - e.originalEvent.dataTransfer.setData("text/x-iri-title",_annotation.title); - e.originalEvent.dataTransfer.setData("text/x-iri-description",_annotation.description); - e.originalEvent.dataTransfer.setData("text/x-iri-uri",url); - if (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail) { - e.originalEvent.dataTransfer.setData("text/x-iri-image",_annotation.thumbnail); + e.originalEvent.dataTransfer.setData("text/x-iri-title",_annotation.title); + e.originalEvent.dataTransfer.setData("text/x-iri-description",_annotation.description); + e.originalEvent.dataTransfer.setData("text/x-iri-uri",url); + if (typeof _annotation.thumbnail !== "undefined" && _annotation.thumbnail) { + e.originalEvent.dataTransfer.setData("text/x-iri-image",_annotation.thumbnail); } }) .appendTo(list_$) diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/metadataplayer/Tweet.js diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/static/ldt/swf/ldt/LignesDeTempsFlex.swf diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/utils/projectldt_parser.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldt/ldt/utils/projectldt_parser.py Sat May 11 23:09:05 2013 +0200 @@ -0,0 +1,40 @@ +from ldt.utils.url import absolute_media_url, is_absolute +from ldt.ldt_utils.models import Content + +def absolute_src_xml(doc): + media_list = doc.xpath("/iri/medias/media") + for element in media_list: + src = element.get("src") #we split to hate two parts, one with the src + if not is_absolute(src): + new_src = absolute_media_url()+src + element.set('src', new_src) #we replace the old value by the new one + return doc + +def relative_src_xml(ldt): + modif = False + no_more_media=False + media_list = ldt.xpath("/iri/medias/media") + if len(media_list) == 0 : + no_more_media = True + if not no_more_media : + for element in media_list: + src = element.get("src") + id_content=element.get("id") + content_list = Content.objects.filter(iri_id=id_content) + if len(content_list) == 0: + element.getparent().remove(element) + modif = True + for content_elem in ldt.xpath("/iri/annotations/content[@id=\"%s\"]" % id_content): + content_elem.getparent().remove(content_elem) + media_list = ldt.xpath("/iri/medias/media") + if len(media_list) == 0 : + no_more_media = True + else: + content = content_list[0] + right_src = content.relative_iri_url() + if not src == right_src: #we will modify only the project that have an absolute url + modif = True + new_src = right_src + element.set('src', new_src) #we replace the old value by the new one + + return ldt, modif, no_more_media \ No newline at end of file diff -r eb9cc63ce742 -r 54ef33bb4065 src/ldt/ldt/utils/url.py --- a/src/ldt/ldt/utils/url.py Tue May 07 15:30:41 2013 +0200 +++ b/src/ldt/ldt/utils/url.py Sat May 11 23:09:05 2013 +0200 @@ -2,15 +2,22 @@ from django.core.urlresolvers import reverse from ldt.utils.web_url_management import get_web_url from ldt import settings +from django.conf import settings as djangosettings import httplib2 import re import urlparse +import logging def absstatic(request, path): domain=get_web_url(request) new_path = staticfiles_storage.url(path) return urlparse.urljoin(domain, new_path) +def absolute_media_url(): + domain=get_web_url() + + return urlparse.urljoin(domain, djangosettings.MEDIA_URL) + def absurl(request, viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None): domain=get_web_url(request) path=reverse(viewname, urlconf, args, kwargs, prefix, current_app)