work on pdf presenter support
This commit is contained in:
parent
2307bdc188
commit
3c691b9937
@ -31,6 +31,10 @@
|
|||||||
"ckeditor": "~4.5.4",
|
"ckeditor": "~4.5.4",
|
||||||
"angular-ckeditor": "~1.0.0",
|
"angular-ckeditor": "~1.0.0",
|
||||||
"roboto-condensed": "~0.3.0",
|
"roboto-condensed": "~0.3.0",
|
||||||
"open-sans-fontface": "https://github.com/OpenSlides/open-sans.git#1.4.2.post1"
|
"open-sans-fontface": "https://github.com/OpenSlides/open-sans.git#1.4.2.post1",
|
||||||
|
"angular-pdf": "~1.3.0"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"angular": ">= 1.4.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import mimetypes
|
|||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models as dbmodels
|
from django.db import models as dbmodels
|
||||||
|
from PyPDF2 import PdfFileReader
|
||||||
|
|
||||||
from ..utils.rest_api import FileField, ModelSerializer, SerializerMethodField
|
from ..utils.rest_api import FileField, ModelSerializer, SerializerMethodField
|
||||||
from .models import Mediafile
|
from .models import Mediafile
|
||||||
@ -17,10 +18,14 @@ class AngularCompatibleFileField(FileField):
|
|||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
return {
|
filetype = mimetypes.guess_type(value.path)[0]
|
||||||
|
result = {
|
||||||
'name': value.name,
|
'name': value.name,
|
||||||
'type': mimetypes.guess_type(value.path)[0]
|
'type': filetype
|
||||||
}
|
}
|
||||||
|
if filetype == 'application/pdf':
|
||||||
|
result['pages'] = PdfFileReader(open(value.path, 'rb')).getNumPages()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class MediafileSerializer(ModelSerializer):
|
class MediafileSerializer(ModelSerializer):
|
||||||
|
@ -4,4 +4,62 @@
|
|||||||
|
|
||||||
angular.module('OpenSlidesApp.mediafiles.projector', ['OpenSlidesApp.mediafiles']);
|
angular.module('OpenSlidesApp.mediafiles.projector', ['OpenSlidesApp.mediafiles']);
|
||||||
|
|
||||||
}());
|
.config([
|
||||||
|
'slidesProvider',
|
||||||
|
function(slidesProvider) {
|
||||||
|
slidesProvider.registerSlide('mediafiles/mediafile', {
|
||||||
|
template: 'static/templates/mediafiles/slide_mediafile.html'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.controller('SlideMediafileCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'Mediafile',
|
||||||
|
function($scope, Mediafile) {
|
||||||
|
|
||||||
|
var id = $scope.element.mediafile;
|
||||||
|
$scope.page = $scope.element.page;
|
||||||
|
|
||||||
|
function updateScale() {
|
||||||
|
if($scope.element.pageFit) {
|
||||||
|
$scope.scale = 'page-fit';
|
||||||
|
} else {
|
||||||
|
$scope.scale = $scope.element.scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.$watch(function() {
|
||||||
|
return $scope.element.scale;
|
||||||
|
}, updateScale);
|
||||||
|
|
||||||
|
updateScale();
|
||||||
|
|
||||||
|
var mediafile = Mediafile.find(id);
|
||||||
|
mediafile.then(function(mediafile) {
|
||||||
|
$scope.pdfName = mediafile.title;
|
||||||
|
$scope.pdfUrl = mediafile.mediafileUrl;
|
||||||
|
})
|
||||||
|
|
||||||
|
$scope.scroll = 0;
|
||||||
|
|
||||||
|
$scope.getNavStyle = function(scroll) {
|
||||||
|
if(scroll > 100) return 'pdf-controls fixed';
|
||||||
|
else return 'pdf-controls';
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onError = function(error) {
|
||||||
|
console.log(error);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onLoad = function() {
|
||||||
|
$scope.loading = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.onProgress = function(progress) {
|
||||||
|
console.log(progress);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
||||||
|
@ -59,6 +59,20 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
|
|||||||
$scope.sortColumn = 'title';
|
$scope.sortColumn = 'title';
|
||||||
$scope.filterPresent = '';
|
$scope.filterPresent = '';
|
||||||
$scope.reverse = false;
|
$scope.reverse = false;
|
||||||
|
|
||||||
|
function updatePresentedMediafiles() {
|
||||||
|
var projectorElements = _.map(Projector.get(1).elements, function(element) { return element });
|
||||||
|
$scope.presentedMediafiles = _.filter(projectorElements, function (element) {
|
||||||
|
return element.name === 'mediafiles/mediafile';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.$watch(function() {
|
||||||
|
return Projector.get(1).elements;
|
||||||
|
}, updatePresentedMediafiles);
|
||||||
|
|
||||||
|
updatePresentedMediafiles();
|
||||||
|
|
||||||
// function to sort by clicked column
|
// function to sort by clicked column
|
||||||
$scope.toggleSort = function ( column ) {
|
$scope.toggleSort = function ( column ) {
|
||||||
if ( $scope.sortColumn === column ) {
|
if ( $scope.sortColumn === column ) {
|
||||||
@ -111,6 +125,110 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
|
|||||||
$scope.delete = function (mediafile) {
|
$scope.delete = function (mediafile) {
|
||||||
Mediafile.destroy(mediafile.id);
|
Mediafile.destroy(mediafile.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// show document on projector
|
||||||
|
$scope.showPdf = function (mediafile) {
|
||||||
|
var postUrl,
|
||||||
|
data;
|
||||||
|
if($scope.presentedMediafiles.length > 0) {
|
||||||
|
// update first mediafile, at the moment there should not be more
|
||||||
|
var uuid = $scope.presentedMediafiles[0].uuid;
|
||||||
|
postUrl = '/rest/core/projector/1/update_elements/';
|
||||||
|
data = {};
|
||||||
|
data[uuid] = {
|
||||||
|
mediafile: mediafile.id,
|
||||||
|
numPages: mediafile.mediafile.pages,
|
||||||
|
page: 1,
|
||||||
|
pageFit: true,
|
||||||
|
scale: 1,
|
||||||
|
visible: true
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
postUrl = '/rest/core/projector/1/activate_elements/';
|
||||||
|
data = [{
|
||||||
|
name: 'mediafiles/mediafile',
|
||||||
|
visible: true,
|
||||||
|
numPages: mediafile.mediafile.pages,
|
||||||
|
pageFit: true,
|
||||||
|
scale: 1,
|
||||||
|
mediafile: mediafile.id,
|
||||||
|
page: 1
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
$http.post(postUrl, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
function sendMediafileCommand(data) {
|
||||||
|
var mediafileElement = getCurrentlyPresentedMediafile();
|
||||||
|
var updateData = _.extend({}, mediafileElement);
|
||||||
|
_.extend(updateData, data);
|
||||||
|
var postData = {};
|
||||||
|
postData[mediafileElement.uuid] = updateData;
|
||||||
|
$http.post('/rest/core/projector/1/update_elements/', postData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentlyPresentedMediafile() {
|
||||||
|
return $scope.presentedMediafiles[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.mediafileGoPrevious = function () {
|
||||||
|
var mediafileElement = getCurrentlyPresentedMediafile();
|
||||||
|
if (mediafileElement.page <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendMediafileCommand({
|
||||||
|
page: parseInt(mediafileElement.page) - 1
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileGoNext = function () {
|
||||||
|
var mediafileElement = getCurrentlyPresentedMediafile();
|
||||||
|
if (mediafileElement.page >= mediafileElement.numPages) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendMediafileCommand({
|
||||||
|
page: parseInt(mediafileElement.page) + 1
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileZoomIn = function () {
|
||||||
|
var mediafileElement = getCurrentlyPresentedMediafile();
|
||||||
|
sendMediafileCommand({
|
||||||
|
pageFit: false,
|
||||||
|
scale: parseFloat(mediafileElement.scale) + 0.2
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileFit = function () {
|
||||||
|
sendMediafileCommand({
|
||||||
|
pageFit: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileZoomOut = function () {
|
||||||
|
var mediafileElement = getCurrentlyPresentedMediafile();
|
||||||
|
sendMediafileCommand({
|
||||||
|
pageFit: false,
|
||||||
|
scale: parseFloat(mediafileElement.scale) - 0.2
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileChangePage = function(pageNum) {
|
||||||
|
sendMediafileCommand({
|
||||||
|
pageToDisplay: pageNum
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$scope.mediafileRotate = function () {
|
||||||
|
var rotation;
|
||||||
|
var currentRotation = $scope.mediafile.rotation;
|
||||||
|
if (currentRotation === 0) {
|
||||||
|
rotation = 90;
|
||||||
|
} else if (currentRotation === 90) {
|
||||||
|
rotation = 180;
|
||||||
|
} else if (currentRotation === 180) {
|
||||||
|
rotation = 270;
|
||||||
|
} else {
|
||||||
|
rotation = 0;
|
||||||
|
}
|
||||||
|
sendMediafileCommand({
|
||||||
|
rotation: rotation
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -10,6 +10,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- mediafile pdf controls -->
|
||||||
|
<div os-perms-lite="core.can_manage_projector" ng-if="presentedMediafiles.length">
|
||||||
|
|
||||||
|
<div ng-repeat="presentedMediafile in presentedMediafiles">
|
||||||
|
<h3 translate>PDF controls</h3>
|
||||||
|
<nav ng-class="getNavStyle(scroll)">
|
||||||
|
<button ng-click="mediafileGoPrevious()"><</span></button>
|
||||||
|
<button ng-click="mediafileGoNext()">></span></button>
|
||||||
|
|
||||||
|
<button ng-click="mediafileZoomIn()">+</span></button>
|
||||||
|
<button ng-click="mediafileFit()">100%</span></button>
|
||||||
|
<button ng-click="mediafileZoomOut()">-</span></button>
|
||||||
|
|
||||||
|
<span>Page: </span>
|
||||||
|
<input type="text" min=1 ng-model="presentedMediafile.page">
|
||||||
|
<span> / {{presentedMediafile.numPages}}</span>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<div ng-controller="SlideMediafileCtrl" class="content">
|
||||||
|
<ng-pdf template-url="/static/templates/mediafiles/slide_mediafile_partial.html"
|
||||||
|
scale="page-fit"
|
||||||
|
ng-attr-scale="{{ scale }}"
|
||||||
|
ng-attr-page="{{ page }}"
|
||||||
|
debug="true">
|
||||||
|
</ng-pdf>
|
||||||
|
</div>
|
@ -0,0 +1 @@
|
|||||||
|
<canvas id="pdf-canvas" class="rotate0"></canvas>
|
@ -9,4 +9,5 @@ reportlab>=3.0,<3.3
|
|||||||
roman>=2.0,<2.1
|
roman>=2.0,<2.1
|
||||||
setuptools>=2.2,<20.0
|
setuptools>=2.2,<20.0
|
||||||
sockjs-tornado>=1.0,<1.1
|
sockjs-tornado>=1.0,<1.1
|
||||||
Whoosh>=2.7,<2.8
|
Whoosh>=2.7.0,<2.8
|
||||||
|
PyPDF2==1.25.1
|
||||||
|
Loading…
Reference in New Issue
Block a user