Add server file picker to TinyMCE (close #20)

This commit is contained in:
Skylar Ittner 2018-05-07 00:43:52 -06:00
parent b1edda1f86
commit 7072d4c343
6 changed files with 184 additions and 9 deletions

112
lib/filepicker.php Normal file
View 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>

View File

@ -40,7 +40,8 @@ define("PAGES", [
"title" => "editor",
"styles" => [
"static/css/editorparent.css",
"static/css/iconselector.css"
"static/css/iconselector.css",
"static/css/filepicker.css",
],
"scripts" => [
"static/js/editorparent.js",

View File

@ -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">&times;</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-dialog" role="document">
<form class="modal-content" action="action.php" method="POST">

10
static/css/filepicker.css Normal file
View 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;
}

View File

@ -31,6 +31,8 @@ function saveEdits() {
parent.postMessage('save ' + json, "*");
}
var filePickerCallback = null;
$(document).ready(function () {
$('a').click(function (e) {
e.preventDefault();
@ -46,25 +48,22 @@ $(document).ready(function () {
tinymce.init({
selector: '.sw-editable',
inline: true,
paste_data_images: true,
plugins: [
'autolink lists link image imagetools charmap',
'searchreplace visualblocks code fullscreen',
'media table contextmenu paste code'
],
branding: false,
/*menu: {
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'}
},*/
elementpath: false,
menubar: 'edit insert view format table tools',
toolbar: 'insert | undo redo | formatselect | bold italic | bullist numlist outdent indent | removeformat | fullscreen',
link_list: function (success) {
success(pages_list);
},
file_picker_callback: function (callback, value, meta) {
filePickerCallback = callback;
parent.postMessage('browse ' + meta.filetype, "*");
},
mobile: {
theme: 'mobile'
}
@ -114,6 +113,10 @@ $(document).ready(function () {
var comp = json["component"];
var data = json["content"];
$(".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);
}
});
});

View File

@ -78,6 +78,34 @@ function editComplex(json) {
$("#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 () {
var data = {};
data["component"] = $("#editModal").data("component");
@ -102,6 +130,8 @@ window.addEventListener('message', function (event) {
save(event.data.slice(5));
} else if (event.data.startsWith("editcomplex ")) {
editComplex(event.data.slice(12));
} else if (event.data.startsWith("browse ")) {
openFilePicker(event.data.slice(7));
}
});