New approach when the page is created, remove UUID, remove symlinks for upload images, modal for filemanager, and more

This commit is contained in:
dignajar 2021-01-01 23:13:01 +01:00
parent 39de732f3b
commit ff2a51fae8
16 changed files with 712 additions and 519 deletions

View file

@ -14,26 +14,5 @@ checkRole(array('admin', 'editor', 'author'));
// Main // Main
// ============================================================================ // ============================================================================
// UUID of the page is need it for autosave and media manager
$uuid = $pages->generateUUID();
// Images prefix directory
define('PAGE_IMAGES_KEY', $uuid);
// Images and thubmnails directories
if (IMAGE_RESTRICT) {
define('PAGE_IMAGES_DIRECTORY', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : HTML_PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/'));
define('PAGE_IMAGES_URL', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : DOMAIN_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/'));
define('PAGE_THUMBNAILS_DIRECTORY', PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.DS.'thumbnails'.DS);
define('PAGE_THUMBNAILS_HTML', HTML_PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/thumbnails/');
define('PAGE_THUMBNAILS_URL', DOMAIN_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/thumbnails/');
} else {
define('PAGE_IMAGES_DIRECTORY', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : HTML_PATH_UPLOADS));
define('PAGE_IMAGES_URL', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : DOMAIN_UPLOADS));
define('PAGE_THUMBNAILS_DIRECTORY', PATH_UPLOADS_THUMBNAILS);
define('PAGE_THUMBNAILS_HTML', HTML_PATH_UPLOADS_THUMBNAILS);
define('PAGE_THUMBNAILS_URL', DOMAIN_UPLOADS_THUMBNAILS);
}
// View HTML <title> // View HTML <title>
$layout['title'] = $L->g('New content') . ' - ' . $layout['title']; $layout['title'] = $L->g('New content') . ' - ' . $layout['title'];

View file

@ -5,7 +5,13 @@ a {
/* Remove Focus glow */ /* Remove Focus glow */
.btn:focus, .btn:focus,
.form-control:focus { .form-control:focus,
.form-select:focus {
outline: none; outline: none;
box-shadow: none; box-shadow: none;
} }
/* Icons */
.bi {
margin-right: .5rem!important;
}

View file

@ -0,0 +1,19 @@
<div aria-live="polite" aria-atomic="true" class="position-relative">
<div class="toast-container position-absolute top-0 end-0 p-3">
<div id="alert" class="toast d-flex align-items-center text-white bg-primary border-0" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-body">Hello, I'm a Bludit alert!</div>
<button type="button" class="btn-close btn-close-white ms-auto me-2" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</div>
<script>
function showAlert(text) {
$('#alert').children('.toast-body').html(text);
$('#alert').toast('show');
}
function hideAlert(text) {
$('#alert').toast('hide');
}
</script>

View file

@ -0,0 +1,156 @@
<div class="modal" id="modal-fileManager" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<div class="container-fluid">
<div class="row">
<div class="col">
<div class="d-flex align-items-center mb-2">
<h3 class="me-auto m-0 p-0"><i class="bi bi-image"></i><?php $L->p('File Manager'); ?></h3>
<label class="btn btn-primary"><i class="bi bi-upload"></i><?php $L->p('Upload file'); ?><input type="file" id="filesToUpload" name="filesToUpload[]" multiple hidden></label>
<div class="progress d-none">
<div class="progress-bar" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Preview</th>
<th scope="col">Filename</th>
<th scope="col">Type</th>
<th scope="col">Size</th>
<th scope="col"></th>
</tr>
</thead>
<tbody id="fmFiles">
<tr>
<td class="align-middle">
<img style="width: 32px" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />
</td>
<td class="align-middle">photo.jpg</td>
<td class="align-middle">image/jpeg</td>
<td class="align-middle">300Kb</td>
<td class="align-middle">
<i class="bi bi-trash"></i><span><?php $L->p('Delete') ?></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Open File Manager modal
function fmOpen() {
$('#modal-fileManager').modal('show');
}
// Get files for the current page and show them
function fmGetFiles() {
logs('File Manager. Get files for page: ' + _pageKey);
api.getPageFiles({
'pageKey': _pageKey
}).then(function(files) {
fmDisplayFiles(files);
});
}
// Show the files in the table
function fmDisplayFiles(files) {
$('#fmFiles').empty();
if (files.length == 0) {
logs('File Manager. File list empty.');
return false;
}
$.each(files, function(key, file) {
var row = '<tr>' +
' <td class="align-middle">' +
' <img style="width: 32px" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />' +
' </td>' +
' <td class="align-middle">' + file.filename + '</td>' +
' <td class="align-middle">' + file.mime + '</td>' +
' <td class="align-middle">' + formatBytes(file.size) + '</td>' +
' <td class="align-middle">' +
' <i class="bi bi-trash"></i><span><?php $L->p('Delete') ?></span>' +
' </td>' +
' </tr>';
$('#fmFiles').append(row);
});
return true;
}
// Upload a file for the current page
function fmUploadFile(file) {
logs('File Manager. Uploading file.');
// Check file type/extension
const validImageTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml'];
if (!validImageTypes.includes(file.type)) {
logs("File Manager. File type is not supported.");
showAlert("<?php echo $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']) ?>");
return false;
}
// Check file size and compare with PHP upload_max_filesize
if (file.size > UPLOAD_MAX_FILESIZE) {
logs("File Manager. File size to big for PHP configuration.");
showAlert("<?php echo $L->g('Maximum load file size allowed:') . ' ' . ini_get('upload_max_filesize') ?>");
return false;
}
// Data to send via AJAX
var formData = new FormData();
formData.append("file", file);
formData.append("token", api.body.token);
formData.append("authentication", api.body.authentication);
$.ajax({
url: api.apiURL + 'files/' + _pageKey,
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false,
xhr: function() {
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
logs("File Manager. Uploading file, percent complete: " + percentComplete + "%");
}
}, false);
}
return xhr;
}
}).done(function(data) {
logs("File Manager. File uploaded.")
logs(data);
fmGetFiles();
});
}
$(document).ready(function() {
// Input file change event
$("#filesToUpload").on("change", function(e) {
var filesToUpload = $("#filesToUpload")[0].files;
for (var i = 0; i < filesToUpload.length; i++) {
fmUploadFile(filesToUpload[i]);
}
});
});
</script>

View file

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html class="h-100"> <html class="h-100">
<head> <head>
<title><?php echo $layout['title'] ?></title> <title><?php echo $layout['title'] ?></title>
<meta charset="<?php echo CHARSET ?>"> <meta charset="<?php echo CHARSET ?>">
@ -12,34 +13,34 @@
<!-- CSS --> <!-- CSS -->
<?php <?php
echo HTML::cssBootstrap(); echo HTML::cssBootstrap();
echo HTML::cssBootstrapIcons(); echo HTML::cssBootstrapIcons();
echo HTML::css(array( echo HTML::css(array(
'bludit-bootstrap.css', 'bludit-bootstrap.css',
'bludit.css' 'bludit.css'
), DOMAIN_ADMIN_THEME_CSS); ), DOMAIN_ADMIN_THEME_CSS);
echo HTML::css(array( echo HTML::css(array(
'jquery.datetimepicker.min.css', 'jquery.datetimepicker.min.css',
'jquery-ui.min.css', 'jquery-ui.min.css',
'select2.min.css', 'select2.min.css',
'select2-bootstrap4.min.css', 'select2-bootstrap4.min.css',
'tagsinput-revisited.min.css' 'tagsinput-revisited.min.css'
), DOMAIN_CORE_CSS); ), DOMAIN_CORE_CSS);
?> ?>
<!-- Javascript --> <!-- Javascript -->
<?php <?php
echo HTML::jquery(); echo HTML::jquery();
echo HTML::jsBootstrap(); echo HTML::jsBootstrap();
echo HTML::jsSortable(); echo HTML::jsSortable();
echo HTML::js(array( echo HTML::js(array(
'jquery.datetimepicker.full.min.js', 'jquery.datetimepicker.full.min.js',
'jquery-ui.min.js', 'jquery-ui.min.js',
'select2.full.min.js', 'select2.full.min.js',
'tagsinput-revisited.min.js', 'tagsinput-revisited.min.js',
'functions.js', 'functions.js',
'api.js' 'api.js'
), DOMAIN_CORE_JS); ), DOMAIN_CORE_JS);
?> ?>
<!-- Execute plugins for the admin area inside the HTML <head> tag --> <!-- Execute plugins for the admin area inside the HTML <head> tag -->
@ -54,11 +55,12 @@
<!-- Javascript global variable generated by PHP --> <!-- Javascript global variable generated by PHP -->
<?php include(PATH_CORE_JS . 'variables.php') ?> <?php include(PATH_CORE_JS . 'variables.php') ?>
<!-- Navbar, only for small devices -->
<?php include('html/navbar.php'); ?>
<div class="container-fluid p-0 m-0 d-flex flex-column h-100"> <div class="container-fluid p-0 m-0 d-flex flex-column h-100">
<!-- Alerts -->
<?php include('html/alerts.php') ?>
<!-- End Alerts -->
<!-- Top Navbar --> <!-- Top Navbar -->
<div class="container-fluid p-0 bg-dark"> <div class="container-fluid p-0 bg-dark">
<div class="container"> <div class="container">
@ -72,19 +74,19 @@
</div> </div>
</div> </div>
</div> </div>
<!-- END Top Navbar --> <!-- End Top Navbar -->
<!-- Main --> <!-- Main -->
<div class="container mt-3 h-100 flex-grow-1"> <div class="container h-100 flex-grow-1">
<div class="row h-100 flex-grow-1"> <div class="row h-100 flex-grow-1">
<!-- LEFT Main, display only on large devices --> <!-- LEFT Main, display only on large devices -->
<div class="sidebar col-lg-2 d-none d-lg-block"> <div class="sidebar col-lg-2 d-none d-lg-block mt-4">
<?php include('html/sidebar.php'); ?> <?php include('html/sidebar.php'); ?>
</div> </div>
<!-- RIGHT Main --> <!-- RIGHT Main -->
<div class="main col-lg-10"> <div class="main col-lg-10 mt-2">
<?php <?php
if (Sanitize::pathFile(PATH_ADMIN_VIEWS . $layout['view'] . '.php')) { if (Sanitize::pathFile(PATH_ADMIN_VIEWS . $layout['view'] . '.php')) {
include(PATH_ADMIN_VIEWS . $layout['view'] . '.php'); include(PATH_ADMIN_VIEWS . $layout['view'] . '.php');
@ -98,7 +100,7 @@
</div> </div>
</div> </div>
</div> </div>
<!-- END Main --> <!-- End Main -->
</div> </div>
@ -106,4 +108,5 @@
<?php execPluginsByHook('adminBodyEnd') ?> <?php execPluginsByHook('adminBodyEnd') ?>
</body> </body>
</html> </html>

View file

@ -1,6 +1,6 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); <?php defined('BLUDIT') or die('Bludit CMS.');
echo '<h1 class="text-center font-weight-normal mb-5">'.$site->title().'</h1>'; echo '<h1 class="text-center fw-normal mb-5">'.$site->title().'</h1>';
echo Bootstrap::formOpen(array()); echo Bootstrap::formOpen(array());

View file

@ -1,253 +1,256 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?> <?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script> <script>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Variables for the view // Variables for the view
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
var _pageKey = null; // The page key is generated the first time the user click on the button "Save" var _pageKey = null; // The page key is generated the first time the user click on the button "Save"
var _uuid = '<?php echo $uuid ?>'; // The UUID is generated at the begining if the user uploaded files to the page
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Functions for the view // Functions for the view
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Default function for the editor area (textarea)
// This helps if the user doesn't activate any plugin as editor
if (typeof editorGetContent != 'function') {
window.editorGetContent = function(){
return $('#editor').val();
};
}
if (typeof editorInsertContent != 'function') {
window.editorInsertContent = function(html){
$('#editor').val($('#editor').val()+html);
};
}
// Creates or save the page // Default function for the editor
// This function set the global variable "_pageKey" // These functions work if the user does not activate any plugin
function save(args) { if (typeof editorGetContent != 'function') {
args['uuid'] = _uuid; window.editorGetContent = function() {
// If the "page key" doesn't exists means the page not was created return $('#editor').val();
// Create the page to generate a "page key" };
if (_pageKey == null) { }
if (typeof editorInsertContent != 'function') {
window.editorInsertContent = function(html) {
$('#editor').val($('#editor').val() + html);
};
}
// Create the a page
// This function set the global variable "_pageKey"
function createPage() {
logs('Creating page'); logs('Creating page');
api.createPage(args).then(function(key) { api.createPage().then(function(key) {
logs('Page created. Key: '+key); logs('Page created. Key: ' + key);
// Set the global variable with the page key // Set the global variable with the page key
_pageKey = key; _pageKey = key;
// Disable the button save and change text
//$("#btnSave").attr("disabled", true).html("Saved");
}); });
} else { return true;
}
// Save the current page
// This function set the global variable "_pageKey"
function save(args) {
logs('Saving page'); logs('Saving page');
if (_pageKey == null) {
showAlert("Error, page not created.");
return false;
}
args['pageKey'] = _pageKey; args['pageKey'] = _pageKey;
api.savePage(args).then(function(key) { api.savePage(args).then(function(key) {
logs('Page saved. Old key: '+_pageKey+' / New key: '+key); logs('Page saved. Old key: ' + _pageKey + ' / New key: ' + key);
// Set the global variable with the page key // Set the global variable with the page key
// The page key can change after save the page so you need to set again the variable // The page key can change after save the page so you need to set again the variable
_pageKey = key; _pageKey = key;
// Disable the button save and change text
//$("#btnSave").attr("disabled", true).html("Saved");
}); });
return true;
} }
// Close all modals // Open the modal and store the current value
$('.modal').modal('hide'); // The current value is store to recover it if the user click on the button "Cancel"
return true; function openModal(fieldName) {
} var value = $('#' + fieldName).val();
localStorage.setItem(fieldName, value);
// Open the modal and store the current value $('#modal-' + fieldName).modal('show');
// The current value is store to recover it if the user click on the button "Cancel"
function openModal(fieldName) {
var value = $('#'+fieldName).val();
localStorage.setItem(fieldName, value);
$('#modal-'+fieldName).modal('show');
}
// Close the modal when the user click in the button "Cancel"
// The function also recover the old value
function closeModal(fieldName) {
var value = localStorage.getItem(fieldName);
$('#'+fieldName).val(value);
$('#modal-'+fieldName).modal('hide');
}
// This function is to catch all key press
// Provides Shortcuts
// The editor plugin need to call this function for the event "keydown"
function keypress(event) {
logs(event);
// Shortcuts
// ------------------------------------------------------------------------
// Ctrl+S or Command+S
if ((event.ctrlKey || event.metaKey) && event.which == 83) {
var args = {
title: $('#title').val(),
content: editorGetContent(),
category: $('#category option:selected').val(),
tags: $('#tags').val()
}
save(args);
$('#btnSave').addClass('btn-primary-disabled').html('<?php $L->p('Saved') ?>');
event.preventDefault();
return false;
} }
$('#btnSave').removeClass('btn-primary-disabled').html('<?php $L->p('Save') ?>'); // Close the modal when the user click in the button "Cancel"
} // The function also recover the old value
function closeModal(fieldName) {
var value = localStorage.getItem(fieldName);
$('#' + fieldName).val(value);
$('#modal-' + fieldName).modal('hide');
}
// ---------------------------------------------------------------------------- // This function is to catch all key press and provides shortcuts
// Events for the view // The editor plugin need to call this function for the event "keydown"
// ---------------------------------------------------------------------------- function keypress(event) {
$(document).ready(function() { logs(event);
// Main interface events // Shortcuts
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
$(this).keydown(function(event){ // Ctrl+S or Command+S
keypress(event); if ((event.ctrlKey || event.metaKey) && event.which == 83) {
}); var args = {
title: $('#title').val(),
$('#btnSave').on('click', function() { content: editorGetContent(),
var args = { category: $('#category option:selected').val(),
title: $('#title').val(), tags: $('#tags').val()
content: editorGetContent(), }
category: $('#category option:selected').val(), save(args);
tags: $('#tags').val() $('#btnSave').addClass('btn-primary-disabled').html('<?php $L->p('Saved') ?>');
event.preventDefault();
return false;
} }
save(args);
$(this).addClass('btn-primary-disabled').html('<?php $L->p('Saved') ?>');
});
$("#btnPreview").on("click", function() { $('#btnSave').removeClass('btn-primary-disabled').html('<?php $L->p('Save') ?>');
var title = $("#jstitle").val(); }
var content = editorGetContent();
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) { // ----------------------------------------------------------------------------
var preview = window.open("<?php echo DOMAIN_PAGES.'autosave-'.$uuid.'?preview='.md5('autosave-'.$uuid) ?>", "bludit-preview"); // Events for the view
preview.focus(); // ----------------------------------------------------------------------------
$(document).ready(function() {
// Main interface events
// ------------------------------------------------------------------------
$(this).keydown(function(event) {
keypress(event);
}); });
});
$('#btnCurrenStatus').on('click', function() { $('#btnSave').on('click', function() {
openModal('status'); var args = {
}); title: $('#title').val(),
content: editorGetContent(),
$('#category').on("change", function() { category: $('#category option:selected').val(),
$('#btnSave').html('<?php $L->p('Save') ?>'); tags: $('#tags').val()
}); }
save(args);
// Modal description events $(this).addClass('btn-primary-disabled').html('<?php $L->p('Saved') ?>');
// ------------------------------------------------------------------------
$('#btnSaveDescription').on('click', function() {
var args = {
description: $('#description').val()
};
save(args);
});
$('#btnCancelDescription').on('click', function() {
closeModal('description');
});
// Modal date events
// ------------------------------------------------------------------------
$('#btnSaveDate').on('click', function() {
var args = {
date: $('#date').val()
};
save(args);
});
$('#btnCancelDate').on('click', function() {
closeModal('date');
});
// Modal friendly-url events
// ------------------------------------------------------------------------
$('#btnSaveFriendlyURL').on('click', function() {
var args = {
slug: $('#friendlyURL').val()
};
save(args);
});
$('#btnCancelFriendlyURL').on('click', function() {
closeModal('friendlyURL');
});
$('#btnGenURLFromTitle').on('click', function() {
var args = {
text: $('#title').val(),
parentKey: $('#parent').val(),
pageKey: _pageKey
}
api.friendlyURL(args).then(function(slug) {
$('#friendlyURL').val(slug);
}); });
$("#btnPreview").on("click", function() {
var title = $("#jstitle").val();
var content = editorGetContent();
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
var preview = window.open("<?php echo DOMAIN_PAGES . 'autosave-' . $uuid . '?preview=' . md5('autosave-' . $uuid) ?>", "bludit-preview");
preview.focus();
});
});
$('#btnCurrenStatus').on('click', function() {
openModal('status');
});
$('#category').on("change", function() {
$('#btnSave').html('<?php $L->p('Save') ?>');
});
// Modal description events
// ------------------------------------------------------------------------
$('#btnSaveDescription').on('click', function() {
var args = {
description: $('#description').val()
};
save(args);
});
$('#btnCancelDescription').on('click', function() {
closeModal('description');
});
// Modal date events
// ------------------------------------------------------------------------
$('#btnSaveDate').on('click', function() {
var args = {
date: $('#date').val()
};
save(args);
});
$('#btnCancelDate').on('click', function() {
closeModal('date');
});
// Modal friendly-url events
// ------------------------------------------------------------------------
$('#btnSaveFriendlyURL').on('click', function() {
var args = {
slug: $('#friendlyURL').val()
};
save(args);
});
$('#btnCancelFriendlyURL').on('click', function() {
closeModal('friendlyURL');
});
$('#btnGenURLFromTitle').on('click', function() {
var args = {
text: $('#title').val(),
parentKey: $('#parent').val(),
pageKey: _pageKey
}
api.friendlyURL(args).then(function(slug) {
$('#friendlyURL').val(slug);
});
});
// Modal status events
// ------------------------------------------------------------------------
$('#btnSaveStatus').on('click', function() {
var args = {
type: $('input[name="status"]:checked').val()
};
save(args);
if (args['type'] == 'draft') {
$('#btnCurrenStatus').html('<i class="bi-square-fill"></i> <?php $L->p('Draft') ?>');
} else if (args['type'] == 'published') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Published') ?>');
} else if (args['type'] == 'unlisted') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Unlisted') ?>');
} else if (args['type'] == 'sticky') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Sticky') ?>');
} else if (args['type'] == 'static') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Static') ?>');
}
});
$('#btnCancelStatus').on('click', function() {
closeModal('status');
});
// Modal SEO events
// ------------------------------------------------------------------------
$('#btnSaveSeo').on('click', function() {
var args = {
parent: $('#parent').val()
};
save(args);
});
$('#btnCancelSeo').on('click', function() {
closeModal('seo');
});
// Modal parent events
// ------------------------------------------------------------------------
$('#btnSaveParent').on('click', function() {
var args = {
parent: $('#parent').val()
};
save(args);
});
$('#btnCancelParent').on('click', function() {
closeModal('parent');
});
}); });
// Modal status events // ----------------------------------------------------------------------------
// ------------------------------------------------------------------------ // Initlization for the view
$('#btnSaveStatus').on('click', function() { // ----------------------------------------------------------------------------
var args = { $(document).ready(function() {
type: $('input[name="status"]:checked').val() // Create the page at the beggining
}; // How do you hang your toilet paper ? over or under ?
save(args); createPage();
if (args['type']=='draft') {
$('#btnCurrenStatus').html('<i class="bi-square-fill"></i> <?php $L->p('Draft') ?>');
} else if (args['type']=='published') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Published') ?>');
} else if (args['type']=='unlisted') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Unlisted') ?>');
} else if (args['type']=='sticky') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Sticky') ?>');
} else if (args['type']=='static') {
$('#btnCurrenStatus').html('<i class="bi-check-square-fill"></i> <?php $L->p('Static') ?>');
}
}); });
$('#btnCancelStatus').on('click', function() {
closeModal('status');
});
// Modal SEO events
// ------------------------------------------------------------------------
$('#btnSaveSeo').on('click', function() {
var args = {
parent: $('#parent').val()
};
save(args);
});
$('#btnCancelSeo').on('click', function() {
closeModal('seo');
});
// Modal parent events
// ------------------------------------------------------------------------
$('#btnSaveParent').on('click', function() {
var args = {
parent: $('#parent').val()
};
save(args);
});
$('#btnCancelParent').on('click', function() {
closeModal('parent');
});
});
// ----------------------------------------------------------------------------
// Initlization for the view
// ----------------------------------------------------------------------------
$(document).ready(function() {
// nothing here yet
// how do you hang your toilet paper ? over or under ?
});
</script> </script>
<!-- File manager -->
<?php include(PATH_ADMIN_THEMES . 'booty/html/file-manager.php'); ?>
<!-- End File manager -->
<!-- Modal Description --> <!-- Modal Description -->
<div class="modal" id="modal-description" tabindex="-1"> <div class="modal" id="modal-description" tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
@ -287,9 +290,11 @@ $(document).ready(function() {
</div> </div>
</div> </div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$("#date").datetimepicker({format:DB_DATE_FORMAT}); $("#date").datetimepicker({
}); format: DB_DATE_FORMAT
});
});
</script> </script>
<!-- End Modal Date --> <!-- End Modal Date -->
@ -412,198 +417,169 @@ $(document).ready(function() {
</div> </div>
</div> </div>
<script> <script>
$(document).ready(function() {
var parent = $("#parent").select2({
placeholder: "",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT+"ajax/get-published",
data: function (params) {
var query = {
checkIsParent: true,
query: params.term
}
return query;
},
processResults: function (data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: function(data) {
var html = data.text;
if (data.type=="static") {
html += '<span class="badge badge-pill badge-light">'+data.type+'</span>';
}
return html;
}
});
});
</script>
<!-- End Modal Parent -->
<!-- Modal Files / Images -->
<div class="modal" id="modal-files" tabindex="-1" aria-labelledby="modal-files" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label class="fw-bold">Files</label>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelSeo" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi-x-square me-2"></i>Cancel</button>
<button id="btnSaveSeo" type="button" class="btn btn-save fw-bold text-success"><i class="bi-check-square me-2"></i>Save</button>
</div>
</div>
</div>
</div>
<!-- End Modal SEO -->
<div class="container-fluid h-100">
<div class="row h-100">
<div class="col-sm-9 d-flex flex-column h-100">
<!-- Toolbar > Save, Preview, Status and Options -->
<div id="editorToolbar">
<div id="editorToolbarRight" class="btn-group btn-group-sm float-end" role="group" aria-label="Toolbar right">
<div class="dropdown">
<button type="button" class="btn dropdown-toggle" type="button" id="dropdownMenuOptions" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi-gear me-2"></i></span><?php $L->p('Options') ?>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuOptions">
<a onclick="openModal('description')" class="dropdown-item" href="#"><i class="bi-info-square me-2"></i>Description</a>
<a onclick="openModal('date')" class="dropdown-item" href="#"><i class="bi-calendar me-2"></i>Publish date</a>
<a onclick="openModal('friendlyURL')" class="dropdown-item" href="#"><i class="bi-link me-2"></i>Change URL</a>
<a onclick="openModal('status')" class="dropdown-item" href="#"><i class="bi-eye me-2"></i>Status</a>
<a onclick="openModal('seo')" class="dropdown-item" href="#"><i class="bi-compass me-2"></i>SEO features</a>
<a onclick="openModal('parent')" class="dropdown-item" href="#"><i class="bi-diagram-2 me-2"></i>Parent page</a>
</div>
</div>
</div>
<div id="editorToolbarLeft">
<button id="btnSave" type="button" class="btn btn-sm btn-primary" ><?php $L->p('Save') ?></button>
<button id="btnPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<span id="btnCurrenStatus"><i class="bi-square-fill ms-1 me-1"></i><span><?php $L->p('Draft') ?></span></span>
</div>
</div>
<!-- End Toolbar > Save, Preview, Status and Options -->
<!-- Title -->
<div class="mb-1">
<input id="title" name="title" type="text" class="form-control form-control-lg" value="" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- End Title -->
<!-- Editor -->
<textarea class="form-control flex-grow-1" placeholder="" id="editor"></textarea>
<!-- End Editor -->
</div> <!-- End <div class="col-sm-9 h-100"> -->
<div class="col-sm-3 h-100">
<!-- Cover Image -->
<h6 class="mt-1 mb-2 pb-2 text-uppercase"><?php $L->p('Cover Image') ?></h6>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />
</div>
<!-- End Cover Image -->
<!-- Images -->
<h6 class="mt-4 mb-2 pb-2 text-uppercase"><?php $L->p('Images') ?></h6>
<div class="media text-muted pt-3">
<svg class="align-self-center me-3 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32"><title>Placeholder</title><rect width="100%" height="100%" fill="#007bff"></rect><text x="50%" y="50%" fill="#007bff" dy=".3em">32x32</text></svg>
<div class="media-body">
<div class="mt-0">
photo1.jpg
</div>
</div>
</div>
<div class="media text-muted pt-3">
<svg class="align-self-center me-3 rounded" width="32" height="32" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 32x32"><title>Placeholder</title><rect width="100%" height="100%" fill="#007bff"></rect><text x="50%" y="50%" fill="#007bff" dy=".3em">32x32</text></svg>
<div class="media-body">
<div class="mt-0">
photo2.jpg
</div>
</div>
</div>
<div class="d-block text-end mt-3">
<a href="#">All images</a>
</div>
<!-- End Images -->
<!-- Category -->
<div class="m-0">
<h6 class="mt-4 mb-2 pb-2 text-uppercase">Category</h6>
<select id="category" name="category" class="custom-select">
<option value="">- Uncategorized -</option>
<?php foreach ($categories->db as $key=>$fields): ?>
<option value="<?php echo $key ?>"><?php echo $fields['name']?></option>
<?php endforeach; ?>
</select>
</div>
<!-- End Category -->
<!-- Tags -->
<h6 class="mt-4 mb-2 pb-2 text-uppercase">Tags</h6>
<input id="tags" name="tags" type="text" value="">
<script>
$(document).ready(function() { $(document).ready(function() {
$('#tags').tagsInput({ var parent = $("#parent").select2({
placeholder:'Add a tag', placeholder: "",
delimiter:',', allowClear: true,
removeWithBackspace:true, theme: "bootstrap4",
'autocomplete': { minimumInputLength: 2,
source: [ ajax: {
<?php url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
foreach ($tags->db as $key=>$fields) { data: function(params) {
echo '"'.$fields['name'].'",'; var query = {
checkIsParent: true,
query: params.term
} }
?> return query;
] },
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: function(data) {
var html = data.text;
if (data.type == "static") {
html += '<span class="badge badge-pill badge-light">' + data.type + '</span>';
}
return html;
} }
}); });
}); });
</script> </script>
<!-- End Tags --> <!-- End Modal Parent -->
</div> <!-- End <div class="col-sm-3 h-100"> --> <div class="container-fluid h-100">
</div> <!-- End <div class="row h-100"> --> <div class="row h-100">
<div class="col-sm-9 d-flex flex-column h-100">
<!-- Toolbar > Save, Preview, Status and Options -->
<div id="editorToolbar" class="d-flex align-items-center mb-2">
<div id="editorToolbarLeft">
<button id="btnSave" type="button" class="btn btn-sm btn-primary"><?php $L->p('Save') ?></button>
<button id="btnPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<span id="btnCurrenStatus"><i class="bi-square-fill ms-1 me-1"></i><span><?php $L->p('Draft') ?></span></span>
</div>
<div id="editorToolbarRight" class="ms-auto">
<div class="dropdown">
<button type="button" class="btn dropdown-toggle" type="button" id="dropdownMenuOptions" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi-gear me-2"></i></span><?php $L->p('Options') ?>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuOptions">
<a onclick="openModal('description')" class="dropdown-item" href="#"><i class="bi-info-square me-2"></i>Description</a>
<a onclick="openModal('date')" class="dropdown-item" href="#"><i class="bi-calendar me-2"></i>Publish date</a>
<a onclick="openModal('friendlyURL')" class="dropdown-item" href="#"><i class="bi-link me-2"></i>Change URL</a>
<a onclick="openModal('status')" class="dropdown-item" href="#"><i class="bi-eye me-2"></i>Status</a>
<a onclick="openModal('seo')" class="dropdown-item" href="#"><i class="bi-compass me-2"></i>SEO features</a>
<a onclick="openModal('parent')" class="dropdown-item" href="#"><i class="bi-diagram-2 me-2"></i>Parent page</a>
</div>
</div>
</div>
</div>
<!-- End Toolbar > Save, Preview, Status and Options -->
<!-- Title -->
<div class="mb-2">
<input id="title" name="title" type="text" class="form-control form-control-lg" value="" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- End Title -->
<!-- Editor -->
<textarea class="form-control flex-grow-1" placeholder="" id="editor"></textarea>
<!-- End Editor -->
</div> <!-- End <div class="col-sm-9 h-100"> -->
<div class="col-sm-3 h-100 mt-2">
<!-- Cover Image -->
<h6 class="text-uppercase"><?php $L->p('Cover Image') ?></h6>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />
</div>
<!-- End Cover Image -->
<!-- Category -->
<h6 class="text-uppercase mt-4">Category</h6>
<?php
echo Bootstrap::formSelect(array(
'id' => 'category',
'name' => 'category',
'options' => array_merge(array('' => $L->g('Uncategorized')), $categories->getKeyNameArray())
));
?>
<!-- End Category -->
<!-- Tags -->
<h6 class="mt-4 mb-2 pb-2 text-uppercase">Tags</h6>
<input id="tags" name="tags" type="text" value="">
<script>
$(document).ready(function() {
$('#tags').tagsInput({
placeholder: 'Add a tag',
delimiter: ',',
removeWithBackspace: true,
'autocomplete': {
source: [
<?php
foreach ($tags->db as $key => $fields) {
echo '"' . $fields['name'] . '",';
}
?>
]
}
});
});
</script>
<!-- End Tags -->
<!-- Quick files -->
<h6 class="text-uppercase mt-4"><?php $L->p('Images') ?></h6>
<div id="quickFiles">
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image me-2" style="font-size: 1.6rem;"></i>
<span>photo1.jpg</span>
</div>
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image me-2" style="font-size: 1.6rem;"></i>
<span>test.txt</span>
</div>
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image me-2" style="font-size: 1.6rem;"></i>
<span>test.txt</span>
</div>
</div>
<!-- End Quick files -->
</div> <!-- End <div class="col-sm-3 h-100"> -->
</div> <!-- End <div class="row h-100"> -->
</div> <!-- End <div class="container-fluid h-100"> --> </div> <!-- End <div class="container-fluid h-100"> -->
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Autosave
// Autosave var currentContent = editorGetContent();
var currentContent = editorGetContent(); setInterval(function() {
setInterval(function() {
var uuid = $("#jsuuid").val(); var uuid = $("#jsuuid").val();
var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]"; var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]";
var content = editorGetContent(); var content = editorGetContent();
// Autosave when content has at least 100 characters // Autosave when content has at least 100 characters
if (content.length<100) { if (content.length < 100) {
return false; return false;
} }
// Autosave only when the user change the content // Autosave only when the user change the content
if (currentContent!=content) { if (currentContent != content) {
currentContent = content; currentContent = content;
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) { bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
if (data.status==0) { if (data.status == 0) {
showAlert("<?php $L->p('Autosave') ?>"); showAlert("<?php $L->p('Autosave') ?>");
} }
}); });
} }
},1000*60*AUTOSAVE_INTERVAL); }, 1000 * 60 * AUTOSAVE_INTERVAL);
}); });
</script> </script>

View file

@ -304,25 +304,14 @@ function execPluginsByHook($hook, $args = array()) {
} }
} }
/* /* Create a new page
Create a new page
The array $args support all the keys from variable $dbFields of the class pages.class.php @args array The array $args supports all the keys from the variable $dbFields of the class pages.class.php. If you don't pass all the keys, the default values are used.
If you don't pass all the keys, the default values are used, the default values are from $dbFields in the class pages.class.php @returns string/boolean Returns the page key if the page is successfully created, FALSE otherwise
*/ */
function createPage($args) { function createPage($args) {
global $pages; global $pages;
global $syslog; global $syslog;
global $L;
// Check if the autosave page exists for this new page and delete it
if (isset($args['uuid'])) {
$autosaveKey = $pages->getByUUID('autosave-'.$args['uuid']);
if (!empty($autosaveKey)) {
Log::set('Function createPage()'.LOG_SEP.'Autosave deleted for '.$args['title'], LOG_TYPE_INFO);
deletePage($autosaveKey);
}
}
// The user is always the one logged // The user is always the one logged
$args['username'] = Session::get('username'); $args['username'] = Session::get('username');
@ -334,8 +323,9 @@ function createPage($args) {
$key = $pages->add($args); $key = $pages->add($args);
if ($key) { if ($key) {
// Call the plugins after page created // Call the plugins after page created
Theme::plugins('afterPageCreate', array($key)); execPluginsByHook('afterPageCreate', array($key));
// Reindex categories and tags
reindexCategories(); reindexCategories();
reindexTags(); reindexTags();
@ -345,47 +335,43 @@ function createPage($args) {
'notes'=>(empty($args['title'])?$key:$args['title']) 'notes'=>(empty($args['title'])?$key:$args['title'])
)); ));
Log::set('Function createPage()'.LOG_SEP.'Page created successfully.', LOG_TYPE_INFO);
return $key; return $key;
} }
Log::set('Function createNewPage()'.LOG_SEP.'Error occurred when trying to create the page', LOG_TYPE_ERROR); Log::set('Function createPage()'.LOG_SEP.'Something happened when you tried to create the page.', LOG_TYPE_ERROR);
Log::set('Function createNewPage()'.LOG_SEP.'Cleaning database...', LOG_TYPE_ERROR);
deletePage($key); deletePage($key);
Log::set('Function createNewPage()'.LOG_SEP.'Cleaning finished...', LOG_TYPE_ERROR);
return false; return false;
} }
/* Edit a page
@args array The array $args supports all the keys from the variable $dbFields of the class pages.class.php. If you don't pass all the keys, the default values are used.
@args['key'] string The key of the page to be edited
@returns string/boolean Returns the page key if the page is successfully edited, FALSE otherwise
*/
function editPage($args) { function editPage($args) {
global $pages; global $pages;
global $syslog; global $syslog;
// Check if the autosave/preview page exists for this new page and delete it
if (isset($args['uuid'])) {
$autosaveKey = $pages->getByUUID('autosave-'.$args['uuid']);
if ($autosaveKey) {
Log::set('Function editPage()'.LOG_SEP.'Autosave/Preview deleted for '.$autosaveKey, LOG_TYPE_INFO);
deletePage($autosaveKey);
}
}
// Check if the key is not empty // Check if the key is not empty
if (empty($args['key'])) { if (empty($args['key'])) {
Log::set('Function editPage()'.LOG_SEP.'Empty key.', LOG_TYPE_ERROR); Log::set('Function editPage()'.LOG_SEP.'Empty page key.', LOG_TYPE_ERROR);
return false; return false;
} }
// Check if the page key exist // Check if the page key exist
if (!$pages->exists($args['key'])) { if (!$pages->exists($args['key'])) {
Log::set('Function editPage()'.LOG_SEP.'Page key does not exist, '.$args['key'], LOG_TYPE_ERROR); Log::set('Function editPage()'.LOG_SEP.'Page key doesn\'t exist: '.$args['key'], LOG_TYPE_ERROR);
return false; return false;
} }
$key = $pages->edit($args); $key = $pages->edit($args);
if ($key) { if ($key) {
// Call the plugins after page modified // Call the plugins after page modified
Theme::plugins('afterPageModify', array($key)); execPluginsByHook('afterPageModify', array($key));
// Reindex categories and tags
reindexCategories(); reindexCategories();
reindexTags(); reindexTags();
@ -395,21 +381,28 @@ function editPage($args) {
'notes'=>empty($args['title'])?$key:$args['title'] 'notes'=>empty($args['title'])?$key:$args['title']
)); ));
Log::set('Function editPage()'.LOG_SEP.'Page edited successfully.', LOG_TYPE_INFO);
return $key; return $key;
} }
Log::set('Function editPage()'.LOG_SEP.'Something happen when try to edit the page.', LOG_TYPE_ERROR); Log::set('Function editPage()'.LOG_SEP.'Something happened when you tried to edit the page.', LOG_TYPE_ERROR);
return false; return false;
} }
/* Delete a page
@key string The key of the page to be deleted
@returns string/boolean Returns TRUE if the page is successfully deleted, FALSE otherwise
*/
function deletePage($key) { function deletePage($key) {
global $pages; global $pages;
global $syslog; global $syslog;
if ($pages->delete($key)) { if ($pages->delete($key)) {
// Call the plugins after page deleted // Call the plugins after page deleted
Theme::plugins('afterPageDelete', array($key)); execPluginsByHook('afterPageDelete', array($key));
// Reindex categories and tags
reindexCategories(); reindexCategories();
reindexTags(); reindexTags();
@ -419,9 +412,11 @@ function deletePage($key) {
'notes'=>$key 'notes'=>$key
)); ));
Log::set('Function deletePage()'.LOG_SEP.'Page deleted successfully.', LOG_TYPE_INFO);
return true; return true;
} }
Log::set('Function deletePage()'.LOG_SEP.'Something happened when you tried to delete the page.', LOG_TYPE_ERROR);
return false; return false;
} }

View file

@ -8,11 +8,10 @@ class Bootstrap {
{ {
$name = $args['name']; $name = $args['name'];
$id = isset($args['id'])?$args['id']:$name; $id = isset($args['id'])?$args['id']:$name;
$disabled = empty($args['disabled'])?'':'disabled';
$readonly = empty($args['readonly'])?'':'readonly';
$placeholder = isset($args['placeholder'])?$args['placeholder']:'';
$value = isset($args['value'])?$args['value']:''; $value = isset($args['value'])?$args['value']:'';
$type = isset($args['type'])?$args['type']:'text'; $type = isset($args['type'])?$args['type']:'text';
$placeholder = isset($args['placeholder'])?$args['placeholder']:'';
$label = isset($args['label'])?$args['label']:$placeholder; $label = isset($args['label'])?$args['label']:$placeholder;
$class = 'form-control'; $class = 'form-control';
@ -22,12 +21,36 @@ class Bootstrap {
return <<<EOF return <<<EOF
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input type="$type" class="$class" id="$id" name="$name" placeholder="$placeholder"> <input type="$type" class="$class" id="$id" name="$name" value="$value" placeholder="$placeholder">
<label for="$id">$label</label> <label for="$id">$label</label>
</div> </div>
EOF; EOF;
} }
public static function formSelect($args)
{
$name = $args['name'];
$id = isset($args['id'])?$args['id']:$name;
$class = 'form-select';
if (isset($args['class'])) {
$class = $class.' '.$args['class'];
}
$html = '<div>';
if (isset($args['label'])) {
$html .= '<label for="'.$id.'">'.$args['label'].'</label>';
}
$html .= '<select id="'.$id.'" name="'.$name.'" class="'.$class.'">';
foreach ($args['options'] as $key=>$value) {
$html .= '<option '.(($key==$args['selected'])?'selected':'').' value="'.$key.'">'.$value.'</option>';
}
$html .= '</select>';
$html .= '</div>';
return $html;
}
public static function formInputText($args) public static function formInputText($args)
{ {
$name = $args['name']; $name = $args['name'];
@ -64,7 +87,7 @@ return <<<EOF
EOF; EOF;
} }
public static function formSelect($args) public static function formSelectOld($args)
{ {
$name = $args['name']; $name = $args['name'];
$id = isset($args['id'])?$args['id']:$name; $id = isset($args['id'])?$args['id']:$name;

View file

@ -12,7 +12,7 @@ class API {
} }
} }
async createPage(args) { async createPage(args={}) {
var url = this.apiURL + "pages"; var url = this.apiURL + "pages";
var body = Object.assign({}, this.body, args); var body = Object.assign({}, this.body, args);
try { try {
@ -32,12 +32,10 @@ class API {
} }
} }
/* /* Save page fields
Save page fields
@args['pageKey'] string Page key from the page to edit @args['pageKey'] string Page key from the page to edit
@args array Arguments can be any of the fields from a page @args array Arguments can be any of the fields from a page
@returns string New page key @returns string New page key
*/ */
async savePage(args) { async savePage(args) {
@ -60,13 +58,11 @@ class API {
} }
} }
/* /* Generates unique slug text for the a page
Generates unique slug text for the a page
@args['pageKey'] string Page key for the page to generate the slug url @args['pageKey'] string Page key for the page to generate the slug url
@args['text'] string Text that you want to generate the slug url @args['text'] string Text that you want to generate the slug url
@args['parentKey'] string Parent page key if the page has one, if not empty string @args['parentKey'] string Parent page key if the page has one, if not empty string
@returns string Slug text @returns string Slug text
*/ */
async friendlyURL(args) { async friendlyURL(args) {
@ -87,11 +83,9 @@ class API {
} }
} }
/* /* Get all files uploaded for the page
Get all files uploaded for the page
@args['pageKey'] string @args['pageKey'] string
@returns array @returns array
*/ */
async getPageFiles(args) { async getPageFiles(args) {
@ -109,11 +103,35 @@ class API {
} }
} }
/* /* Upload files
Save settings
@args['pageKey'] string
@returns array
*/
async uploadPageFiles(args) {
var url = this.apiURL + "files/" + args['pageKey'];
var body = Object.assign({}, this.body, args);
try {
var response = await fetch(url, {
credentials: "same-origin",
method: "POST",
body: JSON.stringify(body),
headers: new Headers({
"Content-Type": "application/json"
})
});
var json = await response.json();
return json.data.key;
} catch (err) {
console.log(err);
return true;
}
}
/* Save settings
@args array Arguments can be any of the fields from settings @args array Arguments can be any of the fields from settings
@returns array @returns array
*/ */
async saveSettings(args) { async saveSettings(args) {

View file

@ -44,3 +44,15 @@ function logs(message) {
console.log(message); console.log(message);
} }
} }
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

View file

@ -50,8 +50,11 @@ class Pages extends dbJSON {
return isset( $this->db[$key] ); return isset( $this->db[$key] );
} }
// Create a new page /* Create a new page
// This function returns the key of the new page
@args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used.
@returns string/boolean Returns the page key if the page is successfully created, FALSE otherwise
*/
public function add($args) public function add($args)
{ {
$row = array(); $row = array();
@ -134,20 +137,26 @@ class Pages extends dbJSON {
// Create the directory // Create the directory
if (Filesystem::mkdir(PATH_PAGES.$key, true) === false) { if (Filesystem::mkdir(PATH_PAGES.$key, true) === false) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the directory ['.PATH_PAGES.$key.']',LOG_TYPE_ERROR); Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the directory: '.PATH_PAGES.$key, LOG_TYPE_ERROR);
return false;
}
// Create the upload directory for the page
if (Filesystem::mkdir(PATH_UPLOADS_PAGES.$key, true) === false) {
Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the directory: '.PATH_UPLOADS_PAGES.$key, LOG_TYPE_ERROR);
return false; return false;
} }
// Create the index.txt and save the file // Create the index.txt and save the file
if (file_put_contents(PATH_PAGES.$key.DS.FILENAME, $contentRaw) === false) { if (file_put_contents(PATH_PAGES.$key.DS.FILENAME, $contentRaw) === false) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the content in the file ['.FILENAME.']',LOG_TYPE_ERROR); Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the file: '.FILENAME, LOG_TYPE_ERROR);
return false; return false;
} }
// Checksum MD5 // Checksum MD5
$row['md5file'] = md5_file(PATH_PAGES.$key.DS.FILENAME); $row['md5file'] = md5_file(PATH_PAGES.$key.DS.FILENAME);
// Insert in database // Insert into database
$this->db[$key] = $row; $this->db[$key] = $row;
// Sort database // Sort database
@ -156,18 +165,14 @@ class Pages extends dbJSON {
// Save database // Save database
$this->save(); $this->save();
// Create symlink for images directory
if (Filesystem::mkdir(PATH_UPLOADS_PAGES.$row['uuid'])) {
symlink(PATH_UPLOADS_PAGES.$row['uuid'], PATH_UPLOADS_PAGES.$key);
}
return $key; return $key;
} }
// Edit a page /* Edit a page
// This function do not edit the current row from the table -
// - instead of that the function creates a new row and is completed by the current - @args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used.
// - values of the page and then the old row is deleted and the new row is inserted. @returns string/boolean Returns the page key if the page is successfully edited, FALSE otherwise
*/
public function edit($args) public function edit($args)
{ {
// This is the new row for the table and is going to replace the old row // This is the new row for the table and is going to replace the old row
@ -248,13 +253,14 @@ class Pages extends dbJSON {
// Move the directory from old key to new key only if the keys are different // Move the directory from old key to new key only if the keys are different
if ($newKey!==$key) { if ($newKey!==$key) {
if (Filesystem::mv(PATH_PAGES.$key, PATH_PAGES.$newKey) === false) { if (Filesystem::mv(PATH_PAGES.$key, PATH_PAGES.$newKey) === false) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to move the directory to '.PATH_PAGES.$newKey); Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to move the directory '.PATH_PAGES.$newKey);
return false; return false;
} }
// Regenerate the symlink to a proper directory if (Filesystem::mv(PATH_UPLOADS_PAGES.$key, PATH_UPLOADS_PAGES.$newKey) === false) {
unlink(PATH_UPLOADS_PAGES.$key); Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to move the directory '.PATH_UPLOADS_PAGES.$newKey);
symlink(PATH_UPLOADS_PAGES.$row['uuid'], PATH_UPLOADS_PAGES.$newKey); return false;
}
} }
// If the content was passed via arguments replace the content // If the content was passed via arguments replace the content

View file

@ -142,7 +142,7 @@ class pluginBackup extends Plugin {
} }
$html .= '<div>'; $html .= '<div>';
$html .= '<h4 class="font-weight-normal">'.$name.($count > 0? " ($count)": "").'</h4>'; $html .= '<h4 class="fw-normal">'.$name.($count > 0? " ($count)": "").'</h4>';
// Allow download if a zip file // Allow download if a zip file
if ($this->zip) { if ($this->zip) {
$html .= '<a class="btn btn-outline-secondary btn-sm me-1 mt-1" href="'.DOMAIN_BASE.'plugin-backup-download?file='.$filename.'.zip"><span class="bi-download"></span> '.$L->get('download').'</a>'; $html .= '<a class="btn btn-outline-secondary btn-sm me-1 mt-1" href="'.DOMAIN_BASE.'plugin-backup-download?file='.$filename.'.zip"><span class="bi-download"></span> '.$L->get('download').'</a>';

View file

@ -597,7 +597,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
<div class="container"> <div class="container">
<div class="row justify-content-md-center pt-5"> <div class="row justify-content-md-center pt-5">
<div class="col-md-4 pt-5"> <div class="col-md-4 pt-5">
<h1 class="text-center mb-5 mt-5 font-weight-normal text-uppercase" style="color: #555;"><?php echo $L->get('Bludit Installer') ?></h1> <h1 class="text-center mb-5 mt-5 fw-normal text-uppercase" style="color: #555;"><?php echo $L->get('Bludit Installer') ?></h1>
<?php <?php
$system = checkSystem(); $system = checkSystem();
if (!empty($system)) { if (!empty($system)) {