'singular' => 'document',
'plural' => 'documents'];
protected static $_permissionBase = 'fluidbook-document';
- protected $_filesData = null;
protected $casts = ['bookmarks' => 'array', 'pdf_data' => 'array', 'file_data' => 'array'];
public function setFields()
$this->addField('bookmarks', Textarea::class, ['cast' => 'array']);
$this->addField('pdf_data', Textarea::class, ['cast' => 'array']);
$this->addField('file_data', Textarea::class, ['cast' => 'array']);
- $this->addField('pagesnumbers', Text::class);
}
public function getResolutionRatio()
public function processUpload($uploadID, $sync = false)
{
- FluidbookDocumentUpload::updateProgression($uploadID, __('Analyse du document'), 1.3);
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Analyse du document'), 1.1);
$this->checkInfos();
- FluidbookDocumentUpload::updateProgression($uploadID, __('Nettoyage du document'), 1.5);
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Nettoyage du document'), 1.2);
$this->fixPDF();
- FluidbookDocumentUpload::updateProgression($uploadID, __('Découpe du document'), 1.8);
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Découpe du document'), 1.3);
$this->splitPDF();
- FluidbookDocumentUpload::updateProgression($uploadID, __('Conversion des pages (:done/:pages)', ['pages' => $this->pages, 'done' => 0]), 2);
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Extraction des textes'), 1.75);
+ $this->extractTexts();
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Extraction des liens'), 1.9);
+ $this->extractLinks();
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Conversion des pages'), 2);
$jobs = [];
$files = [['jpg', 'thumb'], ['jpg', 150]];
-
+ $nbfiles = count($files);
+ $delay = 0;
for ($i = 1; $i <= $this->pages; $i++) {
foreach ($files as $file) {
$job = new FluidbookDocumentFileProcess($this, $i, $file[0], $file[1]);
if ($sync) {
dispatch_sync($job);
} else {
- dispatch($job);
+ dispatch($job)->delay($delay);
}
$jobs[] = $job;
+ if ($i % 20 === 0) {
+ $delay++;
+ }
+ $this->_checkJobs($uploadID, $jobs, $nbfiles);
}
}
- $nbjobs = count($jobs);
- $nbfiles = count($files);
-
while (true) {
- $done = 0;
- foreach ($jobs as $job) {
- /** @var $job FluidbookDocumentFileProcess */
- if ($job->isDone()) {
- $done++;
- }
- }
- $progress = $done / $nbjobs;
- FluidbookDocumentUpload::updateProgression($uploadID, __('Conversion des pages (:done/:pages)', ['pages' => $this->pages, 'done' => round($done / $nbfiles)]), 2 + $progress);
- if ($progress === 1) {
- break;
+ if ($this->_checkJobs($uploadID, $jobs, $nbfiles) === 1) {
+ return;
}
usleep(0.25 * 1000000);
}
}
+ public function extractTexts()
+ {
+ PDFTools::extractTexts($this->path('original.pdf'), $this->path(), '', false, true);
+ PDFTools::extractHighlightsData($this->path('original.pdf'), $this->path());
+ }
+
+ public function extractLinks()
+ {
+ PDFTools::extractLinks($this->path('original.pdf'), $this->path());
+ }
+
+ protected function _checkJobs($uploadID, $jobs, $nbfiles)
+ {
+ $nbjobs = $nbfiles * $this->pages;
+
+ $done = 0;
+ foreach ($jobs as $job) {
+ /** @var $job FluidbookDocumentFileProcess */
+ if ($job->isDone()) {
+ $done++;
+ }
+ }
+ $progress = $done / $nbjobs;
+ if ($progress === 1) {
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Conversion terminée'), 3);
+ } else {
+ FluidbookDocumentUpload::updateProgression($uploadID, __('Conversion des pages (:done/:pages)', ['pages' => $this->pages, 'done' => round($done / $nbfiles)]), 2 + $progress);
+ }
+ return $progress;
+ }
+
public function getMobileFirstRatio()
{
$this->checkInfos();
$this->pages = $infos['pages'];
$this->pdf_data = $infos['infos'];
$this->bookmarks = $infos['bookmarks'];
- $this->pagesnumbers = $infos['numberSections'];
$this->saveWithoutFlushingCache();
}
}
*/
public function path($path = ''): string
{
- return rtrim(self::WS_DOCS . $this->id . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : $path), DIRECTORY_SEPARATOR);
+ $res = rtrim(self::WS_DOCS . $this->id . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : $path), DIRECTORY_SEPARATOR);
+ if (!$path) {
+ $res .= DIRECTORY_SEPARATOR;
+ }
+ return $res;
}
public function hasFile($page, $format = 'jpg', $resolution = 150, $withText = true, $withGraphics = true, $version = 'html')
if (filesize($path) < $minsize) {
return false;
}
+ if (file_exists($path . '.lock')) {
+ return false;
+ }
if ($format === 'svg') {
$reffile = $this->path('/html/fp' . $page . '.svg');
if (!file_exists($reffile) || filemtime($path) < filemtime($reffile)) {
"source": {
"type": "git",
"url": "git://git.cubedesigners.com/cubist_cms-back.git",
- "reference": "5037fafa790b4d6a0157f38f7237c45aa69bf157"
+ "reference": "f2cddfa7b1a8446ba3430147ec045dd4777a8658"
},
"dist": {
"type": "tar",
- "url": "https://composer.cubedesigners.com/dist/cubist/cms-back/cubist-cms-back-dev-master-bc5679.tar",
- "reference": "5037fafa790b4d6a0157f38f7237c45aa69bf157",
- "shasum": "0bccb1ee64d0f71da2e451ced0a4c329decbe0ec"
+ "url": "https://composer.cubedesigners.com/dist/cubist/cms-back/cubist-cms-back-dev-master-4b1d60.tar",
+ "reference": "f2cddfa7b1a8446ba3430147ec045dd4777a8658",
+ "shasum": "e2470e1897d0463adc15af5c713ccfbde756bcf2"
},
"require": {
"backpack/backupmanager": "^3.0",
}
],
"description": "Cubist Backpack extension",
- "time": "2022-07-19T13:22:56+00:00"
+ "time": "2022-07-21T18:23:21+00:00"
},
{
"name": "cubist/cms-front",
"source": {
"type": "git",
"url": "git://git.cubedesigners.com/cubist_pdf.git",
- "reference": "dfbda143ad4963784a2251af488978d92da79d51"
+ "reference": "b93a3841c212ca8bf9793da611d90497b4f9a6de"
},
"dist": {
"type": "tar",
- "url": "https://composer.cubedesigners.com/dist/cubist/pdf/cubist-pdf-dev-master-1ba061.tar",
- "reference": "dfbda143ad4963784a2251af488978d92da79d51",
- "shasum": "1fd430d15409cfcc232ded890019e8dcebf061db"
+ "url": "https://composer.cubedesigners.com/dist/cubist/pdf/cubist-pdf-dev-master-876ad1.tar",
+ "reference": "b93a3841c212ca8bf9793da611d90497b4f9a6de",
+ "shasum": "7c956335d1f230f7f7bd313e72dd04115f2fea1f"
},
"require": {
"cubist/util": "dev-master",
"cubist",
"pdf"
],
- "time": "2022-07-13T16:13:36+00:00"
+ "time": "2022-07-21T18:23:40+00:00"
},
{
"name": "cubist/scorm",
},
{
"name": "laravel/framework",
- "version": "v8.83.20",
+ "version": "v8.83.21",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "aa5908e83fccb18b135ca31aa0342cf4bd6909a8"
+ "reference": "1b3b06e5f419eef9bc3dfa06376dd60f5de524bc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/aa5908e83fccb18b135ca31aa0342cf4bd6909a8",
- "reference": "aa5908e83fccb18b135ca31aa0342cf4bd6909a8",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/1b3b06e5f419eef9bc3dfa06376dd60f5de524bc",
+ "reference": "1b3b06e5f419eef9bc3dfa06376dd60f5de524bc",
"shasum": ""
},
"require": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2022-07-19T14:11:02+00:00"
+ "time": "2022-07-21T19:36:48+00:00"
},
{
"name": "laravel/serializable-closure",
@push('crud_fields_scripts')
<script>
$(function () {
- var conversion = '';
var conversionOperation;
var conversionPages;
- var progressInterval;
+ var conversionDocument;
+ var selected = [];
function initPages() {
var data = JSON.parse($("#compositionField").val());
$.each(data, function (pageNr, page) {
- addPage(page[0], page[1], numbers[pageNr - 1], sizes[page[0]]);
+ var size = sizes[page[0]];
+ if (size === undefined) {
+ size = [210, 297]
+ }
+ addPage(page[0], page[1], numbers[pageNr - 1], size);
});
var composition = $('#composition_pages').get(0);
handle: '.handle',
onSort: function (e) {
updateComposition();
+ },
+ onSelect: function (e) {
+ $(".pdfselected").removeClass('pdfselected');
+ selected = e.items;
}
});
$("#pagenumber_input").remove();
if (v !== $(this).attr('data-orig-value')) {
- console.log('change', v, $(this).data('orig-value'));
updateNumFromEdit(v, p);
}
$(document).on('change', '#compositionUploadBrowse', function () {
$("#compositionUploadForm").submit();
});
+
$(document).on('submit', '#compositionUploadForm', function () {
$(this).ajaxSubmit({
success: function (data) {
var uploadID = data.uploadID;
- progressInterval = setInterval(function () {
- updateProgressBar(uploadID);
- }, 250);
+ conversionDocument = data.document;
+ updateProgressBar(uploadID);
},
uploadProgress: function (event, position, total, percentComplete) {
var progress = position / total;
var message = '{{__('Chargement du document')}}';
if (progress === 1) {
message = '{{__('Initialisation de la conversion')}}';
+ progress = 1.05;
}
showProgressBar(message, progress);
},
type: 'error',
text: '{{__('Une erreur s\'est produite lors du chargement du document')}}',
}).show();
- conversion = '';
+ hideProgressBar();
}
});
return false;
$.ajax({
url: '{{backpack_url($entry->getOption('name').'/uploadProgress')}}' + '/' + uploadID,
success: function (data) {
- showProgressBar(data.message, data.progress);
+ showProgressBar(data.message, parseFloat(data.progress), uploadID);
}
- })
+ });
}
- function showProgressBar(message, progress) {
- console.log(message, progress);
+ function showProgressBar(message, progress, uploadID) {
if ($("#compositionProgress").length === 0) {
- $('body').append('<div id="compositionProgress"><div><span></span><progress max="100"></progress></div></div>');
+ $('body').append('<div id="compositionProgress"><div><span></span><progress data-progress="" data-step="0" value="0" max="100"></progress></div></div>');
}
- var p = Math.round((progress % 1) * 100);
-
- var step = Math.floor(progress);
-
- $("#compositionProgress progress").attr('data-step', step).attr('value', p).text(p + '%');
- $("#compositionProgress span").text(message);
+ if (message !== '' && progress > 0) {
+ $("#compositionProgress span").text(message);
+ if ($("#compositionProgress progress").attr('data-progress') == progress) {
+ return;
+ }
+ var dp = (progress % 1);
+ if (dp === 0 && progress > 0) {
+ dp = 1;
+ }
+ var p = Math.round(dp * 100);
+ var step = progress - dp;
+ var duration = 0.5;
+ if (p < $("#compositionProgress progress").attr('value')) {
+ duration = 0;
+ }
+ gsap.to($("#compositionProgress progress"), {
+ duration: duration, ease: 'none', attr: {'value': p}, onComplete: function () {
+ $("#compositionProgress progress").attr('data-step', step);
+ }
+ });
+ }
- if (progress === 3) {
+ if (progress >= 3) {
hideProgressBar();
+ endConversion();
+ } else if (uploadID !== undefined) {
+ setTimeout(function () {
+ updateProgressBar(uploadID);
+ }, 250);
}
}
+ function endConversion() {
+ $.ajax({
+ url: '{{backpack_url($entry->getOption('name').'/docInfos')}}' + '/' + conversionDocument,
+ success: function (data) {
+ putDocumentInComposition(conversionDocument, data.pages, data.numbers, data.size, conversionOperation, conversionPages);
+ }
+ });
+ }
+
function hideProgressBar() {
- clearInterval(progressInterval);
- console.log('End conversion');
- $("#compositionProgress").remove();
+ setTimeout(function () {
+ $("#compositionProgress").remove();
+ }, 2000);
}
function updateComposition() {
});
}
-
function compositionDeselectAll() {
$(".page").each(function () {
Sortable.utils.deselect(this);
$("#composition_pages .page.selected").each(function () {
compositionDeletePage(this);
});
+ updateComposition();
}
function compositionDeletePage(page) {
return $("#composition_pages .page.selected").length > 0;
}
- function addPage(document_id, document_page, pageNumber, size) {
- $("#composition_pages").append('<div class="page" data-id="[' + document_id + ',' + document_page + ']"><div class="handle"><img width="' + size[0] + '" height="' + size[1] + '" src="/fluidbook-publication/docs/' + document_id + '/thumb_' + document_page + '.jpg" /></div><span>' + pageNumber + '</span></div>');
+ function addPage(document_id, document_page, pageNumber, size, selector, operation) {
+ if (selector === undefined) {
+ selector = "#composition_pages";
+ }
+ if (operation === undefined) {
+ operation = 'append';
+ }
+ $(selector)[operation](getPage(document_id, document_page, pageNumber, size));
}
- function compositionBrowse(operation, pages) {
- if (conversion !== '') {
- new Noty({
- type: 'warning',
- text: '{{__("Un document est déjà en cours d'ajout")}}',
- }).show();
- return;
+ function getPage(document_id, document_page, pageNumber, size) {
+ return '<div class="page" data-id="[' + document_id + ',' + document_page + ']"><div class="handle"><img width="' + size[0] + '" height="' + size[1] + '" src="/fluidbook-publication/docs/' + document_id + '/thumb_' + document_page + '.jpg" /></div><span>' + pageNumber + '</span></div>';
+ }
+
+ function addPages(pages, selector, operation) {
+ var p = '';
+ $.each(pages, function (k, v) {
+ p += getPage(v.document_id, v.document_page, v.pageNumber, v.size);
+ });
+ if (selector === undefined) {
+ selector = "#composition_pages";
+ }
+ if (operation === undefined) {
+ operation = 'append';
}
+ $(selector)[operation](p);
+ }
+
+ function compositionBrowse(operation, pages) {
conversionOperation = operation;
conversionPages = pages;
'<input type="file" id="compositionUploadBrowse" name="file" value="" accept=".pdf" />' +
'<input type="hidden" name="_token" value="{{csrf_token()}}" />' +
'</form>');
- $('body').append(form);
-
+ $('#composition_pages').append(form);
$("#compositionUploadBrowse").click();
}
deleteSelection: {
name: "{{__('Supprimer la selection')}}",
callback: function (key, opt, e) {
+ $.each(selected, function (k, v) {
+ $(v).addClass('selected');
+ });
compositionDeleteSelection();
},
},
replaceSelection: {
name: "{{__('Remplacer les pages de la sélection')}}",
callback: function (key, opt) {
+ var selection = [];
+ $.each(selected, function (k, v) {
+ $(v).addClass('selected');
+ });
+ $('#composition_pages .page.selected').each(function () {
+ $(this).removeClass('selected').addClass('pdfselected');
+ selection.push($(this).index() + 1);
+ });
compositionBrowse('replace', selection);
}
},
insertBefore: {
name: "{{__('Insérer des pages avant cette page')}}",
callback: function (key, opt) {
- compositionBrowse('before', opt.$trigger[0].index() + 1);
+ compositionBrowse('before', $(opt.$trigger[0]).index() + 1);
+ $(opt.$trigger[0]).addClass('pdfselected');
}
},
insertAfter: {
name: "{{__('Insérer des pages après cette page')}}",
callback: function (key, opt) {
- compositionBrowse('before', opt.$trigger[0].index() + 1);
+ compositionBrowse('after', $(opt.$trigger[0]).index() + 1);
+ $(opt.$trigger[0]).addClass('pdfselected');
}
},
replacePage: {
name: "{{__('Remplacer cette page')}}",
callback: function (key, opt) {
- compositionBrowse('replace', [opt.$trigger[0].index() + 1]);
+ compositionBrowse('replace', [$(opt.$trigger[0]).index() + 1]);
+ $(opt.$trigger[0]).addClass('pdfselected');
}
},
sep3: "---------",
from = $(page).index() + 1;
}
- var j = start;
- var pages = getPageNumber();
- for (var i = from; i <= pages; i++) {
- var n = prefix + separator + getNumByType(j, type);
+ if (type === 'free') {
+ $("#composition_pages .page").eq(from - 1).find('span').text(start);
+ } else {
+ var j = start;
+ var pages = getPageNumber();
+ for (var i = from; i <= pages; i++) {
+ var n = prefix + separator + getNumByType(j, type);
- $("#composition_pages .page").eq(i - 1).find('span').text(n);
- j++;
+ $("#composition_pages .page").eq(i - 1).find('span').text(n);
+ j++;
+ }
}
updateComposition();
}
var type;
var start;
var prefix = '';
+ var origv = v;
if (v.indexOf('.') != -1) {
separator = '.';
} else if (v.indexOf(' ') != -1) {
type = 'decnum';
start = parseInt(v);
} else {
- return;
+ type = 'free';
+ start = origv;
}
updateNum(type, p, start, prefix, separator);
}
return roman;
}
+ function putDocumentInComposition(doc, pages, numbers, size, operation, place) {
+ if (operation === 'replace') {
+ if (pages === place.length) {
+ // Keep page numbers if selection has the same size as the new pdf
+ $.each(place, function (k, p) {
+ numbers[k] = $('#composition_pages .page:eq(' + (p - 1) + ') span').text();
+ });
+ }
+ $(".pdfselected").each(function () {
+ compositionDeletePage($(this));
+ });
+ operation = 'after';
+ place = place[0] - 1;
+ }
+ place = Math.min(getPageNumber(), Math.max(1, place));
+ if (operation === 'after' || operation === 'before') {
+ var list = [];
+ for (var i = 1; i <= pages; i++) {
+ list.push({document_id: doc, document_page: i, pageNumber: numbers[i - 1], size});
+ }
+ var selector;
+ if (getPageNumber() === 0) {
+ operation = 'append';
+ selector = '#composition_pages';
+ } else {
+ selector = '#composition_pages .page:eq(' + (place - 1) + ')';
+ }
+ addPages(list, selector, operation);
+ }
+ updateComposition();
+ $(".pdfselected").removeClass('pdfselected');
+ }
+
initPages();
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.2/jquery.ui.position.min.js"
integrity="sha512-878jmOO2JNhN+hi1+jVWRBv1yNB7sVFanp2gA1bG++XFKNj4camtC1IyNi/VQEhM2tIbne9tpXD4xaPC4i4Wtg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.4/gsap.min.js"></script>
@endpush
@push('crud_fields_styles')
}
#composition_pages .page:hover, #composition_pages .page.selected {
- border-color: #467fcf;
+ border-color: #467fcf !important;
}
+ #composition_pages .page.pdfselected {
+ border-color: #0ba234;
+ background-color: #7dde98;
+ }
+
+
#composition_pages .page.selected {
- background-color: #b5cbf5;
+ background-color: #b5cbf5 !important;
}
#composition_pages .page .handle {
#compositionProgress div {
position: absolute;
- top: 50%;
- left: 50%;
- width: 20%;
+ top: calc(50% - 65px);
+ left: calc(50% - 200px);
+ width: 400px;
+ height: 130px;
padding: 20px;
background-color: #fff;
+ border-radius: 4px;
+ }
+
+ #compositionProgress span {
+ display: block;
+ text-align: center;
+ font-size: 17px;
+ }
+
+ #compositionProgress progress {
+ width: 100%;
+ margin: 10px auto;
+ height: 25px;
+ appearance: none;
+ border-radius: 2px;
+ border: 1px solid rgba(0, 40, 100, .12);
+ }
+
+ #compositionProgress progress::-moz-progress-bar, #compositionProgress progress::-webkit-progress-value {
+ border-radius: 2px;
+ }
+
+ #compositionProgress progress[data-step="0"] {
+ background-color: #fff;
+ }
+
+ #compositionProgress progress[data-step="0"]::-moz-progress-bar, #compositionProgress progress[data-step="0"]::-webkit-progress-value {
+ background-color: #3d86ee;
+ }
+
+ #compositionProgress progress[data-step="1"] {
+ background-color: #3d86ee;
+ }
+
+ #compositionProgress progress[data-step="1"]::-moz-progress-bar, #compositionProgress progress[data-step="1"]::-webkit-progress-value {
+ background-color: #3471c8;
+ }
+
+ #compositionProgress progress[data-step="2"] {
+ background-color: #3471c8;
+ }
+
+ #compositionProgress progress[data-step="2"]::-moz-progress-bar, #compositionProgress progress[data-step="2"]::-webkit-progress-value {
+ background-color: #20457b;
+ }
+
+ .pace {
+ opacity: 0;
+ }
+
+ #compositionUploadForm {
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
}
</style>