Commits

Apostolis Bessas committed 998641f

Remove API v1 code.

Comments (0)

Files changed (19)

transifex/addons/autofetch/models.py

 import urllib2, urlparse
 from uuid import uuid4
 
-StorageFile = models.get_model("storage", "StorageFile")
 
 class URLInfo(models.Model):
 

transifex/api/urls.py

 from transifex.resources.api import ResourceHandler, FileHandler, StatsHandler, \
         TranslationHandler, FormatsHandler, TranslationObjectsHandler,\
         SingleTranslationHandler
-from transifex.storage.api import StorageHandler
 from transifex.releases.api import ReleaseHandler
 from transifex.actionlog.api import ActionlogHandler
 from transifex.api.views import reject_legacy_api
 
 resource_handler = Resource(ResourceHandler, authentication=auth)
 release_handler = Resource(ReleaseHandler, authentication=auth)
-storage_handler = Resource(StorageHandler, authentication=auth)
 project_handler = Resource(ProjectHandler, authentication=auth)
 projectresource_handler = Resource(ProjectResourceHandler, authentication=auth)
 translationfile_handler = Resource(FileHandler, authentication=auth)

transifex/projects/api.py

 from transifex.resources.formats.registry import registry
 from transifex.resources.handlers import get_project_teams
 from transifex.resources.models import *
-from transifex.storage.models import StorageFile
 from transifex.teams.models import Team
 from transifex.txcommon.log import logger
 from transifex.txcommon.decorators import one_perm_required_or_403
         """
         # Reset fields to default value
         ProjectHandler.fields = ProjectHandler.default_fields
-        if api_version == 2:
-            if "details" in request.GET.iterkeys():
-                if project_slug is None:
-                    return rc.NOT_IMPLEMENTED
-                ProjectHandler.fields = ProjectHandler.details_fields
-        else:
+        if "details" in request.GET.iterkeys():
+            if project_slug is None:
+                return rc.NOT_IMPLEMENTED
             ProjectHandler.fields = ProjectHandler.details_fields
         return self._read(request, project_slug)
 
         API call to create new projects via POST.
         """
         data = getattr(request, 'data', None)
-        if api_version == 2:
-            if project_slug is not None:
-                return BAD_REQUEST("POSTing to this url is not allowed.")
-            if data is None:
-                return BAD_REQUEST(
-                    "At least parameters 'slug', 'name' and "
-                    "'source_language' are needed."
-                )
-            return self._create(request, data)
-        else:
-            return self._createv1(request, data)
+        if project_slug is not None:
+            return BAD_REQUEST("POSTing to this url is not allowed.")
+        if data is None:
+            return BAD_REQUEST(
+                "At least parameters 'slug', 'name' and "
+                "'source_language' are needed."
+            )
+        return self._create(request, data)
 
     @require_mime('json')
     @method_decorator(one_perm_required_or_403(pr_project_add_change,
         data = request.data
         if data is None:
             return BAD_REQUEST("Empty request.")
-        if api_version == 2:
-            return self._update(request, project_slug, data)
-        else:
-            return self._updatev1(request, project_slug, data)
+        return self._update(request, project_slug, data)
 
     @method_decorator(one_perm_required_or_403(pr_project_delete,
         (Project, 'slug__exact', 'project_slug')))
         p.save()
         return rc.CREATED
 
-    def _createv1(self, request, data):
-        """
-        Create a new project following the v1 API.
-        """
-        outsource = data.pop('outsource', {})
-        maintainers = data.pop('maintainers', {})
-        lang = data.pop('source_language', 'en')
-        try:
-            source_language = Language.objects.by_code_or_alias(lang)
-        except Language.DoesNotExist:
-            return BAD_REQUEST("Language %s does not exist." % lang)
-        try:
-            p, created = Project.objects.get_or_create(
-                source_language=source_language, **data)
-        except:
-            return BAD_REQUEST("Project not found")
-
-        if created:
-            # Owner
-            p.owner = request.user
-
-            # Outsourcing
-            if outsource:
-                try:
-                    outsource_project = Project.objects.get(slug=outsource)
-                except Project.DoesNotExist:
-                    # maybe fail when wrong user is given?
-                    pass
-                p.outsource = outsource_project
-
-            # Handler m2m with maintainers
-            if maintainers:
-                for user in maintainers.split(','):
-                    try:
-                        p.maintainers.add(User.objects.get(username=user))
-                    except User.DoesNotExist:
-                        # maybe fail when wrong user is given?
-                        pass
-            else:
-                p.maintainers.add(p.owner)
-
-            try:
-                p.full_clean()
-            except ValidationError, e:
-                return BAD_REQUEST("%s" % e)
-            p.save()
-
-            return rc.CREATED
-        else:
-            return BAD_REQUEST("Unsupported request")
-
     def _update(self, request, project_slug, data):
         try:
             self._check_fields(data.iterkeys(), extra_exclude=['slug'])
             return BAD_REQUEST("Error parsing request data: %s" % e)
         return rc.ALL_OK
 
-    def _updatev1(self, request, project_slug, data):
-        """
-        Update a project per API v1.
-        """
-        outsource = data.pop('outsource', {})
-        maintainers = data.pop('maintainers', {})
-        try:
-            p = Project.objects.get(slug=project_slug)
-        except Project.DoesNotExist:
-            return BAD_REQUEST("Project not found")
-        try:
-            for key,value in data.items():
-                if key == 'slug':
-                    continue
-                setattr(p, key,value)
-                # Outsourcing
-            if outsource:
-                if outsource == p.slug:
-                    return BAD_REQUEST("Original and outsource projects are the same.")
-                try:
-                    outsource_project = Project.objects.get(slug=outsource)
-                except Project.DoesNotExist:
-                    # maybe fail when wrong user is given?
-                    pass
-                p.outsource = outsource_project
-
-            # Handler m2m with maintainers
-            if maintainers:
-                # remove existing maintainers
-                p.maintainers.all().clear()
-                # add then all anew
-                for user in maintainers.split(','):
-                    try:
-                        p.maintainers.add(User.objects.get(username=user))
-                    except User.DoesNotExist:
-                        # maybe fail when wrong user is given?
-                        pass
-            p.save()
-        except Exception, e:
-            return BAD_REQUEST("Error parsing request data: %s" % e)
-        return rc.ALL_OK
-
     def _delete(self, request, project_slug):
         try:
             project = Project.objects.get(slug=project_slug)
         for field in fields:
             if field not in self.allowed_fields or field in extra_exclude:
                 raise AttributeError(field)
-
-
-class ProjectResourceHandler(BaseHandler):
-    """
-    API handler for creating resources under projects
-    """
-
-    allowed_methods = ('POST', 'PUT')
-
-    @throttle(settings.API_MAX_REQUESTS, settings.API_THROTTLE_INTERVAL)
-    @method_decorator(one_perm_required_or_403(pr_resource_add_change,
-        (Project, 'slug__exact', 'project_slug')))
-    @transaction.commit_manually
-    def create(self, request, project_slug, api_version=1):
-        """
-        Create resource for project by UUID of StorageFile.
-        """
-        if "application/json" in request.content_type:
-            if "uuid" in request.data:
-                uuid = request.data['uuid']
-                project = Project.objects.get(slug=project_slug)
-                try:
-                    storagefile = StorageFile.objects.get(uuid=uuid)
-                except StorageFile.DoesNotExist, e:
-                    transaction.rollback()
-                    return BAD_REQUEST("Specified uuid is invalid.")
-                resource_slug = None
-                if "slug" in request.data:
-                    resource_slug = request.data['slug']
-                    if len(resource_slug) > 51:
-                        transaction.rollback()
-                        return BAD_REQUEST("Resouce slug is too long "
-                            "(Max. 50 chars).")
-
-                slang = project.source_language
-                if slang is not None and storagefile.language != slang:
-                    return BAD_REQUEST(
-                        "You have to use %s for source language" % slang
-                    )
-
-                try:
-                    resource, created = Resource.objects.get_or_create(
-                        slug = resource_slug or slugify(storagefile.name),
-                        source_language = storagefile.language,
-                        project = project
-                    )
-                except DatabaseError, e:
-                    transaction.rollback()
-                    logger.error(e.message, exc_info=True)
-                    return BAD_REQUEST(e.message)
-                except IntegrityError, e:
-                    transaction.rollback()
-                    logger.error(e.message, exc_info=True)
-                    return BAD_REQUEST(e.message)
-
-                if created:
-                    resource.name = resource_slug or storagefile.name
-                    resource.save()
-                    # update i18n_type
-                    i18n_type = registry.guess_method(storagefile.get_storage_path())
-                    if not i18n_type:
-                        transaction.rollback()
-                        return BAD_REQUEST("File type not supported.")
-                    resource.i18n_method = i18n_type
-                    resource.save()
-                else:
-                    i18n_type = resource.i18n_method
-
-                # Set StorageFile to 'bound' status, which means that it is
-                # bound to some translation resource
-                storagefile.bound = True
-                storagefile.save()
-
-                logger.debug("Going to insert strings from %s (%s) to %s/%s" %
-                    (storagefile.name, storagefile.uuid, project.slug,
-                    resource.slug))
-
-                strings_added, strings_updated = 0, 0
-                fhandler = storagefile.find_parser()
-                fhandler.bind_file(filename=storagefile.get_storage_path())
-                fhandler.bind_resource(resource)
-                fhandler.set_language(storagefile.language)
-
-                try:
-                    fhandler.is_content_valid()
-                    fhandler.parse_file(True)
-                    strings_added, strings_updated = fhandler.save2db(True,
-                        user=request.user)
-                except Exception, e:
-                    transaction.rollback()
-                    return BAD_REQUEST("Resource not created. Could not "
-                        "import file: %s" % e)
-                else:
-                    messages = []
-                    if strings_added > 0:
-                        messages.append(_("%i strings added") % strings_added)
-                    if strings_updated > 0:
-                        messages.append(_("%i strings updated") % strings_updated)
-                retval= {
-                    'strings_added': strings_added,
-                    'strings_updated': strings_updated,
-                    'redirect': reverse('resource_detail',args=[project_slug,
-                        resource.slug])
-                    }
-                logger.debug("Extraction successful, returning: %s" % retval)
-
-                if created:
-                    post_resource_save.send(sender=None, instance=resource,
-                            created=created, user=request.user)
-
-                # transaction has been commited by save2db
-                # but logger message above marks it dirty again
-                transaction.commit()
-
-                return HttpResponse(simplejson.dumps(retval),
-                    mimetype='text/plain')
-
-            else:
-                transaction.rollback()
-                return BAD_REQUEST("Request data missing.")
-        else:
-            transaction.rollback()
-            return BAD_REQUEST("Unsupported request")
-
-    def update(self, request, project_slug, resource_slug, language_code=None, api_version=1):
-        """
-        Update resource translations of a project by the UUID of a StorageFile.
-        """
-        try:
-            project = Project.objects.get(slug=project_slug)
-            resource = Resource.objects.get(slug=resource_slug,
-                project=project)
-        except (Project.DoesNotExist, Resource.DoesNotExist):
-            return rc.NOT_FOUND
-
-        # Permissions handling
-        team = Team.objects.get_or_none(project, language_code)
-        check = ProjectPermission(request.user)
-        if (not check.submit_translations(team or project) or\
-            not resource.accept_translations) and not\
-                check.maintain(project):
-            return rc.FORBIDDEN
-
-        if "application/json" in request.content_type:
-            if "uuid" in request.data:
-                uuid = request.data['uuid']
-                storagefile = StorageFile.objects.get(uuid=uuid)
-                language = storagefile.language
-
-                logger.debug("Going to insert strings from %s (%s) to %s/%s" %
-                    (storagefile.name, storagefile.uuid, project_slug,
-                    resource.slug))
-
-                strings_added, strings_updated = 0, 0
-                fhandler = storagefile.find_parser()
-                language = storagefile.language
-                fhandler.bind_file(filename=storagefile.get_storage_path())
-                fhandler.set_language(language)
-                fhandler.bind_resource(resource)
-                fhandler.is_content_valid()
-
-                try:
-                    fhandler.parse_file()
-                    strings_added, strings_updated = fhandler.save2db(
-                        user=request.user)
-                except Exception, e:
-                    logger.error(e.message, exc_info=True)
-                    return BAD_REQUEST("Error importing file: %s" % e)
-                else:
-                    messages = []
-                    if strings_added > 0:
-                        messages.append(_("%i strings added") % strings_added)
-                    if strings_updated > 0:
-                        messages.append(_("%i strings updated") % strings_updated)
-                retval= {
-                    'strings_added':strings_added,
-                    'strings_updated':strings_updated,
-                    'redirect':reverse('resource_detail',args=[project_slug,
-                        resource.slug])
-                    }
-
-                logger.debug("Extraction successful, returning: %s" % retval)
-
-                # Set StorageFile to 'bound' status, which means that it is
-                # bound to some translation resource
-                storagefile.bound = True
-                storagefile.save()
-
-                # If any string added/updated
-                if retval['strings_added'] > 0 or retval['strings_updated'] > 0:
-                    modified = True
-                else:
-                    modified=False
-                post_submit_translation.send(None, request=request,
-                    resource=resource, language=language, modified=modified)
-
-                return HttpResponse(simplejson.dumps(retval),
-                    mimetype='application/json')
-            else:
-                return BAD_REQUEST("Missing request data.")
-        else:
-            return BAD_REQUEST("Unsupported request")

transifex/projects/tests/api.py

 from transifex.txcommon.utils import log_skip_transaction_test
 from transifex.resources.models import RLStats, Resource
 from transifex.projects.models import Project
-from transifex.storage.models import StorageFile
-from transifex.storage.tests.api import BaseStorageTests
-
-class ProjectResourceAPITests(BaseStorageTests):
-    """
-    Test the status codes.
-    """
-    def test_resource_creation(self):
-        """Test creation of resource through the API."""
-
-        self.create_storage()
-
-        data = '{"uuid": "%s"}' % self.uuid
-        resp = self.client['registered'].post(reverse('api_project_files',
-            args=[self.project.slug]), data, content_type="application/json")
-        self.assertTrue('Forbidden access' in resp.content)
-        self.assertEqual(resp.status_code, 403)
-
-        resp = self.client['maintainer'].post(reverse('api_project_files',
-            args=[self.project.slug]), data, content_type="application/json")
-        r = simplejson.loads(resp.content)
-        self.assertEqual(r['strings_added'], 3)
-        self.assertEqual(resp.status_code, 200)
-
-        # To be used in other tests
-        self.resource_slug = eval(resp.content)['redirect'].split(
-            '/resource/')[1].replace('/','')
-
-        # Some extra check around denormalization
-        rls = RLStats.objects.get(resource__project=self.project,
-            resource__slug=self.resource_slug, language=self.language_en)
-
-        self.assertEqual(rls.translated, 3)
-        self.assertEqual(rls.total, 3)
-        self.assertEqual(rls.translated_perc, 100)
-
-    def test_submission_translation(self):
-        """Test submission of translation through the API."""
-
-        self.test_resource_creation()
-
-        # Changing language of the storagefile object
-        sf = StorageFile.objects.get(uuid=self.uuid)
-        sf.language = self.language
-        sf.save()
-
-        data = '{"uuid": "%s"}' % self.uuid
-        resp = self.client['maintainer'].put(reverse('api_resource_storage',
-            args=[self.project.slug, self.resource_slug, self.language.code]),
-            data, content_type="application/json")
-        self.assertEqual(eval(resp.content)['strings_added'], 3)
-
-        # Some extra check around denormalization
-        rls = RLStats.objects.get(resource__project=self.project,
-            resource__slug=self.resource_slug, language=self.language)
-
-        resource = Resource.objects.get(project=self.project,
-            slug=self.resource_slug)
-
-        self.assertEqual(rls.translated, 3)
-        self.assertEqual(rls.total, 3)
-        self.assertEqual(rls.translated_perc, 100)
-
-    def test_same_source_language(self):
-        filename = 'pt_BR.po'
-        path = os.path.join(settings.TX_ROOT, 'storage/tests/', filename)
-
-        # same language: success
-        upload_file = open(path)
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        uuid = simplejson.loads(resp.content)['files'][0]['uuid']
-        data = '{"uuid": "%s"}' % uuid
-        resp = self.client['maintainer'].post(
-            reverse('api_project_files', args=[self.project.slug]),
-            data, content_type="application/json"
-        )
-        self.assertEqual(eval(resp.content)['strings_added'], 3)
-        self.assertEqual(resp.status_code, 200)
-        upload_file.close()
-
-        # different language: error
-        upload_file = open(path)
-        data = {'language': self.language_ar.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        uuid = simplejson.loads(resp.content)['files'][0]['uuid']
-        data = '{"uuid": "%s"}' % uuid
-        resp = self.client['maintainer'].post(
-            reverse('api_project_files', args=[self.project.slug]),
-            data, content_type="application/json"
-        )
-        self.assertContains(resp, "for source language", status_code=400)
-        upload_file.close()
-
-@unittest.skipUnless(settings.DATABASES['default']['ENGINE'].endswith(
-        'postgresql_psycopg2'), log_skip_transaction_test(
-            "Skipping transaction test because database backend"
-            " is not postgres."))
-class TestTransactionProjectResourceAPI(TransactionNoticeTypes,
-                                        TransactionLanguages,
-                                        TransactionProjects,
-                                        TransactionTestCase):
-
-    def setUp(self):
-        # Have to run now, because the TransactionTestCase resets
-        # the database *every* time.
-        super(TestTransactionProjectResourceAPI, self).setUp()
-        self.project = Project.objects.get(slug='project1')
-        self.project.maintainers.add(self.user['maintainer'])
-        self.project.owner = self.user['maintainer']
-        self.project.save()
-
-    def test_second_create_with_error(self):
-        """Test that calling create a second time with the same parameters
-        and a bogus source file does not delete the resource.
-        """
-        rslug = "oops"
-        self.assertEqual(Resource.objects.filter(slug=rslug).count(), 0)
-
-        upload_file = open(os.path.join(
-                settings.TX_ROOT,
-                'resources/tests/lib/qt/en.ts'
-        ))
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        self.assertEqual(resp.status_code, 200)
-        uuid = simplejson.loads(resp.content)['files'][0]['uuid']
-
-        resp = self.client['maintainer'].post(
-            reverse('api_project_files', args=[self.project.slug]),
-            data='{"uuid": "%s", "slug": "%s"}' % (uuid, rslug),
-            content_type="application/json"
-        )
-        self.assertEqual(resp.status_code, 200)
-        self.assertEqual(Resource.objects.filter(slug=rslug).count(), 1)
-
-        upload_file = open(os.path.join(
-                settings.TX_ROOT,
-                'resources/tests/lib/qt/error.ts'
-        ))
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        self.assertEqual(resp.status_code, 200)
-        uuid = simplejson.loads(resp.content)['files'][0]['uuid']
-
-        resp = self.client['maintainer'].post(
-            reverse('api_project_files', args=[self.project.slug]),
-            data='{"uuid": "%s", "slug": "%s"}' % (uuid, rslug),
-            content_type="application/json"
-        )
-        self.assertEqual(Resource.objects.filter(slug=rslug).count(), 1)
-
-        rslug = 'noop'
-        upload_file = open(os.path.join(
-                settings.TX_ROOT,
-                'resources/tests/lib/qt/error.ts'
-        ))
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        self.assertEqual(resp.status_code, 200)
-        uuid = simplejson.loads(resp.content)['files'][0]['uuid']
-
-        resp = self.client['maintainer'].post(
-            reverse('api_project_files', args=[self.project.slug]),
-            data='{"uuid": "%s", "slug": "%s"}' % (uuid, rslug),
-            content_type="application/json"
-        )
-        self.assertEqual(resp.status_code, 400)
-        self.assertEqual(Resource.objects.filter(slug=rslug).count(), 0)
 
 
 class TestProjectAPI(BaseTestCase):

transifex/resources/formats/xliff.py

 Translation = get_model('resources', 'Translation')
 SourceEntity = get_model('resources', 'SourceEntity')
 Template = get_model('resources', 'Template')
-Storage = get_model('storage', 'StorageFile')
 
 plural_regex = _HashRegex(plurals=True).plural_regex
 

transifex/resources/forms.py

 from transifex.resources.formats.core import ParseError
 from transifex.resources.backends import ResourceBackend, \
         ResourceBackendError, content_from_uploaded_file
-from transifex.storage.models import StorageFile
+
 
 class ResourceForm(forms.ModelForm):
 

transifex/storage/__init__.py

Empty file removed.

transifex/storage/admin.py

-from django.contrib import admin
-from transifex.storage.models import StorageFile
-
-class StorageAdmin(admin.ModelAdmin):
-    search_fields = ['name', 'size', 'language__name', 'user__username',
-        'uuid']
-    list_display = ['name', 'size', 'language', 'user', 'uuid', 'created']
-
-admin.site.register(StorageFile, StorageAdmin)

transifex/storage/api.py

-# -*- coding: utf-8 -*-
-from piston.handler import BaseHandler
-from piston.utils import rc, throttle
-from django.conf import settings
-from django.http import HttpResponse
-from django.template.defaultfilters import slugify
-from django.utils import simplejson
-from django.utils.translation import ugettext as _
-from django.core.urlresolvers import reverse
-from django.contrib.auth.models import User
-from transifex.languages.models import Language
-from transifex.projects.models import Project
-from transifex.resources.models import Resource, SourceEntity, Translation
-from transifex.resources.formats.core import ParseError
-from transifex.storage.models import StorageFile
-from transifex.txcommon.exceptions import FileCheckError
-from transifex.txcommon.log import logger
-from django.db import transaction
-from transifex.api.utils import BAD_REQUEST
-from uuid import uuid4
-import os
-
-
-class StorageHandler(BaseHandler):
-    allowed_methods = ('GET', 'POST', 'DELETE')
-    model = StorageFile
-    fields = ('language',('language',('code',)),'total_strings','name','created','uuid','mime_type','size')
-
-    def delete(self, request, uuid=None, api_version=1):
-        """
-        Deletes file by storage UUID
-        """
-        if request.user.is_anonymous():
-            return rc.FORBIDDEN
-        try:
-            StorageFile.objects.get(uuid=uuid, user=request.user).delete()
-        except StorageFile.DoesNotExist:
-            return rc.NOT_FOUND
-        logger.debug("Deleted file %s" % uuid)
-        return rc.DELETED
-
-    def read(self, request, uuid=None, api_version=1):
-        """
-        Returns list of StorageFile objects
-        [
-            {
-                "total_strings": 1102,
-                "uuid": "71f4964c-817b-4778-b3e0-693375cb1355",
-                "language": {
-                    "code": "et"
-                },
-                "created": "2010-05-13 07:22:36",
-                "size": 187619,
-                "mime_type": "application/x-gettext",
-                "name": "kmess.master.et.po"
-            },
-            ...
-        ]
-        """
-        if request.user.is_anonymous():
-            return rc.FORBIDDEN
-        retval = StorageFile.objects.filter(user = request.user, bound=False)
-        logger.debug("Returned list of users uploaded files: %s" % retval)
-        return retval
-
-    @throttle(settings.API_MAX_REQUESTS, settings.API_THROTTLE_INTERVAL)
-    def create(self, request, uuid=None, api_version=1):
-        """
-        API call for uploading a file via POST or updating storage file attributes
-        """
-        if request.user.is_anonymous():
-            return rc.FORBIDDEN
-
-        if "application/json" in request.content_type: # Do API calls
-            if 'language' in request.data.keys() and uuid: # API call for changing language
-                lang_code = request.data['language'] # TODO: Sanitize
-                try:
-                    sf = StorageFile.objects.get(uuid = uuid)
-                    if lang_code == "": # Set to 'Not detected'
-                        sf.language = None
-                    else:
-                        sf.language = Language.objects.by_code_or_alias(lang_code)
-                except StorageFile.DoesNotExist:
-                    return rc.NOT_FOUND # Translation file does not exist
-                except Language.DoesNotExist:
-                    return rc.NOT_FOUND # Translation file not found
-                sf.save() # Save the change
-                logger.debug("Changed language of file %s (%s) to %s" % (sf.uuid, sf.name, lang_code))
-                return rc.ALL_OK
-            return BAD_REQUEST("Unsupported request") # Unknown API call
-        elif "multipart/form-data" in request.content_type: # Do file upload
-            files=[]
-            retval = None
-            for name, submitted_file in request.FILES.items():
-                submitted_file = submitted_file
-                sf = StorageFile()
-                sf.name = str(submitted_file.name.encode('UTF-8'))
-                sf.uuid = str(uuid4())
-                fh = open(sf.get_storage_path(), 'wb')
-                for chunk in submitted_file.chunks():
-                    fh.write(chunk)
-                fh.close()
-                sf.size = os.path.getsize(sf.get_storage_path())
-                sf.user = request.user
-                if 'language' in request.data.keys():
-                    lang_code = request.data['language']
-                    try:
-                        sf.language =  Language.objects.by_code_or_alias(lang_code)
-                    except Language.DoesNotExist:
-                        logger.error("Weird! Selected language code (%s) does "
-                            "not match with any language in the database."
-                            % lang_code)
-                        return BAD_REQUEST("Selected language code (%s) does "
-                            "not match with any language in the database." % lang_code)
-                else:
-                    return BAD_REQUEST(
-                        "Language for the file has not been specified."
-                    )
-
-                try:
-                    sf.update_props()
-                    sf.save()
-
-                    logger.debug("Uploaded file %s (%s)" % (sf.uuid, sf.name))
-                    files.append({'uuid':sf.uuid, 'id':str(sf.id),
-                        'name':sf.name})
-                except UnicodeDecodeError, e:
-                    message = (
-                        "The encoding of the uploaded file is not UTF-8. "
-                        "Currently, transifex supports only UTF-8"
-                        "encoded files. Please, visit"
-                        "http://help.transifex.net/user-guide/formats.html#encoding"
-                        "for further information."
-                    )
-                except Exception, e:
-                    if isinstance(e, UnicodeDecodeError):
-                        message = (
-                            "The encoding of the uploaded file is not UTF-8. "
-                            "Currently, transifex supports only UTF-8"
-                            "encoded files. Please, visit"
-                            "http://help.transifex.net/user-guide/formats.html#encoding"
-                            "for further information."
-                        )
-                    elif isinstance(e, (FileCheckError, ParseError)):
-                        #FIXME: Custom Exception should use an extra attr for
-                        # localized string.
-                        message = "%s" % e
-                    else:
-                        message = "Error: %s" % e
-                        logger.error("Unhandled exception raised: %s" % e)
-
-                    # The object is not saved yet, but it removes file from
-                    # the filesystem
-                    sf.delete()
-
-                    # Delete possible uploaded files from the same request.
-                    # It allows multiple files per request, but if one fails,
-                    # the whole request must fail.
-                    StorageFile.objects.filter(
-                        id__in=[f['id'] for f in files]).delete()
-
-                    retval=dict(status='Error', message=message)
-
-            if not retval:
-                retval=dict(status='Created', files=files,
-                    message=_("File uploaded successfully."))
-                status = 200
-            else:
-                status = 400
-
-            return HttpResponse(simplejson.dumps(retval),
-                    mimetype='text/plain', status=status)
-        else: # Unknown content type/API call
-            return BAD_REQUEST("Unsupported request")

transifex/storage/fields.py

-from django import forms
-from django.utils.translation import ugettext as _
-from transifex.languages.models import Language
-from transifex.storage.models import StorageFile
-from transifex.storage.widgets import StorageFileWidget
-
-
-class StorageFileField(forms.MultiValueField):
-    """
-    Field for handling creation/deletion of StorageFile objects based on
-    file upload.
-
-    Whenever a file is chosen to be uploaded, the upload happens through AJAX
-    using the storage app API, creating a StorageFile object accordingly. The
-    deletion of the uploaded file happens through AJAX too, as the setting of
-    the related language to the StogareFile object.
-
-    In the end this field just returns the StorageFile id, which is the
-    important data used in the forms.
-    """
-    def __init__(self, language=None, *args, **kwargs):
-        attrs = kwargs.pop('attrs', {})
-        language_initial = getattr(language, 'code', None)
-        if language_initial:
-            language_queryset = Language.objects.filter(code=language_initial)
-        else:
-            language_queryset = Language.objects.all()
-
-        language_choices = [(l.code, l) for l in language_queryset]
-        storagefile_choices = StorageFile.objects.all()
-        # Hard coded fields
-        fields = [
-            # The API uses language code, so it can't be a ModelChoiceField
-            forms.ChoiceField(choices=language_choices, initial=language_initial),
-            forms.ModelChoiceField(queryset=storagefile_choices)
-        ]
-        # Hard coded widget
-        widget = StorageFileWidget(attrs=attrs, language=language,
-            language_choices=language_choices,  *args, **kwargs)
-        # Remove unsupported kwarg
-        kwargs.pop('display_language', None)
-        super(StorageFileField, self).__init__(fields, widget=widget,
-            *args, **kwargs)
-
-    def compress(self, data_list):
-        if data_list:
-            return data_list
-        return ['','']
-
-    def clean(self, value):
-        """Return only the StorageFile id/object after all the validations."""
-        data = super(StorageFileField, self).clean(value)
-        return data[1]

transifex/storage/migrations/0001_initial.py

-# encoding: utf-8
-import datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-class Migration(SchemaMigration):
-
-    depends_on = (
-        ("languages", "0001_initial"),
-    )
-
-    def forwards(self, orm):
-
-        # Adding model 'StorageFile'
-        db.create_table('storage_storagefile', (
-            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.CharField')(max_length=1024)),
-            ('size', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
-            ('mime_type', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('uuid', self.gf('django.db.models.fields.CharField')(max_length=1024)),
-            ('language', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['languages.Language'], null=True)),
-            ('bound', self.gf('django.db.models.fields.BooleanField')(default=False)),
-            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True)),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-            ('total_strings', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
-        ))
-        db.send_create_signal('storage', ['StorageFile'])
-
-
-    def backwards(self, orm):
-
-        # Deleting model 'StorageFile'
-        db.delete_table('storage_storagefile')
-
-
-    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'})
-        },
-        'languages.language': {
-            'Meta': {'ordering': "('name',)", 'object_name': 'Language', 'db_table': "'translations_language'"},
-            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
-            'code_aliases': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'null': 'True'}),
-            'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
-            'nplurals': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
-            'pluralequation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
-            'rule_few': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'rule_many': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'rule_one': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'rule_other': ('django.db.models.fields.CharField', [], {'default': "'everything'", 'max_length': '255'}),
-            'rule_two': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'rule_zero': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
-            'specialchars': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
-        },
-        'storage.storagefile': {
-            'Meta': {'object_name': 'StorageFile'},
-            'bound': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'language': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['languages.Language']", 'null': 'True'}),
-            'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
-            'size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
-            'total_strings': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
-            'uuid': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
-        }
-    }
-
-    complete_apps = ['storage']

transifex/storage/migrations/__init__.py

Empty file removed.

transifex/storage/models.py

-# -*- coding: utf-8 -*-
-import os
-import datetime, hashlib, sys
-from django.conf import settings
-from django.db.models import permalink
-from django.contrib.auth.models import User
-from django.db import models
-from django.utils.translation import ugettext_lazy as _
-from django.utils.translation import ugettext
-
-from transifex.languages.models import Language
-from transifex.txcommon.exceptions import FileCheckError
-from transifex.txcommon.log import logger
-
-
-class StorageFile(models.Model):
-    """
-    StorageFile refers to a uploaded file. Initially
-    """
-    # File name of the uploaded file
-    name = models.CharField(max_length=1024)
-    size = models.IntegerField(_('File size in bytes'), blank=True, null=True)
-    mime_type = models.CharField(max_length=255)
-
-    # Path for storage
-    uuid = models.CharField(max_length=1024)
-
-    # Foreign Keys
-    language = models.ForeignKey(Language,
-        verbose_name=_('Source language'),blank=False, null=True,
-        help_text=_("The language in which this translation string is written."))
-
-    #resource = models.ForeignKey(Resource, verbose_name=_('Resource'),
-        #blank=False, null=True,
-        #help_text=_("The translation resource which owns the source string."))
-
-#    project = models.ForeignKey(Project, verbose_name=_('Project'), blank=False, null=True)
-
-    bound = models.BooleanField(verbose_name=_('Bound to any object'), default=False,
-        help_text=_('Whether this file is bound to a project/translation resource, otherwise show in the upload box'))
-
-    user = models.ForeignKey(User,
-        verbose_name=_('Owner'), blank=False, null=True,
-        help_text=_("The user who uploaded the specific file."))
-
-    created = models.DateTimeField(auto_now_add=True, editable=False)
-    total_strings = models.IntegerField(_('Total number of strings'), blank=True, null=True)
-
-    def __unicode__(self):
-        return "%s (%s)" % (self.name, self.uuid)
-
-    def delete(self, *args, **kwargs):
-        """
-        Delete file from filesystem even if object has not been saved yet.
-        """
-        try:
-            os.remove(self.get_storage_path())
-        except OSError, e:
-            if self.id:
-                logger.debug("Error deleting StorageFile: %s" % str(e))
-        if self.id:
-            super(StorageFile, self).delete(*args, **kwargs)
-
-    def get_storage_path(self):
-        filename = "%s-%s" % (self.uuid, self.name)
-        return os.path.join(settings.STORAGE_DIR, filename)
-
-    def translatable(self):
-        """
-        Whether we could extract any strings -> whether we can translate file
-        """
-        return (self.total_strings > 0)
-
-    def find_parser(self):
-        from transifex.resources.formats.registry import registry
-        i18n_type = registry.guess_method(self.name, self.mime_type)
-        if i18n_type is None:
-            msg = "Unsupported resource"
-            if self.name is not None:
-                msg = "Unsupported extension of file: %s" % self.name
-            elif self.mimetype is not None:
-                msg = "Unsupported mimetype %s" % self.mimetype
-            raise FileCheckError(msg)
-        if self.name.endswith('pot'):
-            i18n_type = 'POT'
-        return registry.handler_for(i18n_type)
-
-    def update_props(self):
-        """Try to parse the file and fill in information fields
-        in current model.
-        """
-        from transifex.resources.formats.registry import registry
-        try:
-            parser = self.find_parser()
-        except IndexError, e:
-            raise FileCheckError("Invalid format")
-        if not parser:
-            return
-        self.mime_type = registry.mimetypes_for(parser.method_name)[0]
-        self.save()
-
-        parser.bind_file(filename=self.get_storage_path())
-        parser.set_language(self.language)
-        parser.is_content_valid()
-        parser.parse_file()
-
-        stringset = parser.stringset
-        if not stringset:
-            return
-
-        if stringset.target_language:
-            try:
-                self.language = Language.objects.by_code_or_alias(stringset.target_language)
-            except Language.DoesNotExist:
-                pass
-
-        self.total_strings = len([s for s in stringset if s.rule==5])
-        return

transifex/storage/tests/__init__.py

-from api import *

transifex/storage/tests/api.py

-# -*- coding: utf-8 -*-
-import os
-from django.core.urlresolvers import reverse
-from transifex.txcommon.tests.base import BaseTestCase
-
-FILENAME = 'pt_BR.po'
-
-class BaseStorageTests(BaseTestCase):
-    """Base test abstraction for storage app."""
-
-    def create_storage(self):
-        """Create StorageFile"""
-
-        upload_file = open('%s/%s' % (os.path.split(__file__)[0], FILENAME))
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['anonymous'].post(reverse('api.storage'), data)
-        self.assertEqual(resp.status_code, 401)
-
-        upload_file = open('%s/%s' % (os.path.split(__file__)[0], FILENAME))
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        self.assertTrue(FILENAME in resp.content)
-
-        for f in eval(resp.content)['files']:
-            if f['name'] == FILENAME:
-                self.uuid = f['uuid']
-                break
-
-class StorageTests(BaseStorageTests):
-    """Test the storage app."""
-
-    def test_create_storage_with_invalid_file(self):
-        """Create StorageFile with invalid file."""
-
-        # Test empty file
-        upload_file = open('%s/empty.pot' % os.path.split(__file__)[0]) # hack
-        data = {'language': self.language_en.code, 'file': upload_file}
-        resp = self.client['registered'].post(reverse('api.storage'), data)
-        self.assertIn('Uploaded file is empty', resp.content)
-
-
-    def test_update_storage_language(self):
-        """Test update of language for StorageFile."""
-        self.create_storage()
-        data = '{"language": "%s"}' % self.language.code
-        resp = self.client['registered'].post(reverse('api.storage.file',
-            args=[self.uuid]), data=data, content_type="application/json")
-        print resp.content
-        self.assertEqual(resp.status_code, 200)
-        self.assertTrue('OK' in resp.content)
-
-
-    def test_get_storage(self):
-        """Get info for StorageFile"""
-        self.create_storage()
-
-        resp = self.client['registered'].get(reverse('api.storage.file',
-            args=[self.uuid]))
-        self.assertEqual(resp.status_code, 200)
-        self.assertTrue(self.uuid in resp.content)
-        self.assertTrue(self.language_en.name in resp.content)
-
-
-    def test_delete_storage(self):
-        """Delete StorageFile"""
-        self.create_storage()
-
-        # Storage only can be deleted by the person who created it
-        resp = self.client['maintainer'].delete(reverse('api.storage.file',
-            args=[self.uuid]))
-        self.assertEqual(resp.status_code, 404)
-
-        resp = self.client['registered'].delete(reverse('api.storage.file',
-            args=[self.uuid]))
-        self.assertEqual(resp.status_code, 204)

transifex/storage/tests/empty.pot

Empty file removed.

transifex/storage/tests/pt_BR.po

-# Diego Búrigo Zacarão <diegobz@indifex.com>, 2010.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: tests\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-06-08 10:12+0300\n"
-"PO-Revision-Date: 2010-06-08 10:12+0300\n"
-"Last-Translator: Diego Búrigo Zacarão <diegobz@indifex.com>\n"
-"Language-Team: Brazilian Portuguese\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-
-#: actionlog/templates/object_action_list.html:7 txpermissions/forms.py:18
-msgid "User"
-msgstr "Usuário"
-
-#: actionlog/templates/object_action_list.html:8
-msgid "Action"
-msgstr "Ação"
-
-#: foo/templates/bar.html:180
-msgid "{0} result"
-msgid_plural "{0} results"
-msgstr[0] "{0} resultado"
-msgstr[1] "{0} resultados"

transifex/storage/widgets.py

-from django import forms
-from django.forms.util import flatatt
-from django.template.loader import render_to_string
-from django.utils.safestring import mark_safe
-from django.utils.translation import ugettext as _
-
-from transifex.languages.models import Language
-from transifex.storage.models import StorageFile
-from transifex.txcommon.log import logger
-from transifex.txcommon.utils import get_url_pattern
-
-class StorageFileWidget(forms.MultiWidget):
-    """
-    Widgets for handling StorageFile objects creation/deletion. It can be
-    used with normal Django forms. Everything happens through AJAX using the
-    storage app API.
-    """
-    def __init__(self, *args, **kwargs):
-        attrs = kwargs.pop('attrs', {})
-        language = kwargs.pop('language', {})
-        display_language = kwargs.pop('display_language', False)
-        
-        if not display_language:
-            language_field=forms.HiddenInput(attrs=attrs)
-        else:
-            self.language_choices = kwargs.pop('language_choices', [])
-            if not self.language_choices:
-                queryset = Language.objects.all()
-                self.language_choices = [(l.code, l) for l in queryset]
-            self.language_choices.insert(0, ("", "---------"))
-
-            language_field = forms.Select(attrs=attrs,
-                choices=self.language_choices)
-
-        widgets=(
-            language_field,
-            forms.HiddenInput(attrs=attrs)
-        )
-        super(StorageFileWidget, self).__init__(widgets, attrs)
-
-    def render(self, name, value, attrs):
-        if hasattr(self, 'initial'):
-            value = self.initial
-
-        final_attrs = self.build_attrs(attrs)
-        self.html_id = final_attrs.pop('id', name)
-
-        if not isinstance(value, list):
-            value = self.decompress(value)
-
-        # Querying objects
-        language, storagefile = None, None
-        if value:
-            try:
-                language = Language.objects.by_code_or_alias(value[0])
-            except Exception, e:
-                pass
-            try:
-                storagefile = StorageFile.objects.get(id=int(value[1]))
-            except Exception, e:
-                pass
-
-        # Fields in HTML
-        rendered_fields = []
-        rendered_fields.append(self.widgets[0].render(name + '_0',
-            getattr(language, 'code', None), final_attrs))
-        rendered_fields.append(self.widgets[1].render(name + '_1',
-            getattr(storagefile, 'id', None), final_attrs))
-
-        context = {
-                'name': name,
-                'names': [name + '_%s' %n for n, w in enumerate(self.widgets)],
-                'storagefile': storagefile,
-                'rendered_fields': rendered_fields,
-                'api_storagefile_url': get_url_pattern('api.storage.file'),
-                }
-
-        return mark_safe(
-            render_to_string('storage/storagefilewidget.html', context)
-            )
-
-    def decompress(self, value):
-        if value:
-            return value
-        return ['','']

transifex/templates/storage/storagefilewidget.html

-{% load i18n %}
-
-{% comment %}
-
-Expected context vars:
-    name: StorageFile field name from the form
-    names: List of StorageFileField field names - [language, storagefile]
-    rendered_fields: List of HTML rendered field of StorageFileField - [language, storagefile]
-    storagefile: StorageFile object, when it exists
-
-{% endcomment %}
-
-{{ rendered_fields.0 }}
-{{ rendered_fields.1 }}
-<input id="{{ name }}-id-uuid" type="hidden" name="{{ name }}-uuid" value="{{ storagefile.uuid }}" />
-<span id="{{ name }}-upload_button" class="i16 send_file buttonized" style="line-height:1em; {% if storagefile %}display:none;{% endif %} margin-left:1em;">{% trans "Upload file" %}</span>
-<span id="{{ name }}-uploaded_file" class="i16 delete buttonized" style="line-height:1.12em;{% if not storagefile %}display:none;{% endif %} margin-left:1em;">{{ storagefile.name }}</span>
-
-<script type="text/javascript">
-/*
-TODO: Write it using Classes
-*/
-
-function show_uploadedfile(file, uuid){
-    /*
-    Handle and add events of top of a uploaded file.
-    */
-    $("#{{ name }}-upload_button").hide();
-    $("#{{ name }}-uploaded_file").html(file);
-    $("#{{ name }}-uploaded_file").show();
-    $("#{{ name }}-uploaded_file").hover(function () {
-      $(this).addClass("underline");
-    }, function () {
-      $(this).removeClass("underline");
-    });
-
-    $("#{{ name }}-uploaded_file").unbind("click").click(function() {
-        $.ajax({
-            url : sprintf('{{ api_storagefile_url }}', uuid),
-            type : 'DELETE',
-            beforeSend: function(){
-            $("div#notification-container div").html(sprintf("Deleting '%s'", file));
-            $("div#notification-container").fadeIn("fast");
-            },
-            complete : function(xmlhttpreq, textStatus) {
-                $("#{{ name }}-uploaded_file").hide();
-                $("#{{ name }}-upload_button").show();
-                $("input[name='{{ names.1 }}']").val('');
-                $("input[name='{{ name }}-uuid']").val('');
-                $("div#notification-container").fadeOut("fast");
-                first_select_language(update_language=true);
-            }
-        });
-    });
-}
-
-function first_select_language(update_language){
-    /*
-    Make sure user can see the upload button only if a language is already selected.
-    */
-    if($("select[name='{{ names.0 }}'] option:selected").val()!=''){
-        if($("input[name={{ names.1 }}]").val()!=''){
-            $("#{{ name }}-uploaded_file").show();
-            if(update_language==true){
-                $.ajax({
-                    url : sprintf('{{ api_storagefile_url }}',  $("#{{ name }}-id-uuid").val()),
-                    contentType : 'application/json',
-                    type : 'POST',
-                    data : JSON.stringify({
-                        'language':$("select[name='{{ names.0 }}'] option:selected").val()
-                    }),
-                    beforeSend: function(){
-                    $("div#notification-container div").html(
-                        sprintf("Updating language info for uploaded file."));
-                    $("div#notification-container").fadeIn("fast");
-                    },
-                    complete : function(xmlhttpreq, textStatus) {
-                        $("div#notification-container").fadeOut("fast");
-                    }
-                });
-            }
-        }else{
-            $("#{{ name }}-upload_button").show();
-        }
-    }else{
-        $("#{{ name }}-upload_button").hide();
-    }
-}
-
-
-jQuery(document).ready(function($){
-
-    /* Bind ajax upload button */
-    new AjaxUpload("{{ name }}-upload_button", {
-        action: "{% url api.storage %}",
-        responseType: "json",
-        onSubmit : function(file, extension) {
-            this.setData({
-                'language': $("[name='{{ names.0 }}']").val(),
-                });
-
-            $("div#notification-container div").html(sprintf("Uploading '%s'", file));
-            $("div#notification-container").fadeIn("fast");
-            this.disable();
-        },
-        onComplete : function(file, response) {
-            if(typeof(response['status']) !== 'undefined' && response['status'] == "Created"){
-                storagefile = response['files'][0]
-                show_uploadedfile(file, storagefile['uuid'])
-                $("input[name={{ names.1 }}]").val(storagefile['id']);
-                $("#{{ name }}-id-uuid").val(storagefile['uuid']);
-                $("#{{ name }}-id-uuid").trigger('change');
-                $("#create-resource-btn").fadeIn("slow");
-            }else{
-                if (typeof(response['message']) !== 'undefined')
-                    alert(response['message']);
-            }
-            $("div#notification-container").fadeOut("fast");
-            this.enable();
-        }
-    });
-
-    {% if storagefile %}
-        show_uploadedfile('{{ storagefile.name }}', '{{ storagefile.uuid }}');
-    {% endif %}
-
-    $("[name='{{ names.0 }}']").change(function () {
-        first_select_language(update_language=true);
-    });
-
-    first_select_language(update_language=false);
-
-});
-</script>