This commit is contained in:
Ty Clifford
2026-07-03 07:31:09 -04:00
commit cebb0d3af1
800 changed files with 89782 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('About'), 'icon'=>'info-circle'));
echo '
<table class="table table-striped mt-3">
<tbody>
';
echo '<tr>';
echo '<td>Bludit Edition</td>';
if (defined('BLUDIT_PRO')) {
echo '<td>PRO - '.$L->g('Thanks for supporting Bludit').' <span class="fa fa-heart" style="color: #ffc107"></span></td>';
} else {
echo '<td>Standard - <a target="_blank" href="https://pro.bludit.com">'.$L->g('Upgrade to Bludit PRO').'</a></td>';
}
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Version</td>';
echo '<td>'.BLUDIT_VERSION.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Codename</td>';
echo '<td>'.BLUDIT_CODENAME.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Build Number</td>';
echo '<td>'.BLUDIT_BUILD.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Disk usage</td>';
echo '<td>'.Filesystem::bytesToHumanFileSize(Filesystem::getSize(PATH_ROOT)).'</td>';
echo '</tr>';
echo '<tr>';
echo '<td><a href="'.HTML_PATH_ADMIN_ROOT.'developers'.'">Bludit Developers</a></td>';
echo '<td></td>';
echo '</tr>';
echo '
</tbody>
</table>
';
+59
View File
@@ -0,0 +1,59 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'themes' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Blocks'), 'icon'=>'box')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
foreach ($blocks->getAll() as $block) {
echo Bootstrap::formTitle(array('title'=>$block->title()));
if (Text::isNotEmpty( $block->description() )) {
echo Bootstrap::alert(array('class'=>'alert-primary', 'text'=>$block->description()));
}
echo Bootstrap::formInputText(array(
'name'=>'key[]',
'label'=>$L->g('Key'),
'value'=>$block->key(),
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'readonly'=>true
));
echo Bootstrap::formInputText(array(
'name'=>'title[]',
'label'=>$L->g('title'),
'value'=>$block->title(),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formTextarea(array(
'name'=>'value[]',
'label'=>$L->g('Value'),
'value'=>$block->value(),
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'rows'=>5
));
}
echo Bootstrap::formClose();
?>
+33
View File
@@ -0,0 +1,33 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
echo Bootstrap::pageTitle(array('title'=>$L->g('Categories'), 'icon'=>'tags'));
echo Bootstrap::link(array(
'title'=>$L->g('Add a new category'),
'href'=>HTML_PATH_ADMIN_ROOT.'new-category',
'icon'=>'plus'
));
echo '
<table class="table table-striped mt-3">
<thead>
<tr>
<th class="border-bottom-0" scope="col">'.$L->g('Name').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('URL').'</th>
</tr>
</thead>
<tbody>
';
foreach ($categories->keys() as $key) {
$category = new Category($key);
echo '<tr>';
echo '<td><a href="'.HTML_PATH_ADMIN_ROOT.'edit-category/'.$key.'">'.$category->name().'</a></td>';
echo '<td><a href="'.$category->permalink().'">'.$url->filters('category', false).$key.'</a></td>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
@@ -0,0 +1,31 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'plugin-form')); ?>
<div class="align-middle">
<?php if ($plugin->formButtons()): ?>
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php endif; ?>
<?php echo Bootstrap::pageTitle(array('title'=>$plugin->name(), 'icon'=>'cog')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
// Compatibility warning
if (!$plugin->isCompatible()) {
echo '<div class="alert alert-warning mt-2">' . $L->g('This plugin may not be supported by this version of Bludit') . '</div>';
}
// Print the plugin form
echo $plugin->form();
?>
<?php echo Bootstrap::formClose(); ?>
+417
View File
@@ -0,0 +1,417 @@
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Content'), 'icon'=>'archive'));
function moveTypeIcon($type) {
$icons = array(
'published' => 'fa-file-text-o',
'sticky' => 'fa-thumb-tack',
'static' => 'fa-file',
'draft' => 'fa-pencil',
);
return isset($icons[$type]) ? $icons[$type] : 'fa-file';
}
function moveTypeLabel($current, $target, $L) {
if ($target === 'sticky') {
return $L->g('Sticky');
}
if ($current === 'sticky' && $target === 'published') {
return $L->g('Unstick');
}
$labels = array(
'published' => $L->g('Move to Page'),
'static' => $L->g('Move to Static'),
'draft' => $L->g('Move to Draft'),
);
return isset($labels[$target]) ? $labels[$target] : $target;
}
// Render a single row (or row + nested children) for a page key.
// $type controls which columns/buttons are shown; $isSticky adds the Sticky badge
// and flips the toggle button into "Unstick" mode.
function tableRow($pageKey, $type, $isSticky = false, $renderChildren = false) {
global $url;
global $L;
try {
$page = new Page($pageKey);
} catch (Exception $e) {
return;
}
$showURL = ($type === 'published' || $type === 'static' || $type === 'sticky');
// Allowed "Move to" transitions per current type.
$moves = array(
'published' => array('sticky', 'static', 'draft'),
'sticky' => array('published', 'static', 'draft'),
'draft' => array('published', 'static'),
'static' => array('published', 'draft'),
);
$dateLabel = '';
if ($type === 'scheduled') {
$dateLabel = $L->g('Scheduled').': '.$page->date(SCHEDULED_DATE_FORMAT);
} elseif ((ORDER_BY === 'position') || ($type !== 'published' && $type !== 'sticky')) {
$dateLabel = $L->g('Position').': '.$page->position();
} else {
$dateLabel = $page->date(MANAGE_CONTENT_DATE_FORMAT);
}
echo '<tr>';
echo '<td class="pt-3">';
echo '<div>';
echo '<a style="font-size: 1.1em" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'">';
echo ($page->title() ? $page->title() : '<span class="label-empty-title">'.$L->g('Empty title').'</span> ');
echo '</a>';
if ($isSticky) {
echo ' <span class="badge badge-warning align-middle ml-1" title="'.$L->g('Sticky').'"><i class="fa fa-thumb-tack"></i> '.$L->g('Sticky').'</span>';
}
echo '</div>';
echo '<div><p style="font-size: 0.8em" class="m-0 text-uppercase text-muted">'.$dateLabel.'</p></div>';
echo '</td>';
if ($showURL) {
$friendlyURL = Text::isEmpty($url->filters('page')) ? '/'.$page->key() : '/'.$url->filters('page').'/'.$page->key();
echo '<td class="pt-3 d-none d-xl-table-cell contentURL"><a target="_blank" href="'.$page->permalink().'" title="'.$friendlyURL.'">'.$friendlyURL.'</a></td>';
}
echo '<td class="contentTools pt-3 text-center align-middle">'.PHP_EOL;
echo '<div class="dropdown actionsDropdown">';
echo '<button class="btn btn-link text-secondary p-1 actionsDropdownToggle" type="button" data-toggle="dropdown" data-boundary="viewport" aria-haspopup="true" aria-expanded="false" title="'.$L->g('Actions').'"><i class="fa fa-bars"></i></button>';
echo '<div class="dropdown-menu dropdown-menu-right">';
// View / Edit
if ($showURL) {
echo '<a class="dropdown-item" target="_blank" href="'.$page->permalink().'"><i class="fa fa-desktop fa-fw mr-2"></i>'.$L->g('View').'</a>';
}
echo '<a class="dropdown-item" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'"><i class="fa fa-edit fa-fw mr-2"></i>'.$L->g('Edit').'</a>';
// Sticky / Unstick toggle, between View/Edit and Move-to.
$stickyToggleTarget = false;
if ($type === 'published') {
$stickyToggleTarget = 'sticky';
} elseif ($type === 'sticky') {
$stickyToggleTarget = 'published';
}
if ($stickyToggleTarget) {
echo '<div class="dropdown-divider"></div>';
echo '<a href="#" class="dropdown-item changeTypeButton" data-key="'.$page->key().'" data-type="'.$stickyToggleTarget.'"><i class="fa '.moveTypeIcon($stickyToggleTarget).' fa-fw mr-2"></i>'.moveTypeLabel($type, $stickyToggleTarget, $L).'</a>';
}
// Move to ... (everything except the sticky toggle target rendered above).
if (isset($moves[$type])) {
$remaining = array();
foreach ($moves[$type] as $target) {
if ($target !== $stickyToggleTarget) {
$remaining[] = $target;
}
}
if (!empty($remaining)) {
echo '<div class="dropdown-divider"></div>';
foreach ($remaining as $target) {
echo '<a href="#" class="dropdown-item changeTypeButton" data-key="'.$page->key().'" data-type="'.$target.'"><i class="fa '.moveTypeIcon($target).' fa-fw mr-2"></i>'.moveTypeLabel($type, $target, $L).'</a>';
}
}
}
if (count($page->children()) == 0) {
echo '<div class="dropdown-divider"></div>';
echo '<a href="#" class="dropdown-item text-danger deletePageButton" data-toggle="modal" data-target="#jsdeletePageModal" data-key="'.$page->key().'"><i class="fa fa-trash fa-fw mr-2"></i>'.$L->g('Delete').'</a>';
}
echo '</div></div>';
echo '</td>';
echo '</tr>';
if ($renderChildren) {
foreach ($page->children() as $child) {
echo '<tr>';
echo '<td class="child">';
echo '<div>';
echo '<a style="font-size: 1.1em" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$child->key().'">';
echo ($child->title() ? $child->title() : '<span class="label-empty-title">'.$L->g('Empty title').'</span> ');
echo '</a>';
echo '</div>';
echo '<div><p style="font-size: 0.8em" class="m-0 text-uppercase text-muted">'.$L->g('Position').': '.$child->position().'</p></div>';
echo '</td>';
if ($showURL) {
$friendlyChildURL = Text::isEmpty($url->filters('page')) ? '/'.$child->key() : '/'.$url->filters('page').'/'.$child->key();
echo '<td class="d-none d-xl-table-cell contentURL"><a target="_blank" href="'.$child->permalink().'" title="'.$friendlyChildURL.'">'.$friendlyChildURL.'</a></td>';
}
echo '<td class="contentTools pt-3 text-center align-middle">'.PHP_EOL;
echo '<div class="dropdown actionsDropdown">';
echo '<button class="btn btn-link text-secondary p-1 actionsDropdownToggle" type="button" data-toggle="dropdown" data-boundary="viewport" aria-haspopup="true" aria-expanded="false" title="'.$L->g('Actions').'"><i class="fa fa-bars"></i></button>';
echo '<div class="dropdown-menu dropdown-menu-right">';
if ($showURL) {
echo '<a class="dropdown-item" target="_blank" href="'.$child->permalink().'"><i class="fa fa-desktop fa-fw mr-2"></i>'.$L->g('View').'</a>';
}
echo '<a class="dropdown-item" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$child->key().'"><i class="fa fa-edit fa-fw mr-2"></i>'.$L->g('Edit').'</a>';
echo '<div class="dropdown-divider"></div>';
echo '<a href="#" class="dropdown-item text-danger deletePageButton" data-toggle="modal" data-target="#jsdeletePageModal" data-key="'.$child->key().'"><i class="fa fa-trash fa-fw mr-2"></i>'.$L->g('Delete').'</a>';
echo '</div></div>';
echo '</td>';
echo '</tr>';
}
}
}
// Render rows for a list, applying the parent/child nesting rules used by the
// Static tab and by the Pages/Sticky lists when ORDER_BY is "position".
function tableRows($list, $type, $isSticky = false) {
$nestChildren = ($type === 'static') || (ORDER_BY === 'position');
foreach ($list as $pageKey) {
try {
$page = new Page($pageKey);
} catch (Exception $e) {
continue;
}
if ($nestChildren) {
if ($page->isChild()) {
continue;
}
tableRow($pageKey, $type, $isSticky, true);
} else {
tableRow($pageKey, $type, $isSticky, false);
}
}
}
// Render a full table for a single tab (Static, Scheduled, Draft, Autosave).
function table($type) {
global $L;
global $drafts;
global $scheduled;
global $static;
global $autosave;
if ($type === 'draft') {
$list = $drafts;
$emptyMessage = $L->g('There are no draft pages at this moment.');
} elseif ($type === 'scheduled') {
$list = $scheduled;
$emptyMessage = $L->g('There are no scheduled pages at this moment.');
} elseif ($type === 'static') {
$list = $static;
$emptyMessage = $L->g('There are no static pages at this moment.');
} elseif ($type === 'autosave') {
$list = $autosave;
$emptyMessage = '';
} else {
return;
}
if (empty($list) && $type !== 'autosave') {
echo '<p class="mt-4 text-muted">'.$emptyMessage.'</p>';
return;
}
echo '<table class="table mt-3"><thead><tr>';
echo '<th class="border-0" scope="col">'.$L->g('Title').'</th>';
if ($type === 'static') {
echo '<th class="border-0 d-none d-xl-table-cell" scope="col">'.$L->g('URL').'</th>';
}
echo '<th class="border-0 text-center d-sm-table-cell" scope="col">'.$L->g('Actions').'</th>';
echo '</tr></thead><tbody>';
tableRows($list, $type);
echo '</tbody></table>';
}
// Render the Pages tab: sticky rows first, then the paginated published list,
// in a single table.
function tablePages() {
global $L;
global $published;
global $sticky;
global $url;
$isFirstPage = ($url->pageNumber() <= 1);
if (empty($published) && (empty($sticky) || !$isFirstPage)) {
echo '<p class="mt-4 text-muted">'.$L->g('There are no pages at this moment.').'</p>';
return;
}
echo '<table class="table mt-3"><thead><tr>';
echo '<th class="border-0" scope="col">'.$L->g('Title').'</th>';
echo '<th class="border-0 d-none d-xl-table-cell" scope="col">'.$L->g('URL').'</th>';
echo '<th class="border-0 text-center d-sm-table-cell" scope="col">'.$L->g('Actions').'</th>';
echo '</tr></thead><tbody>';
if (!empty($sticky) && $isFirstPage) {
tableRows($sticky, 'sticky', true);
}
if (!empty($published)) {
tableRows($published, 'published', false);
}
echo '</tbody></table>';
}
?>
<!-- TABS -->
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pages-tab" data-toggle="tab" href="#pages" role="tab"><?php $L->p('Pages') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="static-tab" data-toggle="tab" href="#static" role="tab"><?php $L->p('Static') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="scheduled-tab" data-toggle="tab" href="#scheduled" role="tab"><?php $L->p('Scheduled') ?> <?php if (count($scheduled)>0) { echo '<span class="badge badge-danger">'.count($scheduled).'</span>'; } ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="draft-tab" data-toggle="tab" href="#draft" role="tab"><?php $L->p('Draft') ?></a>
</li>
<?php if (!empty($autosave)): ?>
<li class="nav-item">
<a class="nav-link" id="autosave-tab" data-toggle="tab" href="#autosave" role="tab"><?php $L->p('Autosave') ?></a>
</li>
<?php endif; ?>
</ul>
<div class="tab-content">
<!-- TABS PAGES (includes sticky on top) -->
<div class="tab-pane show active" id="pages" role="tabpanel">
<?php tablePages(); ?>
<?php if (Paginator::numberOfPages() > 1): ?>
<!-- Paginator -->
<nav class="paginator">
<ul class="pagination flex-wrap justify-content-center">
<!-- First button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::firstPageUrl() ?>"><span class="align-middle fa fa-media-skip-backward"></span> <?php echo $L->get('First'); ?></a>
</li>
<!-- Previous button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::previousPageUrl() ?>"><?php echo $L->get('Previous'); ?></a>
</li>
<!-- Next button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::nextPageUrl() ?>"><?php echo $L->get('Next'); ?></a>
</li>
<!-- Last button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::lastPageUrl() ?>"><?php echo $L->get('Last'); ?> <span class="align-middle fa fa-media-skip-forward"></span></a>
</li>
</ul>
</nav>
<?php endif; ?>
</div>
<!-- TABS STATIC -->
<div class="tab-pane" id="static" role="tabpanel">
<?php table('static'); ?>
</div>
<!-- TABS SCHEDULED -->
<div class="tab-pane" id="scheduled" role="tabpanel">
<?php table('scheduled'); ?>
</div>
<!-- TABS DRAFT -->
<div class="tab-pane" id="draft" role="tabpanel">
<?php table('draft'); ?>
</div>
<!-- TABS AUTOSAVE -->
<?php if (!empty($autosave)): ?>
<div class="tab-pane" id="autosave" role="tabpanel">
<?php table('autosave'); ?>
</div>
<?php endif; ?>
</div>
<!-- Modal for delete page -->
<?php
echo Bootstrap::modal(array(
'buttonPrimary'=>$L->g('Delete'),
'buttonPrimaryClass'=>'btn-danger deletePageModalAcceptButton',
'buttonSecondary'=>$L->g('Cancel'),
'buttonSecondaryClass'=>'btn-link',
'modalTitle'=>$L->g('Delete content'),
'modalText'=>$L->g('Are you sure you want to delete this page'),
'modalId'=>'jsdeletePageModal'
));
?>
<script>
$(document).ready(function() {
var key = false;
// Button for delete a page in the table
$(document).on("click", ".deletePageButton", function() {
key = $(this).data('key');
});
// Event from button accept from the modal
$(".deletePageModalAcceptButton").on("click", function() {
var currentTab = window.location.hash ? window.location.hash.substring(1) : 'pages';
var form = jQuery('<form>', {
'action': HTML_PATH_ADMIN_ROOT+'edit-content/'+key,
'method': 'post',
'target': '_top'
}).append(jQuery('<input>', {
'type': 'hidden',
'name': 'tokenCSRF',
'value': tokenCSRF
})).append(jQuery('<input>', {
'type': 'hidden',
'name': 'key',
'value': key
})).append(jQuery('<input>', {
'type': 'hidden',
'name': 'type',
'value': 'delete'
})).append(jQuery('<input>', {
'type': 'hidden',
'name': 'tab',
'value': currentTab
}));
form.hide().appendTo("body").submit();
});
// Move-to: change page type via AJAX
$(document).on("click", ".changeTypeButton", function(e) {
e.preventDefault();
var $btn = $(this);
if ($btn.data('busy')) { return; }
$btn.data('busy', true).css('opacity', 0.5);
$.ajax({
type: "POST",
url: HTML_PATH_ADMIN_ROOT + "ajax/change-type",
data: {
tokenCSRF: tokenCSRF,
key: $btn.data('key'),
type: $btn.data('type')
},
dataType: "json"
}).done(function(response) {
if (response && response.status === 0) {
window.location.reload();
} else {
$btn.data('busy', false).css('opacity', 1);
alert((response && response.message) ? response.message : <?php echo json_encode($L->g('Failed to change type.')); ?>);
}
}).fail(function() {
$btn.data('busy', false).css('opacity', 1);
alert(<?php echo json_encode($L->g('Failed to change type.')); ?>);
});
});
});
</script>
<script>
// Open the tab defined in the URL
const anchor = window.location.hash;
$(`a[href="${anchor}"]`).tab('show');
</script>
+352
View File
@@ -0,0 +1,352 @@
<div id="dashboard" class="container">
<!-- Search with welcome message -->
<?php
$username = $login->username();
$user = new User($username);
$name = '';
if ($user->nickname()) {
$name = $user->nickname();
} elseif ($user->firstName()) {
$name = $user->firstName();
}
?>
<div class="quick-search-trigger mb-4" id="searchTrigger">
<div class="quick-search-icon">
<span class="fa fa-hand-spock-o" id="hello-icon"></span>
</div>
<span class="quick-search-text">
<span id="hello-text"><?php echo $L->g('welcome') . ($name ? ', ' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') : '') ?></span>
<small class="quick-search-hint"><?php $L->p('click-here-for-quick-search') ?></small>
</span>
<span class="quick-search-shortcut">⌘K</span>
</div>
<script>
$(document).ready(function() {
var date = new Date()
var hours = date.getHours()
var icon, greeting
var suffix = <?php echo json_encode($name ? ', ' . $name : '', JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?>
if (hours >= 6 && hours < 12) {
icon = 'fa-sun-o'; greeting = <?php echo json_encode($L->g('good-morning'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?> + suffix
} else if (hours >= 12 && hours < 18) {
icon = 'fa-sun-o'; greeting = <?php echo json_encode($L->g('good-afternoon'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?> + suffix
} else if (hours >= 18 && hours < 22) {
icon = 'fa-moon-o'; greeting = <?php echo json_encode($L->g('good-evening'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?> + suffix
} else {
icon = 'fa-moon-o'; greeting = <?php echo json_encode($L->g('good-night'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?> + suffix
}
$('#hello-icon').attr('class', 'fa ' + icon)
$('#hello-text').text(greeting)
});
</script>
<!-- Quick Search Modal -->
<div class="quick-search-modal" id="searchModal">
<div class="quick-search-overlay" id="searchOverlay"></div>
<div class="quick-search-content">
<div class="quick-search-header">
<span class="fa fa-search"></span>
<input type="text" id="jsclippy" class="quick-search-input" placeholder="<?php $L->p('search-placeholder') ?>">
</div>
<div id="searchResults" class="quick-search-results"></div>
</div>
</div>
<script>
$(document).ready(function() {
var searchInput = $('#jsclippy');
var searchResults = $('#searchResults');
var modal = $('#searchModal');
var trigger = $('#searchTrigger');
var overlay = $('#searchOverlay');
var searchTimeout;
function openSearch() {
modal.addClass('active');
$('body').css('overflow', 'hidden');
setTimeout(function() {
searchInput.focus();
}, 150);
}
function closeSearch() {
modal.removeClass('active');
$('body').css('overflow', '');
searchInput.val('');
searchResults.empty();
}
function performSearch(query) {
if (!query) {
searchResults.empty();
return;
}
$.ajax({
url: HTML_PATH_ADMIN_ROOT + "ajax/clippy",
data: { query: query },
success: function(data) {
searchResults.empty();
if (data.results && data.results.length > 0) {
data.results.forEach(function(item) {
var resultHtml = '';
if (item.type == 'menu') {
resultHtml = '<a href="' + item.url + '" class="search-suggestion">';
resultHtml += '<span class="fa fa-' + item.icon + '"></span>' + item.text + '</a>';
} else {
resultHtml = '<div class="search-suggestion">';
resultHtml += '<div class="search-suggestion-item">' + item.text + ' <span class="badge badge-pill badge-light">' + item.type + '</span></div>';
resultHtml += '<div class="search-suggestion-options">';
resultHtml += '<a target="_blank" href="' + DOMAIN_PAGES + item.id + '"><?php $L->p('view') ?></a>';
resultHtml += '<a class="ml-2" href="' + DOMAIN_ADMIN + 'edit-content/' + item.id + '"><?php $L->p('edit') ?></a>';
resultHtml += '</div></div>';
}
searchResults.append(resultHtml);
});
} else {
searchResults.html('<div class="search-no-results"><?php $L->p("no-results-found") ?></div>');
}
}
});
}
searchInput.on('input', function() {
clearTimeout(searchTimeout);
var query = $(this).val();
searchTimeout = setTimeout(function() {
performSearch(query);
}, 300);
});
trigger.on('click', openSearch);
overlay.on('click', closeSearch);
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && modal.hasClass('active')) {
closeSearch();
}
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
openSearch();
}
});
});
</script>
<!-- Dashboard Metric Cards -->
<div class="container px-0">
<div class="row">
<!-- Content Metrics Card -->
<div class="col-lg col-12 mb-4">
<div class="card metric-card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<h5 class="card-title mb-0"><?php $L->p('Content') ?></h5>
</div>
<div class="mt-3 metric-card-list">
<div class="list-group list-group-flush">
<a href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>" class="list-group-item d-flex justify-content-between align-items-center">
<span><?php $L->p('Published') ?></span>
<span class="badge badge-primary badge-pill"><?php echo count($pages->getPublishedDB()); ?></span>
</a>
<a href="<?php echo HTML_PATH_ADMIN_ROOT.'content#draft' ?>" class="list-group-item d-flex justify-content-between align-items-center">
<span><?php $L->p('Drafts') ?></span>
<span class="badge badge-primary badge-pill"><?php echo count($pages->getDraftDB()); ?></span>
</a>
<a href="<?php echo HTML_PATH_ADMIN_ROOT.'content#scheduled' ?>" class="list-group-item d-flex justify-content-between align-items-center">
<span><?php $L->p('Scheduled') ?></span>
<span class="badge badge-primary badge-pill"><?php echo count($pages->getScheduledDB()); ?></span>
</a>
</div>
</div>
</div>
</div>
</div>
<?php
// Categories Card - Only show if Categories plugin is active
if (pluginActivated('pluginCategories')) {
$categoryList = $categories->keys();
?>
<!-- Categories Card -->
<div class="col-lg col-12 mb-4">
<div class="card metric-card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<h5 class="card-title mb-0"><?php $L->p('Categories') ?></h5>
</div>
<div class="mt-3 metric-card-list">
<?php if (!empty($categoryList)): ?>
<div class="list-group list-group-flush">
<?php foreach ($categoryList as $categoryKey):
$category = new Category($categoryKey);
$pageCount = count($category->pages());
?>
<a href="<?php echo HTML_PATH_ADMIN_ROOT . 'edit-category/' . $categoryKey ?>" class="list-group-item d-flex justify-content-between align-items-center">
<span><?php echo $category->name() ?></span>
<span class="badge badge-primary badge-pill"><?php echo $pageCount ?></span>
</a>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="text-muted text-center py-3"><?php $L->p('No categories') ?></p>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php } ?>
<?php
// Tags Card - Only show if Tags plugin is active
if (pluginActivated('pluginTags')) {
$tagList = $tags->keys();
?>
<!-- Tags Card -->
<div class="col-lg col-12 mb-4">
<div class="card metric-card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<h5 class="card-title mb-0"><?php $L->p('Tags') ?></h5>
</div>
<div class="mt-3 metric-card-list">
<?php if (!empty($tagList)): ?>
<div class="list-group list-group-flush">
<?php foreach ($tagList as $tagKey):
$tag = new Tag($tagKey);
$pageCount = count($tag->pages());
?>
<a href="<?php echo HTML_PATH_ADMIN_ROOT . 'content/tag/' . $tagKey ?>" class="list-group-item d-flex justify-content-between align-items-center">
<span><?php echo $tag->name() ?></span>
<span class="badge badge-primary badge-pill"><?php echo $pageCount ?></span>
</a>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="text-muted text-center py-3"><?php $L->p('No tags') ?></p>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php } ?>
</div>
</div>
<?php
// Analytics Section - Only show if Visits Stats plugin is active
$visitsStats = getPlugin('pluginVisitsStats');
if ($visitsStats && $visitsStats->installed()):
$currentDate = Date::current('Y-m-d');
$visitsToday = $visitsStats->visits($currentDate);
$uniqueVisitors = $visitsStats->uniqueVisitors($currentDate);
$weekData = $visitsStats->getLastDaysData(7);
?>
<!-- Analytics Section -->
<div class="analytics-section mb-4">
<ul class="list-group list-group-striped b-0 mb-3">
<li class="list-group-item">
<h4 class="m-0"><?php $L->p('Analytics') ?></h4>
</li>
</ul>
<div class="row align-items-center">
<div class="col-lg-3 col-12 mb-3 mb-lg-0">
<div class="row text-center">
<div class="col-4 col-lg-12 mb-0 mb-lg-4">
<div class="metric-value"><?php echo $visitsToday; ?></div>
<div class="metric-label"><?php $L->p('Visits Today') ?></div>
</div>
<div class="col-4 col-lg-12 mb-0 mb-lg-4">
<div class="metric-value"><?php echo $uniqueVisitors; ?></div>
<div class="metric-label"><?php $L->p('Unique Visitors') ?></div>
</div>
<div class="col-4 col-lg-12">
<div class="metric-value"><?php echo $weekData['total']; ?></div>
<div class="metric-label"><?php $L->p('7-Day Total') ?></div>
</div>
</div>
</div>
<div class="col-lg-9 col-12">
<canvas id="analytics-chart"></canvas>
</div>
</div>
</div>
<script>
(function() {
var ctx = document.getElementById('analytics-chart');
if (!ctx || typeof Chart === 'undefined') { return; }
new Chart(ctx, {
type: 'bar',
data: {
labels: <?php echo json_encode($weekData['labels']); ?>,
datasets: [{
label: <?php echo json_encode($L->g('unique-visitors'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?>,
backgroundColor: 'rgba(0,120,212,0.45)',
borderColor: 'rgba(0,120,212,0.75)',
borderWidth: 1,
data: <?php echo json_encode($weekData['unique']); ?>
}, {
label: <?php echo json_encode($L->g('visits-today'), JSON_HEX_TAG | JSON_UNESCAPED_UNICODE) ?>,
backgroundColor: 'rgba(148,163,184,0.5)',
borderColor: 'rgba(100,116,139,0.8)',
borderWidth: 1,
data: <?php echo json_encode($weekData['visits']); ?>
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
aspectRatio: 4,
legend: {
display: true,
position: 'bottom',
labels: { fontSize: 11, boxWidth: 12, fontColor: '#475569' }
},
scales: {
yAxes: [{
ticks: { beginAtZero: true, stepSize: 1, fontColor: '#94A3B8', fontSize: 11 },
gridLines: { color: 'rgba(0,0,0,0.05)', zeroLineColor: 'rgba(0,0,0,0.1)' }
}],
xAxes: [{
ticks: { fontColor: '#94A3B8', fontSize: 11 },
gridLines: { display: false }
}]
},
tooltips: { mode: 'index', intersect: false }
}
});
})();
</script>
<?php endif; ?>
<!-- Notifications -->
<div class="mt-4">
<ul class="list-group list-group-striped b-0">
<li class="list-group-item">
<h4 class="m-0"><?php $L->p('Notifications') ?></h4>
</li>
<?php
$logs = array_slice($syslog->db, 0, NOTIFICATIONS_AMOUNT);
foreach ($logs as $log) {
$phrase = $L->g($log['dictionaryKey']);
echo '<li class="list-group-item">';
echo $phrase;
if (!empty($log['notes'])) {
echo ' « <b>' . htmlspecialchars($log['notes'], ENT_QUOTES, 'UTF-8') . '</b> »';
}
echo '<br><span class="notification-date"><small>';
echo Date::format($log['date'], DB_DATE_FORMAT, NOTIFICATIONS_DATE_FORMAT);
echo ' [ ' . htmlspecialchars($log['username'], ENT_QUOTES, 'UTF-8') . ' ]';
echo '</small></span>';
echo '</li>';
}
?>
</ul>
</div>
</div>
+38
View File
@@ -0,0 +1,38 @@
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Developers'), 'icon'=>'gears'));
echo '<h2 class="mb-4 mt-4"><b>PHP version: '.phpversion().'</b></h2>';
// PHP Ini
$uploadOptions = array(
'upload_max_filesize'=>ini_get('upload_max_filesize'),
'post_max_size'=>ini_get('post_max_size'),
'upload_tmp_dir'=>ini_get('upload_tmp_dir')
);
printTable('File Uploads', $uploadOptions);
// Loaded extensions
printTable('Server information ( $_SERVER )', $_SERVER);
// PHP Ini
printTable('PHP Configuration options ( ini_get_all() )', ini_get_all());
// Loaded extensions
printTable('Loaded extensions',get_loaded_extensions());
// Locales installed
exec('locale -a', $locales);
printTable('Locales installed', $locales);
echo '<hr>';
echo '<h2>BLUDIT</h2>';
echo '<hr>';
// Constanst defined by Bludit
$constants = get_defined_constants(true);
printTable('Bludit Constants', $constants['user']);
// Site object
printTable('$site object database',$site->db);
+92
View File
@@ -0,0 +1,92 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#jsdeleteModal"><?php $L->p('Delete') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'dashboard' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Edit Category'), 'icon'=>'cog')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputHidden(array(
'name'=>'action',
'value'=>'edit'
));
echo Bootstrap::formInputHidden(array(
'name'=>'oldKey',
'value'=>$categoryMap['key']
));
echo Bootstrap::formInputText(array(
'name'=>'name',
'label'=>$L->g('Name'),
'value'=>$categoryMap['name'],
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formTextarea(array(
'name'=>'description',
'label'=>$L->g('Description'),
'value'=>isset($categoryMap['description'])?$categoryMap['description']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'rows'=>3
));
echo Bootstrap::formInputText(array(
'name'=>'template',
'label'=>$L->g('Template'),
'value'=>isset($categoryMap['template'])?$categoryMap['template']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formInputText(array(
'name'=>'newKey',
'label'=>$L->g('Friendly URL'),
'value'=>$categoryMap['key'],
'class'=>'',
'placeholder'=>'',
'tip'=>DOMAIN_CATEGORIES.$categoryMap['key']
));
echo Bootstrap::formClose();
?>
<!-- Modal for delete category -->
<?php
echo Bootstrap::modal(array(
'buttonPrimary'=>$L->g('Delete'),
'buttonPrimaryClass'=>'btn-danger jsbuttonDeleteAccept',
'buttonSecondary'=>$L->g('Cancel'),
'buttonSecondaryClass'=>'btn-link',
'modalTitle'=>$L->g('Delete category'),
'modalText'=>$L->g('Are you sure you want to delete this category?'),
'modalId'=>'jsdeleteModal'
));
?>
<script>
$(document).ready(function() {
// Delete content
$(".jsbuttonDeleteAccept").on("click", function() {
$("#jsaction").val("delete");
$("#jsform").submit();
});
});
</script>
+564
View File
@@ -0,0 +1,564 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php
// FORM START
echo Bootstrap::formOpen(array(
'id' => 'jsform',
'class' => 'd-flex flex-column h-100'
));
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// UUID
// The UUID is generated in the controller
echo Bootstrap::formInputHidden(array(
'name' => 'uuid',
'value' => $page->uuid()
));
// Type = published, draft, sticky, static
echo Bootstrap::formInputHidden(array(
'name' => 'type',
'value' => $page->type()
));
// Cover image
echo Bootstrap::formInputHidden(array(
'name' => 'coverImage',
'value' => $page->coverImage(false)
));
// Content
echo Bootstrap::formInputHidden(array(
'name' => 'content',
'value' => ''
));
// Current page key
echo Bootstrap::formInputHidden(array(
'name' => 'key',
'value' => $page->key()
));
?>
<!-- TOOLBAR -->
<div id="jseditorToolbar" class="mb-1">
<div id="jseditorToolbarRight" class="btn-group btn-group-sm float-right" role="group" aria-label="Toolbar right">
<button type="button" class="btn btn-light" id="jsmediaManagerOpenModal" data-toggle="modal" data-target="#jsmediaManagerModal"><span class="fa fa-image"></span> <?php $L->p('Images') ?></button>
<?php Theme::plugins('editorToolbar') ?>
<button type="button" class="btn btn-light" id="jsoptionsSidebar" style="z-index:30"><span class="fa fa-cog"></span> <?php $L->p('Options') ?></button>
</div>
<div id="jseditorToolbarLeft">
<button type="button" class="btn btn-sm btn-primary" id="jsbuttonSave"><?php echo $L->g('Save') ?></button>
<button id="jsbuttonPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<span id="jsswitchButton" data-switch="<?php echo ($page->draft() ? 'draft' : 'publish') ?>" class="ml-2 text-secondary switch-button"><i class="fa fa-square switch-icon-<?php echo ($page->draft() ? 'draft' : 'publish') ?>"></i> <?php echo ($page->draft() ? $L->g('Draft') : $L->g('Publish')) ?></span>
</div>
<?php if ($page->scheduled()) : ?>
<div class="alert alert-warning p-1 mt-1 mb-0"><?php $L->p('scheduled') ?>: <?php echo $page->date(SCHEDULED_DATE_FORMAT) ?></div>
<?php endif; ?>
</div>
<script>
$(document).ready(function() {
$("#jsoptionsSidebar").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
$("#jsshadow").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
});
</script>
<!-- SIDEBAR OPTIONS -->
<div id="jseditorSidebar">
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active show" id="nav-general-tab" data-toggle="tab" href="#nav-general" role="tab" aria-controls="general"><?php $L->p('General') ?></a>
<a class="nav-link" id="nav-advanced-tab" data-toggle="tab" href="#nav-advanced" role="tab" aria-controls="advanced"><?php $L->p('Advanced') ?></a>
<?php if (!empty($site->customFields())) : ?>
<a class="nav-link" id="nav-custom-tab" data-toggle="tab" href="#nav-custom" role="tab" aria-controls="custom"><?php $L->p('Custom') ?></a>
<?php endif ?>
<a class="nav-link" id="nav-seo-tab" data-toggle="tab" href="#nav-seo" role="tab" aria-controls="seo"><?php $L->p('SEO') ?></a>
</div>
</nav>
<div class="tab-content pr-3 pl-3 pb-3">
<div id="nav-general" class="tab-pane fade show active" role="tabpanel" aria-labelledby="general-tab">
<?php
// Category
echo Bootstrap::formSelectBlock(array(
'name' => 'category',
'label' => $L->g('Category'),
'selected' => $page->categoryKey(),
'class' => '',
'emptyOption' => '- ' . $L->g('Uncategorized') . ' -',
'options' => $categories->getKeyNameArray()
));
// Description
echo Bootstrap::formTextareaBlock(array(
'name' => 'description',
'label' => $L->g('Description'),
'selected' => '',
'class' => '',
'value' => $page->description(),
'rows' => 5,
'placeholder' => $L->get('this-field-can-help-describe-the-content')
));
?>
<!-- Cover Image -->
<?php
$coverImage = $page->coverImage(false);
$externalCoverImage = '';
if (filter_var($coverImage, FILTER_VALIDATE_URL)) {
$coverImage = '';
$externalCoverImage = $page->coverImage(false);
}
?>
<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100"><?php $L->p('Cover Image') ?></label>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo (empty($coverImage) ? HTML_PATH_CORE_IMG . 'default.svg' : $page->coverImage()) ?>" />
</div>
<div class="mt-2 text-center">
<button type="button" id="jsbuttonSelectCoverImage" class="btn btn-primary btn-sm"><?php echo $L->g('Select cover image') ?></button>
<button type="button" id="jsbuttonRemoveCoverImage" class="btn btn-secondary btn-sm"><?php echo $L->g('Remove cover image') ?></button>
</div>
<script>
$(document).ready(function() {
$("#jscoverImagePreview").on("click", function() {
openMediaManager();
});
$("#jsbuttonSelectCoverImage").on("click", function() {
openMediaManager();
});
$("#jsbuttonRemoveCoverImage").on("click", function() {
$("#jscoverImage").val('');
$("#jscoverImagePreview").attr('src', HTML_PATH_CORE_IMG + 'default.svg');
});
});
</script>
</div>
<div id="nav-advanced" class="tab-pane fade" role="tabpanel" aria-labelledby="advanced-tab">
<?php
// Date
echo Bootstrap::formInputTextBlock(array(
'name' => 'date',
'label' => $L->g('Date'),
'placeholder' => '',
'value' => $page->dateRaw(),
'tip' => $L->g('date-format-format')
));
// Type
echo Bootstrap::formSelectBlock(array(
'name' => 'typeSelector',
'label' => $L->g('Type'),
'selected' => $page->type(),
'options' => array(
'published' => '- ' . $L->g('Default') . ' -',
'sticky' => $L->g('Sticky'),
'static' => $L->g('Static')
),
'tip' => ''
));
// Position
echo Bootstrap::formInputTextBlock(array(
'name' => 'position',
'label' => $L->g('Position'),
'tip' => $L->g('Field used when ordering content by position'),
'value' => $page->position()
));
// Tags
echo Bootstrap::formInputTextBlock(array(
'name' => 'tags',
'label' => $L->g('Tags'),
'placeholder' => '',
'tip' => $L->g('Write the tags separated by commas'),
'value' => $page->tags()
));
// Parent
try {
$options = array();
$parentKey = $page->parent();
if (!empty($parentKey)) {
$parent = new Page($parentKey);
$options = array($parentKey => $parent->title());
}
} catch (Exception $e) {
// continue
}
echo Bootstrap::formSelectBlock(array(
'name' => 'parent',
'label' => $L->g('Parent'),
'options' => $options,
'selected' => false,
'class' => '',
'tip' => $L->g('Start typing a page title to see a list of suggestions.'),
));
?>
<script>
$(document).ready(function() {
var parent = $("#jsparent").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>
<?php
// Template
echo Bootstrap::formInputTextBlock(array(
'name' => 'template',
'label' => $L->g('Template'),
'placeholder' => '',
'value' => $page->template(),
'tip' => $L->g('Write a template name to filter the page in the theme and change the style of the page.')
));
echo Bootstrap::formInputTextBlock(array(
'name' => 'externalCoverImage',
'label' => $L->g('External cover image'),
'placeholder' => "https://",
'value' => $externalCoverImage,
'tip' => $L->g('Set a cover image from external URL, such as a CDN or some server dedicated for images.')
));
// Username
echo Bootstrap::formInputTextBlock(array(
'name' => '',
'label' => $L->g('Author'),
'placeholder' => '',
'value' => $page->username(),
'tip' => '',
'disabled' => true
));
?>
<script>
$(document).ready(function() {
// Changes in External cover image input
$("#jsexternalCoverImage").change(function() {
$("#jscoverImage").val($(this).val());
});
// Datepicker
$("#jsdate").datetimepicker({
format: DB_DATE_FORMAT
});
});
</script>
</div>
<?php if (!empty($site->customFields())) : ?>
<div id="nav-custom" class="tab-pane fade" role="tabpanel" aria-labelledby="custom-tab">
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (!isset($options['position'])) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'value' => $page->custom($field)
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : '')
));
}
}
}
?>
</div>
<?php endif ?>
<div id="nav-seo" class="tab-pane fade" role="tabpanel" aria-labelledby="seo-tab">
<?php
// Friendly URL
echo Bootstrap::formInputTextBlock(array(
'name' => 'slug',
'tip' => $L->g('URL associated with the content'),
'label' => $L->g('Friendly URL'),
'placeholder' => $L->g('Leave empty for autocomplete by Bludit.'),
'value' => $page->slug()
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noindex',
'label' => 'Robots',
'labelForCheckbox' => $L->g('apply-code-noindex-code-to-this-page'),
'placeholder' => '',
'checked' => $page->noindex(),
'tip' => $L->g('This tells search engines not to show this page in their search results.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'nofollow',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-nofollow-code-to-this-page'),
'placeholder' => '',
'checked' => $page->nofollow(),
'tip' => $L->g('This tells search engines not to follow links on this page.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noarchive',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-noarchive-code-to-this-page'),
'placeholder' => '',
'checked' => $page->noarchive(),
'tip' => $L->g('This tells search engines not to save a cached copy of this page.')
));
?>
</div>
</div>
</div>
<!-- Custom fields: TOP -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'top')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => $page->custom($field),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
<!-- Title -->
<div class="form-group mb-1">
<input id="jstitle" name="title" type="text" dir="auto" class="form-control form-control-lg rounded-0" value="<?php echo $page->title() ?>" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- Editor -->
<textarea id="jseditor" class="editable h-100" style=""><?php echo $page->contentRaw(true) ?></textarea>
<!-- Custom fields: BOTTOM -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'bottom')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => $page->custom($field),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
</form>
<!-- Modal for Delete page -->
<div id="jsdeletePageModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<h3><?php $L->p('Delete content') ?></h3>
<p><?php $L->p('Are you sure you want to delete this page') ?></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal"><?php $L->p('Cancel') ?></button>
<button type="button" class="btn btn-danger" data-dismiss="modal" id="jsbuttonDeleteAccept"><?php $L->p('Delete') ?></button>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$("#jsbuttonDeleteAccept").on("click", function() {
$("#jstype").val("delete");
$("#jscontent").val("");
$("#jsform").submit();
});
});
</script>
</div>
<!-- Modal for Media Manager -->
<?php include(PATH_ADMIN_THEMES . 'booty/html/media.php'); ?>
<script>
$(document).ready(function() {
// Define function if they don't exist
// This helps if the user doesn't activate any plugin as editor
if (typeof editorGetContent != "function") {
window.editorGetContent = function() {
return $("#jseditor").val();
};
}
if (typeof editorInsertMedia != "function") {
window.editorInsertMedia = function(filename) {
$("#jseditor").val($('#jseditor').val() + '<img src="' + filename + '" alt="">');
};
}
if (typeof editorInsertLinkedMedia != "function") {
window.editorInsertLinkedMedia = function(filename, link) {
$("#jseditor").val($('#jseditor').val() + '<a href="' + link + '"><img src="' + filename + '" alt=""></a>');
};
}
// Button switch
$("#jsswitchButton").on("click", function() {
if ($(this).data("switch") == "publish") {
$(this).html('<i class="fa fa-square switch-icon-draft"></i> <?php $L->p('Draft') ?>');
$(this).data("switch", "draft");
} else {
$(this).html('<i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?>');
$(this).data("switch", "publish");
}
});
// Button preview
$("#jsbuttonPreview").on("click", function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val();
var content = editorGetContent();
var ajax = new bluditAjax();
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
var preview = window.open("<?php echo DOMAIN_PAGES . 'autosave-' . $page->uuid() . '?preview=' . hash_hmac('sha256', 'autosave-' . $page->uuid(), DB_SITE) ?>", "bludit-preview");
preview.focus();
});
});
// Button Save
$("#jsbuttonSave").on("click", function() {
// If the switch is setted to "published", get the value from the selector
if ($("#jsswitchButton").data("switch") == "publish") {
var value = $("#jstypeSelector option:selected").val();
$("#jstype").val(value);
} else {
$("#jstype").val("draft");
}
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").submit();
});
// Button Save as draft
$("#jsbuttonDraft").on("click", function() {
// Set the type as draft
$("#jstype").val("draft");
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").submit();
});
// Autosave
var currentContent = editorGetContent();
setInterval(function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]";
var content = editorGetContent();
// Autosave when content has at least 100 characters
if (content.length < 100) {
return false;
}
// Autosave only when the user change the content
if (currentContent != content) {
currentContent = content;
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
if (data.status == 0) {
showAlert("<?php $L->p('Autosave') ?>");
}
});
}
}, 1000 * 60 * AUTOSAVE_INTERVAL);
});
</script>
+334
View File
@@ -0,0 +1,334 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id' => 'jsform', 'class' => 'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title' => $L->g('Edit user'), 'icon' => 'user')); ?>
</div>
<!-- TABS -->
<nav class="mb-3">
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="nav-profile" aria-selected="false"><?php $L->p('Profile') ?></a>
<a class="nav-item nav-link" id="nav-picture-tab" data-toggle="tab" href="#picture" role="tab" aria-controls="nav-picture" aria-selected="false"><?php $L->p('Profile picture') ?></a>
<a class="nav-item nav-link" id="nav-security-tab" data-toggle="tab" href="#security" role="tab" aria-controls="nav-security" aria-selected="false"><?php $L->p('Security') ?></a>
<a class="nav-item nav-link" id="nav-social-tab" data-toggle="tab" href="#social" role="tab" aria-controls="nav-social" aria-selected="false"><?php $L->p('Social Networks') ?></a>
</div>
</nav>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// Username
echo Bootstrap::formInputHidden(array(
'name' => 'username',
'value' => $user->username()
));
?>
<div class="tab-content" id="nav-tabContent">
<!-- Profile tab -->
<div class="tab-pane fade show active" id="profile" role="tabpanel" aria-labelledby="nav-profile-tab">
<?php
// Display username but disable the field
echo Bootstrap::formInputText(array(
'name' => 'usernameDisabled',
'label' => $L->g('Username'),
'value' => $user->username(),
'class' => '',
'placeholder' => '',
'disabled' => true,
'tip' => ''
));
if ($login->role() === 'admin') {
echo Bootstrap::formSelect(array(
'name' => 'role',
'label' => $L->g('Role'),
'options' => array('author' => $L->g('Author'), 'editor' => $L->g('Editor'), 'admin' => $L->g('Administrator')),
'selected' => $user->role(),
'class' => '',
'tip' => $L->g('author-can-write-and-edit-their-own-content')
));
}
echo Bootstrap::formInputText(array(
'name' => 'email',
'label' => $L->g('Email'),
'value' => $user->email(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'nickname',
'label' => $L->g('Nickname'),
'value' => $user->nickname(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('The nickname is almost used in the themes to display the author of the content')
));
echo Bootstrap::formInputText(array(
'name' => 'firstName',
'label' => $L->g('First Name'),
'value' => $user->firstName(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'lastName',
'label' => $L->g('Last Name'),
'value' => $user->lastName(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
?>
</div>
<!-- Profile picture tab -->
<div class="tab-pane fade" id="picture" role="tabpanel" aria-labelledby="nav-picture-tab">
<div class="container">
<div class="row">
<div class="col-lg-4 col-sm-12 p-0 pr-2">
<div class="custom-file">
<input type="file" class="custom-file-input" id="jsprofilePictureInputFile" name="profilePictureInputFile">
<label class="custom-file-label" for="jsprofilePictureInputFile"><?php $L->p('Upload image'); ?></label>
</div>
<!-- <button id="jsbuttonRemovePicture" type="button" class="btn btn-primary w-100 mt-4 mb-4"><i class="fa fa-trash"></i> Remove picture</button> -->
</div>
<div class="col-lg-8 col-sm-12 p-0 text-center">
<img id="jsprofilePicturePreview" class="img-fluid img-thumbnail" alt="Profile picture preview" src="<?php echo (Sanitize::pathFile(PATH_UPLOADS_PROFILES . $user->username() . '.png') ? DOMAIN_UPLOADS_PROFILES . $user->username() . '.png?version=' . time() : HTML_PATH_CORE_IMG . 'default.svg') ?>" />
</div>
</div>
</div>
<script>
// $("#jsbuttonRemovePicture").on("click", function() {
// var username = $("#jsusername").val();
// bluditAjax.removeProfilePicture(username);
// $("#jsprofilePicturePreview").attr("src", "<?php echo HTML_PATH_CORE_IMG . 'default.svg' ?>");
// });
$("#jsprofilePictureInputFile").on("change", function() {
var formData = new FormData();
formData.append('tokenCSRF', tokenCSRF);
formData.append('profilePictureInputFile', $(this)[0].files[0]);
formData.append('username', $("#jsusername").val());
$.ajax({
url: HTML_PATH_ADMIN_ROOT + "ajax/profile-picture-upload",
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data) {
if (data.status == 0) {
$("#jsprofilePicturePreview").attr('src', data.absoluteURL + "?time=" + Math.random());
} else {
showAlert(data.message);
}
});
});
</script>
</div>
<!-- Security tab -->
<div class="tab-pane fade" id="security" role="tabpanel" aria-labelledby="nav-security-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Password')));
echo '
<div class="form-group">
<a href="' . HTML_PATH_ADMIN_ROOT . 'user-password/' . $user->username() . '" class="btn btn-primary mr-2">' . $L->g('Change password') . '</a>
</div>
';
echo Bootstrap::formTitle(array('title' => $L->g('Authentication Token')));
echo Bootstrap::formInputText(array(
'name' => 'tokenAuth',
'label' => $L->g('Token'),
'value' => $user->tokenAuth(),
'class' => '',
'tip' => $L->g('this-token-is-similar-to-a-password-it-should-not-be-shared')
));
if (checkRole(array('admin'), false)) {
echo Bootstrap::formTitle(array('title' => $L->g('Status')));
echo Bootstrap::formInputText(array(
'name' => 'status',
'label' => $L->g('Current status'),
'value' => $user->enabled() ? $L->g('Enabled') : $L->g('Disabled'),
'class' => '',
'disabled' => true,
'tip' => $user->enabled() ? '' : $L->g('To enable the user you must set a new password')
));
if ($user->enabled()) {
echo '
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<button type="submit" class="btn btn-warning mr-2" id="jsdisableUser" name="disableUser">' . $L->g('Disable user') . '</button>
<button type="submit" class="btn btn-danger mr-2" id="jsdeleteUserAndKeepContent" name="deleteUserAndKeepContent">' . $L->g('Delete user and keep content') . '</button>
<button type="submit" class="btn btn-danger mr-2" id="jsdeleteUserAndDeleteContent" name="deleteUserAndDeleteContent">' . $L->g('Delete user and delete content') . '</button>
</div>
</div>
';
}
}
?>
</div>
<!-- Social Networks tab -->
<div class="tab-pane fade" id="social" role="tabpanel" aria-labelledby="nav-social-tab">
<?php
echo Bootstrap::formInputText(array(
'name' => 'twitter',
'label' => 'Twitter',
'value' => $user->twitter(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'facebook',
'label' => 'Facebook',
'value' => $user->facebook(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'codepen',
'label' => 'CodePen',
'value' => $user->codepen(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'instagram',
'label' => 'Instagram',
'value' => $user->instagram(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'gitlab',
'label' => 'GitLab',
'value' => $user->gitlab(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'github',
'label' => 'GitHub',
'value' => $user->github(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'linkedin',
'label' => 'LinkedIn',
'value' => $user->linkedin(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'xing',
'label' => 'Xing',
'value' => $user->xing(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'telegram',
'label' => 'Telegram',
'value' => $user->telegram(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'mastodon',
'label' => 'Mastodon',
'value' => $user->mastodon(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'vk',
'label' => 'VK',
'value' => $user->vk(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'youtube',
'label' => 'Youtube',
'value' => $user->youtube(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'bluesky',
'label' => 'Bluesky',
'value' => $user->bluesky(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
?>
</div>
</div>
<?php echo Bootstrap::formClose(); ?>
<script>
// Open current tab after refresh page
$(function() {
$('a[data-toggle="tab"]').on('click', function(e) {
window.localStorage.setItem('activeTab', $(e.target).attr('href'));
console.log($(e.target).attr('href'));
});
var activeTab = window.localStorage.getItem('activeTab');
if (activeTab) {
$('#nav-tab a[href="' + activeTab + '"]').tab('show');
//window.localStorage.removeItem("activeTab");
}
});
</script>
+100
View File
@@ -0,0 +1,100 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// Logo and title
$logoPath = HTML_PATH_CORE_IMG . 'logo.svg';
$logoClass = 'logo-icon';
if (defined('BLUDIT_PRO') && $site->logo(false)) {
$logoPath = $site->logo(true);
$logoClass = 'logo-icon custom-logo';
}
echo '
<div class="login-logo">
<div class="' . $logoClass . '">
<img src="' . $logoPath . '" alt="Logo">
</div>
<h1>' . (defined('BLUDIT_PRO') ? Sanitize::html($site->title()) : 'BLUDIT') . '</h1>
</div>
';
echo Bootstrap::formOpen(array());
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// Username field with icon
echo '
<div class="form-group">
<label for="jsusername">' . $L->g('Username') . '</label>
<div class="input-icon-wrapper">
<input type="text"
dir="auto"
value="' . (isset($_POST['username']) ? Sanitize::html($_POST['username']) : '') . '"
class="form-control"
id="jsusername"
name="username"
placeholder="' . $L->g('Username') . '"
autocomplete="username"
autofocus>
<span class="input-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</span>
</div>
</div>
';
// Password field with icon
echo '
<div class="form-group">
<label for="jspassword">' . $L->g('Password') . '</label>
<div class="input-icon-wrapper">
<input type="password"
class="form-control"
id="jspassword"
name="password"
placeholder="' . $L->g('Password') . '"
autocomplete="current-password">
<span class="input-icon">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
</span>
</div>
</div>
';
// Remember me checkbox
echo '
<div class="form-check">
<input class="form-check-input" type="checkbox" value="true" id="jsremember" name="remember">
<label class="form-check-label" for="jsremember">' . $L->g('Remember me') . '</label>
</div>
';
// Submit button
echo '
<button type="submit" class="btn btn-login" name="save">
<span>' . $L->g('Login') . '</span>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-left: 8px; vertical-align: middle;">
<path d="M5 12h14"></path>
<path d="M12 5l7 7-7 7"></path>
</svg>
</button>
';
echo '</form>';
// Footer
if (!defined('BLUDIT_PRO')) {
echo '
<div class="login-footer">
<p>Powered by <a href="https://www.bludit.com" target="_blank" rel="noopener">Bludit</a></p>
</div>
';
}
+39
View File
@@ -0,0 +1,39 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'categories' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('New category'), 'icon'=>'tag')); ?>
</div>
<?php
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputText(array(
'name'=>'name',
'label'=>$L->g('Name'),
'value'=>isset($_POST['category'])?$_POST['category']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formTextarea(array(
'name'=>'description',
'label'=>$L->g('Description'),
'value'=>isset($_POST['description'])?$_POST['description']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'rows'=>3
));
?>
<?php echo Bootstrap::formClose(); ?>
+516
View File
@@ -0,0 +1,516 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php
// Start form
echo Bootstrap::formOpen(array(
'id' => 'jsform',
'class' => 'd-flex flex-column h-100'
));
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// UUID
// The UUID is generated in the controller
echo Bootstrap::formInputHidden(array(
'name' => 'uuid',
'value' => $uuid
));
// Type = published, draft, sticky, static
echo Bootstrap::formInputHidden(array(
'name' => 'type',
'value' => $site->defaultContentStatus()
));
// Cover image
echo Bootstrap::formInputHidden(array(
'name' => 'coverImage',
'value' => ''
));
// Content
echo Bootstrap::formInputHidden(array(
'name' => 'content',
'value' => ''
));
?>
<!-- TOOLBAR -->
<div id="jseditorToolbar" class="mb-1">
<div id="jseditorToolbarRight" class="btn-group btn-group-sm float-right" role="group" aria-label="Toolbar right">
<button type="button" class="btn btn-light" id="jsmediaManagerOpenModal" data-toggle="modal" data-target="#jsmediaManagerModal"><span class="fa fa-image"></span> <?php $L->p('Images') ?></button>
<?php Theme::plugins('editorToolbar') ?>
<button type="button" class="btn btn-light" id="jsoptionsSidebar" style="z-index:30"><span class="fa fa-cog"></span> <?php $L->p('Options') ?></button>
</div>
<div id="jseditorToolbarLeft">
<button id="jsbuttonSave" type="button" class="btn btn-sm btn-primary"><?php $L->p('Save') ?></button>
<button id="jsbuttonPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<?php if ($site->defaultContentStatus() == 'draft'): ?>
<span id="jsbuttonSwitch" data-switch="draft" class="ml-2 text-secondary switch-button"><i class="fa fa-square switch-icon-draft"></i> <?php $L->p('Draft') ?></span>
<?php else: ?>
<span id="jsbuttonSwitch" data-switch="publish" class="ml-2 text-secondary switch-button"><i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?></span>
<?php endif; ?>
</div>
</div>
<script>
$(document).ready(function() {
$("#jsoptionsSidebar").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
$("#jsshadow").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
});
</script>
<!-- SIDEBAR OPTIONS -->
<div id="jseditorSidebar">
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active show" id="nav-general-tab" data-toggle="tab" href="#nav-general" role="tab" aria-controls="general"><?php $L->p('General') ?></a>
<a class="nav-link" id="nav-advanced-tab" data-toggle="tab" href="#nav-advanced" role="tab" aria-controls="advanced"><?php $L->p('Advanced') ?></a>
<?php if (!empty($site->customFields())) : ?>
<a class="nav-link" id="nav-custom-tab" data-toggle="tab" href="#nav-custom" role="tab" aria-controls="custom"><?php $L->p('Custom') ?></a>
<?php endif ?>
<a class="nav-link" id="nav-seo-tab" data-toggle="tab" href="#nav-seo" role="tab" aria-controls="seo"><?php $L->p('SEO') ?></a>
</div>
</nav>
<div class="tab-content pr-3 pl-3 pb-3">
<div id="nav-general" class="tab-pane fade show active" role="tabpanel" aria-labelledby="general-tab">
<?php
// Category
echo Bootstrap::formSelectBlock(array(
'name' => 'category',
'label' => $L->g('Category'),
'selected' => '',
'class' => '',
'emptyOption' => '- ' . $L->g('Uncategorized') . ' -',
'options' => $categories->getKeyNameArray()
));
// Description
echo Bootstrap::formTextareaBlock(array(
'name' => 'description',
'label' => $L->g('Description'),
'selected' => '',
'class' => '',
'value' => '',
'rows' => 5,
'placeholder' => $L->get('this-field-can-help-describe-the-content')
));
?>
<!-- Cover Image -->
<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100"><?php $L->p('Cover Image') ?></label>
<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>
<div class="mt-2 text-center">
<button type="button" id="jsbuttonSelectCoverImage" class="btn btn-primary btn-sm"><?php echo $L->g('Select cover image') ?></button>
<button type="button" id="jsbuttonRemoveCoverImage" class="btn btn-secondary btn-sm"><?php echo $L->g('Remove cover image') ?></button>
</div>
<script>
$(document).ready(function() {
$("#jscoverImagePreview").on("click", function() {
openMediaManager();
});
$("#jsbuttonSelectCoverImage").on("click", function() {
openMediaManager();
});
$("#jsbuttonRemoveCoverImage").on("click", function() {
$("#jscoverImage").val('');
$("#jscoverImagePreview").attr('src', HTML_PATH_CORE_IMG + 'default.svg');
});
});
</script>
</div>
<div id="nav-advanced" class="tab-pane fade" role="tabpanel" aria-labelledby="advanced-tab">
<?php
// Date
echo Bootstrap::formInputTextBlock(array(
'name' => 'date',
'label' => $L->g('Date'),
'placeholder' => '',
'value' => Date::current(DB_DATE_FORMAT),
'tip' => $L->g('date-format-format')
));
// Type
echo Bootstrap::formSelectBlock(array(
'name' => 'typeSelector',
'label' => $L->g('Type'),
'selected' => '',
'options' => array(
'published' => '- ' . $L->g('Default') . ' -',
'sticky' => $L->g('Sticky'),
'static' => $L->g('Static')
),
'tip' => ''
));
// Position
echo Bootstrap::formInputTextBlock(array(
'name' => 'position',
'label' => $L->g('Position'),
'tip' => $L->g('Field used when ordering content by position'),
'value' => $pages->nextPositionNumber()
));
// Tags
echo Bootstrap::formInputTextBlock(array(
'name' => 'tags',
'label' => $L->g('Tags'),
'placeholder' => '',
'tip' => $L->g('Write the tags separated by commas')
));
// Parent
echo Bootstrap::formSelectBlock(array(
'name' => 'parent',
'label' => $L->g('Parent'),
'options' => array(),
'selected' => false,
'class' => '',
'tip' => $L->g('Start typing a page title to see a list of suggestions.'),
));
?>
<script>
$(document).ready(function() {
var parent = $("#jsparent").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>
<?php
// Template
echo Bootstrap::formInputTextBlock(array(
'name' => 'template',
'label' => $L->g('Template'),
'placeholder' => '',
'value' => '',
'tip' => $L->g('Write a template name to filter the page in the theme and change the style of the page.')
));
echo Bootstrap::formInputTextBlock(array(
'name' => 'externalCoverImage',
'label' => $L->g('External cover image'),
'placeholder' => "https://",
'value' => '',
'tip' => $L->g('Set a cover image from external URL, such as a CDN or some server dedicated for images.')
));
// Username
echo Bootstrap::formInputTextBlock(array(
'name' => '',
'label' => $L->g('Author'),
'placeholder' => '',
'value' => $login->username(),
'tip' => '',
'disabled' => true
));
?>
<script>
$(document).ready(function() {
// Changes in External cover image input
$("#jsexternalCoverImage").change(function() {
$("#jscoverImage").val($(this).val());
});
// Generate slug when the user type the title
$("#jstitle").keyup(function() {
var text = $(this).val();
var parent = $("#jsparent").val();
var currentKey = "";
var ajax = new bluditAjax();
var callBack = $("#jsslug");
ajax.generateSlug(text, parent, currentKey, callBack);
});
// Datepicker
$("#jsdate").datetimepicker({
format: DB_DATE_FORMAT
});
});
</script>
</div>
<?php if (!empty($site->customFields())) : ?>
<div id="nav-custom" class="tab-pane fade" role="tabpanel" aria-labelledby="custom-tab">
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (!isset($options['position'])) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : '')
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : '')
));
}
}
}
?>
</div>
<?php endif ?>
<div id="nav-seo" class="tab-pane fade" role="tabpanel" aria-labelledby="seo-tab">
<?php
// Friendly URL
echo Bootstrap::formInputTextBlock(array(
'name' => 'slug',
'tip' => $L->g('URL associated with the content'),
'label' => $L->g('Friendly URL'),
'placeholder' => $L->g('Leave empty for autocomplete by Bludit.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noindex',
'label' => 'Robots',
'labelForCheckbox' => $L->g('apply-code-noindex-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to show this page in their search results.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'nofollow',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-nofollow-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to follow links on this page.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noarchive',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-noarchive-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to save a cached copy of this page.')
));
?>
</div>
</div>
</div>
<!-- Custom fields: TOP -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'top')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
<!-- Title -->
<div id="jseditorTitle" class="form-group mb-1">
<input id="jstitle" name="title" type="text" dir="auto" class="form-control form-control-lg rounded-0" value="" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- Editor -->
<textarea id="jseditor" class="editable h-100 mb-1"></textarea>
<!-- Custom fields: BOTTOM -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'bottom')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
</form>
<!-- Modal for Media Manager -->
<?php include(PATH_ADMIN_THEMES . 'booty/html/media.php'); ?>
<script>
$(document).ready(function() {
// Define functions if they don't exist
// This helps if the user doesn't activate any plugin as editor
if (typeof editorGetContent != "function") {
window.editorGetContent = function() {
return $("#jseditor").val();
};
}
if (typeof editorInsertMedia != "function") {
window.editorInsertMedia = function(filename) {
$("#jseditor").val($('#jseditor').val() + '<img src="' + filename + '" alt="">');
};
}
if (typeof editorInsertLinkedMedia != "function") {
window.editorInsertLinkedMedia = function(filename, link) {
$("#jseditor").val($('#jseditor').val() + '<a href="' + link + '"><img src="' + filename + '" alt=""></a>');
};
}
// Button switch
$("#jsbuttonSwitch").on("click", function() {
if ($(this).data("switch") == "publish") {
$(this).html('<i class="fa fa-square switch-icon-draft"></i> <?php $L->p('Draft') ?>');
$(this).data("switch", "draft");
} else {
$(this).html('<i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?>');
$(this).data("switch", "publish");
}
});
// Button preview
$("#jsbuttonPreview").on("click", function() {
var uuid = $("#jsuuid").val();
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=' . hash_hmac('sha256', 'autosave-' . $uuid, DB_SITE) ?>", "bludit-preview");
preview.focus();
});
});
// Button Save
$("#jsbuttonSave").on("click", function() {
let actionParameters = '';
// If the switch is setted to "published", get the value from the selector
if ($("#jsbuttonSwitch").data("switch") == "publish") {
var value = $("#jstypeSelector option:selected").val();
$("#jstype").val(value);
actionParameters = '#' + value;
} else {
$("#jstype").val("draft");
actionParameters = '#draft';
}
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").attr('action', actionParameters);
$("#jsform").submit();
});
// Autosave
var currentContent = editorGetContent();
setInterval(function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]";
var content = editorGetContent();
// Autosave when content has at least 100 characters
if (content.length < 100) {
return false;
}
// Autosave only when the user change the content
if (currentContent != content) {
currentContent = content;
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
if (data.status == 0) {
showAlert("<?php $L->p('Autosave') ?>");
}
});
}
}, 1000 * 60 * AUTOSAVE_INTERVAL);
});
</script>
+67
View File
@@ -0,0 +1,67 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Add a new user'), 'icon'=>'user')); ?>
</div>
<?php
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputText(array(
'name'=>'new_username',
'label'=>$L->g('Username'),
'value'=>(isset($_POST['new_username'])?$_POST['new_username']:''),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formInputText(array(
'name'=>'new_password',
'type'=>'password',
'label'=>$L->g('Password'),
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formInputText(array(
'name'=>'confirm_password',
'type'=>'password',
'label'=>$L->g('Confirm Password'),
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formSelect(array(
'name'=>'role',
'label'=>$L->g('Role'),
'options'=>array('author'=>$L->g('Author'), 'editor'=>$L->g('Editor'), 'admin'=>$L->g('Administrator')),
'selected'=>'Author',
'class'=>'',
'tip'=>$L->g('author-can-write-and-edit-their-own-content')
));
echo Bootstrap::formInputText(array(
'name'=>'email',
'label'=>$L->g('Email'),
'value'=>(isset($_POST['email'])?$_POST['email']:''),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
?>
<?php echo Bootstrap::formClose(); ?>
@@ -0,0 +1,51 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="button" class="btn btn-primary btn-sm jsbuttonSave" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Plugins position'), 'icon'=>'tags')); ?>
</div>
<div class="alert alert-primary"><?php $L->p('Drag and Drop to sort the plugins') ?></div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputHidden(array(
'name'=>'plugin-list',
'value'=>''
));
echo '<ul class="list-group list-group-sortable">';
foreach ($plugins['siteSidebar'] as $Plugin) {
echo '<li class="list-group-item" data-plugin="'.$Plugin->className().'"><span class="fa fa-arrows-v"></span> '.$Plugin->name().'</li>';
}
echo '</ul>';
?>
<?php echo Bootstrap::formClose(); ?>
<script>
$(document).ready(function() {
$('.list-group-sortable').sortable({
placeholderClass: 'list-group-item'
});
$(".jsbuttonSave").on("click", function() {
var tmp = [];
$("li.list-group-item").each(function() {
tmp.push( $(this).attr("data-plugin") );
});
$("#jsplugin-list").attr("value", tmp.join(",") );
$("#jsform").submit();
});
});
</script>
+128
View File
@@ -0,0 +1,128 @@
<?php
echo Bootstrap::pageTitle(array('title' => $L->g('Plugins'), 'icon' => 'puzzle-piece'));
echo Bootstrap::link(array(
'title' => $L->g('Change the position of the plugins'),
'href' => HTML_PATH_ADMIN_ROOT . 'plugins-position',
'icon' => 'arrows'
));
echo Bootstrap::formTitle(array('title' => $L->g('Search plugins')));
?>
<input type="text" dir="auto" class="form-control" id="search" placeholder="<?php $L->p('Search') ?>">
<script>
$(document).ready(function() {
$("#search").on("keyup", function() {
var textToSearch = $(this).val().toLowerCase();
$(".searchItem").each(function() {
var item = $(this);
item.hide();
item.find(".searchText").each(function() {
var element = $(this).text().toLowerCase();
if (element.indexOf(textToSearch) != -1) {
item.show();
}
});
});
});
});
</script>
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Enabled plugins')));
echo '
<table class="table">
<tbody>
';
// Show installed plugins
foreach ($pluginsInstalled as $plugin) {
if ($plugin->type() == 'theme') {
// Do not display theme's plugins
continue;
}
echo '<tr id="' . $plugin->className() . '" class="bg-light searchItem">';
echo '<td class="align-middle pt-3 pb-3 w-25">
<div class="searchText">' . $plugin->name() . '</div>
<div class="mt-1">';
if (method_exists($plugin, 'form')) {
echo '<a class="mr-3" href="' . HTML_PATH_ADMIN_ROOT . 'configure-plugin/' . $plugin->className() . '">' . $L->g('Settings') . '</a>';
}
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'uninstall-plugin/' . $plugin->className() . '">' . $L->g('Deactivate') . '</a>';
echo '</div>';
echo '</td>';
echo '<td class="searchText align-middle d-none d-sm-table-cell">';
echo $plugin->description();
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">';
echo '<span>' . $plugin->version() . '</span>';
if (!$plugin->isCompatible()) {
echo ' <span class="badge badge-pill badge-warning" title="' . $L->g('This plugin may not be supported by this version of Bludit') . '">' . $L->g('Update') . '</span>';
}
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">
<a target="_blank" href="' . $plugin->website() . '">' . $plugin->author() . '</a>
</td>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
echo Bootstrap::formTitle(array('title' => $L->g('Disabled plugins')));
echo '
<table class="table">
<tbody>
';
// Plugins not installed
$pluginsNotInstalled = array_diff_key($plugins['all'], $pluginsInstalled);
foreach ($pluginsNotInstalled as $plugin) {
if ($plugin->type() == 'theme') {
// Do not display theme's plugins
continue;
}
echo '<tr id="' . $plugin->className() . '" class="searchItem">';
echo '<td class="align-middle pt-3 pb-3 w-25">
<div class="searchText">' . $plugin->name() . '</div>
<div class="mt-1">
<a href="' . HTML_PATH_ADMIN_ROOT . 'install-plugin/' . $plugin->className() . '">' . $L->g('Activate') . '</a>
</div>
</td>';
echo '<td class="searchText align-middle d-none d-sm-table-cell">';
echo $plugin->description();
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">';
echo '<span>' . $plugin->version() . '</span>';
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">
<a target="_blank" href="' . $plugin->website() . '">' . $plugin->author() . '</a>
</td>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
+650
View File
@@ -0,0 +1,650 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id' => 'jsform', 'class' => 'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'dashboard' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title' => $L->g('Settings'), 'icon' => 'cog')); ?>
</div>
<!-- TABS -->
<nav class="mb-3">
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-general-tab" data-toggle="tab" href="#general" role="tab" aria-controls="nav-general" aria-selected="false"><?php $L->p('General') ?></a>
<a class="nav-item nav-link" id="nav-advanced-tab" data-toggle="tab" href="#advanced" role="tab" aria-controls="nav-advanced" aria-selected="false"><?php $L->p('Advanced') ?></a>
<a class="nav-item nav-link" id="nav-seo-tab" data-toggle="tab" href="#seo" role="tab" aria-controls="nav-seo" aria-selected="false"><?php $L->p('SEO') ?></a>
<a class="nav-item nav-link" id="nav-social-tab" data-toggle="tab" href="#social" role="tab" aria-controls="nav-social" aria-selected="false"><?php $L->p('Social Networks') ?></a>
<a class="nav-item nav-link" id="nav-images-tab" data-toggle="tab" href="#images" role="tab" aria-controls="nav-images" aria-selected="false"><?php $L->p('Images') ?></a>
<a class="nav-item nav-link" id="nav-language-tab" data-toggle="tab" href="#language" role="tab" aria-controls="nav-language" aria-selected="false"><?php $L->p('Language') ?></a>
<a class="nav-item nav-link" id="nav-custom-fields-tab" data-toggle="tab" href="#custom-fields" role="tab" aria-controls="nav-custom-fields" aria-selected="false"><?php $L->p('Custom fields') ?></a>
<a class="nav-item nav-link" id="nav-logo-tab" data-toggle="tab" href="#logo" role="tab" aria-controls="nav-logo" aria-selected="false"><?php $L->p('Logo') ?></a>
</div>
</nav>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
?>
<!-- General tab -->
<div class="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Site')));
echo Bootstrap::formInputText(array(
'name' => 'title',
'label' => $L->g('Site title'),
'value' => $site->title(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('use-this-field-to-name-your-site')
));
echo Bootstrap::formInputText(array(
'name' => 'slogan',
'label' => $L->g('Site slogan'),
'value' => $site->slogan(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('use-this-field-to-add-a-catchy-phrase')
));
echo Bootstrap::formInputText(array(
'name' => 'description',
'label' => $L->g('Site description'),
'value' => $site->description(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('you-can-add-a-site-description-to-provide')
));
echo Bootstrap::formInputText(array(
'name' => 'footer',
'label' => $L->g('Footer text'),
'value' => $site->footer(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('you-can-add-a-small-text-on-the-bottom')
));
?>
</div>
<!-- Advanced tab -->
<div class="tab-pane fade" id="advanced" role="tabpanel" aria-labelledby="advanced-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Content')));
echo Bootstrap::formInputText(array(
'name' => 'itemsPerPage',
'label' => $L->g('Items per page'),
'value' => $site->itemsPerPage(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Number of items to show per page')
));
echo Bootstrap::formSelect(array(
'name' => 'orderBy',
'label' => $L->g('Order content by'),
'options' => array('date' => $L->g('Date'), 'position' => $L->g('Position')),
'selected' => $site->orderBy(),
'class' => '',
'tip' => $L->g('order-the-content-by-date-to-build-a-blog')
));
echo Bootstrap::formSelect(array(
'name' => 'defaultContentStatus',
'label' => $L->g('Default content status'),
'options' => array('published' => $L->g('Published'), 'draft' => $L->g('Draft')),
'selected' => $site->defaultContentStatus(),
'class' => '',
'tip' => $L->g('default-status-for-new-content')
));
echo Bootstrap::formTitle(array('title' => $L->g('Predefined pages')));
// Homepage
try {
$options = array();
$homeKey = $site->homepage();
if (!empty($homeKey)) {
$home = new Page($homeKey);
$options = array($homeKey => $home->title());
}
} catch (Exception $e) {
// continue
}
echo Bootstrap::formSelect(array(
'name' => 'homepage',
'label' => $L->g('Homepage'),
'options' => $options,
'selected' => false,
'class' => '',
'tip' => $L->g('Returning page for the main page')
));
?>
<script>
$(document).ready(function() {
var homepage = $("#jshomepage").select2({
placeholder: "<?php $L->p('Start typing to see a list of suggestions.') ?>",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
data: function(params) {
var query = {
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
}
});
});
</script>
<?php
// Page not found 404
try {
$options = array();
$pageNotFoundKey = $site->pageNotFound();
if (!empty($pageNotFoundKey)) {
$pageNotFound = new Page($pageNotFoundKey);
$options = array($pageNotFoundKey => $pageNotFound->title());
}
} catch (Exception $e) {
// continue
}
echo Bootstrap::formSelect(array(
'name' => 'pageNotFound',
'label' => $L->g('Page not found'),
'options' => $options,
'selected' => false,
'class' => '',
'tip' => $L->g('Returning page when the page doesnt exist')
));
?>
<script>
$(document).ready(function() {
var homepage = $("#jspageNotFound").select2({
placeholder: "<?php $L->p('Start typing to see a list of suggestions.') ?>",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
data: function(params) {
var query = {
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
}
});
});
</script>
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Email account settings')));
echo Bootstrap::formInputText(array(
'name' => 'emailFrom',
'label' => $L->g('Sender email'),
'value' => $site->emailFrom(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Emails will be sent from this address')
));
echo Bootstrap::formTitle(array('title' => $L->g('Autosave')));
echo Bootstrap::formInputText(array(
'name' => 'autosaveInterval',
'label' => $L->g('Interval'),
'value' => $site->autosaveInterval(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Number in minutes for every execution of autosave')
));
echo Bootstrap::formTitle(array('title' => $L->g('Site URL')));
echo Bootstrap::formInputText(array(
'name' => 'url',
'label' => 'URL',
'value' => $site->url(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('full-url-of-your-site'),
'placeholder' => 'https://'
));
echo Bootstrap::formTitle(array('title' => $L->g('Page content')));
echo Bootstrap::formSelect(array(
'name' => 'markdownParser',
'label' => $L->g('Markdown parser'),
'options' => array('true' => $L->g('Enabled'), 'false' => $L->g('Disabled')),
'selected' => ($site->markdownParser() ? 'true' : 'false'),
'class' => '',
'tip' => $L->g('Enable the markdown parser for the content of the page.')
));
echo Bootstrap::formTitle(array('title' => $L->g('URL Filters')));
echo Bootstrap::formInputText(array(
'name' => 'uriPage',
'label' => $L->g('Pages'),
'value' => $site->uriFilters('page'),
'class' => '',
'placeholder' => '',
'tip' => DOMAIN_PAGES
));
echo Bootstrap::formInputText(array(
'name' => 'uriTag',
'label' => $L->g('Tags'),
'value' => $site->uriFilters('tag'),
'class' => '',
'placeholder' => '',
'tip' => DOMAIN_TAGS
));
echo Bootstrap::formInputText(array(
'name' => 'uriCategory',
'label' => $L->g('Category'),
'value' => $site->uriFilters('category'),
'class' => '',
'placeholder' => '',
'tip' => DOMAIN_CATEGORIES
));
echo Bootstrap::formInputText(array(
'name' => 'uriBlog',
'label' => $L->g('Blog'),
'value' => $site->uriFilters('blog'),
'class' => '',
'placeholder' => '',
'tip' => DOMAIN . $site->uriFilters('blog'),
'disabled' => Text::isEmpty($site->uriFilters('blog'))
));
?>
</div>
<!-- SEO tab -->
<div class="tab-pane fade" id="seo" role="tabpanel" aria-labelledby="seo-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Extreme friendly URL')));
echo Bootstrap::formSelect(array(
'name' => 'extremeFriendly',
'label' => $L->g('Allow Unicode'),
'options' => array('true' => $L->g('Enabled'), 'false' => $L->g('Disabled')),
'selected' => ($site->extremeFriendly() ? 'true' : 'false'),
'class' => '',
'tip' => $L->g('Allow unicode characters in the URL and some part of the system.')
));
echo Bootstrap::formTitle(array('title' => $L->g('Title formats')));
echo Bootstrap::formInputText(array(
'name' => 'titleFormatHomepage',
'label' => $L->g('Homepage'),
'value' => $site->titleFormatHomepage(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Variables allowed') . ' <code>{{site-title}}</code> <code>{{site-slogan}}</code> <code>{{site-description}}</code>',
'placeholder' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'titleFormatPages',
'label' => $L->g('Pages'),
'value' => $site->titleFormatPages(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Variables allowed') . ' <code>{{page-title}}</code> <code>{{page-description}}</code> <code>{{site-title}}</code> <code>{{site-slogan}}</code> <code>{{site-description}}</code>',
'placeholder' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'titleFormatCategory',
'label' => $L->g('Category'),
'value' => $site->titleFormatCategory(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Variables allowed') . ' <code>{{category-name}}</code> <code>{{site-title}}</code> <code>{{site-slogan}}</code> <code>{{site-description}}</code>',
'placeholder' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'titleFormatTag',
'label' => $L->g('Tag'),
'value' => $site->titleFormatTag(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Variables allowed') . ' <code>{{tag-name}}</code> <code>{{site-title}}</code> <code>{{site-slogan}}</code> <code>{{site-description}}</code>',
'placeholder' => ''
));
?>
</div>
<!-- Social Network tab -->
<div class="tab-pane fade" id="social" role="tabpanel" aria-labelledby="social-tab">
<?php
echo Bootstrap::formInputText(array(
'name' => 'twitter',
'label' => 'Twitter',
'value' => $site->twitter(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'facebook',
'label' => 'Facebook',
'value' => $site->facebook(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'codepen',
'label' => 'CodePen',
'value' => $site->codepen(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'instagram',
'label' => 'Instagram',
'value' => $site->instagram(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'gitlab',
'label' => 'GitLab',
'value' => $site->gitlab(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'github',
'label' => 'GitHub',
'value' => $site->github(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'linkedin',
'label' => 'LinkedIn',
'value' => $site->linkedin(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'xing',
'label' => 'Xing',
'value' => $site->xing(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'telegram',
'label' => 'Telegram',
'value' => $site->telegram(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'mastodon',
'label' => 'Mastodon',
'value' => $site->mastodon(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'dribbble',
'label' => 'Dribbble',
'value' => $site->dribbble(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'vk',
'label' => 'VK',
'value' => $site->vk(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'youtube',
'label' => 'Youtube',
'value' => $site->youtube(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'bluesky',
'label' => 'Bluesky',
'value' => $site->bluesky(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
?>
</div>
<!-- Images tab -->
<div class="tab-pane fade" id="images" role="tabpanel" aria-labelledby="images-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Thumbnails')));
echo Bootstrap::formSelect(array(
'name' => 'thumbnailEnable',
'label' => $L->g('Thumbnail generation'),
'options' => array('true' => $L->g('Enabled'), 'false' => $L->g('Disabled')),
'selected' => ($site->thumbnailEnable() ? 'true' : 'false'),
'class' => '',
'tip' => $L->g('Enable or disable automatic thumbnail generation on image upload.')
));
echo Bootstrap::formInputText(array(
'name' => 'thumbnailWidth',
'label' => $L->g('Width'),
'value' => $site->thumbnailWidth(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Thumbnail width in pixels')
));
echo Bootstrap::formInputText(array(
'name' => 'thumbnailHeight',
'label' => $L->g('Height'),
'value' => $site->thumbnailHeight(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Thumbnail height in pixels')
));
echo Bootstrap::formInputText(array(
'name' => 'thumbnailQuality',
'label' => $L->g('Quality'),
'value' => $site->thumbnailQuality(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Thumbnail quality in percentage')
));
?>
</div>
<!-- Timezone and language tab -->
<div class="tab-pane fade" id="language" role="tabpanel" aria-labelledby="language-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Language and timezone')));
echo Bootstrap::formSelect(array(
'name' => 'language',
'label' => $L->g('Language'),
'options' => $L->getLanguageList(),
'selected' => $site->language(),
'class' => '',
'tip' => $L->g('select-your-sites-language')
));
echo Bootstrap::formSelect(array(
'name' => 'timezone',
'label' => $L->g('Timezone'),
'options' => Date::timezoneList(),
'selected' => $site->timezone(),
'class' => '',
'tip' => $L->g('select-a-timezone-for-a-correct')
));
echo Bootstrap::formInputText(array(
'name' => 'locale',
'label' => $L->g('Locale'),
'value' => $site->locale(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('with-the-locales-you-can-set-the-regional-user-interface')
));
echo Bootstrap::formTitle(array('title' => $L->g('Date and time formats')));
echo Bootstrap::formInputText(array(
'name' => 'dateFormat',
'label' => $L->g('Date format'),
'value' => $site->dateFormat(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('Current format') . ': ' . Date::current($site->dateFormat())
));
?>
</div>
<!-- Custom fields -->
<div class="tab-pane fade" id="custom-fields" role="tabpanel" aria-labelledby="custom-fields-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Custom fields')));
echo Bootstrap::formTextarea(array(
'name' => 'customFields',
'label' => 'JSON Format',
'value' => json_encode($site->customFields(), JSON_PRETTY_PRINT),
'class' => '',
'placeholder' => '',
'tip' => $L->g('define-custom-fields-for-the-content'),
'rows' => 15
));
?>
</div>
<!-- Site logo tab -->
<div class="tab-pane fade" id="logo" role="tabpanel" aria-labelledby="logo-tab">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Site logo')));
?>
<div class="container">
<div class="row">
<div class="col-lg-4 col-sm-12 p-0 pr-2">
<div class="custom-file">
<input id="jssiteLogoInputFile" class="custom-file-input" type="file" name="inputFile">
<label for="jssiteLogoInputFile" class="custom-file-label"><?php $L->p('Upload image'); ?></label>
</div>
<button id="jsbuttonRemoveLogo" type="button" class="btn btn-primary w-100 mt-4 mb-4"><i class="fa fa-trash"></i><?php $L->p('Remove logo') ?></button>
</div>
<div class="col-lg-8 col-sm-12 p-0 text-center">
<img id="jssiteLogoPreview" class="img-fluid img-thumbnail" alt="Site logo preview" src="<?php echo ($site->logo() ? DOMAIN_UPLOADS . $site->logo(false) . '?version=' . time() : HTML_PATH_CORE_IMG . 'default.svg') ?>" />
</div>
</div>
</div>
<script>
$("#jsbuttonRemoveLogo").on("click", function() {
bluditAjax.removeLogo();
$("#jssiteLogoPreview").attr("src", "<?php echo HTML_PATH_CORE_IMG . 'default.svg' ?>");
});
$("#jssiteLogoInputFile").on("change", function() {
var formData = new FormData();
formData.append('tokenCSRF', tokenCSRF);
formData.append('inputFile', $(this)[0].files[0]);
$.ajax({
url: HTML_PATH_ADMIN_ROOT + "ajax/logo-upload",
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data) {
if (data.status == 0) {
$("#jssiteLogoPreview").attr('src', data.absoluteURL + "?time=" + Math.random());
} else {
showAlert(data.message);
}
});
});
</script>
</div>
<?php echo Bootstrap::formClose(); ?>
<script>
// Open current tab after refresh page
$(function() {
$('a[data-toggle="tab"]').on('click', function(e) {
window.localStorage.setItem('activeTab', $(e.target).attr('href'));
});
var activeTab = window.localStorage.getItem('activeTab');
if (activeTab) {
$('#nav-tab a[href="' + activeTab + '"]').tab('show');
//window.localStorage.removeItem("activeTab");
}
});
</script>
+57
View File
@@ -0,0 +1,57 @@
<?php
echo Bootstrap::pageTitle(array('title' => $L->g('Themes'), 'icon' => 'desktop'));
echo '
<table class="table mt-3">
<thead>
<tr>
<th class="border-bottom-0 w-25" scope="col">' . $L->g('Name') . '</th>
<th class="border-bottom-0 d-none d-sm-table-cell" scope="col">' . $L->g('Description') . '</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">' . $L->g('Version') . '</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">' . $L->g('Author') . '</th>
</tr>
</thead>
<tbody>
';
foreach ($themes as $theme) {
echo '
<tr ' . ($theme['dirname'] == $site->theme() ? 'class="bg-light"' : '') . '>
<td class="align-middle pt-3 pb-3">
<div>'.$theme['name'].($theme['dirname']==$site->theme()?'<span class="badge badge-primary ml-2">'.$L->g('Active').'</span>':'').'</div>
<div class="mt-1">
';
if ($theme['dirname'] != $site->theme()) {
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'install-theme/' . $theme['dirname'] . '">' . $L->g('Activate') . '</a>';
} else {
if (isset($theme['plugin'])) {
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'configure-plugin/' . $theme['plugin'] . '">' . $L->g('Settings') . '</a>';
}
}
echo '
</div>
</td>
';
echo '<td class="align-middle d-none d-sm-table-cell">';
echo $theme['description'];
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">';
echo '<span>' . $theme['version'] . '</span>';
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">
<a target="_blank" href="' . $theme['website'] . '">' . $theme['author'] . '</a>
</td>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
+60
View File
@@ -0,0 +1,60 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'edit-user/'.$user->username() ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Change password'), 'icon'=>'user')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
// Username
echo Bootstrap::formInputHidden(array(
'name'=>'username',
'value'=>$user->username()
));
// Username disabled
echo Bootstrap::formInputText(array(
'name'=>'usernameDisabled',
'label'=>$L->g('Username'),
'value'=>$user->username(),
'class'=>'',
'placeholder'=>'',
'disabled'=>true,
'tip'=>''
));
// New password
echo Bootstrap::formInputText(array(
'name'=>'newPassword',
'label'=>$L->g('New password'),
'type'=>'password',
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
// Confirm password
echo Bootstrap::formInputText(array(
'name'=>'confirmPassword',
'label'=>$L->g('Confirm new password'),
'type'=>'password',
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
?>
<?php echo Bootstrap::formClose(); ?>
+56
View File
@@ -0,0 +1,56 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Users'), 'icon'=>'users'));
echo Bootstrap::link(array(
'title'=>$L->g('add-a-new-user'),
'href'=>HTML_PATH_ADMIN_ROOT.'new-user',
'icon'=>'plus'
));
echo '
<table class="table table-striped mt-3">
<thead>
<tr>
<th class="border-bottom-0" scope="col">'.$L->g('Username').'</th>
<th class="border-bottom-0 d-none d-lg-table-cell" scope="col">'.$L->g('Nickname').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('Email').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('Status').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('Role').'</th>
<th class="border-bottom-0 d-none d-lg-table-cell" scope="col">'.$L->g('Registered').'</th>
</tr>
</thead>
<tbody>
';
$list = $users->keys();
foreach ($list as $username) {
try {
$user = new User($username);
echo '<tr>';
echo '<td><img class="profilePicture mr-1" alt="" src="'.(Sanitize::pathFile(PATH_UPLOADS_PROFILES.$user->username().'.png')?DOMAIN_UPLOADS_PROFILES.$user->username().'.png':HTML_PATH_CORE_IMG.'default.svg').'" /><a href="'.HTML_PATH_ADMIN_ROOT.'edit-user/'.$username.'">'.$username.'</a></td>';
echo '<td class="d-none d-lg-table-cell">'.$user->nickname().'</td>';
echo '<td>'.$user->email().'</td>';
echo '<td>'.($user->enabled()?'<b>'.$L->g('Enabled').'</b>':$L->g('Disabled')).'</td>';
if ($user->role()=='admin') {
echo '<td>'.$L->g('Administrator').'</td>';
} elseif ($user->role()=='editor') {
echo '<td>'.$L->g('Editor').'</td>';
} elseif ($user->role()=='author') {
echo '<td>'.$L->g('Author').'</td>';
} else {
echo '<td>'.$L->g('Reader').'</td>';
}
echo '<td class="d-none d-lg-table-cell">'.Date::format($user->registered(), DB_DATE_FORMAT, ADMIN_PANEL_DATE_FORMAT).'</td>';
echo '</tr>';
} catch (Exception $e) {
// Continue
}
}
echo '
</tbody>
</table>
';