forked from CRSS/Website
feat: start making the admin panel
This commit is contained in:
parent
8bcebc7069
commit
a4e5c331e3
|
@ -6,6 +6,7 @@
|
||||||
require __DIR__ . '/vendor/autoload.php';
|
require __DIR__ . '/vendor/autoload.php';
|
||||||
require __DIR__ . '/util/Database.php';
|
require __DIR__ . '/util/Database.php';
|
||||||
require __DIR__ . '/util/Discord.php';
|
require __DIR__ . '/util/Discord.php';
|
||||||
|
require __DIR__ . '/util/Admin.php';
|
||||||
|
|
||||||
use Twig\Loader\FilesystemLoader;
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
|
||||||
|
|
2
css/map.min.css
vendored
2
css/map.min.css
vendored
|
@ -1 +1 @@
|
||||||
*{padding:0;margin:0;box-sizing:border-box}#map{height:100vh}#homeLink{position:absolute;bottom:10px;left:10px;padding:5px 10px;z-index:400;background-color:#fff;background-clip:padding-box;border:2px solid rgba(0,0,0,.2);border-radius:5px;text-decoration:none;color:#000}img.leaflet-tile{image-rendering:pixelated}.leaflet-control{color:#333}.leaflet-control-mouseposition{background:rgba(255,255,255,.8);margin:0 !important;padding:6px;width:calc(100% - 12px);text-align:end;border-top-left-radius:5px}.leaflet-marker-icon{transition:300ms}/*# sourceMappingURL=map.min.css.map */
|
*{padding:0;margin:0;box-sizing:border-box}#map{height:100vh}#homeLink{position:absolute;bottom:10px;left:10px;padding:5px 10px;z-index:400;background-color:#fff;background-clip:padding-box;border:2px solid rgba(0,0,0,.2);border-radius:5px;text-decoration:none;color:#000}img.leaflet-tile,img.leaflet-marker-icon{image-rendering:pixelated}.leaflet-control{color:#333}.leaflet-control-mouseposition{background:rgba(255,255,255,.8);margin:0 !important;padding:6px;width:100%;text-align:end;border-top-left-radius:5px}.leaflet-marker-icon{transition:300ms}/*# sourceMappingURL=map.min.css.map */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":3,"sourceRoot":"","sources":["src/map.scss"],"names":[],"mappings":"AAAA,EACE,UACA,SAEA,sBAKF,kBAEA,UACE,kBACA,YACA,UACA,iBACA,YAEA,sBACA,4BAEA,gCACA,kBAEA,qBACA,WAGF,iBACE,0BAGF,iBACE,WAGF,+BACE,gCAEA,oBACA,YAEA,wBAEA,eAEA,2BAGF,qBACE","file":"map.min.css"}
|
{"version":3,"sourceRoot":"","sources":["src/map.scss"],"names":[],"mappings":"AAAA,EACE,UACA,SAEA,sBAKF,kBAEA,UACE,kBACA,YACA,UACA,iBACA,YAEA,sBACA,4BAEA,gCACA,kBAEA,qBACA,WAGF,yCACE,0BAGF,iBACE,WAGF,+BACE,gCAEA,oBACA,YAEA,WAEA,eAEA,2BAGF,qBACE","file":"map.min.css"}
|
|
@ -26,7 +26,7 @@
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.leaflet-tile {
|
img.leaflet-tile, img.leaflet-marker-icon {
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ img.leaflet-tile {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
|
||||||
width: calc(100% - 2 * 6px);
|
width: 100%;
|
||||||
|
|
||||||
text-align: end;
|
text-align: end;
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
@use "colors/dark" as dark;
|
@use "colors/dark" as dark;
|
||||||
|
|
||||||
* {
|
* {
|
||||||
-webkit-tap-highlight-color: transparent; // fuck you
|
-webkit-tap-highlight-color: transparent; // fuck you (L)
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body { overflow-x: hidden;}
|
html, body {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -169,13 +171,11 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageHero {
|
.pageHero {
|
||||||
background-image:
|
background-image: linear-gradient(rgba(light.$headerOverlay, 0.9), rgba(light.$headerOverlay, 0.9)), // white overlay. yeah that's a bit of an ugly hack?
|
||||||
linear-gradient(rgba(light.$headerOverlay, 0.9),rgba(light.$headerOverlay, 0.9)), // white overlay. yeah that's a bit of an ugly hack?
|
|
||||||
url('/img/Panorama-Lens-Blur.png');
|
url('/img/Panorama-Lens-Blur.png');
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
background-image:
|
background-image: linear-gradient(rgba(dark.$headerOverlay, 0.9), rgba(dark.$headerOverlay, 0.9)),
|
||||||
linear-gradient(rgba(dark.$headerOverlay, 0.9),rgba(dark.$headerOverlay, 0.9)),
|
|
||||||
url('/img/Panorama-Lens-Blur.png');
|
url('/img/Panorama-Lens-Blur.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,9 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
img { filter: invert(1) }
|
img {
|
||||||
|
filter: invert(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
|
@ -312,14 +314,18 @@ a {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 64px;
|
gap: 64px;
|
||||||
|
|
||||||
&, > * { transition: 0.16s }
|
&, > * {
|
||||||
|
transition: 0.16s
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.opened) {
|
&:not(.opened) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
//&, > * { transition: 0.12s }
|
//&, > * { transition: 0.12s }
|
||||||
> * { transform: translateX(32px); }
|
> * {
|
||||||
|
transform: translateX(32px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +350,9 @@ a {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: light.$navLinkNormalColor;
|
color: light.$navLinkNormalColor;
|
||||||
@media (prefers-color-scheme: dark) { color: dark.$navLinkNormalColor; }
|
@media (prefers-color-scheme: dark) {
|
||||||
|
color: dark.$navLinkNormalColor;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":3,"sourceRoot":"","sources":["src/_fonts.scss","src/style.scss","src/colors/_light.scss","src/colors/_dark.scss"],"names":[],"mappings":"CAEQ,qKAER,WACE,sDAGF,kBACE,mDACA,gBAIF,UACE,uECXF,EACC,0CAGD,4BAEA,KACE,SAEA,WCXO,KDYP,MCXO,KDaP,mCANF,KAOI,WEfK,QFgBL,MEfK,MFmBT,KACC,gBAEA,eACC,sBACA,gBACA,WACA,oBACA,iBAGD,gBACC,sBACA,gBACA,UAIF,WACE,gBAEA,WAEA,cAEA,aACA,sBAGF,MACE,2BAGF,EACE,gBACA,YAGF,IACE,eAGF,OACC,aACA,eACA,QACA,WAEA,yBAND,OAOE,UAIF,MACC,kBACA,aACA,sBACA,sBACA,eACA,aACC,qBACA,kBACA,iBACA,eACA,gBAED,0BACC,WCzEa,QD0Eb,MCvFO,KD+FP,gBAsBD,iCA5BC,mCAjBF,MAkBI,cE3Ee,QF4Ef,WE9EW,QF+EZ,ME5FM,MFiGP,YACC,kBACA,cCxFS,QDyFT,WC1FK,QD2FL,MCnGM,QD2GP,gBANC,mCAND,YAOG,cE7FO,QF8FP,WE/FG,QFgGJ,MEvGQ,SF4GT,kBACC,gBACA,qBAMF,yBA/CF,MAgDE,uBAGD,yBAnDD,MAoDG,kBACD,YAGA,SACC,SACA,gBACA,gBAGD,YACC,kBACA,MACA,QACA,YACA,iBACA,iBAEA,wEAKA,gBAJA,mCATD,YAUE,yEAMF,QACC,aAIH,EACE,MC1JO,QD4JP,mCAHF,EAII,ME5JQ,SF+JV,UACE,WAIJ,UACE,iBACE,uGASF,2BACA,sBAEA,aATA,mCALF,UAMI,iBACA,kGASF,qBACE,YAEA,aACA,mBAEA,mBACA,8BAEA,yBATF,qBAUI,wBAGF,yBACE,aACA,sBAEA,SAEA,kCACE,uBAEA,yBAHF,kCAII,oBAGF,mCACE,wDAGF,uCACE,eACA,YAIJ,4CAKE,mBACA,QALA,yBADF,4CAEI,cAMF,kDACE,kBACA,eAEA,qEACE,cACA,2BACA,yBAQZ,WAIE,WAEA,eACA,QACA,UACA,eAEA,WC3PO,QD4PP,MCxPY,KD+PZ,iBAEA,mBAEA,iBACA,iBAEA,eAzBA,yBADF,WAEI,cAYF,mCAdF,WAeG,WE/PM,QFgQN,ME5PW,MFyQd,SACE,WAEA,qBACA,uBAEA,WC3QM,QD6QN,mCARF,SASI,aE7QQ,QF8QR,WE/QI,SFkRN,oBACE,kBAEA,aACA,eAEA,mBACA,8BAEA,yBATF,oBAUI,eACA,MACA,OACA,WACA,YACA,UAEF,2BACC,iCAKA,uBACC,sBACA,UANF,yDAnBF,oBAoBI,8BAXF,yBAkBE,0DAEA,iCACE,UACA,oBAGA,+DAIJ,wBACE,SAEA,aACA,eACA,qBAEA,QAEA,yBATF,wBAUG,WACC,uBAGF,0BACE,mBACA,iBAEA,eACA,sBACA,MC7Ta,QD4Ub,qBAEA,iBAEA,mBAEA,gCAEA,gBAtBA,mCAPF,0BAOwC,MElUzB,SFoUb,yBATF,0BAUI,eACA,aACA,iBACA,eAEA,yCACC,aAeH,iCACC,oBAGD,iEAEE,MCnXD,QDoXC,cC9VY,QDsWZ,gBANA,mCALF,iEAMI,MEnWS,QFoWT,cEtWU,SF6Wd,yBACC,wCACE,WCjYF,QDkYE,MC9XG,KDqYH,4BALA,yDAJF,wCAKI,WErYJ,QFsYI,MElYC,MFiZd,YACE,WAEA,uBACE,aACA,eACA,SAEA,yBACE,aACA,QAEA,eAEA,cAEA,6BACE,UAEA,mCAHF,6BAII,kBAIJ,4CACE","file":"style.min.css"}
|
{"version":3,"sourceRoot":"","sources":["src/_fonts.scss","src/style.scss","src/colors/_light.scss","src/colors/_dark.scss"],"names":[],"mappings":"CAEQ,qKAER,WACE,sDAGF,kBACE,mDACA,gBAIF,UACE,uECXF,EACE,0CAGF,UACE,kBAGF,KACE,SAEA,WCbO,KDcP,MCbO,KDeP,mCANF,KAOI,WEjBK,QFkBL,MEjBK,MFqBT,KACE,gBAEA,eACE,sBACA,gBACA,WACA,oBACA,iBAGF,gBACE,sBACA,gBACA,UAIJ,WACE,gBAEA,WAEA,cAEA,aACA,sBAGF,MACE,2BAGF,EACE,gBACA,YAGF,IACE,eAGF,OACE,aACA,eACA,QACA,WAEA,yBANF,OAOI,UAIJ,MACE,kBACA,aACA,sBACA,sBACA,eACA,aACA,qBACA,kBACA,iBACA,eACA,gBAEA,0BACA,WC3Ea,QD4Eb,MCzFO,KDiGP,gBAsBA,iCA5BA,mCAjBF,MAkBI,cE7Ee,QF8Ef,WEhFW,QFiFX,ME9FK,MFmGP,YACE,kBACA,cC1FQ,QD2FR,WC5FI,QD6FJ,MCrGK,QD6GL,gBANA,mCANF,YAOI,cE/FM,QFgGN,WEjGE,QFkGF,MEzGM,SF8GR,kBACE,gBACA,qBAMJ,yBA/CF,MAgDI,uBAGF,yBAnDF,MAoDI,kBACA,YAGF,SACE,SACA,gBACA,gBAGF,YACE,kBACA,MACA,QACA,YACA,iBACA,iBAEA,wEAKA,gBAJA,mCATF,YAUI,yEAMJ,QACE,aAIJ,EACE,MC5JO,QD8JP,mCAHF,EAII,ME9JQ,SFiKV,UACE,WAIJ,UACE,wHAQA,2BACA,sBAEA,aARA,mCAJF,UAKI,mHASF,qBACE,YAEA,aACA,mBAEA,mBACA,8BAEA,yBATF,qBAUI,wBAGF,yBACE,aACA,sBAEA,SAEA,kCACE,uBAEA,yBAHF,kCAII,oBAGF,mCACE,sCACE,kBAIJ,uCACE,eACA,YAIJ,4CAKE,mBACA,QALA,yBADF,4CAEI,cAMF,kDACE,kBACA,eAEA,qEACE,cACA,2BACA,yBAQZ,WAIE,WAEA,eACA,QACA,UACA,eAEA,WC7PO,QD8PP,MC1PY,KDiQZ,iBAEA,mBAEA,iBACA,iBAEA,eAzBA,yBADF,WAEI,cAYF,mCAdF,WAeI,WEjQK,QFkQL,ME9PU,MF2Qd,SACE,WAEA,qBACA,uBAEA,WC7QM,QD+QN,mCARF,SASI,aE/QQ,QFgRR,WEjRI,SFoRN,oBACE,kBAEA,aACA,eAEA,mBACA,8BAEA,yBATF,oBAUI,eACA,MACA,OACA,WACA,YACA,UAEA,2BACA,iCAKA,uBACA,sBACA,UANA,yDAnBJ,oBAoBM,8BAXJ,yBAkBE,0CACE,gBAGF,iCACE,UACA,oBAGA,mCACE,4BAKN,wBACE,SAEA,aACA,eACA,qBAEA,QAEA,yBATF,wBAUI,WACA,uBAGF,0BACE,mBACA,iBAEA,eACA,sBACA,MCnUa,QDoVb,qBAEA,iBAEA,mBAEA,gCAEA,gBAxBA,mCAPF,0BAQI,MEzUW,SF4Ub,yBAXF,0BAYI,eACA,aACA,iBACA,eAEA,yCACE,aAeJ,iCACE,oBAGF,iEAEE,MC3XD,QD4XC,cCtWY,QD8WZ,gBANA,mCALF,iEAMI,ME3WS,QF4WT,cE9WU,SFqXd,yBACE,wCACE,WCzYH,QD0YG,MCtYE,KD6YF,4BALA,yDAJF,wCAKI,WE7YL,QF8YK,ME1YA,MFyZd,YACE,WAEA,uBACE,aACA,eACA,SAEA,yBACE,aACA,QAEA,eAEA,cAEA,6BACE,UAEA,mCAHF,6BAII,kBAIJ,4CACE","file":"style.min.css"}
|
27
index.php
27
index.php
|
@ -85,15 +85,21 @@
|
||||||
|
|
||||||
$twig->addGlobal('pageUri', '/profile');
|
$twig->addGlobal('pageUri', '/profile');
|
||||||
|
|
||||||
|
if (isset($_SESSION['user'])) {
|
||||||
$user = $mysql->getUserRecordFromId($_SESSION['user']['id']);
|
$user = $mysql->getUserRecordFromId($_SESSION['user']['id']);
|
||||||
|
|
||||||
if($user == null) {
|
if ($user == null && $user['admin'] == 0) {
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
|
|
||||||
echo $twig->render('404.twig');
|
echo $twig->render('404.twig');
|
||||||
} else {
|
} else {
|
||||||
echo $twig->render('profile.twig', array('db_data' => $user));
|
echo $twig->render('profile.twig', array('db_data' => $user));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
http_response_code(404);
|
||||||
|
|
||||||
|
echo $twig->render('404.twig');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$router->get('/nation/([a-z]+)', function ($nation) {
|
$router->get('/nation/([a-z]+)', function ($nation) {
|
||||||
|
@ -133,17 +139,32 @@
|
||||||
|
|
||||||
$twig->addGlobal('pageUri', '/admin');
|
$twig->addGlobal('pageUri', '/admin');
|
||||||
|
|
||||||
|
if (isset($_SESSION['user'])) {
|
||||||
$user = $mysql->getUserRecordFromId($_SESSION['user']['id']);
|
$user = $mysql->getUserRecordFromId($_SESSION['user']['id']);
|
||||||
|
|
||||||
if($user == null && $user['admin'] == 0) {
|
$users = $mysql->getUsers();
|
||||||
|
$markers = $mysql->getMarkers();
|
||||||
|
|
||||||
|
if ($user == null && $user['admin'] == 0) {
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
|
|
||||||
echo $twig->render('404.twig');
|
echo $twig->render('404.twig');
|
||||||
} else {
|
} else {
|
||||||
echo $twig->render('admin/index.twig', array('db_data' => $user));
|
echo $twig->render('admin/index.twig', array('users' => $users, 'markers' => $markers));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
http_response_code(404);
|
||||||
|
|
||||||
|
echo $twig->render('404.twig');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ---------------- Admin API ---------------- //
|
||||||
|
|
||||||
|
$adminApi = new Admin($router);
|
||||||
|
|
||||||
|
$adminApi->registerApiRoutes();
|
||||||
|
|
||||||
// ----------------- 404 ----------------- //
|
// ----------------- 404 ----------------- //
|
||||||
|
|
||||||
$router->set404(function() {
|
$router->set404(function() {
|
||||||
|
|
|
@ -137,13 +137,13 @@ const updatePlayerPos = (players) =>{
|
||||||
mappedPlayers[player.uniqueId] = playerMarker;
|
mappedPlayers[player.uniqueId] = playerMarker;
|
||||||
} else {
|
} else {
|
||||||
const playerIcon = L.icon({
|
const playerIcon = L.icon({
|
||||||
iconUrl: `https://mc-heads.net/avatar/${player.displayName}`,
|
iconUrl: `https://mc-heads.net/avatar/${player.displayName}/16`,
|
||||||
iconSize: [28, 28],
|
iconSize: [28, 28],
|
||||||
iconAnchor: [14, 14],
|
iconAnchor: [14, 14],
|
||||||
popupAnchor: [0, -14]
|
popupAnchor: [0, -14]
|
||||||
});
|
});
|
||||||
|
|
||||||
const marker = L.marker([player.location.z, player.location.x], { icon: playerIcon })
|
const marker = L.marker([player.location.z, player.location.x], { icon: playerIcon, alt: player.displayName })
|
||||||
.bindPopup(`${player.displayName} (${Math.floor(player.location.x)}; ${Math.floor(player.location.y)}; ${Math.floor(player.location.z)})`);
|
.bindPopup(`${player.displayName} (${Math.floor(player.location.x)}; ${Math.floor(player.location.y)}; ${Math.floor(player.location.z)})`);
|
||||||
|
|
||||||
playerMarkers.addLayer(marker);
|
playerMarkers.addLayer(marker);
|
||||||
|
|
|
@ -11,7 +11,138 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="text-center">soon</h1>
|
<h3>Users</h3>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">id</th>
|
||||||
|
<th scope="col">username</th>
|
||||||
|
<th scope="col">display_name</th>
|
||||||
|
<th scope="col">is_admin</th>
|
||||||
|
<th scope="col">date</th>
|
||||||
|
<th scope="col">actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ user.id }}</th>
|
||||||
|
<td>{{ user.username }}</td>
|
||||||
|
<td>{{ user.display_name }}</td>
|
||||||
|
<td>{{ user.is_admin == 1 ? "true" : "false" }}</td>
|
||||||
|
<td>{{ user.date }}</td>
|
||||||
|
<td>
|
||||||
|
{% if user.is_admin == 1 %}
|
||||||
|
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#confirmModal">Revoke Admin</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#confirmModal">Make Admin</button>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Are you sure?</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aspernatur fugit id impedit iusto perferendis possimus provident quos sunt vero. Assumenda blanditiis culpa eaque error ipsa non quasi sint unde?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" data-bs-dismiss="modal">Yes</button>
|
||||||
|
<button type="button" class="btn btn-danger">No</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h3>Markers</h3>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">id</th>
|
||||||
|
<th scope="col">name</th>
|
||||||
|
<th scope="col">category</th>
|
||||||
|
<th scope="col">data</th>
|
||||||
|
<th scope="col">actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for marker in markers %}
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{{ marker.id }}</th>
|
||||||
|
<td>{{ marker.name }}</td>
|
||||||
|
<td>{{ marker.category }}</td>
|
||||||
|
<td>{{ marker.data }}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#editModal">Edit</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="confirmModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Are you sure?</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aspernatur fugit id impedit iusto perferendis possimus provident quos sunt vero. Assumenda blanditiis culpa eaque error ipsa non quasi sint unde?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" data-bs-dismiss="modal">Yes</button>
|
||||||
|
<button type="button" class="btn btn-danger">No</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="editModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Editing "${name}"</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="frm">
|
||||||
|
<input value="update_marker" name="action" class="visually-hidden">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleInputEmail1" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
|
||||||
|
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="exampleInputPassword1" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="exampleInputPassword1">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3 form-check">
|
||||||
|
<input type="checkbox" class="form-check-input" id="exampleCheck1">
|
||||||
|
<label class="form-check-label" for="exampleCheck1">Check me out</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" data-bs-dismiss="modal" onclick="document.querySelector('.frm').submit()">Save</button>
|
||||||
|
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
|
81
util/Admin.php
Normal file
81
util/Admin.php
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
class Admin {
|
||||||
|
private Bramus\Router\Router $router;
|
||||||
|
|
||||||
|
function __construct($router) {
|
||||||
|
$this->router = $router;
|
||||||
|
}
|
||||||
|
|
||||||
|
function notFound($error): void {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
http_response_code(404);
|
||||||
|
|
||||||
|
echo json_encode(array(
|
||||||
|
'error' => true,
|
||||||
|
'error_description' => $error
|
||||||
|
));
|
||||||
|
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSignedInAdmin(): void {
|
||||||
|
global $mysql;
|
||||||
|
|
||||||
|
if(!isset($_SESSION['user'])) {
|
||||||
|
$this->notFound('You are not logged in.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $mysql->getUserRecordFromId($_SESSION['user']['id']);
|
||||||
|
|
||||||
|
if($user == null && $user['admin'] == 0) {
|
||||||
|
$this->notFound('You are not an admin.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerApiRoutes(): void {
|
||||||
|
$router = $this->router;
|
||||||
|
|
||||||
|
$router->mount('/admin/api', function() use ($router) {
|
||||||
|
$router->mount('/v1', function() use ($router) {
|
||||||
|
$router->get('/markers', function() {
|
||||||
|
global $mysql;
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$this->isSignedInAdmin();
|
||||||
|
|
||||||
|
$markers = $mysql->getMarkers();
|
||||||
|
|
||||||
|
$markersNew = array();
|
||||||
|
|
||||||
|
foreach ($markers as $marker) {
|
||||||
|
$markersNew[] = array(
|
||||||
|
'id' => $marker['id'],
|
||||||
|
'name' => $marker['name'],
|
||||||
|
'category' => $marker['category'],
|
||||||
|
'x' => floatval(explode(';', $marker['data'])[1]),
|
||||||
|
'y' => floatval(explode(';', $marker['data'])[0])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$finalOut = array(
|
||||||
|
'error' => false,
|
||||||
|
'markers' => $markersNew
|
||||||
|
);
|
||||||
|
|
||||||
|
echo json_encode($finalOut);
|
||||||
|
});
|
||||||
|
|
||||||
|
$router->get('/users', function() {
|
||||||
|
global $mysql;
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$this->isSignedInAdmin();
|
||||||
|
|
||||||
|
echo json_encode($mysql->getUsers());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -58,7 +58,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMarkers() {
|
function getUsers(): array | null {
|
||||||
|
$sql = 'SELECT * FROM users';
|
||||||
|
|
||||||
|
$stmt = $this->conn->prepare($sql);
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$res = $stmt->get_result();
|
||||||
|
|
||||||
|
if($res->num_rows > 0) {
|
||||||
|
return $res->fetch_all(MYSQLI_ASSOC);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMarkers(): array | null {
|
||||||
$sql = 'SELECT * FROM markers';
|
$sql = 'SELECT * FROM markers';
|
||||||
|
|
||||||
$stmt = $this->conn->prepare($sql);
|
$stmt = $this->conn->prepare($sql);
|
||||||
|
|
Loading…
Reference in a new issue