Add server file picker to TinyMCE (close #20)
This commit is contained in:
parent
b1edda1f86
commit
7072d4c343
112
lib/filepicker.php
Normal file
112
lib/filepicker.php
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../required.php';
|
||||||
|
|
||||||
|
dieifnotloggedin();
|
||||||
|
|
||||||
|
include_once __DIR__ . "/../lib/mimetypes.php";
|
||||||
|
|
||||||
|
$base = FILE_UPLOAD_PATH;
|
||||||
|
|
||||||
|
$folder = "";
|
||||||
|
if (isset($VARS['path']) && file_exists($base . $VARS['path']) && strpos(realpath($base . $VARS['path']), FILE_UPLOAD_PATH) === 0) {
|
||||||
|
$folder = $VARS['path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($folder == "/") {
|
||||||
|
$folder = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$fullpath = $base . $folder;
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<nav aria-label="breadcrumb" class="my-auto">
|
||||||
|
<ol class="breadcrumb m-0">
|
||||||
|
<?php
|
||||||
|
$pathparts = explode("/", "$folder");
|
||||||
|
$pstr = "";
|
||||||
|
for ($i = 0; $i < count($pathparts); $i++) {
|
||||||
|
$p = $pathparts[$i];
|
||||||
|
$pstr .= "/$p";
|
||||||
|
$pstr = "/" . ltrim($pstr, "/");
|
||||||
|
if ($i == 0) {
|
||||||
|
$p = "<span class=\"fas fa-home\"></span>";
|
||||||
|
}
|
||||||
|
if ($i == count($pathparts) - 1) {
|
||||||
|
echo "\t<li aria-current=\"page\" class=\"breadcrumb-item active\">$p</li>";
|
||||||
|
} else {
|
||||||
|
echo "\t<li class=\"breadcrumb-item\"><span class=\"filepicker-item\" data-type=\"dir\" data-path=\"$pstr\">$p</a></li>";
|
||||||
|
}
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="list-group">
|
||||||
|
<?php
|
||||||
|
$files = scandir($fullpath);
|
||||||
|
$count = 0;
|
||||||
|
foreach ($files as $f) {
|
||||||
|
if (strpos($f, '.') !== 0) {
|
||||||
|
$count++;
|
||||||
|
$link = "$folder/$f";
|
||||||
|
$target = "_BLANK";
|
||||||
|
$isdir = false;
|
||||||
|
$icon = "fas fa-file";
|
||||||
|
if (is_dir($fullpath . "/" . $f)) {
|
||||||
|
$isdir = true;
|
||||||
|
$link = "app.php?page=files&path=$folder/$f";
|
||||||
|
$icon = "fas fa-folder";
|
||||||
|
$target = "";
|
||||||
|
} else {
|
||||||
|
$link = "public/file.php?file=$folder/$f";
|
||||||
|
$extension = pathinfo($fullpath . "/" . $f)['extension'];
|
||||||
|
// If we don't have an extension, try using the whole filename
|
||||||
|
if ($extension == "") {
|
||||||
|
$extension = $f;
|
||||||
|
}
|
||||||
|
$mimetype = "application/octet-stream";
|
||||||
|
// Lookup mimetype from extension
|
||||||
|
if (array_key_exists($extension, $EXT2MIME)) {
|
||||||
|
$mimetype = $EXT2MIME[$extension];
|
||||||
|
}
|
||||||
|
// Lookup icon from mimetype
|
||||||
|
if (array_key_exists($mimetype, $MIMEICONS)) {
|
||||||
|
$icon = $MIMEICONS[$mimetype];
|
||||||
|
} else { // Allow broad generic <format>/other icons
|
||||||
|
$mimefirst = explode("/", $mimetype, 2)[0];
|
||||||
|
if (array_key_exists($mimefirst . "/other", $MIMEICONS)) {
|
||||||
|
$icon = $MIMEICONS[$mimetype];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div
|
||||||
|
class="list-group-item filepicker-item"
|
||||||
|
data-type="<?php echo $isdir ? "dir" : "file" ?>"
|
||||||
|
data-path="<?php echo "$folder/$f"; ?>"
|
||||||
|
data-file="<?php echo $f; ?>">
|
||||||
|
<span class="<?php echo $icon; ?> fa-fw"></span> <?php echo $f; ?>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($count == 0) {
|
||||||
|
?>
|
||||||
|
<div class="list-group-item text-center">
|
||||||
|
<p class="text-muted">
|
||||||
|
<i class="far fa-folder-open fa-5x fa-fw"></i>
|
||||||
|
</p>
|
||||||
|
<p class="h5 text-muted">
|
||||||
|
<?php lang("nothing here"); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
@ -40,7 +40,8 @@ define("PAGES", [
|
|||||||
"title" => "editor",
|
"title" => "editor",
|
||||||
"styles" => [
|
"styles" => [
|
||||||
"static/css/editorparent.css",
|
"static/css/editorparent.css",
|
||||||
"static/css/iconselector.css"
|
"static/css/iconselector.css",
|
||||||
|
"static/css/filepicker.css",
|
||||||
],
|
],
|
||||||
"scripts" => [
|
"scripts" => [
|
||||||
"static/js/editorparent.js",
|
"static/js/editorparent.js",
|
||||||
|
@ -68,6 +68,25 @@ if (!is_empty($VARS['siteid'])) {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<div class="modal fade" id="fileBrowseModal" tabindex="-1" role="dialog" aria-labelledby="fileBrowseLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="fileBrowseLabel"><i class="far fa-folder-open"></i> <?php lang("browse"); ?></h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="fileBrowseModalBody">
|
||||||
|
<i class="fas fa-spin fa-circle-notch"></i> <?php lang("loading"); ?>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal"><?php lang("cancel"); ?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="pageSettingsModal" tabindex="-1" role="dialog" aria-labelledby="pageSettingsLabel" aria-hidden="true">
|
<div class="modal fade" id="pageSettingsModal" tabindex="-1" role="dialog" aria-labelledby="pageSettingsLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<form class="modal-content" action="action.php" method="POST">
|
<form class="modal-content" action="action.php" method="POST">
|
||||||
|
10
static/css/filepicker.css
Normal file
10
static/css/filepicker.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.filepicker-item {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #2196F3;
|
||||||
|
}
|
@ -31,6 +31,8 @@ function saveEdits() {
|
|||||||
parent.postMessage('save ' + json, "*");
|
parent.postMessage('save ' + json, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var filePickerCallback = null;
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('a').click(function (e) {
|
$('a').click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -46,25 +48,22 @@ $(document).ready(function () {
|
|||||||
tinymce.init({
|
tinymce.init({
|
||||||
selector: '.sw-editable',
|
selector: '.sw-editable',
|
||||||
inline: true,
|
inline: true,
|
||||||
paste_data_images: true,
|
|
||||||
plugins: [
|
plugins: [
|
||||||
'autolink lists link image imagetools charmap',
|
'autolink lists link image imagetools charmap',
|
||||||
'searchreplace visualblocks code fullscreen',
|
'searchreplace visualblocks code fullscreen',
|
||||||
'media table contextmenu paste code'
|
'media table contextmenu paste code'
|
||||||
],
|
],
|
||||||
branding: false,
|
branding: false,
|
||||||
/*menu: {
|
elementpath: false,
|
||||||
edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | findreplace'},
|
|
||||||
view: {title: 'View', items: 'sourcecode | visualaid showblocks'},
|
|
||||||
insert: {title: 'Insert', items: 'image link media table | charmap'},
|
|
||||||
format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript | blocks align formats | removeformat'},
|
|
||||||
table: {title: 'Table', items: 'inserttable tableprops deletetable | cell row column'}
|
|
||||||
},*/
|
|
||||||
menubar: 'edit insert view format table tools',
|
menubar: 'edit insert view format table tools',
|
||||||
toolbar: 'insert | undo redo | formatselect | bold italic | bullist numlist outdent indent | removeformat | fullscreen',
|
toolbar: 'insert | undo redo | formatselect | bold italic | bullist numlist outdent indent | removeformat | fullscreen',
|
||||||
link_list: function (success) {
|
link_list: function (success) {
|
||||||
success(pages_list);
|
success(pages_list);
|
||||||
},
|
},
|
||||||
|
file_picker_callback: function (callback, value, meta) {
|
||||||
|
filePickerCallback = callback;
|
||||||
|
parent.postMessage('browse ' + meta.filetype, "*");
|
||||||
|
},
|
||||||
mobile: {
|
mobile: {
|
||||||
theme: 'mobile'
|
theme: 'mobile'
|
||||||
}
|
}
|
||||||
@ -114,6 +113,10 @@ $(document).ready(function () {
|
|||||||
var comp = json["component"];
|
var comp = json["component"];
|
||||||
var data = json["content"];
|
var data = json["content"];
|
||||||
$(".sw-complex[data-component='" + comp + "']").data("json", JSON.stringify(data));
|
$(".sw-complex[data-component='" + comp + "']").data("json", JSON.stringify(data));
|
||||||
|
} else if (event.data.startsWith("picked ")) {
|
||||||
|
var json = JSON.parse(event.data.slice(7));
|
||||||
|
console.log(json);
|
||||||
|
filePickerCallback(json.path, json.meta);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -78,6 +78,34 @@ function editComplex(json) {
|
|||||||
$("#editModal").modal();
|
$("#editModal").modal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadFilePickerFolder(path) {
|
||||||
|
$.get("lib/filepicker.php", {
|
||||||
|
path: path
|
||||||
|
}, function (data) {
|
||||||
|
$("#fileBrowseModalBody").html(data);
|
||||||
|
$(".filepicker-item").click(function () {
|
||||||
|
if ($(this).data("type") == "dir") {
|
||||||
|
loadFilePickerFolder($(this).data("path"));
|
||||||
|
} else {
|
||||||
|
var path = "file.php?file=" + $(this).data("path");
|
||||||
|
var data = {
|
||||||
|
path: path,
|
||||||
|
meta: {}
|
||||||
|
};
|
||||||
|
json = JSON.stringify(data);
|
||||||
|
document.getElementById("editorframe").contentWindow.postMessage("picked " + json, "*");
|
||||||
|
$("#fileBrowseModal").modal('hide');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openFilePicker(type) {
|
||||||
|
loadFilePickerFolder("/");
|
||||||
|
$("#fileBrowseModal").modal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$("#editModalSave").on("click", function () {
|
$("#editModalSave").on("click", function () {
|
||||||
var data = {};
|
var data = {};
|
||||||
data["component"] = $("#editModal").data("component");
|
data["component"] = $("#editModal").data("component");
|
||||||
@ -102,6 +130,8 @@ window.addEventListener('message', function (event) {
|
|||||||
save(event.data.slice(5));
|
save(event.data.slice(5));
|
||||||
} else if (event.data.startsWith("editcomplex ")) {
|
} else if (event.data.startsWith("editcomplex ")) {
|
||||||
editComplex(event.data.slice(12));
|
editComplex(event.data.slice(12));
|
||||||
|
} else if (event.data.startsWith("browse ")) {
|
||||||
|
openFilePicker(event.data.slice(7));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user