use App\Models\FluidbookPublication;
use App\Util\FluidbookLinks;
use Cubist\Backpack\Http\Controllers\Base\XSendFileController;
+use Cubist\Util\Files\Files;
use Illuminate\Support\Facades\Route;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
trait EditOperation
{
{
Route::match(['get'], $segment . '/{id}/edit/links', $controller . '@links');
Route::match(['get'], $segment . '/{id}/edit/links/versions', $controller . '@getLinkVersions');
+ Route::match(['get'], $segment . '/{id}/edit/links/versions/export/{version}', $controller . '@exportLinks');
+ Route::match(['get'], $segment . '/{id}/edit/links/versions/restore/{version}', $controller . '@restoreLinks');
Route::put($segment . '/{id}/save/links', $controller . '@saveLinks');
Route::get($segment . '/{id}/edit/{type}_{page}.{format}', $controller . '@getLinkPage')
// ->whereIn('type', ['raster', 'images', 'texts', 'vector'])
return response()->json($links);
}
+ protected function exportLinks($fluidbook_id, $version)
+ {
+ if (!FluidbookPublication::hasPermission($fluidbook_id)) {
+ abort(401);
+ }
+ FluidbookLinks::getLinksAndRulers($fluidbook_id, $links, $rulers, $version);
+ $xlsx = FluidbookLinks::linksToExcel($links, $rulers);
+ $tmpfile = Files::tempnam() . '.xlsx';
+ $writer = new Xlsx($xlsx);
+ $writer->save($tmpfile);
+ return response()->file($tmpfile)->deleteFileAfterSend();
+ }
+
+ protected function restoreLinks($fluidbook_id, $version)
+ {
+ if (!FluidbookPublication::hasPermission($fluidbook_id)) {
+ abort(401);
+ }
+ $comments = 'Restore links from ' . date('Y-m-d H:i:s', $version);
+
+ // New way
+ FluidbookLinks::getLinksAndRulers($fluidbook_id, $links, $rulers, $version);
+ FluidbookLinks::saveLinksInFile($fluidbook_id, backpack_user()->id, $comments, $links, $rulers, [], []);
+ }
+
// protected function getThumb($doc_id, $doc_page)
// {
//
$s->setTitle('Links');
// Labels
- $i = 0;
+ $i = 1;
foreach ($cols as $id => $label) {
$s->setCellValueByColumnAndRow($i, 1, $id);
$s->getColumnDimensionByColumn($i)->setAutoSize(true);
self::_correctImageSpecialLinks($links);
$j = 2;
foreach ($links as $l) {
- $i = 0;
+ $i = 1;
foreach ($cols as $id => $label) {
if (($id == 'document_id' || $id == 'document_page')) {
if (!is_null($pages)) {
$s->setTitle('Rulers');
$rcols = array('page', 'type', 'pos');
- $i = 0;
+ $i = 1;
// Labels
foreach ($rcols as $id) {
$s->setCellValueByColumnAndRow($i, 1, $id);
// Contents
$j = 2;
foreach ($rulers as $r) {
- $i = 0;
+ $i = 1;
foreach ($rcols as $id) {
if (!is_null($pages) && ($id == 'document_id' || $id == 'document_page')) {
$infos = $pages[$r['page']];
continue;
}
$link->$attr = trim($link->$attr);
- if (strpos($link->$attr, '///') === 0 || $link->$attr == '') {
+ if (str_starts_with($link->$attr, '///') || $link->$attr == '') {
continue;
}
$link->$attr = '///' . Crypt::safeEncrypt($link->uid . '|||' . $link->$attr, self::_getLinkKey());
}
foreach ($link as $attr => $item) {
- if (strpos($item, '///') !== 0) {
+ if (!str_starts_with($item, '///')) {
continue;
}
$v = Crypt::safeDecrypt(substr($item, 3), self::_getLinkKey());
$res = [];
foreach ($updates as $timestamp => $u) {
- $u['name'] = User::find($u['user'])->name;
+ try {
+ $u['name'] = User::find($u['user'])->name;
+ } catch (\Exception $e) {
+ $u['name'] = '-';
+ }
$u['date'] = date('Y-m-d H:i:s', $timestamp);
$u['timestamp'] = $timestamp;
$res[] = $u;
});
},
+ initTooltips: function () {
+ $('[data-tooltip]:not(.init-tooltip)').each(function () {
+ tippy($(this).get(0), {content: $(this).data('tooltip')});
+ });
+ $(this).addClass('init-tooltip');
+ },
+
initEvents: function () {
var $this = this;
$(window).on('hashchange', function () {
this.changePage();
},
- runAction: function (act) {
+ runAction: function (act, args) {
+ if (arguments === undefined) {
+ args = [];
+ }
var a = act.split('.');
var o = this;
let po = this;
po = o;
o = o[a[i]];
}
- return o.call(po);
+ try {
+ return o.apply(po, args);
+ } catch (e) {
+ console.log(e);
+ console.error('Error while calling ' + act, args);
+ }
},
firstPage: function () {
}
},
- save: function (message) {
+ save: function (message, notify, callback) {
+ if (notify === undefined) {
+ notify = true;
+ }
+ if (callback === undefined) {
+ callback = function () {
+
+ };
+ }
var $this = this;
if (message === undefined) {
message = TRANSLATIONS.manual_save_message;
}
- var notificationTimeout=5000;
+ var notificationTimeout = 5000;
$.ajax({
url: '/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/save/links', method: 'post', data: {
_method: 'put', 'message': message, rulers: window.RULERS, links: window.LINKS,
},
success: function (data) {
- new Noty({
- type: "success",
- text: TRANSLATIONS.success_save,
- timeout: notificationTimeout,
- }).show();
+ if (notify) {
+ new Noty({
+ type: "success",
+ text: TRANSLATIONS.success_save,
+ timeout: notificationTimeout,
+ }).show();
+ }
clearTimeout($this.automaticSaveTimeout);
$this.unsavedChanges = false;
$this.runningAutomaticSaveTimeout = false;
+
+ $this.linkeditor.versions.refresh();
+ callback();
},
error: function (jqXHR, status, error) {
$this.linkeditor.hasChanged();
LinkeditorToolbar.prototype = {
init: function () {
- var $this=this;
+ var $this = this;
$("#linkeditor-page-field input").on('change', function () {
$this.linkeditor.changePage($(this).val());
$(this).blur();
});
});
- $('[data-action]').click(function () {
- $this.linkeditor.runAction($(this).data('action'));
+ $(document).on('click', '[data-action]', function () {
+ $this.linkeditor.runAction($(this).data('action'), $(this).is('[data-action-args]') ? $(this).data('action-args') : []);
return false;
});
- $('[data-tooltip]').each(function () {
- tippy($(this).get(0), {content: $(this).data('tooltip')});
- });
+ this.linkeditor.initTooltips();
},
};
module.exports = LinkeditorToolbar;
setVersions: function (data) {
var list = $("#linkeditor-panel-versions-list");
list.html('');
- $.each(data, function (timestamp, version) {
+ $.each(data, function (k, version) {
+ let actionArgs = JSON.stringify([version.timestamp]);
var item = '<div class="row">';
item += '<div class="col1">';
item += '<div class="date">' + version.date + '</div>';
item += '<div class="rulers"><b>' + version.rulers + '</b> rulers</div>';
item += '</div>'
item += '<div class="col3">';
- item += '<div class="actions"><a href="#" data-icon="wayback-machine" data-tooltip="Restaurer cette version"></a></td><td><a href="#" data-icon="export-links" data-tooltip="Exporter les liens au format xlsx"></a></div>';
+ item += '<div class="actions"><a nohref data-action="versions.restoreVersion" data-action-args="' + actionArgs + '" data-icon="wayback-machine" data-tooltip="Restaurer cette version"></a>' +
+ '<a download="links_' + FLUIDBOOK_DATA.id + '_' + version.timestamp + '.xlsx" href="/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/edit/links/versions/export/' + version.timestamp + '" data-icon="export-links" data-tooltip="Exporter les liens au format xlsx"></a></div>';
item += '</div>'
item += '</div>'
list.append(item);
});
this.linkeditor.initIcons();
+ this.linkeditor.initTooltips();
this.resize();
},
+ restoreVersion: function (timestamp) {
+ var $this = this;
+ var callback = function () {
+ $this._restoreVersion(timestamp);
+ }
+
+ //Restore links from 2022-12-07 13:37:15
+ if (this.linkeditor.save.unsavedChanges) {
+ console.log('save save save');
+ this.linkeditor.save.save('Save before restoring links', false, function () {
+ setTimeout(function () {
+ callback();
+ }, 1000);
+ });
+ } else {
+ callback();
+ }
+ },
+
+ _restoreVersion(timestamp) {
+ $.ajax({
+ url: '/fluidbook-publication/' + FLUIDBOOK_DATA.id + '/edit/links/versions/restore/' + timestamp + '',
+ success: function (data) {
+ window.location.reload();
+ },
+ });
+ },
+
resize: function () {
- var w=$("#linkeditor-panel-versions-list").outerWidth();
- if(w<=0){
+ var w = $("#linkeditor-panel-versions-list").outerWidth();
+ if (w <= 0) {
return;
}
- if(w<300){
+ if (w < 300) {
$("#linkeditor-panel-versions-list").addClass('small');
- }else{
+ } else {
$("#linkeditor-panel-versions-list").removeClass('small');
}
},
+
+
};
module.exports = LinkeditorVersions;
#linkeditor-panel-versions
padding: 5px 10px
+ user-select: none
#linkeditor-panel-versions-list
font-size: 12px
height: $icon-size
margin-left: 7px
color: currentColor
+ cursor: pointer
svg
width: $icon-size
data-tooltip="{{__('Importer les liens (Remplacer)')}}"></a>
<a href="#" data-action="mergeExcel" data-icon="merge-links"
data-tooltip="{{__('Importer les liens (Ajouter)')}}"></a>
- <a href="#" data-action="export" data-icon="export-links"
- data-tooltip="{{__('Exporter les liens')}}"></a>
+ <a download="links_{{$fbdata['id']}}.xlsx"
+ href="/fluidbook-publication/{{$fbdata['id']}}/edit/links/versions/export/latest"
+ data-icon="export-links" data-tooltip="Exporter les liens"></a>
<a href="#" data-action="moveLinks" data-icon="move-links"
data-tooltip="{{__('Déplacer les liens')}}"></a>
</nav>