Mediafile: Improvements for pdf presentaiton and list view.

This commit is contained in:
Emanuel Schuetze 2016-02-01 12:51:37 +01:00
parent 15bb62b39a
commit af023f30bc
7 changed files with 119 additions and 105 deletions

View File

@ -85,6 +85,20 @@ body{
transition-property: margin, font-size; transition-property: margin, font-size;
transition-duration: 1s; transition-duration: 1s;
} }
.fullscreen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background-color: black;
}
.fullscreen canvas {
margin: auto;
display: block !important;
}
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
font-family: "Roboto Condensed",Helvetica,Arial,sans-serif; font-family: "Roboto Condensed",Helvetica,Arial,sans-serif;
font-weight: normal; font-weight: normal;
@ -213,6 +227,19 @@ hr {
z-index: 301; z-index: 301;
} }
/*** PDF presentation ***/
.rotate0 {
transform: rotate(0deg);
}
.rotate90 {
transform: rotate(90deg);
}
.rotate180 {
transform: rotate(180deg);
}
.rotate270 {
transform: rotate(270deg);
}
/*** Table style ***/ /*** Table style ***/
.table { .table {

View File

@ -11,6 +11,12 @@ angular.module('OpenSlidesApp.mediafiles', [])
var name = 'mediafiles/mediafile'; var name = 'mediafiles/mediafile';
return DS.defineResource({ return DS.defineResource({
name: name, name: name,
useClass: jsDataModel,
methods: {
getResourceName: function () {
return name;
}
},
computed: { computed: {
is_presentable: ['filetype', function (filetype) { is_presentable: ['filetype', function (filetype) {
var PRESENTABLE_FILE_TYPES = ['application/pdf']; var PRESENTABLE_FILE_TYPES = ['application/pdf'];

View File

@ -23,35 +23,6 @@ angular.module('OpenSlidesApp.mediafiles.projector', ['OpenSlidesApp.mediafiles'
$scope.pdfName = mediafile.title; $scope.pdfName = mediafile.title;
$scope.pdfUrl = mediafile.mediafileUrl; $scope.pdfUrl = mediafile.mediafileUrl;
}) })
// get page from projector
$scope.page = $scope.element.page;
$scope.scroll = 0;
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();
$scope.getNavStyle = function(scroll) {
if (scroll > 100) {
return 'pdf-controls fixed';
} else {
return 'pdf-controls';
}
};
$scope.onLoad = function() {
$scope.loading = '';
};
} }
]); ]);

View File

@ -66,6 +66,11 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
$scope.presentedMediafiles = _.filter(projectorElements, function (element) { $scope.presentedMediafiles = _.filter(projectorElements, function (element) {
return element.name === 'mediafiles/mediafile'; return element.name === 'mediafiles/mediafile';
}); });
if ($scope.presentedMediafiles.length) {
$scope.isMeta = false;
} else {
$scope.isMeta = true;
}
} }
$scope.$watch(function() { $scope.$watch(function() {
@ -141,8 +146,8 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
id: mediafile.id, id: mediafile.id,
numPages: mediafile.mediafile.pages, numPages: mediafile.mediafile.pages,
page: 1, page: 1,
pageFit: true,
scale: 1, scale: 1,
rotate: 0,
visible: true visible: true
}; };
} else { } else {
@ -151,10 +156,10 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
name: 'mediafiles/mediafile', name: 'mediafiles/mediafile',
id: mediafile.id, id: mediafile.id,
numPages: mediafile.mediafile.pages, numPages: mediafile.mediafile.pages,
visible: true, page: 1,
pageFit: true,
scale: 1, scale: 1,
page: 1 rotate: 0,
visible: true
}]; }];
} }
$http.post(postUrl, data); $http.post(postUrl, data);
@ -173,38 +178,32 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
return $scope.presentedMediafiles[0]; return $scope.presentedMediafiles[0];
} }
$scope.mediafileGoPrevious = function () { $scope.getTitle = function (presentedMediafile) {
var mediafileElement = getCurrentlyPresentedMediafile(); return Mediafile.get(presentedMediafile.id).title;
if (mediafileElement.page > 1) {
sendMediafileCommand({
page: parseInt(mediafileElement.page) - 1
});
}
}; };
$scope.mediafileGoNext = function () {
$scope.mediafileGoToPage = function (page) {
var mediafileElement = getCurrentlyPresentedMediafile(); var mediafileElement = getCurrentlyPresentedMediafile();
if (mediafileElement.page < mediafileElement.numPages) { if (parseInt(page) > 0) {
sendMediafileCommand({ sendMediafileCommand({
page: parseInt(mediafileElement.page) + 1 page: parseInt(page)
}); });
} }
}; };
$scope.mediafileZoomIn = function () { $scope.mediafileZoomIn = function () {
var mediafileElement = getCurrentlyPresentedMediafile(); var mediafileElement = getCurrentlyPresentedMediafile();
sendMediafileCommand({ sendMediafileCommand({
pageFit: false,
scale: parseFloat(mediafileElement.scale) + 0.2 scale: parseFloat(mediafileElement.scale) + 0.2
}); });
}; };
$scope.mediafileFit = function () { $scope.mediafileFit = function () {
sendMediafileCommand({ sendMediafileCommand({
pageFit: true scale: 1
}); });
}; };
$scope.mediafileZoomOut = function () { $scope.mediafileZoomOut = function () {
var mediafileElement = getCurrentlyPresentedMediafile(); var mediafileElement = getCurrentlyPresentedMediafile();
sendMediafileCommand({ sendMediafileCommand({
pageFit: false,
scale: parseFloat(mediafileElement.scale) - 0.2 scale: parseFloat(mediafileElement.scale) - 0.2
}); });
}; };
@ -214,15 +213,15 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp.
}); });
}; };
$scope.mediafileRotate = function () { $scope.mediafileRotate = function () {
var rotation; var mediafileElement = getCurrentlyPresentedMediafile();
var currentRotation = $scope.mediafile.rotation; var rotation = mediafileElement.rotate;
if (currentRotation === 270) { if (rotation === 270) {
rotation = 0; rotation = 0;
} else { } else {
rotation = currentRotation + 90; rotation = rotation + 90;
} }
sendMediafileCommand({ sendMediafileCommand({
rotation: rotation rotate: rotation
}); });
}; };
} }

View File

@ -10,6 +10,65 @@
</div> </div>
</div> </div>
<div class="meta" os-perms="core.can_manage_projector">
<div class="title" ng-click="isMeta = !isMeta">
<div class="name">
<i class="fa fa-play-circle"></i>
<translate>Presentation control elements</translate>
</div>
<div class="icon">
<i class="fa fa-lg" ng-class="isMeta ? 'fa-angle-down' : 'fa-angle-up'"></i>
</div>
</div>
<div class="detail" uib-collapse="isMeta">
<!-- mediafile pdf controls -->
<div class="row">
<div class="col-md-12">
<div ng-repeat="presentedMediafile in presentedMediafiles">
<h3>{{ getTitle(presentedMediafile) }}</h3>
<nav ng-class="getNavStyle(scroll)" class="form-inline">
<div class="btn-group">
<button class="btn btn-default" ng-click="mediafileGoToPage(presentedMediafile.page - 1)"
title="{{ 'Previous page' | translate }}">
<i class="fa fa-backward"></i>
</button>
<button class="btn btn-default" ng-click="mediafileGoToPage(presentedMediafile.page + 1)"
title="{{ 'Next page' | translate }}">
<i class="fa fa-forward"></i>
</button>
</div>
<div class="input-group">
<span class="input-group-addon" translate>Page</span>
<input type="number" min=1 ng-model="presentedMediafile.page" class="form-control" style="width: 80px"
ng-change="mediafileGoToPage(presentedMediafile.page)">
<span class="input-group-addon"><translate>of</translate> {{presentedMediafile.numPages}}</span>
</div>
<div class="btn-group">
<button class="btn btn-default" ng-click="mediafileRotate()" title="{{ 'Rotate clockwise' | translate }}">
<i class="fa fa-repeat"></i>
</button>
</div>
<div class="btn-group">
<button class="btn btn-default" ng-click="mediafileZoomOut()" title="{{ 'Zoom out' | translate }}">
<i class="fa fa-search-minus"></i>
</button>
<button class="btn btn-default" ng-click="mediafileFit()" title="{{ 'Reset zoom' | translate }}">
100%
</button>
<button class="btn btn-default" ng-click="mediafileZoomIn()" title="{{ 'Zoom in' | translate }}">
<i class="fa fa-search-plus"></i>
</button>
</div>
</nav>
</div>
<div ng-show="!presentedMediafiles.length" class="spacer">
<i translate>No PDF file projected.</i>
</div>
</div>
</div>
</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">
@ -60,40 +119,6 @@
</div> </div>
</div> </div>
<!-- mediafile pdf controls -->
<div os-perms="core.can_manage_projector" ng-show="presentedMediafiles.length">
<div ng-repeat="presentedMediafile in presentedMediafiles" class="well well-sm">
<h3 translate>PDF control elements</h3>
<!-- TODO: show filename / title of mediafile -->
<nav ng-class="getNavStyle(scroll)" class="form-inline">
<div class="btn-group">
<button class="btn btn-default" ng-click="mediafileGoPrevious()" title="{{ 'Previous page' | translate }}">
<i class="fa fa-backward"></i>
</button>
<button class="btn btn-default" ng-click="mediafileGoNext()" title="{{ 'Next page' | translate }}">
<i class="fa fa-forward"></i>
</button>
</div>
<div class="btn-group">
<button class="btn btn-default" ng-click="mediafileZoomOut()" title="{{ 'Zoom out' | translate }}">
<i class="fa fa-search-minus"></i>
</button>
<button class="btn btn-default" ng-click="mediafileFit()" title="{{ 'Reset zoom' | translate }}">
100%
</button>
<button class="btn btn-default" ng-click="mediafileZoomIn()" title="{{ 'Zoom in' | translate }}">
<i class="fa fa-search-plus"></i>
</button>
</div>
<div class="input-group">
<span class="input-group-addon" translate>Page</span>
<input type="number" min=1 ng-model="presentedMediafile.page" class="form-control" style="width: 80px">
<span class="input-group-addon"><translate>of</translate> {{presentedMediafile.numPages}}</span>
</div>
</nav>
</div>
</div>
<div class="spacer-top-lg italic"> <div class="spacer-top-lg italic">
{{ mediafilesFiltered.length }} / {{ mediafilesFiltered.length }} /
{{ mediafiles.length }} {{ "files" | translate }}<span ng-if="(mediafiles|filter:{selected:true}).length > 0">, {{ mediafiles.length }} {{ "files" | translate }}<span ng-if="(mediafiles|filter:{selected:true}).length > 0">,
@ -113,18 +138,6 @@
<i class="pull-right fa" ng-show="sortColumn === 'title_or_filename' && header.sortable != false" <i class="pull-right fa" ng-show="sortColumn === 'title_or_filename' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'"> ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i> </i>
<!-- filetype -->
<th ng-click="toggleSort('filetype')" class="sortable optional">
<translate>Filetype</translate>
<i class="pull-right fa" ng-show="sortColumn === 'filetype' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i>
<!-- filesize -->
<th ng-click="toggleSort('filesize')" class="sortable optional">
<translate>Filesize</translate>
<i class="pull-right fa" ng-show="sortColumn === 'filesize' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i>
<!-- upload time --> <!-- upload time -->
<th ng-click="toggleSort('timestamp')" class="sortable optional"> <th ng-click="toggleSort('timestamp')" class="sortable optional">
<translate>Upload time</translate> <translate>Upload time</translate>
@ -159,6 +172,8 @@
<!-- mediafile data colums --> <!-- mediafile data colums -->
<td ng-mouseover="mediafile.hover=true" ng-mouseleave="mediafile.hover=false"> <td ng-mouseover="mediafile.hover=true" ng-mouseleave="mediafile.hover=false">
<strong><a ng-href="{{ mediafile.mediafileUrl }}" target="_blank">{{ mediafile.title_or_filename }}</a></strong> <strong><a ng-href="{{ mediafile.mediafileUrl }}" target="_blank">{{ mediafile.title_or_filename }}</a></strong>
<br><small><i class="fa fa-file"></i> {{ mediafile.filetype }}</small>
<br><small><i class="fa fa-database"></i> {{ mediafile.filesize }}</small>
<div os-perms="mediafiles.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !mediafile.hover}"> <div os-perms="mediafiles.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !mediafile.hover}">
<a href="" ng-click="openDialog(mediafile)" translate>Edit</a> | <a href="" ng-click="openDialog(mediafile)" translate>Edit</a> |
<a href="" class="text-danger" <a href="" class="text-danger"
@ -166,8 +181,6 @@
<b>{{ mediafile.title }} [{{ mediafile.mediafile.name }}]</b>" <b>{{ mediafile.title }} [{{ mediafile.mediafile.name }}]</b>"
ng-bootbox-confirm-action="delete(mediafile)" translate>Delete</a> ng-bootbox-confirm-action="delete(mediafile)" translate>Delete</a>
</div> </div>
<td class="optional">{{ mediafile.mediafile.type }}
<td class="optional">{{ mediafile.filesize }}
<td class="optional">{{ mediafile.timestamp | date:'yyyy-MM-dd HH:mm:ss' }} <td class="optional">{{ mediafile.timestamp | date:'yyyy-MM-dd HH:mm:ss' }}
<td>{{ mediafile.uploader.get_full_name() }} <td>{{ mediafile.uploader.get_full_name() }}
</tbody> </tbody>

View File

@ -1,8 +1,6 @@
<div ng-controller="SlideMediafileCtrl" class="content"> <div ng-controller="SlideMediafileCtrl" class="content fullscreen">
<ng-pdf template-url="/static/templates/mediafiles/slide_mediafile_partial.html" <ng-pdf template-url="/static/templates/mediafiles/slide_mediafile_partial.html"
scale="page-fit" ng-attr-scale="{{ element.scale }}"
ng-attr-scale="{{ scale }}" ng-attr-page="{{ element.page }}">
ng-attr-page="{{ page }}"
debug="true">
</ng-pdf> </ng-pdf>
</div> </div>

View File

@ -1 +1 @@
<canvas id="pdf-canvas" class="rotate0"></canvas> <canvas id="pdf-canvas" class="rotate{{element.rotate}}"></canvas>