diff --git a/app.php b/app.php
index 2da0b7e..be0083b 100644
--- a/app.php
+++ b/app.php
@@ -52,6 +52,13 @@ $f3->route('GET /signature',
echo View::instance()->render('signature.html.php');
}
);
+$f3->route('GET /organization',
+ function($f3) {
+ $f3->set('maxSize', min(array(convertPHPSizeToBytes(ini_get('post_max_size')), convertPHPSizeToBytes(ini_get('upload_max_filesize')))));
+
+ echo View::instance()->render('organization.html.php');
+ }
+);
$f3->route('POST /image2svg',
function($f3) {
$files = Web::instance()->receive(function($file,$formFieldName){
@@ -143,4 +150,37 @@ $f3->route('POST /sign',
}
);
+$f3->route('POST /organize',
+ function($f3) {
+ $filename = null;
+ $tmpfile = tempnam($f3->get('UPLOADS'), 'pdfsignature_organize');
+ unlink($tmpfile);
+
+ $files = Web::instance()->receive(function($file,$formFieldName){
+ if($formFieldName == "pdf" && strpos(Web::instance()->mime($file['tmp_name'], true), 'application/pdf') !== 0) {
+ $f3->error(403);
+ }
+ return true;
+ }, false, function($fileBaseName, $formFieldName) use ($f3, $tmpfile, &$filename, &$svgFiles) {
+ if($formFieldName == "pdf") {
+ $filename = str_replace(".pdf", "_organise.pdf", $fileBaseName);
+ return basename($tmpfile).".pdf";
+ }
+ });
+
+ if(!is_file($tmpfile.".pdf")) {
+ $f3->error(403);
+ }
+
+ shell_exec(sprintf("pdftk %s cat %s output %s", $tmpfile.".pdf", implode(" ", $f3->get('POST.pages')), $tmpfile.'_organise.pdf'));
+
+ Web::instance()->send($tmpfile."_organise.pdf", null, 0, TRUE, $filename);
+
+ if($f3->get('DEBUG')) {
+ return;
+ }
+ array_map('unlink', glob($tmpfile."*"));
+ }
+);
+
return $f3;
\ No newline at end of file
diff --git a/public/favicon-organization.ico b/public/favicon-organization.ico
new file mode 100644
index 0000000..113d1c0
Binary files /dev/null and b/public/favicon-organization.ico differ
diff --git a/public/js/organization.js b/public/js/organization.js
new file mode 100644
index 0000000..8e0c978
--- /dev/null
+++ b/public/js/organization.js
@@ -0,0 +1,163 @@
+var pdfRenderTasks = [];
+var pdfPages = [];
+var resizeTimeout;
+var currentScale = 1.5;
+var windowWidth = window.innerWidth;
+
+var loadPDF = async function(pdfBlob, filename) {
+ var pdfjsLib = window['pdfjs-dist/build/pdf'];
+ pdfjsLib.GlobalWorkerOptions.workerSrc = '/vendor/pdf.worker.js?legacy';
+ let url = await URL.createObjectURL(pdfBlob);
+
+ let dataTransfer = new DataTransfer();
+ dataTransfer.items.add(new File([pdfBlob], filename, {
+ type: 'application/pdf'
+ }));
+ document.getElementById('input_pdf').files = dataTransfer.files;
+
+ var loadingTask = pdfjsLib.getDocument(url);
+ loadingTask.promise.then(function(pdf) {
+ for(var pageNumber = 1; pageNumber <= pdf.numPages; pageNumber++ ) {
+ pdf.getPage(pageNumber).then(function(page) {
+ var scale = 0.5;
+ var viewport = page.getViewport({scale: scale});
+ if(viewport.width > document.getElementById('container-pages').clientWidth - 40) {
+ viewport = page.getViewport({scale: 1});
+ scale = (document.getElementById('container-pages').clientWidth - 40) / viewport.width;
+ viewport = page.getViewport({ scale: scale });
+ }
+
+ currentScale = scale;
+
+ var pageIndex = page.pageNumber - 1;
+
+ document.getElementById('container-pages').insertAdjacentHTML('beforeend', '
');
+
+ let canvasContainer = document.getElementById('canvas-container-' + pageIndex);
+ let canvasCheckbox = canvasContainer.querySelector('input[type=checkbox]');
+ canvasCheckbox.addEventListener('click', function(e) {
+ e.stopPropagation();
+ })
+ canvasContainer.addEventListener('click', function(e) {
+ this.querySelector('input[type=checkbox]').checked = !this.querySelector('input[type=checkbox]').checked;
+ document.querySelector('#checkbox_all_pages').checked = (document.querySelectorAll('.checkbox-page:checked').length == document.querySelectorAll('.checkbox-page').length);
+ })
+ var canvasPDF = document.getElementById('canvas-pdf-' + pageIndex);
+
+ // Prepare canvas using PDF page dimensions
+ var context = canvasPDF.getContext('2d');
+ canvasPDF.height = viewport.height;
+ canvasPDF.width = viewport.width;
+
+ var renderContext = {
+ canvasContext: context,
+ viewport: viewport,
+ enhanceTextSelection: true
+ };
+ var renderTask = page.render(renderContext);
+ pdfRenderTasks.push(renderTask);
+ pdfPages.push(page);
+ });
+ }
+ }, function (reason) {
+ console.error(reason);
+ });
+};
+
+var is_mobile = function() {
+ return !(window.getComputedStyle(document.getElementById('is_mobile')).display === "none");
+};
+
+var createEventsListener = function() {
+ document.querySelector('#checkbox_all_pages').addEventListener('change', function() {
+ let checkboxAll = this;
+ document.querySelectorAll('.checkbox-page').forEach(function(checkbox) {
+ checkbox.checked = checkboxAll.checked;
+ });
+ })
+}
+
+async function getPDFBlobFromCache(cacheUrl) {
+ const cache = await caches.open('pdf');
+ let responsePdf = await cache.match(cacheUrl);
+
+ if(!responsePdf) {
+ return null;
+ }
+
+ let pdfBlob = await responsePdf.blob();
+
+ return pdfBlob;
+}
+
+async function uploadFromUrl(url) {
+ history.replaceState({}, '', '/organization');
+ var response = await fetch(url);
+ if(response.status != 200) {
+ return;
+ }
+ var pdfBlob = await response.blob();
+
+ if(pdfBlob.type != 'application/pdf' && pdfBlob.type != 'application/octet-stream') {
+ return;
+ }
+ let dataTransfer = new DataTransfer();
+ let filename = url.replace(/^.*\//, '');
+ dataTransfer.items.add(new File([pdfBlob], filename, {
+ type: 'application/pdf'
+ }));
+ document.getElementById('input_pdf_upload').files = dataTransfer.files;
+ document.getElementById('input_pdf_upload').dispatchEvent(new Event("change"));
+}
+
+var pageUpload = async function() {
+ document.getElementById('input_pdf_upload').value = '';
+ document.getElementById('page-upload').classList.remove('d-none');
+ document.getElementById('page-organization').classList.add('d-none');
+ document.getElementById('input_pdf_upload').focus();
+ const cache = await caches.open('pdf');
+ document.getElementById('input_pdf_upload').addEventListener('change', async function(event) {
+ if(document.getElementById('input_pdf_upload').files[0].size > maxSize) {
+
+ alert("Le PDF ne doit pas dépasser Mo");
+ document.getElementById('input_pdf_upload').value = "";
+ return;
+ }
+ let filename = document.getElementById('input_pdf_upload').files[0].name;
+ let response = new Response(document.getElementById('input_pdf_upload').files[0], { "status" : 200, "statusText" : "OK" });
+ let urlPdf = '/pdf/'+filename;
+ await cache.put(urlPdf, response);
+ history.pushState({}, '', '/organization#'+filename);
+ pageOrganization(urlPdf)
+ });
+}
+
+var pageOrganization = async function(url) {
+ let filename = url.replace('/pdf/', '');
+ document.title = filename + ' - ' + document.title;
+ document.getElementById('page-upload').classList.add('d-none');
+ document.getElementById('page-organization').classList.remove('d-none');
+
+ let pdfBlob = await getPDFBlobFromCache(url);
+ if(!pdfBlob) {
+ document.location = '/organization';
+ return;
+ }
+ createEventsListener();
+ loadPDF(pdfBlob, filename);
+};
+
+(function () {
+ if(window.location.hash && window.location.hash.match(/^\#http/)) {
+ let hashUrl = window.location.hash.replace(/^\#/, '');
+ pageUpload();
+ uploadFromUrl(hashUrl);
+ } else if(window.location.hash) {
+ pageOrganization('/pdf/'+window.location.hash.replace(/^\#/, ''));
+ } else {
+ pageUpload();
+ }
+ window.addEventListener('hashchange', function() {
+ window.location.reload();
+ })
+})();
\ No newline at end of file
diff --git a/templates/organization.html.php b/templates/organization.html.php
new file mode 100644
index 0000000..46b8447
--- /dev/null
+++ b/templates/organization.html.php
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Organiser un PDF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file