From ef6f833b13c36bf8e107e0211ff6c9ccc9e6c3aa Mon Sep 17 00:00:00 2001 From: soufiane Date: Thu, 19 Feb 2026 11:20:24 +0100 Subject: [PATCH] wait #7993 @18:00 --- .../MarkdownOperation.php | 40 +++ resources/markdowneditor/js/markdowneditor.js | 5 + .../markdowneditor/js/markdowneditor.popup.js | 53 +++ .../js/markdowneditor.resize.js | 127 ++++++++ resources/markdowneditor/style/inc/_form.sass | 303 ++++++++++++++++++ .../markdowneditor/style/inc/_popup.sass | 67 ++++ .../markdowneditor/style/inc/_variables.sass | 18 ++ resources/markdowneditor/style/style.sass | 4 + .../markdown_editor.blade.php | 41 ++- 9 files changed, 653 insertions(+), 5 deletions(-) create mode 100644 resources/markdowneditor/js/markdowneditor.popup.js create mode 100644 resources/markdowneditor/js/markdowneditor.resize.js create mode 100644 resources/markdowneditor/style/inc/_form.sass create mode 100644 resources/markdowneditor/style/inc/_popup.sass create mode 100644 resources/markdowneditor/style/inc/_variables.sass diff --git a/app/Http/Controllers/Admin/Operations/FluidbookPublication/MarkdownOperation.php b/app/Http/Controllers/Admin/Operations/FluidbookPublication/MarkdownOperation.php index e737743d4..011022e92 100644 --- a/app/Http/Controllers/Admin/Operations/FluidbookPublication/MarkdownOperation.php +++ b/app/Http/Controllers/Admin/Operations/FluidbookPublication/MarkdownOperation.php @@ -6,6 +6,7 @@ use App\Fluidbook\Link\LinksData; use App\Models\FluidbookPublication; use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; use Cubist\Util\Files\Files; @@ -22,6 +23,7 @@ trait MarkdownOperation Route::match(['get'], $segment . '/{id}/markdown', $controller . '@getFilesById'); Route::match(['put'], $segment . '/{id}/save/markdown', $controller . '@saveMarkdown'); Route::match(['get'], $segment . '/{id}/import/markdown', $controller . '@importMarkdown'); + Route::match(['post'], $segment . '/{id}/edit/markdown/move', $controller . '@moveMarkdown'); } public function markdown($id) @@ -174,4 +176,42 @@ trait MarkdownOperation return response()->json(['success' => $md['pages']]); } + + protected function moveMarkdown($fluidbook_id) { + if (!FluidbookPublication::hasPermission($fluidbook_id)) { + abort(401); + } + + $offset = intval(request('number', 1)); + $from = intval(request('start', 0)); + + $markdown = $this->getLatestMarkdown($fluidbook_id)['pages']; + + $newOrder = []; + $newKey = 1; + + $newOrder = array_slice($markdown, 0, $from > 1 ? $from - 1 : $from,true); + $markdown = array_slice($markdown, $from > 1 ? $from - 1 : $from, count($markdown), true); + + foreach ($markdown as $k => $m) { + + if ($offset < 0) { + $k -= abs($offset); + } else { + $k += $offset; + } + + if(!array_key_exists($newKey,$newOrder)) { + $newOrder[$newKey] = ""; + } + + $newOrder["".$k] = $m; + $newKey++; + } + + ksort($newOrder); + + $this->saveMarkdown($fluidbook_id, __('Décalage de :nb pages à partir de la page :page', ['nb' => $offset, 'page' => $from, 'date' => date('Y-m-d H:i:s')]), $newOrder); + return Redirect::back(); + } } diff --git a/resources/markdowneditor/js/markdowneditor.js b/resources/markdowneditor/js/markdowneditor.js index f181745fc..b385525fa 100644 --- a/resources/markdowneditor/js/markdowneditor.js +++ b/resources/markdowneditor/js/markdowneditor.js @@ -5,6 +5,8 @@ import MarkdowneditorUndo from "./markdowneditor.undo"; import MarkdowneditorSave from "./markdowneditor.save"; import MarkdowneditorVersions from "./markdowneditor.versions"; import MarkdowneditorZoom from "./markdowneditor.zoom"; +import MarkdowneditorPopup from "./markdowneditor.popup"; +import MarkdowneditorResize from "./markdowneditor.resize"; import tippy from "tippy.js"; import 'tippy.js/dist/tippy.css'; @@ -12,6 +14,7 @@ import 'tippy.js/dist/tippy.css'; import Noty from "noty"; import 'noty/lib/noty.css'; import 'noty/lib/themes/mint.css'; +import LinkeditorPopup from "../../linkeditor/js/linkeditor.popup"; window.$ = window.jQuery = require('jquery'); window.key = require('keymaster-reloaded'); @@ -60,9 +63,11 @@ MarkdownEditor.prototype = { init: function() { new MarkdowneditorToolbar(this); this.undo = new MarkdowneditorUndo(this); + this.resize = new MarkdowneditorResize(this); this.save = new MarkdowneditorSave(this); this.versions = new MarkdowneditorVersions(this); this.zoom = new MarkdowneditorZoom(this); + this.popup = new MarkdowneditorPopup(this); this.options = { el: document.querySelector('#editor'), diff --git a/resources/markdowneditor/js/markdowneditor.popup.js b/resources/markdowneditor/js/markdowneditor.popup.js new file mode 100644 index 000000000..059471317 --- /dev/null +++ b/resources/markdowneditor/js/markdowneditor.popup.js @@ -0,0 +1,53 @@ +function MarkdowneditorPopup(markdowneditor) { + this.markdowneditor = markdowneditor; + this.init(); +} + +MarkdowneditorPopup.prototype = { + init: function () { + var $this = this; + $(document).on('click', '.popup .close', function () { + if ($this.hasOpenPopup()) { + $this.close(); + } + }); + }, + + openLinksMove() { + this.open('moveLinks'); + }, + + open: function (name) { + var clone = $("#popup-templates [data-popup=" + name + "]").clone(); + $("#popup-holder").append(clone); + $("#popup-overlay").addClass('show'); + this.resize(); + }, + + close: function (name = '') { + $("#popup-overlay").removeClass('show'); + $("#popup-holder").html(''); + }, + + hasOpenPopup() { + return $("#popup-overlay.show").length === 1; + }, + + resize: function () { + if (!this.hasOpenPopup()) { + return; + } + var p = $("#popup-holder>div"); + var w = $(p).outerWidth(); + var h = $(p).outerHeight(); + var left = (this.markdowneditor.resize.ww - w) / 2; + var top = (this.markdowneditor.resize.hh - h) / 2; + $("#popup-holder").css({ + width: w, + height: h, + left: left, + top: top, + }) + } +}; +export default MarkdowneditorPopup; diff --git a/resources/markdowneditor/js/markdowneditor.resize.js b/resources/markdowneditor/js/markdowneditor.resize.js new file mode 100644 index 000000000..6e63465ae --- /dev/null +++ b/resources/markdowneditor/js/markdowneditor.resize.js @@ -0,0 +1,127 @@ +function MarkdowneditorResize(markdowneditor) { + this.markdowneditor = markdowneditor; + this.init(); +} + +MarkdowneditorResize.prototype = { + init: function () { + var $this = this; + $(window).on('resize', function () { + $this.resize(); + setTimeout(function () { + $this.resize(); + }, 100); + }); + this.updateWindowDimensions(); + }, + + updateWindowDimensions: function () { + this.ww = $(window).outerWidth(); + this.hh = $(window).outerHeight(); + }, + + resize: function () { + let special = this.markdowneditor.utils.isSpecialPage(); + if (this.markdowneditor.single || special) { + $("#markdowneditor").addClass('single').removeClass('double'); + } else { + $("#markdowneditor").addClass('double').removeClass('single'); + } + this.resizePages(); + this.updateWindowDimensions(); + this.resizeMain(); + this.resizeCanvas(); + if (this.markdowneditor.panels) { + this.markdowneditor.panels.resize(this.ww); + } + this.markdowneditor.rulers.updateRulers(); + if (this.markdowneditor.popup) { + this.markdowneditor.popup.resize(); + } + let width = $("#markdowneditor-fluidbook").css("width") + let height = $("#markdowneditor-fluidbook").css("height") + let transform = $("#markdowneditor-fluidbook").css("transform") + let left_ = $("#markdowneditor-fluidbook").css("left") + let top_ = $("#markdowneditor-fluidbook").css("top") + + $("#markdowneditor-layer-links").css({ + 'width':width, + 'height':height, + 'left':left_, + 'top':top_, + 'transform':transform, + }) + //this.markdowneditor.previewLinks.setPreview() + }, + + resizePages: function () { + let $this = this; + let dimCover = $this.markdowneditor.utils.getPageDimensions(1); + let pw; + let ph; + let special = false; + + $(".markdowneditor-page[data-page]:visible").each(function () { + let p = $(this).attr('data-page'); + let dim = $this.markdowneditor.utils.getPageDimensions(p); + if (dim === undefined) { + dim = dimCover; + } + pw = dim[0]; + ph = dim[1]; + + if ($this.markdowneditor.utils.isSpecialPage(p)) { + special = true; + } else if ($this.markdowneditor.mobileFirst) { + pw = dimCover[0]; + } else { + pw = dimCover[0]; + ph = dimCover[1]; + } + $(this).css({width: pw, height: ph}); + }); + + let fw = pw; + if (!this.markdowneditor.single && !special) { + fw *= 2; + } + $("#markdowneditor-page-right").css({left: this.markdowneditor.pw}); + $("#markdowneditor-fluidbook,#markdowneditor-layer-links,.markdowneditor-fluidbook-copy").css({width: fw, height: ph}); + }, + + resizeMain: function () { + $("#markdowneditor-main").css('width', this.ww - $('#markdowneditor-left').outerWidth() - $('#markdowneditor-right').outerWidth()); + }, + + resizeCanvas: function () { + this.markdowneditor.canvasRect = $("#markdowneditor-canvas").get(0).getBoundingClientRect(); + this.markdowneditor.editorRect = $("#markdowneditor-editor").get(0).getBoundingClientRect(); + var aw = this.markdowneditor.canvasRect.width - 30; + var ah = this.markdowneditor.canvasRect.height - 30; + + if (this.markdowneditor.utils.isSpecialPage()) { + let dim = this.markdowneditor.utils.getPageDimensions(); + this.markdowneditor.fs = Math.min(1, aw / dim[0], ah / dim[1]); + } else if (this.markdowneditor.mobileFirst) { + this.markdowneditor.fs = 620 / this.markdowneditor.fw; + } else { + this.markdowneditor.fs = Math.min(aw / this.markdowneditor.fw, ah / this.markdowneditor.fh); + } + + let left, top; + + if (this.markdowneditor.utils.isSpecialPage()) { + let dim = this.markdowneditor.utils.getPageDimensions(); + left = (this.markdowneditor.canvasRect.width - (dim[0] * this.markdowneditor.fs)) / 2; + top = (this.markdowneditor.canvasRect.height - (dim[1] * this.markdowneditor.fs)) / 2; + } else if (!this.markdowneditor.mobileFirst) { + left = ((this.markdowneditor.canvasRect.width * 2) - this.markdowneditor.fw * this.markdowneditor.fs) / 2; + top = ((this.markdowneditor.canvasRect.height * 2) - this.markdowneditor.fh * this.markdowneditor.fs) / 2; + } else { + left = (this.markdowneditor.canvasRect.width - this.markdowneditor.fw * this.markdowneditor.fs) / 2; + top = 75; + } + $("#markdowneditor-fluidbook,#markdowneditor-layer-links").css({left: left, top: top, transform: 'scale(' + this.markdowneditor.fs + ')'}); + }, +}; +export default MarkdowneditorResize; diff --git a/resources/markdowneditor/style/inc/_form.sass b/resources/markdowneditor/style/inc/_form.sass new file mode 100644 index 000000000..77953ba85 --- /dev/null +++ b/resources/markdowneditor/style/inc/_form.sass @@ -0,0 +1,303 @@ +body + --form-text-color: #5d5d5d + --field-background: #fff + --field-color: #bbb + --field-border: #aaa + --field-border-background: #fff + --field-color-button: #bbb + --field-border-button: #aaa + + @include dark-theme + --form-text-color: #aaa + --field-background: #fff + --field-color: #bbb + --field-border: #ccc + --field-background-button: #000 + --field-color-button: #ccc + --field-border-button: #bbb + +textarea, input[type="text"], input[type="number"], input[type="email"], input[type="url"], input[type="tel"] + font-family: $font + font-weight: 400 + color: var(--field-color) + background-color: var(--field-background) + border: 1px solid var(--field-border) + border-radius: 3px + font-size: 13px + transition: box-shadow 500ms, border 500ms + appearance: none + + &:focus + border: 1px solid var(--field-border) + box-shadow: 0 0 8px rgba(0, 0, 0, 0.3) + +input[type="checkbox"] + margin-right: 8px + appearance: none + position: relative + cursor: pointer + color: var(--form-text-color) + + &::before + content: '' + display: inline-block + width: 14px + height: 14px + border: 1px solid currentColor + border-radius: 2px + vertical-align: baseline + + &:checked + &::after + content: '' + display: block + width: 12px + height: 12px + position: absolute + top: 1px + left: 1px + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%) + background-color: currentColor + + +input[type=number] + &, &:hover + appearance: textfield + + &::-webkit-inner-spin-button, &::-webkit-outer-spin-button + -webkit-appearance: none + margin: 0 + visibility: hidden + +button + font-family: $font + font-weight: 500 + font-size: 15px + padding: 5px 10px + border: 1px solid var(--field-border-button) + border-radius: 4px + color: var(--field-color-button) + background-color: var(--field-background-button) + cursor: pointer + +.select2-hidden-accessible + position: fixed !important + +#linkeditor-form-templates + display: none + +.linkeditor-linktype + &::before + display: inline-block + width: 12px + height: 12px + border-radius: 2px + margin: 2px 10px 0 0 + content: "" + vertical-align: top + position: relative + + +#linkeditor-panel-form + + + padding: 12px + font-size: 13px + + .select2-container--bootstrap + font-size: 13px + font-weight: 400 + + hr + border: 0 + height: 1px + background-color: var(--form-text-color) + margin: 5px 0 + + &, .select2-selection + color: var(--form-text-color) + background-color: var(--field-background) + border-color: var(--field-background) + border-radius: 4px + box-shadow: none + + &.select2-container--focus .select2-selection, &.select2-container--open .select2-selection + box-shadow: 0 0 8px rgba(0, 0, 0, 0.1) + border-color: var(--field-border) + + h3 + font-size: 16px + color: var(--form-text-color) + text-transform: uppercase + padding-top: 15px + border-top: 1px solid var(--form-text-color) + margin-top: 20px + + p.help-block + color: var(--form-text-color) + font-size: 11px + padding-top: 2px + white-space: normal + + .freefile-file + position: relative + + &.loading + &::after + background-image: url("/images/linkeditor/dots-animated.svg") + @include dark-theme + background-image: url("/images/linkeditor/dots-dark-animated.svg") + + input + pointer-events: none + cursor: wait + + &::after + content: "" + position: absolute + display: block + padding: 6px + right: 0 + top: 6px + width: 25px + height: 25px + background-image: url("/images/linkeditor/dots.svg") + color: var(--field-color) + box-sizing: border-box + pointer-events: none + font-size: 17px + @include dark-theme + background-image: url("/images/linkeditor/dots-dark.svg") + + input[type=file] + position: absolute + right: 0 + width: 35px + opacity: 0 + height: 100% + cursor: pointer + + a.upload + position: absolute + right: 0 + width: 35px + opacity: 0 + height: 100% + cursor: pointer + z-index: 2 + + + .input-group + position: relative + + .input-group-append + position: absolute + height: 100% + top: 0 + right: 0 + pointer-events: none + padding: 8px + + textarea, input[type="text"], input[type="number"], input[type="email"], input[type="url"], input[type="tel"] + height: 34px + padding: 8px + width: 100% + + textarea + height: auto + min-height: 150px + max-width: 100% + min-width: 100% + + span + font-weight: 400 + font-size: 13px + color: var(--form-text-color) + + label + display: block + font-weight: 600 + font-size: 12px + color: var(--form-text-color) + margin: 8px 0 5px 0 + + .checkbox + margin: 4px 0 5px 0 + + position: relative + top: 6px + + label + vertical-align: baseline + display: inline-block + position: relative + top: -4px + margin: 0 + cursor: pointer + + span + margin-left: 5px + + + #group_position, #group_dimensions, #group_transform + margin-top: 5px + + h4 + font-size: 12px + font-weight: 700 + color: var(--form-text-color) + grid-column: 1 / 3 + grid-row: 1 / 2 + margin-bottom: 5px + + display: grid + grid-template-columns: repeat( 2, 1fr) + grid-gap: 2px 25px + + label + display: inline-block + width: 20px + + input + width: calc(100% - 20px) + + [data-name="rot"] + label + display: block + + .input-group + .input-group-append + right: 0 + + .input-group + display: inline-block + + .input-group-append + right: 20px + + + #group_transform + input + width: 100% + +.select2-container--bootstrap .select2-results > .select2-results__options + max-height: 350px !important + + +[data-name='image_rollover'] label + display: flex !important + align-items: end + justify-content: space-between + +#linkeditor-start-animation + display: flex + width: 26px + height: 26px + background: transparent + padding: 4px 4px + border: 0 + &:hover + background-color: #000 + svg + width: 100% + fill: transparent diff --git a/resources/markdowneditor/style/inc/_popup.sass b/resources/markdowneditor/style/inc/_popup.sass new file mode 100644 index 000000000..ce08b17ea --- /dev/null +++ b/resources/markdowneditor/style/inc/_popup.sass @@ -0,0 +1,67 @@ +#popup-templates + display: none + +#popup-overlay + background-color: rgba(0, 0, 0, 0.5) + position: absolute + top: 0 + left: 0 + opacity: 0 + pointer-events: none + transition: opacity 350ms + width: 100% + height: 100% + z-index: 10000000 + + &.show, + &.unavailable + opacity: 1 + pointer-events: auto + + #popup-holder + position: absolute + max-width: 100% + max-height: 100% + + .popup + background-color: #dbdddf + color: #5D5D5D + font-size: 13px + padding: 20px + box-shadow: 0 0 20px rgba(0,0,0,0.5) + + h2 + font-size: 16px + padding-bottom: 10px + font-weight: 500 + margin: 0 + + a.close + display: block + position: absolute + top: 20px + right: 20px + width: 15px + height: 15px + cursor: pointer + + p + margin: 12px 0 + white-space: normal + + p.button + text-align: right + margin: 20px 0 0 0 + + + @include dark-theme + background-color: #333 + color: #d5d5d5 + + &[data-popup="moveLinks"] + input + &[type="text"],&[type="number"] + width: 50px + height: 20px + margin: 0 5px + padding: 4px diff --git a/resources/markdowneditor/style/inc/_variables.sass b/resources/markdowneditor/style/inc/_variables.sass new file mode 100644 index 000000000..2246963c8 --- /dev/null +++ b/resources/markdowneditor/style/inc/_variables.sass @@ -0,0 +1,18 @@ +$font: Montserrat, sans-serif +$font-size: 16px +$sidebar-icons-width: 46px +$sidebar-handle-width: 3px +$rulers-size: 16px +$ruler-margin: 2px + +$toolbar-height: 40px +$toolbar-color: #5d5d5d +$toolbar-color-dark: #bbb + +$toolbar-color-disabled: #bbb +$toolbar-color-disabled-dark: #666 + +$panel-background: #dcdcdc + +$color: #5d5d5d +$color-dark: #bbb diff --git a/resources/markdowneditor/style/style.sass b/resources/markdowneditor/style/style.sass index 975ebae57..b90d433bd 100644 --- a/resources/markdowneditor/style/style.sass +++ b/resources/markdowneditor/style/style.sass @@ -330,3 +330,7 @@ input::-webkit-inner-spin-button @include dark-theme background-color: #222 !important border-top-color: #222 !important + +@import "inc/_variables" +@import "inc/_form" +@import "inc/_popup" diff --git a/resources/views/fluidbook_publication/markdown_editor.blade.php b/resources/views/fluidbook_publication/markdown_editor.blade.php index 4ff80b9e4..b0f78eb45 100644 --- a/resources/views/fluidbook_publication/markdown_editor.blade.php +++ b/resources/views/fluidbook_publication/markdown_editor.blade.php @@ -69,12 +69,32 @@ @section('content') @include('fluidbook_publication.link_editor_icons') + +
+ data-tooltip="{{__('Paramètres du lien')}} (F8)" data-key="f8">
@@ -86,9 +106,9 @@
-- 2.39.5