Major changes, see source
This commit is contained in:
parent
eafc2588dc
commit
ecb5c59eb7
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* text=auto
|
@ -1,46 +0,0 @@
|
|||||||
$(function() {
|
|
||||||
FormValidator = {};
|
|
||||||
|
|
||||||
FormValidator.onError = function(str)
|
|
||||||
{
|
|
||||||
alert(str);
|
|
||||||
console.log(str);
|
|
||||||
};
|
|
||||||
|
|
||||||
FormValidator.validate = function(callback)
|
|
||||||
{
|
|
||||||
var pass = 1;
|
|
||||||
|
|
||||||
$("[fv-regex]").each(function(i, x) {
|
|
||||||
|
|
||||||
if (pass == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
let input = x.val();
|
|
||||||
let regex = new RegExp(x.attr("fv-regex"), "g");
|
|
||||||
|
|
||||||
if (!input.match(regex))
|
|
||||||
{
|
|
||||||
x.addClass("border-danger");
|
|
||||||
x.focus();
|
|
||||||
x.select();
|
|
||||||
|
|
||||||
let warning = x.attr("fv-warning") ?? "Please correct the highlighted input and try again";
|
|
||||||
|
|
||||||
FormValidator.onError(warning)
|
|
||||||
|
|
||||||
pass = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pass == 1)
|
|
||||||
if (typeof callback === "function")
|
|
||||||
callback();
|
|
||||||
|
|
||||||
x.removeClass("border-danger");
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,37 +0,0 @@
|
|||||||
div.searchable-input input
|
|
||||||
{
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.searchable-input div.items
|
|
||||||
{
|
|
||||||
padding-top: 0.5em;
|
|
||||||
padding-bottom: 0.5em;
|
|
||||||
border: 1px solid #aaa;
|
|
||||||
/*border-top: 0;*/
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 10em;
|
|
||||||
overflow-x: scroll;
|
|
||||||
overflow-y: scroll;
|
|
||||||
position: absolute;
|
|
||||||
background: #fff;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.searchable-input div.item
|
|
||||||
{
|
|
||||||
white-space: normal;
|
|
||||||
padding-left: 0.5em;
|
|
||||||
padding-right: 0.5em;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.searchable-input div.item:hover
|
|
||||||
{
|
|
||||||
/*background: #0af;
|
|
||||||
color: #fff;*/
|
|
||||||
background: highlight;
|
|
||||||
color: highlighttext;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
$(function() {
|
|
||||||
SearchableInput = {};
|
|
||||||
|
|
||||||
SearchableInput.initItems = function()
|
|
||||||
{
|
|
||||||
var items = $("div.searchable-input div.item");
|
|
||||||
|
|
||||||
items.each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
var parent = x.parents("div.searchable-input").first();
|
|
||||||
var input = parent.find("input").first();
|
|
||||||
var item = x;
|
|
||||||
var itemContainer = parent.find("div.items").first();
|
|
||||||
|
|
||||||
if (item.is("[onclick]"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!item.is("[data-value]"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
item.unbind("mousedown");
|
|
||||||
item.bind("mousedown", function() {
|
|
||||||
input.attr("data-value", item.attr("data-value"));
|
|
||||||
input.val(item.text().trim());
|
|
||||||
itemContainer.hide();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
SearchableInput.init = function()
|
|
||||||
{
|
|
||||||
$("div.searchable-input input").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
var parent = x.parents("div.searchable-input").first();
|
|
||||||
var backgroundColor = null;
|
|
||||||
var selectColor = null;
|
|
||||||
var input = x;
|
|
||||||
var itemContainer = parent.find("div.items").first();
|
|
||||||
var items = itemContainer.find("div.item");
|
|
||||||
var strictSearch = parent.attr("strict-search");
|
|
||||||
|
|
||||||
// Get first opaque body color:
|
|
||||||
parent.parents("*").each(function(i, x) {
|
|
||||||
if (backgroundColor !== null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
x = $(x);
|
|
||||||
var color = x.css("backgroundColor");
|
|
||||||
|
|
||||||
if (/^rgba/.test(color))
|
|
||||||
{
|
|
||||||
var alphaPart = parseFloat(color.split(",")[3]);
|
|
||||||
|
|
||||||
if (isNaN(alphaPart))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (alphaPart > 0.9)
|
|
||||||
backgroundColor = color;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^rgb/.test(color))
|
|
||||||
backgroundColor = color;
|
|
||||||
});
|
|
||||||
|
|
||||||
itemContainer.hide();
|
|
||||||
|
|
||||||
x.unbind("blur");
|
|
||||||
x.bind("blur", function() {
|
|
||||||
setTimeout(function() {
|
|
||||||
itemContainer.hide();
|
|
||||||
|
|
||||||
if (input.val().trim().length < 1)
|
|
||||||
input.attr("data-value", null);
|
|
||||||
}, 10);
|
|
||||||
});
|
|
||||||
|
|
||||||
x.unbind("input");
|
|
||||||
x.bind("input", function() {
|
|
||||||
|
|
||||||
var fnOnInputCooldown = function(itemContainer)
|
|
||||||
{
|
|
||||||
var parent = itemContainer.parents("div.searchable-input").first();
|
|
||||||
var input = parent.find("input").first();
|
|
||||||
var items = itemContainer.find("div.item");
|
|
||||||
var searchTermsString = input.val().toLowerCase().trim();
|
|
||||||
var searchTerms = searchTermsString.split(" ");
|
|
||||||
|
|
||||||
items.hide();
|
|
||||||
|
|
||||||
items.each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
var item = x;
|
|
||||||
var pass = 1;
|
|
||||||
var itemText = item.text().toLowerCase().trim();
|
|
||||||
|
|
||||||
if (strictSearch)
|
|
||||||
{
|
|
||||||
if (itemText.includes(searchTermsString))
|
|
||||||
item.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < searchTerms.length; i++)
|
|
||||||
{
|
|
||||||
var searchTerm = searchTerms[i];
|
|
||||||
if (searchTerm.length < 1)
|
|
||||||
continue;
|
|
||||||
if (!itemText.includes(searchTerm))
|
|
||||||
pass = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//item.hide();
|
|
||||||
|
|
||||||
if (pass == 1)
|
|
||||||
item.show();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var dataSourceApi = itemContainer.attr("data-source-api");
|
|
||||||
|
|
||||||
if (dataSourceApi)
|
|
||||||
{
|
|
||||||
if (typeof(SearchableInput.timeout) !== "undefined")
|
|
||||||
clearTimeout(SearchableInput.timeout);
|
|
||||||
|
|
||||||
SearchableInput.timeout = setTimeout(function() {
|
|
||||||
var searchTermsString = input.val().toLowerCase().trim();
|
|
||||||
|
|
||||||
console.log(dataSourceApi);
|
|
||||||
|
|
||||||
$.get({
|
|
||||||
url: `${dataSourceApi}?q=${searchTermsString}`,
|
|
||||||
//url: `${dataSourceApi}`,
|
|
||||||
method: "get",
|
|
||||||
success: function(data)
|
|
||||||
{
|
|
||||||
console.log(data);
|
|
||||||
itemContainer.html("");
|
|
||||||
|
|
||||||
for (var i = 0; i < data.length; i++)
|
|
||||||
{
|
|
||||||
var item = data[i];
|
|
||||||
var itemElement = $("<div></div>");
|
|
||||||
|
|
||||||
itemElement.addClass("item");
|
|
||||||
itemElement.attr("data-value", item.value);
|
|
||||||
itemElement.html(item.name);
|
|
||||||
|
|
||||||
itemContainer.append(itemElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchableInput.initItems();
|
|
||||||
|
|
||||||
fnOnInputCooldown(itemContainer);
|
|
||||||
},
|
|
||||||
error: function(xhr, e, m)
|
|
||||||
{
|
|
||||||
console.log(e);
|
|
||||||
console.log(m);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
fnOnInputCooldown(itemContainer);
|
|
||||||
});
|
|
||||||
|
|
||||||
x.unbind("focus");
|
|
||||||
x.bind("focus", function() {
|
|
||||||
//x.trigger("input");
|
|
||||||
|
|
||||||
itemContainer.css("width", parent.width() + "px");
|
|
||||||
itemContainer.css("background", backgroundColor);
|
|
||||||
|
|
||||||
// If data-source is a valid jQuery selector, use that container's innerHTML:
|
|
||||||
var dataSource = itemContainer.attr("data-source");
|
|
||||||
|
|
||||||
if (dataSource)
|
|
||||||
{
|
|
||||||
var dataSourceObject = $(dataSource);
|
|
||||||
if (dataSourceObject.length > 0)
|
|
||||||
{
|
|
||||||
itemContainer.html(dataSourceObject.first().html());
|
|
||||||
//SearchableInput.init();
|
|
||||||
SearchableInput.initItems();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
itemContainer.show();
|
|
||||||
items.show();
|
|
||||||
input.select();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
SearchableInput.initItems();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
SearchableInput.init();
|
|
||||||
});
|
|
75
footer.php
75
footer.php
@ -1,61 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
global $c;
|
$strDefaults =
|
||||||
$varUser = UserAuth::getUser();
|
"---
|
||||||
$varFooterLinks2 = $c->query("SELECT * from links where position like 'footer' order by sort");
|
|
||||||
$varFooterLinks = [];
|
|
||||||
|
|
||||||
foreach ($varFooterLinks2 as $varLink)
|
Copyright ©
|
||||||
{
|
|
||||||
if (UserAuth::visible($varLink["visibility"]))
|
* [Website Home](/)
|
||||||
$varFooterLinks[] = $varLink;
|
* [Post](/post)
|
||||||
}
|
* [CSS](/edit/css)";
|
||||||
|
|
||||||
|
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
|
||||||
|
$strContent = Settings::get("footer", $strDefaults, true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mb-5">
|
<?php if (strlen($strContent) > 0): ?>
|
||||||
<hr />
|
<div class="footer-content">
|
||||||
|
<?php
|
||||||
<?php
|
$varParsedown = new Parsedown();
|
||||||
$strSidebarContent = Settings::get("footer_content", "Copyright ©", true);
|
echo $varParsedown->text($strContent);
|
||||||
?>
|
?>
|
||||||
|
</div>
|
||||||
<?php if (strlen($strSidebarContent) > 0): ?>
|
<?php endif; ?>
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<div>
|
|
||||||
<?php
|
|
||||||
$varParsedown = new Parsedown();
|
|
||||||
echo $varParsedown->text($strSidebarContent);
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if (count($varFooterLinks) > 0): ?>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<?php foreach ($varFooterLinks as $varLink): ?>
|
|
||||||
<div>
|
|
||||||
<a class="link-underline link-underline-opacity-0" href="<?= $varLink["url"]; ?>"><i class="fa fa-fw fa-<?= $varLink["icon"]; ?> pe-2"></i> <?= $varLink["label"]; ?></a>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
$("input, textarea").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
x.attr("autocomplete", "0");
|
|
||||||
x.attr("autocorrect", "0");
|
|
||||||
x.attr("autocapitalize", "0");
|
|
||||||
x.attr("spellcheck", "false");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
47
head.php
47
head.php
@ -1,26 +1,29 @@
|
|||||||
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
<meta name="viewport" content="initial-scale=1, width=device-width" />
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" />
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" ></script>
|
|
||||||
|
|
||||||
<!-- JQuery -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
||||||
|
|
||||||
<!-- FontAwesome -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" />
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/js/all.min.js"></script>
|
|
||||||
|
|
||||||
<!-- SearchableInput -->
|
|
||||||
<link rel="stylesheet" href="/files/SearchableInput/SearchableInput.css" />
|
|
||||||
<script src="/files/SearchableInput/SearchableInput.js"></script>
|
|
||||||
|
|
||||||
<!-- FormValidator -->
|
|
||||||
<script src="/files/FormValidator/FormValidator.js"></script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* https://github.com/twbs/bootstrap/issues/37184 */
|
<?php
|
||||||
.dropdown-menu {
|
$strDefaults = "
|
||||||
z-index: 1040 !important;
|
/* Put in your custom CSS here: */
|
||||||
}
|
.header-content { margin-bottom: 3em; }
|
||||||
|
.footer-content { margin-top: 3em; }
|
||||||
|
html { background: #aaa; font-family: Georgia; }
|
||||||
|
body { max-width: 7in; margin: 0 auto; padding: 3em; background: #fff; }
|
||||||
|
hr { border: none; background: #aaa; min-height: 1px; }
|
||||||
|
textarea { width: 100%; min-width: 100%; max-width: 100%; min-height: 3in; margin-bottom: 0.5em; }
|
||||||
|
.message-danger { background: #f00; color: #fff; padding: 0.5em; }
|
||||||
|
.message-warning { background: #fd0; color: #000; padding: 0.5em; }
|
||||||
|
.message-success { background: #070; color: #fff; padding: 0.5em; }
|
||||||
|
.message-info { background: #0df; color: #000; padding: 0.5em; }
|
||||||
|
.post-container { margin-top: 3em; margin-bottom: 3em; }
|
||||||
|
.post-container > hr { border: 0; background: none; border-bottom: 2px dotted #aaa; margin-top: 3em; margin-bottom: 3em; }
|
||||||
|
.post img { max-width: 2in; }
|
||||||
|
table { margin-bottom: 1em; }
|
||||||
|
a[href], a[href]:visited { color: #07a; text-decoration: none; }
|
||||||
|
a[href]:hover { text-decoration: underline; }
|
||||||
|
";
|
||||||
|
|
||||||
|
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
|
||||||
|
$strContent = Settings::get("css", $strDefaults, true);
|
||||||
|
echo $strContent;
|
||||||
|
?>
|
||||||
</style>
|
</style>
|
||||||
|
100
header.php
100
header.php
@ -1,92 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
global $c;
|
$strDefaults =
|
||||||
$varUser = UserAuth::getUser();
|
"[Website Home](/) —
|
||||||
$varNavbarLinks = $c->query("SELECT * from links where position like 'navbar' order by sort");
|
[Post](/post) ·
|
||||||
$varSidebarLinks = $c->query("SELECT * from links where position like 'sidebar' order by sort");
|
[CSS](/edit/css)
|
||||||
$varFirstNavbarLink = array_shift($varNavbarLinks);
|
|
||||||
|
---";
|
||||||
|
|
||||||
|
$strDefaults = preg_replace("/[ ]{4,}/", "", $strDefaults);
|
||||||
|
$strContent = Settings::get("header", $strDefaults, true);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<script>
|
<?php if (strlen($strContent) > 0): ?>
|
||||||
// Make the page's theme dark:
|
<div class="header-content">
|
||||||
$("body").first().attr("data-bs-theme", "dark");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="offcanvas offcanvas-start" id="sidebar">
|
|
||||||
<div class="offcanvas-body">
|
|
||||||
<?php
|
<?php
|
||||||
$strSidebarContent = Settings::get("sidebar_content", "#### Sidebar Navigation", true);
|
$varParsedown = new Parsedown();
|
||||||
|
echo $varParsedown->text($strContent);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php if (strlen($strSidebarContent) > 0): ?>
|
|
||||||
<div class="mt-5">
|
|
||||||
<?php
|
|
||||||
$varParsedown = new Parsedown();
|
|
||||||
echo $varParsedown->text($strSidebarContent);
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php foreach ($varSidebarLinks as $varLink): ?>
|
|
||||||
<?php if (!UserAuth::visible($varLink["visibility"])) continue; ?>
|
|
||||||
|
|
||||||
<div class="mb-2">
|
|
||||||
<a class="btn btn-outline-secondary w-100" href="<?= $varLink["url"]; ?>"><i class="fa fa-fw fa-<?= $varLink["icon"]; ?> pe-2"></i> <?= $varLink["label"]; ?></a>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="navbar navbar-expand bg-secondary d-flex px-3">
|
|
||||||
|
|
||||||
<div class="container justify-content-between">
|
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
<a class="btn btn-secondary me-2" data-bs-toggle="offcanvas" data-bs-target="#sidebar"> <i class="fa fa-fw fa-bars"></i> </a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<a class="navbar-brand" href="<?= $varFirstNavbarLink["url"]; ?>"><?= $varFirstNavbarLink["label"]; ?></a>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="dropdown d-lg-none">
|
|
||||||
<a class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown">...</a>
|
|
||||||
|
|
||||||
<div class="dropdown-menu">
|
|
||||||
<?php foreach ($varNavbarLinks as $varLink): ?>
|
|
||||||
<?php if (!UserAuth::visible($varLink["visibility"])) continue; ?>
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="<?= $varLink["url"]; ?>"><i class="fa fa-fw fa-<?= $varLink["icon"]; ?> pe-2"></i> <?= $varLink["label"]; ?></a>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php foreach ($varNavbarLinks as $varLink): ?>
|
|
||||||
<?php if (!UserAuth::visible($varLink["visibility"])) continue; ?>
|
|
||||||
|
|
||||||
<a class="nav-link d-none d-lg-inline" href="<?= $varLink["url"]; ?>"><?= $varLink["label"]; ?></a>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
|
||||||
<div class="dropdown">
|
|
||||||
<a class="btn btn-secondary dropdown-toggle h-100" data-bs-toggle="dropdown"><i class="fa fa-fw fa-user"></i> </a>
|
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-end">
|
|
||||||
|
|
||||||
<?php if ($varUser !== null): ?>
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/user/info"><i class="fa fa-fw fa-user pe-2"></i> <?= $varUser["username"]; ?></a>
|
|
||||||
<a class="dropdown-item" href="/user/signout"><i class="fa fa-fw fa-right-from-bracket pe-2"></i> Sign Out</a>
|
|
||||||
|
|
||||||
<?php else: ?>
|
|
||||||
|
|
||||||
<a class="dropdown-item" href="/user/signin"><i class="fa fa-fw fa-right-to-bracket pe-2"></i> Sign In</a>
|
|
||||||
<a class="dropdown-item" href="/user/register"><i class="fa fa-fw fa-user-plus pe-2"></i> Register</a>
|
|
||||||
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
23
init.php
23
init.php
@ -20,28 +20,5 @@
|
|||||||
"create_links_table.sql",
|
"create_links_table.sql",
|
||||||
"create_posts_table.sql",
|
"create_posts_table.sql",
|
||||||
"create_settings_table.sql"]);
|
"create_settings_table.sql"]);
|
||||||
|
|
||||||
$varLinks = $c->query("SELECT * from links");
|
|
||||||
|
|
||||||
if (count($varLinks) < 1)
|
|
||||||
{
|
|
||||||
$c->query(
|
|
||||||
"INSERT into links (label, url, icon, position, visibility)
|
|
||||||
values
|
|
||||||
('Home', '/', 'home', 'navbar', ''),
|
|
||||||
('Post', '/post', 'edit', 'navbar', 'user'),
|
|
||||||
|
|
||||||
('Home', '/', 'home', 'sidebar', ''),
|
|
||||||
('Edit Links', '/edit/links', 'link', 'sidebar', 'admin'),
|
|
||||||
('Edit CSS', '/settings/css', 'code', 'sidebar', 'admin'),
|
|
||||||
('Edit JS', '/settings/js', 'code', 'sidebar', 'admin'),
|
|
||||||
('Edit sidebar content', '/settings/sidebar_content', 'comment', 'sidebar', 'admin'),
|
|
||||||
('Edit footer content', '/settings/footer_content', 'comment', 'sidebar', 'admin'),
|
|
||||||
|
|
||||||
('Go home', '/', 'home', 'footer', ''),
|
|
||||||
('Search', '/search', 'search', 'footer', '')"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
class BootstrapRender
|
|
||||||
{
|
|
||||||
public static function message()
|
|
||||||
{
|
|
||||||
if (func_num_args() > 0)
|
|
||||||
{
|
|
||||||
Cookie::set("message", func_get_arg(0));
|
|
||||||
|
|
||||||
if (func_num_args() > 1)
|
|
||||||
Cookie::set("messageClass", func_get_arg(1));
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$strMessage = Cookie::get("message");
|
|
||||||
$strMessageClass = Cookie::get("messageClass");
|
|
||||||
|
|
||||||
if (!isset($strMessageClass) || $strMessageClass == null || strlen($strMessageClass) < 1)
|
|
||||||
$strMessageClass = "info";
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div id="page-message-container">
|
|
||||||
<?php if (isset($strMessage) && $strMessage !== null && strlen($strMessage) > 0): ?>
|
|
||||||
<div class="alert alert-<?= $strMessageClass; ?> d-none" id="page-message">
|
|
||||||
<?= $strMessage; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
$("#page-message")
|
|
||||||
.hide()
|
|
||||||
.removeClass("d-none")
|
|
||||||
.fadeIn();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
BootstrapRender = {};
|
|
||||||
|
|
||||||
BootstrapRender.message = function(message, messageClass = "info") {
|
|
||||||
var messageElem = $("<div></div>");
|
|
||||||
|
|
||||||
messageElem.addClass(`alert alert-${messageClass} d-none`);
|
|
||||||
messageElem.attr("id", "page-message");
|
|
||||||
messageElem.html(message);
|
|
||||||
|
|
||||||
$("#page-message-container")
|
|
||||||
.empty()
|
|
||||||
.append(messageElem);
|
|
||||||
|
|
||||||
messageElem
|
|
||||||
.hide()
|
|
||||||
.removeClass("d-none")
|
|
||||||
.fadeIn();
|
|
||||||
|
|
||||||
return messageElem;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
Cookie::set("message");
|
|
||||||
Cookie::set("messageClass");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function input($varOptions)
|
|
||||||
{
|
|
||||||
$varOptions["tag"] = $varOptions["tag"] ?? "input";
|
|
||||||
$varOptionsExtras = $varOptions;
|
|
||||||
$varDefaultKeys = ["tag", "label", "name", "type", "value", "hint"];
|
|
||||||
|
|
||||||
foreach ($varDefaultKeys as $k)
|
|
||||||
if (array_key_exists($k, $varOptionsExtras))
|
|
||||||
unset($varOptionsExtras[$k]);
|
|
||||||
?>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label"><?= $varOptions["label"] ?? $varOptions["name"] ?? "input"; ?></label>
|
|
||||||
<<?= $varOptions["tag"]; ?>
|
|
||||||
type="<?= $varOptions["type"] ?? "text"; ?>"
|
|
||||||
class="form-control"
|
|
||||||
name="<?= $varOptions["name"] ?? "text"; ?>"
|
|
||||||
placeholder="Enter <?= $varOptions["label"] ?? "value"; ?>"
|
|
||||||
<?php if ($varOptions["tag"] !== "textarea"): ?>
|
|
||||||
value="<?= $varOptions["value"] ?? ""; ?>"
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php foreach ($varOptionsExtras as $k => $v): ?>
|
|
||||||
<?= $k; ?>="<?= $v; ?>"
|
|
||||||
<?php endforeach; ?>
|
|
||||||
/><?= $varOptions["tag"] == "textarea"? "{$varOptions["value"]}</textarea>" : ""; ?>
|
|
||||||
<small class="text-muted"><?= $varOptions["hint"] ?? ""; ?></small>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function button($varOptions)
|
|
||||||
{
|
|
||||||
$varOptions["tag"] = $varOptions["tag"] ?? "a";
|
|
||||||
$varOptionsExtras = $varOptions;
|
|
||||||
$varDefaultKeys = ["tag", "label", "name", "type", "value", "hint"];
|
|
||||||
|
|
||||||
foreach ($varDefaultKeys as $k)
|
|
||||||
if (array_key_exists($k, $varOptionsExtras))
|
|
||||||
unset($varOptionsExtras[$k]);
|
|
||||||
?>
|
|
||||||
<<?= $varOptions["tag"]; ?>
|
|
||||||
class="btn btn-<?= $varOptions["class"] ?? "secondary"; ?>"
|
|
||||||
<?php foreach ($varOptionsExtras as $k => $v): ?>
|
|
||||||
<?= $k; ?>="<?= $v; ?>"
|
|
||||||
<?php endforeach; ?>
|
|
||||||
>
|
|
||||||
<?php if (array_key_exists("icon", $varOptions)): ?>
|
|
||||||
<i class="fa fa-fw fa-<?= $varOptions["icon"]; ?>"></i>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?= $varOptions["label"] ?? "Button"; ?>
|
|
||||||
</<?= $varOptions["tag"]; ?>>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function buttons($varButtons)
|
|
||||||
{
|
|
||||||
?>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Actions</label>
|
|
||||||
<div>
|
|
||||||
<?php foreach ($varButtons as $b): ?>
|
|
||||||
<?php BootstrapRender::button($b); ?>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
69
lib/PageRender.php
Normal file
69
lib/PageRender.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
class PageRender
|
||||||
|
{
|
||||||
|
public static function message()
|
||||||
|
{
|
||||||
|
if (func_num_args() > 0)
|
||||||
|
{
|
||||||
|
Cookie::set("message", func_get_arg(0));
|
||||||
|
|
||||||
|
if (func_num_args() > 1)
|
||||||
|
Cookie::set("messageClass", func_get_arg(1));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$strMessage = Cookie::get("message");
|
||||||
|
$strMessageClass = Cookie::get("messageClass");
|
||||||
|
|
||||||
|
if (!isset($strMessageClass) || $strMessageClass == null || strlen($strMessageClass) < 1)
|
||||||
|
$strMessageClass = "info";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if (isset($strMessage) && $strMessage !== null && strlen($strMessage) > 0): ?>
|
||||||
|
<p class="message message-<?= $strMessageClass; ?>">
|
||||||
|
<?= $strMessage; ?>
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
Cookie::set("message");
|
||||||
|
Cookie::set("messageClass");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function uploads()
|
||||||
|
{
|
||||||
|
$varUploads = [];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$varUploads = scandir("files");
|
||||||
|
|
||||||
|
if ($varUploads !== false)
|
||||||
|
{
|
||||||
|
$varUploads = array_diff($varUploads, [".", ".."]);
|
||||||
|
rsort($varUploads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $x) {}
|
||||||
|
$varUploads = array_slice($varUploads, 0, 20);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="uploads">
|
||||||
|
<div>
|
||||||
|
<label>Uploads</label>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/upload" target="_blank">Manage</a></li>
|
||||||
|
<?php foreach ($varUploads as $u): ?>
|
||||||
|
<li><a href="/files/<?= $u; ?>" target="_blank">/files/<?= $u; ?></a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
@ -8,60 +8,47 @@
|
|||||||
$intRenderedRows = 0;
|
$intRenderedRows = 0;
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<style>
|
<div class="post-container">
|
||||||
<?php
|
<?php foreach ($varRows as $r): ?>
|
||||||
echo Settings::get(
|
<?php if (!UserAuth::visible($r["visibility"])) continue; ?>
|
||||||
"css",
|
|
||||||
"/* Put in your custom CSS here: */\nblockquote {\n padding: 1em;\n background:\n rgba(127, 127, 127, 0.2);\n border-left: 3px solid rgba(127, 127, 127, 0.2); \n}",
|
|
||||||
true);
|
|
||||||
?>
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<?php foreach ($varRows as $r): ?>
|
<?php if ($intRenderedRows > 0): ?>
|
||||||
<?php if (!UserAuth::visible($r["visibility"])) continue; ?>
|
<hr />
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="container my-5">
|
<div class="post">
|
||||||
<div class="row">
|
<div class="post-body">
|
||||||
<div class="col-lg-8">
|
<?php echo $varParsedown->text($r["content"]); ?>
|
||||||
<div class="xborder xborder-secondary xrounded xp-3">
|
</div>
|
||||||
<?php echo $varParsedown->text($r["content"]); ?>
|
|
||||||
|
<div class="post-footer">
|
||||||
|
<div class="post-author">by <?= $r["username"]; ?></div>
|
||||||
|
<div class="post-date">on <?= $r["created"]; ?> UTC</div>
|
||||||
|
|
||||||
|
<div class="post-links">
|
||||||
|
<a href="/<?= $r["id"]; ?>">Permalink</a> ·
|
||||||
|
<a href="<?= $r["location"]; ?>">Related</a>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$intOwnership =
|
||||||
|
UserAuth::has("is_admin") ||
|
||||||
|
$varUser["username"] == $r["username"];
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($intOwnership): ?>
|
||||||
|
· <a href="/post/<?= $r["id"]; ?>">Edit</a>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
|
||||||
<div class="text-muted">
|
|
||||||
<div>by <?= $r["username"]; ?></div>
|
|
||||||
<div>on <?= $r["created"]; ?> UTC</div>
|
|
||||||
</div>
|
|
||||||
<?php if (UserAuth::has("is_admin")): ?>
|
|
||||||
<div>
|
|
||||||
<a class="link-underline link-underline-opacity-0" href="/post/<?= $r["id"]; ?>"><i class="fa fa-fw fa-edit"></i> Edit</a>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php $intRenderedRows++; ?>
|
<?php $intRenderedRows++; ?>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php if ($intRenderedRows < 1): ?>
|
|
||||||
<div class="container my-5">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8">
|
|
||||||
<p>Sorry, there is nothing here to show.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
<?php
|
|
||||||
echo Settings::get(
|
|
||||||
"js",
|
|
||||||
"$(function() {\n // My script here.\n});",
|
|
||||||
true);
|
|
||||||
?>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
<?php if ($intRenderedRows < 1): ?>
|
||||||
|
<div>Sorry, there is nothing here to show.</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,264 +0,0 @@
|
|||||||
<?php
|
|
||||||
class TableEditor
|
|
||||||
{
|
|
||||||
public static function render($strTableName, $varColumns)
|
|
||||||
{
|
|
||||||
global $c;
|
|
||||||
|
|
||||||
$varRows = [];
|
|
||||||
$varKeys = [];
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$varRows = $c->query("SELECT * from {$strTableName} order by sort asc");
|
|
||||||
}
|
|
||||||
catch (Exception $x)
|
|
||||||
{
|
|
||||||
$varRows = $c->query("SELECT * from {$strTableName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$strInput = file_get_contents("php://input");
|
|
||||||
|
|
||||||
if (strlen($strInput) > 0)
|
|
||||||
{
|
|
||||||
$a = json_decode($strInput, true);
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
foreach ($a as $r)
|
|
||||||
{
|
|
||||||
$strColumns = "";
|
|
||||||
$strQMarks = "";
|
|
||||||
$strSetLns = "";
|
|
||||||
$varValues = [];
|
|
||||||
|
|
||||||
foreach ($varColumns as $strCol)
|
|
||||||
{
|
|
||||||
$strColumns .= "{$strCol}, ";
|
|
||||||
$strQMarks .= "?, ";
|
|
||||||
$strSetLns .= "{$strCol} = ?, ";
|
|
||||||
$varValues[] = $r[$strCol];
|
|
||||||
}
|
|
||||||
|
|
||||||
$strColumns = preg_replace("/, $/", "", $strColumns);
|
|
||||||
$strQMarks = preg_replace("/, $/", "", $strQMarks);
|
|
||||||
$strSetLns = preg_replace("/, $/", "", $strSetLns);
|
|
||||||
|
|
||||||
if (strlen($r["id"]) < 1)
|
|
||||||
{
|
|
||||||
$c->query(
|
|
||||||
"INSERT into {$strTableName} ({$strColumns}) values ({$strQMarks})",
|
|
||||||
$varValues);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intval($r["delete"]) == 1)
|
|
||||||
{
|
|
||||||
$c->query("DELETE from {$strTableName} where id = ?", $r["id"]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$c->query(
|
|
||||||
"UPDATE {$strTableName}
|
|
||||||
set {$strSetLns}
|
|
||||||
where id = ?",
|
|
||||||
$varValues,
|
|
||||||
$r["id"]);
|
|
||||||
|
|
||||||
$output[] = $r;
|
|
||||||
}
|
|
||||||
|
|
||||||
Respond::json(["message" => "success", "output" => $output]);
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
|
||||||
|
|
||||||
<div class="container justify-content-between">
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
<span class="navbar-brand">Options</span>
|
|
||||||
<a class="btn btn-outline-success" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* https://github.com/twbs/bootstrap/issues/37184 */
|
|
||||||
.dropdown-menu {
|
|
||||||
z-index: 1040 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
th:first-child,
|
|
||||||
th:last-child {
|
|
||||||
width: 7.5%;
|
|
||||||
background: #F00 !important;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
overflow-x: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-input {
|
|
||||||
width: 15em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr td:first-child input[type="text"]
|
|
||||||
{
|
|
||||||
width: 5em !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row my-5">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
|
|
||||||
<?php if (count($varRows) > 0): ?>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-borderless">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<?php foreach($varRows[0] as $k => $v): ?>
|
|
||||||
<?php
|
|
||||||
if ($k == "sort")
|
|
||||||
continue;
|
|
||||||
$varKeys[] = $k;
|
|
||||||
?>
|
|
||||||
<th><?= $k; ?></th>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($varRows as $r): ?>
|
|
||||||
<tr>
|
|
||||||
<?php foreach ($varKeys as $k): ?>
|
|
||||||
<td>
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control w-input" name="<?= $k; ?>" value="<?= $r[$k]; ?>" />
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
|
|
||||||
<td class="align-middle text-nowrap">
|
|
||||||
<input type="hidden" name="delete" value="0" />
|
|
||||||
<a class="" onclick="fnCloneRow(this);"><i class="fa fa-fw fa-copy"></i></a>
|
|
||||||
<a class="" onclick="fnDeleteRow(this);"><i class="fa fa-fw fa-trash"></i></a>
|
|
||||||
|
|
||||||
<?php if (in_array("sort", $varColumns)): ?>
|
|
||||||
<a class="" onclick="fnMoveRowUp(this);"><i class="fa fa-fw fa-arrow-up"></i></a>
|
|
||||||
<a class="" onclick="fnMoveRowDown(this);"><i class="fa fa-fw fa-arrow-down"></i></a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
$("[name='id']").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
x.attr("readonly", 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
fnSerialize = function() {
|
|
||||||
var a = [];
|
|
||||||
|
|
||||||
var sort = 0;
|
|
||||||
|
|
||||||
$("table tbody tr").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
var inputs = x.find("input");
|
|
||||||
var o = {};
|
|
||||||
|
|
||||||
inputs.each(function(i2, x2) {
|
|
||||||
x2 = $(x2);
|
|
||||||
var key = x2.attr("name");
|
|
||||||
var value = x2.val();
|
|
||||||
o[key] = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
o["sort"] = sort;
|
|
||||||
|
|
||||||
a.push(o);
|
|
||||||
sort++;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(a);
|
|
||||||
return a;
|
|
||||||
};
|
|
||||||
|
|
||||||
fnSave = function()
|
|
||||||
{
|
|
||||||
var data = fnSerialize();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "",
|
|
||||||
method: "post",
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
success: function(r)
|
|
||||||
{
|
|
||||||
console.log(r);
|
|
||||||
window.location.href = window.location.href;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fnCloneRow = function(x)
|
|
||||||
{
|
|
||||||
x = $(x);
|
|
||||||
var row = x.parents("tr").first();
|
|
||||||
|
|
||||||
var rowCopy = row.clone();
|
|
||||||
|
|
||||||
rowCopy.insertAfter(row);
|
|
||||||
|
|
||||||
rowCopy.find("input").each(function(i, x2) {
|
|
||||||
x2 = $(x2);
|
|
||||||
x2.val("");
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fnDeleteRow = function(x)
|
|
||||||
{
|
|
||||||
x = $(x);
|
|
||||||
var row = x.parents("tr").first();
|
|
||||||
row.hide();
|
|
||||||
row.find("[name='delete']").first().val("1");
|
|
||||||
};
|
|
||||||
|
|
||||||
fnMoveRowUp = function(x)
|
|
||||||
{
|
|
||||||
x = $(x);
|
|
||||||
var row = x.parents("tr").first();
|
|
||||||
row.insertBefore(row.prev());
|
|
||||||
}
|
|
||||||
|
|
||||||
fnMoveRowDown = function(x)
|
|
||||||
{
|
|
||||||
x = $(x);
|
|
||||||
var row = x.parents("tr").first();
|
|
||||||
row.insertAfter(row.next());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
@ -50,7 +50,7 @@
|
|||||||
{
|
{
|
||||||
if (!UserAuth::has($strColumnName))
|
if (!UserAuth::has($strColumnName))
|
||||||
{
|
{
|
||||||
BootstrapRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
|
PageRender::message("You do not have permission to do that, please sign into an account that does.", "warning");
|
||||||
Respond::redirect("/user/signin");
|
Respond::redirect("/user/signin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,6 +82,9 @@
|
|||||||
$strVisibility = $strVisibility["visibility"];
|
$strVisibility = $strVisibility["visibility"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($strVisibility == null)
|
||||||
|
$strVisibility = "";
|
||||||
|
|
||||||
// Handle hiding the post from non-admins:
|
// Handle hiding the post from non-admins:
|
||||||
if (preg_match("/^(admin|hid(e|den)|invisible|no(ne|body)|private)$/i", $strVisibility))
|
if (preg_match("/^(admin|hid(e|den)|invisible|no(ne|body)|private)$/i", $strVisibility))
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,46 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
global $c;
|
global $c;
|
||||||
$varPostLocations = $c->query("SELECT distinct location from posts order by location");
|
$varPostLocations = $c->query("SELECT distinct location from posts order by location");
|
||||||
$varLinks = $c->query("SELECT * from links order by sort");
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
<div>
|
||||||
<div class="container justify-content-between">
|
<label>Directory</label>
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
|
||||||
<span class="navbar-brand">Directory</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container my-5">
|
<ul>
|
||||||
<div class="row mb-4">
|
<?php foreach ($varPostLocations as $i): ?>
|
||||||
<div class="col-lg-6">
|
<?php
|
||||||
<h5 class="mb-3"><i class="fa fa-fw fa-comment pe-2"></i> Posts</h5>
|
$intPostCount = $c->query("SELECT count(*) as c from posts where location = ?", $i["location"])[0]["c"];
|
||||||
<?php foreach ($varPostLocations as $i): ?>
|
?>
|
||||||
<?php
|
<li><a href="<?= $i["location"]; ?>"><?= $i["location"]; ?></a> <small>— <?= $intPostCount !== 1? "{$intPostCount} posts": "{$intPostCount} post"; ?></small></li>
|
||||||
$intPostCount = $c->query("SELECT count(*) as c from posts where location = ?", $i["location"])[0]["c"];
|
<?php endforeach; ?>
|
||||||
?>
|
</ul>
|
||||||
<div class="border p-2 mb-2">
|
|
||||||
<a class="link-underline link-underline-opacity-0" href="<?= $i["location"]; ?>"><i class="fa fa-fw fa-file pe-2"></i> <?= $i["location"]; ?></a>
|
|
||||||
<small class="text-muted">— <?= $intPostCount !== 1? "{$intPostCount} posts": "{$intPostCount} post"; ?></small>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row mb-4">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<h5 class="mb-3"><i class="fa fa-fw fa-link pe-2"></i> Links</h5>
|
|
||||||
<?php foreach ($varLinks as $i): ?>
|
|
||||||
<?php if (!UserAuth::visible($i["visibility"])) continue; ?>
|
|
||||||
<div class="border p-2 mb-2">
|
|
||||||
<a class="link-underline link-underline-opacity-0" href="<?= $i["url"]; ?>"><i class="fa fa-fw fa-<?= $i["icon"]; ?> pe-2"></i> <?= $i["label"]; ?></a>
|
|
||||||
<small class="text-muted">— <?= $i["position"]; ?></small>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
59
pages/edit.php
Normal file
59
pages/edit.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
global $c;
|
||||||
|
|
||||||
|
UserAuth::require("is_admin");
|
||||||
|
|
||||||
|
$varUser = UserAuth::getUser();
|
||||||
|
$strId = Request::getArg(0);
|
||||||
|
|
||||||
|
// if ($strId == null || strlen($strId) < 1)
|
||||||
|
// $strId = "none";
|
||||||
|
|
||||||
|
if (Request::posts("content"))
|
||||||
|
Settings::set($strId, Request::getPosted("content"));
|
||||||
|
|
||||||
|
$strContent = Settings::get($strId, "");
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($strId == null || strlen($strId) < 1): ?>
|
||||||
|
<?php $varRows = Settings::get(); ?>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label>Edit</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<?php foreach ($varRows as $k => $v): ?>
|
||||||
|
<li><a href="/edit/<?= $k; ?>"><?= $k; ?></a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
textarea {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div>
|
||||||
|
<label><?= $strId; ?></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<textarea
|
||||||
|
class="form-control border-0 shadow-none"
|
||||||
|
name="content"
|
||||||
|
placeholder="Enter content here..."
|
||||||
|
oninput="fnResize(this);"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
spellcheck="false"><?= $strContent; ?></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div><input type="submit" value="Save" /></div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
UserAuth::require("is_admin");
|
|
||||||
TableEditor::render("links", ["label", "url", "icon", "position", "visibility", "sort"]);
|
|
||||||
?>
|
|
@ -1,71 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
|
|
||||||
UserAuth::require("is_admin");
|
|
||||||
|
|
||||||
$varUser = UserAuth::getUser();
|
|
||||||
$strId = Request::getArg(0);
|
|
||||||
|
|
||||||
if ($strId == null || strlen($strId) < 1)
|
|
||||||
$strId = "none";
|
|
||||||
|
|
||||||
if (Request::posts("content"))
|
|
||||||
Settings::set($strId, Request::getPosted("content"));
|
|
||||||
|
|
||||||
$strContent = Settings::get($strId, "");
|
|
||||||
?>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
textarea {
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<form method="post">
|
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
|
||||||
<div class="container justify-content-between">
|
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
|
||||||
<span class="navbar-brand">Setting</span>
|
|
||||||
|
|
||||||
<span class="nav-item text-nowrap me-2">Name</span>
|
|
||||||
<input class="form-control me-2" type="text" name="location" value="<?= $strId; ?>" readonly disabled />
|
|
||||||
|
|
||||||
<a class="btn btn-outline-success text-nowrap" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
<?php BootstrapRender::message(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php /**/ ?>
|
|
||||||
<div class="container my-5">
|
|
||||||
<div class="row">
|
|
||||||
<textarea
|
|
||||||
class="form-control border-0 shadow-none"
|
|
||||||
name="content"
|
|
||||||
placeholder="Enter content here..."
|
|
||||||
oninput="fnResize(this);"
|
|
||||||
autocomplete="off"
|
|
||||||
autocorrect="off"
|
|
||||||
autocapitalize="off"
|
|
||||||
spellcheck="false"><?= $strContent; ?></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
fnSave = function() {
|
|
||||||
$("form").first().submit();
|
|
||||||
};
|
|
||||||
|
|
||||||
fnResize = function(x) {
|
|
||||||
x.style.height = "auto";
|
|
||||||
x.style.height = x.scrollHeight + "px";
|
|
||||||
};
|
|
||||||
|
|
||||||
fnResize($("textarea").first()[0]);
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,163 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
|
|
||||||
UserAuth::require("is_admin");
|
|
||||||
|
|
||||||
$varUser = UserAuth::getUser();
|
|
||||||
$varRows = Settings::get();
|
|
||||||
|
|
||||||
$strInput = file_get_contents("php://input");
|
|
||||||
|
|
||||||
if (strlen($strInput) > 0)
|
|
||||||
{
|
|
||||||
$a = json_decode($strInput, true);
|
|
||||||
$output = [];
|
|
||||||
|
|
||||||
foreach ($a as $r)
|
|
||||||
{
|
|
||||||
$strSetting = $r["setting"];
|
|
||||||
$strValue = $r["value"];
|
|
||||||
Settings::set($strSetting, $strValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Respond::json(["message" => "success", "output" => $output]);
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
|
||||||
|
|
||||||
<div class="container justify-content-between">
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
<span class="navbar-brand">Options</span>
|
|
||||||
<a class="btn btn-outline-success" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* https://github.com/twbs/bootstrap/issues/37184 */
|
|
||||||
.dropdown-menu {
|
|
||||||
z-index: 1040 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
th:first-child,
|
|
||||||
th:last-child {
|
|
||||||
width: 7.5%;
|
|
||||||
background: #F00 !important;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.w-1 { width: 1%; }
|
|
||||||
|
|
||||||
.table-responsive {
|
|
||||||
overflow-x: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-input {
|
|
||||||
width: 15em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr td:first-child input[type="text"]
|
|
||||||
{
|
|
||||||
width: 5em !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row my-5">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<?php if (count($varRows) > 0): ?>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-borderless">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Setting</th>
|
|
||||||
<th>Value<th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($varRows as $k => $v): ?>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control w-input" name="setting" value="<?= $k; ?>" />
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<?php
|
|
||||||
$strClass = "";
|
|
||||||
if (preg_match("/\n/", $v))
|
|
||||||
$strClass = "disabled readonly";
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control w-input <?= $strClass; ?>" name="value" value="<?= $v; ?>" <?= $strClass; ?> />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<small>
|
|
||||||
<a class="link-underline link-underline-opacity-0" href="/edit/setting/<?= $k; ?>">Edit in multi-line editor</a>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
$("[name='setting']").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
x.attr("readonly", 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
fnSerialize = function() {
|
|
||||||
var a = [];
|
|
||||||
$("table tbody tr").each(function(i, x) {
|
|
||||||
x = $(x);
|
|
||||||
|
|
||||||
var valueInput = x.find("[name='value']").first();
|
|
||||||
var o = {};
|
|
||||||
|
|
||||||
o["setting"] = x.find("[name='setting']").first().val().trim();
|
|
||||||
o["value"] = valueInput.val();
|
|
||||||
|
|
||||||
if (valueInput.attr("disabled"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
a.push(o);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(a);
|
|
||||||
return a;
|
|
||||||
};
|
|
||||||
|
|
||||||
fnSave = function()
|
|
||||||
{
|
|
||||||
var data = fnSerialize();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "",
|
|
||||||
method: "post",
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
success: function(r)
|
|
||||||
{
|
|
||||||
console.log(r);
|
|
||||||
window.location.href = window.location.href;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
82
pages/find.php
Normal file
82
pages/find.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
global $c;
|
||||||
|
|
||||||
|
$strPath = "/";
|
||||||
|
$strPath .= implode("/", Request::getPathParts());
|
||||||
|
|
||||||
|
$varPosts = [];
|
||||||
|
$strQuery = Request::getParam("q");
|
||||||
|
$strAuthor = Request::getParam("username");
|
||||||
|
$strId = Request::getParam("id");
|
||||||
|
|
||||||
|
$intHasQuery = $strQuery !== null && strlen($strQuery) > 0;
|
||||||
|
$intHasAuthor = $strAuthor !== null && strlen($strAuthor) > 0;
|
||||||
|
$intHasId = $strId !== null && strlen($strId) > 0;
|
||||||
|
|
||||||
|
if ($intHasQuery)
|
||||||
|
{
|
||||||
|
$strQuery = preg_replace("/[^A-Za-z0-9]/", "", $strQuery);
|
||||||
|
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from posts as p
|
||||||
|
where
|
||||||
|
content like concat('%', ?, '%')
|
||||||
|
order by
|
||||||
|
created desc",
|
||||||
|
$strQuery);
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
for ($i = 0; $i < count($varPosts); $i++)
|
||||||
|
{
|
||||||
|
$varOld = $varPosts[$i];
|
||||||
|
$varOld["content"] = preg_replace("/({$strQuery})/i", "<mark>$1</mark>", $varOld["content"]);
|
||||||
|
$varPosts[$i] = $varOld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($intHasAuthor)
|
||||||
|
{
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from posts as p
|
||||||
|
where
|
||||||
|
username like ?
|
||||||
|
order by
|
||||||
|
created desc",
|
||||||
|
$strAuthor);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($intHasId)
|
||||||
|
{
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from posts as p
|
||||||
|
where
|
||||||
|
id = ?
|
||||||
|
order by
|
||||||
|
created desc",
|
||||||
|
$strId);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if (!$intHasAuthor && !$intHasId): ?>
|
||||||
|
<form method="get">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><label>Search</label></td>
|
||||||
|
<td><input type="text" name="q" value="<?= $strQuery; ?>" /></td>
|
||||||
|
<td>
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($intHasQuery || $intHasAuthor || $intHasId): ?>
|
||||||
|
<?php PostRender::rows($varPosts); ?>
|
||||||
|
<?php endif; ?>
|
@ -1,18 +1,48 @@
|
|||||||
<?php
|
<?php
|
||||||
global $c;
|
global $c;
|
||||||
|
|
||||||
$strPath = "/";
|
$strArg1 = substr(Request::getPath(), 1);
|
||||||
$strPath .= implode("/", Request::getPathParts());
|
$varPosts = [];
|
||||||
|
|
||||||
$varPosts = $c->query(
|
// Get one post by its id:
|
||||||
"SELECT *
|
if (preg_match("/^[0-9]{1,}$/", $strArg1))
|
||||||
from posts as p
|
{
|
||||||
where
|
$varPosts = $c->query(
|
||||||
location like ?
|
"SELECT *
|
||||||
or location like '*'
|
from posts as p
|
||||||
order by
|
where
|
||||||
created desc",
|
id = ?
|
||||||
$strPath);
|
order by
|
||||||
|
created desc",
|
||||||
|
intval($strArg1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get many post by its author:
|
||||||
|
if (preg_match("/^\@[A-Za-z0-9]{1,}$/", $strArg1))
|
||||||
|
{
|
||||||
|
$strArg1 = substr($strArg1, 1);
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from posts as p
|
||||||
|
where
|
||||||
|
username like ?
|
||||||
|
order by
|
||||||
|
created desc",
|
||||||
|
$strArg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($varPosts) < 1)
|
||||||
|
{
|
||||||
|
$varPosts = $c->query(
|
||||||
|
"SELECT *
|
||||||
|
from posts as p
|
||||||
|
where
|
||||||
|
location like ?
|
||||||
|
or location like '*'
|
||||||
|
order by
|
||||||
|
created desc",
|
||||||
|
Request::getPath());
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<?php PostRender::rows($varPosts); ?>
|
<?php PostRender::rows($varPosts); ?>
|
||||||
|
152
pages/post.php
152
pages/post.php
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
if (count($varRows) !== 1)
|
if (count($varRows) !== 1)
|
||||||
{
|
{
|
||||||
BootstrapRender::message("Zero or more than one row returned", "danger");
|
PageRender::message("Zero or more than one row returned", "danger");
|
||||||
Respond::redirect("/post");
|
Respond::redirect("/post");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +26,13 @@
|
|||||||
$strContent = $varRow["content"];
|
$strContent = $varRow["content"];
|
||||||
$strLocation = $varRow["location"];
|
$strLocation = $varRow["location"];
|
||||||
$strVisibility = $varRow["visibility"];
|
$strVisibility = $varRow["visibility"];
|
||||||
|
|
||||||
|
if (!UserAuth::has("is_admin"))
|
||||||
|
if ($varUser["username"] !== $varRow["username"])
|
||||||
|
{
|
||||||
|
PageRender::message("You are not the author of that post.");
|
||||||
|
Respond::redirect("/post");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,12 +53,15 @@
|
|||||||
$strVisibility);
|
$strVisibility);
|
||||||
|
|
||||||
$strId = $c->query("get_last_post.sql")[0]["id"];
|
$strId = $c->query("get_last_post.sql")[0]["id"];
|
||||||
|
|
||||||
|
PageRender::message("Post created.", "success");
|
||||||
|
Respond::redirect("/{$strId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($strContent) < 1)
|
if (strlen($strContent) < 1)
|
||||||
{
|
{
|
||||||
$c->query("DELETE from posts where id = ?", $strId);
|
$c->query("DELETE from posts where id = ?", $strId);
|
||||||
BootstrapRender::message("Post deleted successfully.", "success");
|
PageRender::message("Post deleted successfully.", "success");
|
||||||
Respond::redirect("/post");
|
Respond::redirect("/post");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,11 +79,13 @@
|
|||||||
$strVisibility,
|
$strVisibility,
|
||||||
$strId);
|
$strId);
|
||||||
|
|
||||||
BootstrapRender::message("Post saved.", "success");
|
PageRender::message("Post saved.", "success");
|
||||||
Respond::redirect("/post/{$strId}");
|
Respond::redirect("/post/{$strId}");
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php PageRender::message(); ?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
textarea {
|
textarea {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
@ -81,102 +93,54 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
<div>
|
||||||
<div class="container justify-content-between">
|
<div>
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
<label>Content</label>
|
||||||
<span class="navbar-brand"><?= $strVerb; ?> Post</span>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
|
<textarea
|
||||||
<div class="navbar-nav d-inline-flex">
|
name="content"
|
||||||
</div>
|
placeholder="Enter markdown content here..."
|
||||||
|
><?= $strContent; ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container my-5">
|
<div>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><label>Location</label></td>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="location"
|
||||||
|
placeholder="/"
|
||||||
|
value="<?= $strLocation; ?>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="row">
|
<tr>
|
||||||
<div class="col-lg-3">
|
<td><label>Visible To</label></td>
|
||||||
<?php BootstrapRender::message(); ?>
|
<td>
|
||||||
</div>
|
<input
|
||||||
|
type="text"
|
||||||
|
name="visibility"
|
||||||
|
placeholder="everyone"
|
||||||
|
value="<?= $strVisibility; ?>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="col-lg-12">
|
<tr>
|
||||||
<div class="mb-3">
|
<td></td>
|
||||||
<label class="form-label">Content</label>
|
<td>
|
||||||
<textarea
|
<input
|
||||||
class="form-control"
|
type="submit"
|
||||||
name="content"
|
value="Go" />
|
||||||
placeholder="Enter markdown content here..."
|
</td>
|
||||||
oninput="fnResize(this);"
|
</tr>
|
||||||
><?= $strContent; ?></textarea>
|
</tbody>
|
||||||
<small class="text-muted">Test</small>
|
</table>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-3">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Location</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
name="location"
|
|
||||||
placeholder="/"
|
|
||||||
value="<?= $strLocation; ?>"
|
|
||||||
fv-regex="^\/"
|
|
||||||
fv-warning="Location must start with a forward slash" />
|
|
||||||
<small class="text-muted">e.g. /home or /info</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-3">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Visible To</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
name="visibility"
|
|
||||||
placeholder="everyone"
|
|
||||||
value="<?= $strVisibility; ?>"
|
|
||||||
fv-regex="^(|everyone|users|admins)$"
|
|
||||||
fv-warning="Visibility must be empty, everyone, users, or admins" />
|
|
||||||
<small class="text-muted">e.g. everyone, users, admins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-lg-3">
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Actions</label>
|
|
||||||
<div>
|
|
||||||
<?php if ($strId == null || strlen($strId) < 1): ?>
|
|
||||||
<a class="btn btn-primary" onclick="fnSave();"><i class="fa fa-fw fa-paper-plane"></i> Submit</a>
|
|
||||||
<?php else: ?>
|
|
||||||
<a class="btn btn-success" onclick="fnSave();"><i class="fa fa-fw fa-save"></i> Save</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<script>
|
<?php PageRender::uploads(); ?>
|
||||||
$(function() {
|
|
||||||
fnSave = function() {
|
|
||||||
FormValidator.onError = function(str)
|
|
||||||
{
|
|
||||||
BootstrapRender.message(str, "danger");
|
|
||||||
};
|
|
||||||
|
|
||||||
FormValidator.validate(function() {
|
|
||||||
$("form").first().submit();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
fnResize = function(x) {
|
|
||||||
x.style.minHeight = "2in";
|
|
||||||
x.style.height = "auto";
|
|
||||||
x.style.height = x.scrollHeight + "px";
|
|
||||||
};
|
|
||||||
|
|
||||||
fnResize($("textarea").first()[0]);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
|
|
||||||
$strPath = "/";
|
|
||||||
$strPath .= implode("/", Request::getPathParts());
|
|
||||||
|
|
||||||
$varPosts = [];
|
|
||||||
$strQuery = Request::getParam("q");
|
|
||||||
|
|
||||||
if ($strQuery !== null && strlen($strQuery) > 0)
|
|
||||||
{
|
|
||||||
$varPosts = $c->query(
|
|
||||||
"SELECT *
|
|
||||||
from posts as p
|
|
||||||
where
|
|
||||||
content like concat('%', ?, '%')
|
|
||||||
order by
|
|
||||||
created desc",
|
|
||||||
$strQuery);
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
for ($i = 0; $i < count($varPosts); $i++)
|
|
||||||
{
|
|
||||||
$varOld = $varPosts[$i];
|
|
||||||
$varOld["content"] = preg_replace("/({$strQuery})/i", "<mark>$1</mark>", $varOld["content"]);
|
|
||||||
$varPosts[$i] = $varOld;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<form method="get">
|
|
||||||
<div class="navbar navbar-expand bg-body-tertiary d-flex px-3 sticky-top">
|
|
||||||
<div class="container justify-content-between">
|
|
||||||
<div class="navbar-nav d-inline-flex align-items-center">
|
|
||||||
<span class="navbar-brand">Search</span>
|
|
||||||
<input class="form-control me-2" type="text" name="q" value="<?= $strQuery; ?>" />
|
|
||||||
|
|
||||||
<button type="submit" class="btn btn-outline-info text-nowrap"><i class="fa fa-fw fa-search"></i> Go</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="navbar-nav d-inline-flex"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<?php BootstrapRender::message(); ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php PostRender::rows($varPosts); ?>
|
|
65
pages/upload.php
Normal file
65
pages/upload.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
UserAuth::require("is_admin");
|
||||||
|
|
||||||
|
if (isset($_FILES["file"]))
|
||||||
|
{
|
||||||
|
$varFile = $_FILES["file"];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$strUploadName = basename($varFile["name"]);
|
||||||
|
$strUploadName = preg_replace("/ /", "_", $strUploadName);
|
||||||
|
$strUploadName = preg_replace("/[^A-Za-z0-9_\-\.]/", "", $strUploadName);
|
||||||
|
$strTimestamp = date("YmdHis");
|
||||||
|
$strDestinationPath = "files/{$strTimestamp}_{$strUploadName}";
|
||||||
|
$intAllow = 0;
|
||||||
|
|
||||||
|
// Check file size (optional)
|
||||||
|
if ($varFile["size"] > 1024 * 1024 * 5)
|
||||||
|
throw new Exception("Upload exceeds maximum file size.");
|
||||||
|
|
||||||
|
if (file_exists($strDestinationPath))
|
||||||
|
throw new Exception("Destination file already exists.");
|
||||||
|
|
||||||
|
foreach (["/\.jpg$/", "/\.png$/"] as $strExtension)
|
||||||
|
if (preg_match_all($strExtension, $strDestinationPath))
|
||||||
|
$intAllow = 1;
|
||||||
|
|
||||||
|
if ($intAllow == 0)
|
||||||
|
throw new Exception("File type not allowed.");
|
||||||
|
|
||||||
|
$intResult = move_uploaded_file($varFile["tmp_name"], $strDestinationPath);
|
||||||
|
|
||||||
|
if (!$intResult)
|
||||||
|
throw new Exception("Problem uploading file.");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception $x)
|
||||||
|
{
|
||||||
|
PageRender::message($x->getMessage(), "danger");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php PageRender::message(); ?>
|
||||||
|
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>File</td>
|
||||||
|
<td><input type="file" name="file" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><input type="submit" value="Upload" /></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php PageRender::uploads(); ?>
|
49
pages/user/index.php
Normal file
49
pages/user/index.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
global $c;
|
||||||
|
$strError = null;
|
||||||
|
|
||||||
|
if (UserAuth::getUser() == null)
|
||||||
|
Respond::redirect("/user/signin");
|
||||||
|
|
||||||
|
$varUser = UserAuth::getUser();
|
||||||
|
|
||||||
|
if ($varUser == null)
|
||||||
|
Respond::redirect("/");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Request::posts("user_name", "display_name"))
|
||||||
|
{
|
||||||
|
$strUsername = Request::getPosted("user_name");
|
||||||
|
$strDisplayName = Request::getPosted("display_name");
|
||||||
|
|
||||||
|
if (!preg_match("/^[A-Za-z0-9]{1,}$/", $strUsername))
|
||||||
|
throw new Exception("Username must be alphanumeric characters only");
|
||||||
|
|
||||||
|
$c->query(
|
||||||
|
"INSERT or replace into users (email, user_name, display_name)
|
||||||
|
select
|
||||||
|
?,
|
||||||
|
?,
|
||||||
|
?",
|
||||||
|
$varUser["email"],
|
||||||
|
$strUsername,
|
||||||
|
$strDisplayName);
|
||||||
|
|
||||||
|
PageRender::message("Profile updated", "success");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $x)
|
||||||
|
{
|
||||||
|
PageRender::message($x->getMessage(), "danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
$strUsername = $varUser["username"];
|
||||||
|
PageRender::message("You are signed in as {$strUsername}.");
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php PageRender::message(); ?>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="/user/signout">Sign out</a></li>
|
||||||
|
</ul>
|
@ -1,80 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
$strError = null;
|
|
||||||
|
|
||||||
if (UserAuth::getUser() == null)
|
|
||||||
Respond::redirect("/user/signin");
|
|
||||||
|
|
||||||
$varUser = UserAuth::getUser();
|
|
||||||
|
|
||||||
if ($varUser == null)
|
|
||||||
Respond::redirect("/");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Request::posts("user_name", "display_name"))
|
|
||||||
{
|
|
||||||
$strUsername = Request::getPosted("user_name");
|
|
||||||
$strDisplayName = Request::getPosted("display_name");
|
|
||||||
|
|
||||||
if (!preg_match("/^[A-Za-z0-9]{1,}$/", $strUsername))
|
|
||||||
throw new Exception("Username must be alphanumeric characters only");
|
|
||||||
|
|
||||||
$c->query(
|
|
||||||
"INSERT or replace into users (email, user_name, display_name)
|
|
||||||
select
|
|
||||||
?,
|
|
||||||
?,
|
|
||||||
?",
|
|
||||||
$varUser["email"],
|
|
||||||
$strUsername,
|
|
||||||
$strDisplayName);
|
|
||||||
|
|
||||||
BootstrapRender::message("Profile updated", "success");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception $x)
|
|
||||||
{
|
|
||||||
BootstrapRender::message($x->getMessage(), "danger");
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row my-5">
|
|
||||||
<div class="col-md-4">
|
|
||||||
|
|
||||||
<?php BootstrapRender::message(); ?>
|
|
||||||
|
|
||||||
<form method="post">
|
|
||||||
<?php BootstrapRender::input([
|
|
||||||
"name" => "username",
|
|
||||||
"label" => "Username",
|
|
||||||
"value" => $varUser["username"],
|
|
||||||
"disabled" => 1,
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::input([
|
|
||||||
"name" => "user_name",
|
|
||||||
"label" => "Username",
|
|
||||||
"value" => $strUsername,
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::input([
|
|
||||||
"name" => "display_name",
|
|
||||||
"label" => "Display Name",
|
|
||||||
"value" => $strDisplayName,
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::button([
|
|
||||||
"tag" => "button",
|
|
||||||
"type" => "submit",
|
|
||||||
"class" => "outline-success",
|
|
||||||
"icon" => "save",
|
|
||||||
"label" => "Save"
|
|
||||||
]); ?>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
UserAuth::require("is_admin");
|
|
||||||
TableEditor::render("credentials", ["email", "hash"]);
|
|
||||||
?>
|
|
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
global $c;
|
|
||||||
UserAuth::require("is_admin");
|
|
||||||
TableEditor::render("permissions", ["email", "permission"]);
|
|
||||||
?>
|
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
if ($intUserCount < 1)
|
if ($intUserCount < 1)
|
||||||
{
|
{
|
||||||
BootstrapRender::message(
|
PageRender::message(
|
||||||
"Please create an administrator account.",
|
"Please create an administrator account.",
|
||||||
"warning");
|
"warning");
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@
|
|||||||
if ($intUserCount == 1)
|
if ($intUserCount == 1)
|
||||||
$c->query("UPDATE users set can_post = 1, is_admin = 1");
|
$c->query("UPDATE users set can_post = 1, is_admin = 1");
|
||||||
|
|
||||||
BootstrapRender::message("Registration was a success, please sign in to continue.");
|
PageRender::message("Registration was a success, please sign in to continue.");
|
||||||
|
|
||||||
Respond::redirect("/user/signin");
|
Respond::redirect("/user/signin");
|
||||||
}
|
}
|
||||||
@ -52,57 +52,32 @@
|
|||||||
}
|
}
|
||||||
catch (Exception $x)
|
catch (Exception $x)
|
||||||
{
|
{
|
||||||
BootstrapRender::message($x->getMessage(), "danger");
|
PageRender::message($x->getMessage(), "danger");
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<script>
|
<form method="post">
|
||||||
$(".app-header").hide();
|
<table>
|
||||||
</script>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><label>Username</label></td>
|
||||||
|
<td><input type="text" name="username" value="" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="container">
|
<tr>
|
||||||
<div class="row my-5">
|
<td><label>Password</label></td>
|
||||||
<div class="col-md-4 offset-md-4">
|
<td><input type="password" name="password" value="" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<?php BootstrapRender::message(); ?>
|
<tr>
|
||||||
|
<td><label>Repeat</label></td>
|
||||||
|
<td><input type="password" name="repeat" value="" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<form method="post">
|
<tr>
|
||||||
|
<td></td>
|
||||||
<?php BootstrapRender::input([
|
<td><input type="submit" value="Go" /></td>
|
||||||
"name" => "username",
|
</tr>
|
||||||
"label" => "Username",
|
</tbody>
|
||||||
"value" => Request::getPosted("username")
|
</table>
|
||||||
]); ?>
|
</form>
|
||||||
|
|
||||||
<?php BootstrapRender::input([
|
|
||||||
"name" => "password",
|
|
||||||
"label" => "Password",
|
|
||||||
"value" => Request::getPosted("password"),
|
|
||||||
"type" => "password",
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::input([
|
|
||||||
"name" => "repeat",
|
|
||||||
"label" => "Repeat Password",
|
|
||||||
"value" => Request::getPosted("repeat"),
|
|
||||||
"type" => "password",
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::buttons([
|
|
||||||
[
|
|
||||||
"tag" => "button",
|
|
||||||
"icon" => "right-to-bracket",
|
|
||||||
"label" => "Continue",
|
|
||||||
"type" => "submit",
|
|
||||||
"class" => "outline-primary"
|
|
||||||
]
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<a class="text-decoration-none" href="/user/signin">Already have an account?</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
@ -34,63 +34,39 @@
|
|||||||
|
|
||||||
Cookie::set("token", $strToken);
|
Cookie::set("token", $strToken);
|
||||||
|
|
||||||
BootstrapRender::message(
|
PageRender::message(
|
||||||
"Successfully signed in",
|
"Successfully signed in",
|
||||||
"info");
|
"info");
|
||||||
|
|
||||||
Respond::redirect("/user/info");
|
Respond::redirect("/user");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception $x)
|
catch (Exception $x)
|
||||||
{
|
{
|
||||||
BootstrapRender::message($x->getMessage(), "danger");
|
PageRender::message($x->getMessage(), "danger");
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<script>
|
<?php PageRender::message(); ?>
|
||||||
$(".app-header").hide();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="container">
|
<form method="post">
|
||||||
<div class="row my-5">
|
<table>
|
||||||
<div class="col-md-4 offset-md-4">
|
<tbody>
|
||||||
<?php BootstrapRender::message(); ?>
|
<tr>
|
||||||
|
<td><label>Username</label></td>
|
||||||
|
<td><input type="text" name="username" value="" /></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<form method="post">
|
<tr>
|
||||||
<?php BootstrapRender::input([
|
<td><label>Password</label></td>
|
||||||
"name" => "username",
|
<td><input type="password" name="password" value="" /></td>
|
||||||
"label" => "Username",
|
</tr>
|
||||||
"value" => Request::getPosted("email")
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<?php BootstrapRender::input([
|
<tr>
|
||||||
"name" => "password",
|
<td></td>
|
||||||
"label" => "Password",
|
<td><input type="submit" value="Go" /></td>
|
||||||
"value" => Request::getPosted("password"),
|
</tr>
|
||||||
"type" => "password",
|
</tbody>
|
||||||
]); ?>
|
</table>
|
||||||
|
</form>
|
||||||
<?php BootstrapRender::buttons([
|
|
||||||
[
|
|
||||||
"tag" => "button",
|
|
||||||
"icon" => "right-to-bracket",
|
|
||||||
"label" => "Continue",
|
|
||||||
"type" => "submit",
|
|
||||||
"class" => "outline-primary"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"icon" => "home",
|
|
||||||
"label" => "Home",
|
|
||||||
"href" => "/",
|
|
||||||
"class" => "outline-secondary"
|
|
||||||
]
|
|
||||||
]); ?>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<a class="text-decoration-none" href="/user/register">Don't have an account?</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
@ -24,6 +24,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BootstrapRender::message("You have successfully signed out");
|
PageRender::message("You have successfully signed out");
|
||||||
Respond::redirect("/user/signin");
|
Respond::redirect("/user/signin");
|
||||||
?>
|
?>
|
||||||
|
Loading…
Reference in New Issue
Block a user