diff --git a/bower.json b/bower.json
index dfed8f57a..71c302343 100644
--- a/bower.json
+++ b/bower.json
@@ -24,6 +24,7 @@
"sockjs": "~0.3.4",
"font-awesome-bower": "4.3.0",
"js-data": "~2.3.0",
- "js-data-angular": "~3.0.0"
+ "js-data-angular": "~3.0.0",
+ "ng-file-upload": "~7.0.17"
}
}
diff --git a/openslides/mediafiles/migrations/0002_auto_20150906_1246.py b/openslides/mediafiles/migrations/0002_auto_20150906_1246.py
new file mode 100644
index 000000000..1d1efd94a
--- /dev/null
+++ b/openslides/mediafiles/migrations/0002_auto_20150906_1246.py
@@ -0,0 +1,20 @@
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('mediafiles', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='mediafile',
+ name='is_presentable',
+ ),
+ migrations.AlterField(
+ model_name='mediafile',
+ name='title',
+ field=models.CharField(max_length=255, null=True, unique=True, blank=True, verbose_name='Title'),
+ ),
+ ]
diff --git a/openslides/mediafiles/migrations/0003_auto_20150917_1226.py b/openslides/mediafiles/migrations/0003_auto_20150917_1226.py
new file mode 100644
index 000000000..3c89fd894
--- /dev/null
+++ b/openslides/mediafiles/migrations/0003_auto_20150917_1226.py
@@ -0,0 +1,20 @@
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ('mediafiles', '0002_auto_20150906_1246'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='mediafile',
+ name='filetype',
+ ),
+ migrations.AlterField(
+ model_name='mediafile',
+ name='title',
+ field=models.CharField(unique=True, verbose_name='Title', max_length=255, default='', blank=True),
+ preserve_default=False,
+ ),
+ ]
diff --git a/openslides/mediafiles/models.py b/openslides/mediafiles/models.py
index d645d9948..f2489c482 100644
--- a/openslides/mediafiles/models.py
+++ b/openslides/mediafiles/models.py
@@ -1,5 +1,3 @@
-import mimetypes
-
from django.db import models
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
@@ -13,7 +11,6 @@ class Mediafile(RESTModelMixin, models.Model):
Class for uploaded files which can be delivered under a certain url.
"""
slide_callback_name = 'mediafile'
- PRESENTABLE_FILE_TYPES = ['application/pdf']
mediafile = models.FileField(upload_to='file', verbose_name=ugettext_lazy('File'))
"""
@@ -21,7 +18,7 @@ class Mediafile(RESTModelMixin, models.Model):
for more information.
"""
- title = models.CharField(max_length=255, unique=True, verbose_name=ugettext_lazy('Title'))
+ title = models.CharField(max_length=255, unique=True, blank=True, verbose_name=ugettext_lazy('Title'))
"""A string representing the title of the file."""
uploader = models.ForeignKey(User, null=True, blank=True, verbose_name=ugettext_lazy('Uploaded by'))
@@ -30,15 +27,6 @@ class Mediafile(RESTModelMixin, models.Model):
timestamp = models.DateTimeField(auto_now_add=True)
"""A DateTimeField to save the upload date and time."""
- filetype = models.CharField(max_length=255, editable=False)
- """A string used to show the type of the file."""
-
- is_presentable = models.BooleanField(
- default=False,
- verbose_name=ugettext_lazy("Is Presentable"),
- help_text=ugettext_lazy("If checked, this file can be presented on the projector. "
- "Currently, this is only possible for PDFs."))
-
class Meta:
"""
Meta class for the mediafile model.
@@ -55,16 +43,6 @@ class Mediafile(RESTModelMixin, models.Model):
"""
return self.title
- def save(self, *args, **kwargs):
- """
- Method to read filetype and then save to the database.
- """
- if self.mediafile:
- self.filetype = mimetypes.guess_type(self.mediafile.path)[0] or ugettext_noop('unknown')
- else:
- self.filetype = ugettext_noop('unknown')
- return super(Mediafile, self).save(*args, **kwargs)
-
def get_filesize(self):
"""
Transforms bytes to kilobytes or megabytes. Returns the size as string.
diff --git a/openslides/mediafiles/projector.py b/openslides/mediafiles/projector.py
index 32ec3bd44..fbe2a6be9 100644
--- a/openslides/mediafiles/projector.py
+++ b/openslides/mediafiles/projector.py
@@ -16,11 +16,9 @@ class MediafileSlide(ProjectorElement):
def get_context(self):
pk = self.config_entry.get('id')
try:
- mediafile = Mediafile.objects.get(pk=pk)
+ Mediafile.objects.get(pk=pk)
except Mediafile.DoesNotExist:
raise ProjectorException(_('File does not exist.'))
- if not (mediafile.is_presentable and mediafile.filetype == 'application/pdf'):
- raise ProjectorException(_('File is not presentable.'))
return {'id': pk}
def get_requirements(self, config_entry):
diff --git a/openslides/mediafiles/serializers.py b/openslides/mediafiles/serializers.py
index db2c9a074..01946cd93 100644
--- a/openslides/mediafiles/serializers.py
+++ b/openslides/mediafiles/serializers.py
@@ -1,14 +1,41 @@
-from openslides.utils.rest_api import ModelSerializer, SerializerMethodField
+import mimetypes
+from django.db import models as dbmodels
+
+from ..utils.rest_api import FileField, ModelSerializer, SerializerMethodField
from .models import Mediafile
+class AngularCompatibleFileField(FileField):
+
+ def to_internal_value(self, data):
+ if data == '':
+ return None
+ return super(AngularCompatibleFileField, self).to_internal_value(data)
+
+ def to_representation(self, value):
+ if value is None:
+ return None
+ return {
+ 'name': value.name,
+ 'type': mimetypes.guess_type(value.path)[0]
+ }
+
+
class MediafileSerializer(ModelSerializer):
"""
Serializer for mediafile.models.Mediafile objects.
"""
filesize = SerializerMethodField()
+ def __init__(self, *args, **kwargs):
+ """
+ This constructor overwrites the FileField field serializer to return the file meta data in a way that the
+ angualarjs upload module likes
+ """
+ super(MediafileSerializer, self).__init__(*args, **kwargs)
+ self.serializer_field_mapping[dbmodels.FileField] = AngularCompatibleFileField
+
class Meta:
model = Mediafile
fields = (
@@ -18,8 +45,7 @@ class MediafileSerializer(ModelSerializer):
'uploader',
'filesize',
'filetype',
- 'timestamp',
- 'is_presentable',)
+ 'timestamp',)
def get_filesize(self, mediafile):
return mediafile.get_filesize()
diff --git a/openslides/mediafiles/static/js/mediafiles/mediafiles.js b/openslides/mediafiles/static/js/mediafiles/mediafiles.js
index e08cb4f77..8288841d8 100644
--- a/openslides/mediafiles/static/js/mediafiles/mediafiles.js
+++ b/openslides/mediafiles/static/js/mediafiles/mediafiles.js
@@ -5,13 +5,47 @@ angular.module('OpenSlidesApp.mediafiles', [])
.factory('Mediafile', ['DS', function(DS) {
return DS.defineResource({
name: 'mediafiles/mediafile',
+ computed: {
+ is_presentable: ['filetype', function (filetype) {
+ var PRESENTABLE_FILE_TYPES = ['application/pdf']
+ return _.contains(PRESENTABLE_FILE_TYPES, filetype);
+ }],
+ filename: [function () {
+ var filename = this.mediafile.name;
+ return /\/(.+?)$/.exec(filename)[1];
+ }],
+ title_or_filename: ['title', 'mediafile', function (title) {
+ return title || this.filename;
+ }]
+ }
});
}])
.run(['Mediafile', function(Mediafile) {}]);
+function uploadFile($timeout, $scope, $state, Upload, mediafile) {
+ return function(file) {
+ file.upload = Upload.upload({
+ url: '/rest/mediafiles/mediafile/' + (mediafile ? mediafile.id : ''),
+ method: mediafile ? 'PUT' : 'POST',
+ fields: {title: file.title},
+ file: file.mediafile,
+ fileFormDataName: 'mediafile'
+ });
-angular.module('OpenSlidesApp.mediafiles.site', ['OpenSlidesApp.mediafiles'])
+ file.upload.then(function (response) {
+ $timeout(function () {
+ file.result = response.data;
+ $state.go('mediafiles.mediafile.list');
+ });
+ }, function (response) {
+ if (response.status > 0)
+ $scope.errorMsg = response.status + ': ' + response.data;
+ });
+ }
+}
+
+angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.mediafiles'])
.config([
'mainMenuProvider',
@@ -45,6 +79,18 @@ angular.module('OpenSlidesApp.mediafiles.site', ['OpenSlidesApp.mediafiles'])
}
})
.state('mediafiles.mediafile.create', {})
+ .state('mediafiles.mediafile.detail', {
+ url: '/{id:int}',
+ abstract: true,
+ resolve: {
+ mediafile: function(Mediafile, $stateParams) {
+ var id = $stateParams.id;
+ var file = Mediafile.find(id);
+ return file;
+ }
+ },
+ template: "