From bb3602073c2da9dee66ec1ce0ef99fbabc08cd34 Mon Sep 17 00:00:00 2001 From: Lee <42119604+Leesneaks@users.noreply.github.com> Date: Mon, 4 Jan 2021 12:23:36 +0000 Subject: [PATCH] AdminPanel updates - changelog -Admin menu updates -Moved getchangelogtype/where to functions file and added to twig -Added changelog editor to admin panel and updated changelog page -Renamed the changelog md reader to clmd and edited the version file. --- admin/template/menus.php | 21 ++- system/functions.php | 27 ++++ system/libs/changelog.php | 125 ++++++++++++++++ system/pages/admin/changelog.php | 134 ++++++++++++++++-- system/pages/admin/clmd.php | 27 ++++ system/pages/admin/version.php | 4 +- system/pages/changelog.php | 33 +---- .../templates/admin.changelog.form.html.twig | 59 ++++++++ system/templates/admin.changelog.html.twig | 55 +++++++ system/templates/changelog.html.twig | 28 +++- system/twig.php | 14 ++ 11 files changed, 477 insertions(+), 50 deletions(-) create mode 100644 system/libs/changelog.php create mode 100644 system/pages/admin/clmd.php create mode 100644 system/templates/admin.changelog.form.html.twig create mode 100644 system/templates/admin.changelog.html.twig diff --git a/admin/template/menus.php b/admin/template/menus.php index 37a1c2df..12ffb85c 100644 --- a/admin/template/menus.php +++ b/admin/template/menus.php @@ -2,12 +2,25 @@ return [ ['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'link' => 'dashboard'], - ['name' => 'News', 'icon' => 'newspaper', 'link' => 'news'], + ['name' => 'News', 'icon' => 'newspaper', 'link' => + [ + ['name' => 'View', 'link' => 'news'], + ['name' => 'Add news', 'link' => 'news&action=new&type=1'], + ['name' => 'Add ticker', 'link' => 'news&action=new&type=2'], + ['name' => 'Add article', 'link' => 'news&action=new&type=3'], + ], + ], + ['name' => 'Changelogs', 'icon' => 'newspaper', 'link' => + [ + ['name' => 'View', 'link' => 'changelog'], + ['name' => 'Add', 'link' => 'changelog&action=new'], + ], + ], ['name' => 'Mailer', 'icon' => 'envelope', 'link' => 'mailer', 'disabled' => !config('mail_enabled')], ['name' => 'Pages', 'icon' => 'book', 'link' => [ - ['name' => 'All Pages', 'link' => 'pages'], - ['name' => 'Add new', 'link' => 'pages&action=new'], + ['name' => 'View', 'link' => 'pages'], + ['name' => 'Add', 'link' => 'pages&action=new'], ], ], ['name' => 'Menus', 'icon' => 'list', 'link' => 'menus'], @@ -32,4 +45,4 @@ return [ ['name' => 'Visitors', 'icon' => 'user', 'link' => 'visitors'], ], ], -]; \ No newline at end of file +]; diff --git a/system/functions.php b/system/functions.php index 2a37536f..04aa2584 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1299,6 +1299,33 @@ function getBanType($typeId) return "Unknown Type"; } +function getChangelogType($v) +{ + switch($v) { + case 1: + return 'added'; + case 2: + return 'removed'; + case 3: + return 'changed'; + case 4: + return 'fixed'; + } + + return 'unknown'; +} + +function getChangelogWhere($v) +{ + switch($v) { + case 1: + return 'server'; + case 2: + return 'website'; + } + + return 'unknown'; +} function getPlayerNameByAccount($id) { global $vowels, $ots, $db; diff --git a/system/libs/changelog.php b/system/libs/changelog.php new file mode 100644 index 00000000..89f78bfc --- /dev/null +++ b/system/libs/changelog.php @@ -0,0 +1,125 @@ +<?php + +class Changelog +{ + static public function verify($body,$date, &$errors) + { + if(!isset($date) || !isset($body[0])) { + $errors[] = 'Please fill all inputs.'; + return false; + } + + if(strlen($body) > CL_LIMIT) { + $errors[] = 'Changelog content cannot be longer than ' . CL_LIMIT . ' characters.'; + return false; + } + + return true; + } + + static public function add($body, $type, $where, $player_id, $cdate, &$errors) + { + global $db; + if(!self::verify($body,$cdate, $errors)) + return false; + + $db->insert(TABLE_PREFIX . 'changelog', array('body' => $body, 'type' => $type, 'date' => $cdate, 'where' => $where, 'player_id' => isset($player_id) ? $player_id : 0)); + self::clearCache(); + return true; + } + + static public function get($id) { + global $db; + return $db->select(TABLE_PREFIX . 'changelog', array('id' => $id)); + } + + static public function update($id, $body, $type, $where, $player_id, $date, &$errors) + { + global $db; + if(!self::verify($body,$date, $errors)) + return false; + + $db->update(TABLE_PREFIX . 'changelog', array('body' => $body, 'type' => $type, 'where' => $where, 'player_id' => isset($player_id) ? $player_id : 0, 'date' => $date), array('id' => $id)); + self::clearCache(); + return true; + } + + static public function delete($id, &$errors) + { + global $db; + if(isset($id)) + { + if($db->select(TABLE_PREFIX . 'changelog', array('id' => $id)) !== false) + $db->delete(TABLE_PREFIX . 'changelog', array('id' => $id)); + else + $errors[] = 'Changelog with id ' . $id . ' does not exist.'; + } + else + $errors[] = 'Changelog id not set.'; + + if(count($errors)) { + return false; + } + + self::clearCache(); + return true; + } + + static public function toggleHidden($id, &$errors, &$status) + { + global $db; + if(isset($id)) + { + $query = $db->select(TABLE_PREFIX . 'changelog', array('id' => $id)); + if($query !== false) + { + $db->update(TABLE_PREFIX . 'changelog', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id)); + $status = $query['hidden']; + } + else + $errors[] = 'Changelog with id ' . $id . ' does not exists.'; + } + else + $errors[] = 'Changelog id not set.'; + + if(count($errors)) { + return false; + } + + self::clearCache(); + return true; + } + + static public function getCached($type) + { + global $template_name; + + $cache = Cache::getInstance(); + if ($cache->enabled()) + { + $tmp = ''; + if ($cache->fetch('changelog_' . $template_name, $tmp) && isset($tmp[0])) { + return $tmp; + } + } + + return false; + } + + static public function clearCache() + { + global $template_name; + $cache = Cache::getInstance(); + if (!$cache->enabled()) { + return; + } + + $tmp = ''; + foreach (get_templates() as $template) { + if ($cache->fetch('changelog_' . $template_name, $tmp)) { + $cache->delete('changelog_' . $template_name); + } + + } + } +} diff --git a/system/pages/admin/changelog.php b/system/pages/admin/changelog.php index 0c58c6bc..a6e7d01c 100644 --- a/system/pages/admin/changelog.php +++ b/system/pages/admin/changelog.php @@ -1,26 +1,140 @@ <?php /** - * CHANGELOG viewer + * CHANGELOG modifier * * @package MyAAC * @author Slawkens <slawkens@gmail.com> - * @copyright 2019 MyAAC + * @author Lee + * @copyright 2020 MyAAC * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = 'MyAAC Changelog'; -if (!file_exists(BASE . 'CHANGELOG.md')) { - echo 'File CHANGELOG.md doesn\'t exist.'; +if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { + echo 'Access denied.'; return; } -require LIBS . 'Parsedown.php'; +$title = 'Changelog'; +$use_datatable = true; +define('CL_LIMIT', 600); // maximum changelog body length +?> -$changelog = file_get_contents(BASE . 'CHANGELOG.md'); +<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > +<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> +<?php +$id = isset($_GET['id']) ? $_GET['id'] : 0; +require_once LIBS . 'changelog.php'; -$Parsedown = new Parsedown(); +if(!empty($action)) +{ + $id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null; + $body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null; + $create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null; + $player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null; + $type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null; + $where = isset($_REQUEST['where']) ? (int)$_REQUEST['where'] : null; -$changelog = $Parsedown->text($changelog); # prints: <p>Hello <em>Parsedown</em>!</p> + $errors = array(); -echo '<div>' . $changelog . '</div>'; + if($action == 'add') { + + if(Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) { + $body = ''; + $type = $where = $player_id = $create_date = 0; + + success("Added successful."); + } + } + else if($action == 'delete') { + Changelog::delete($id, $errors); + success("Deleted successful."); + } + else if($action == 'edit') + { + if(isset($id) && !isset($body)) { + $cl = Changelog::get($id); + $body = $cl['body']; + $type = $cl['type']; + $where = $cl['where']; + $create_date = $cl['date']; + $player_id = $cl['player_id']; + } + else { + if(Changelog::update($id, $body, $type, $where, $player_id, $create_date,$errors)) { + $action = $body = ''; + $type = $where = $player_id = $create_date = 0; + + success("Updated successful."); + } + } + } + else if($action == 'hide') { + Changelog::toggleHidden($id, $errors, $status); + success(($status == 1 ? 'Show' : 'Hide') . " successful."); + } + + if(!empty($errors)) + error(implode(", ", $errors)); +} + +$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog' . '` ORDER BY `id` DESC')->fetchAll(); + +$i = 0; + +$log_type = [ + ['id' => 1, 'icon' => 'added'], + ['id' => 2, 'icon' => 'removed'], + ['id' => 3, 'icon' => 'changed'], + ['id' => 4, 'icon' => 'fixed'], +]; + +$log_where = [ + ['id' => 1, 'icon' => 'server'], + ['id' => 2, 'icon' => 'website'], +]; + +foreach($changelogs as $key => &$log) +{ + $log['type'] = getChangelogType($log['type']); + $log['where'] = getChangelogWhere($log['where']); +} + +if($action == 'edit' || $action == 'new') { + if($action == 'edit') { + $player = new OTS_Player(); + $player->load($player_id); + } + + $account_players = $account_logged->getPlayersList(); + $account_players->orderBy('group_id', POT::ORDER_DESC); + $twig->display('admin.changelog.form.html.twig', array( + 'action' => $action, + 'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'add'), + 'cl_id' => isset($id) ? $id : null, + 'body' => isset($body) ? htmlentities($body, ENT_COMPAT, 'UTF-8') : '', + 'create_date' => isset($create_date) ? $create_date : '', + 'player' => isset($player) && $player->isLoaded() ? $player : null, + 'player_id' => isset($player_id) ? $player_id : null, + 'account_players' => $account_players, + 'type' => isset($type) ? $type : 0, + 'where' => isset($where) ? $where : 0, + 'log_type' => $log_type, + 'log_where' => $log_where, + )); +} +$twig->display('admin.changelog.html.twig', array( + 'changelogs' => $changelogs, +)); + +?> +<script> + $(document).ready(function () { + $('#createdate').datetimepicker({format: "M d Y, H:i:s",}); + + $('.tb_datatable').DataTable({ + "order": [[0, "desc"]], + "columnDefs": [{targets: [1, 2,4,5],orderable: false}] + }); + }); +</script> diff --git a/system/pages/admin/clmd.php b/system/pages/admin/clmd.php new file mode 100644 index 00000000..9d27f170 --- /dev/null +++ b/system/pages/admin/clmd.php @@ -0,0 +1,27 @@ +<?php +/** + * CHANGELOG viewer + * + * @package MyAAC + * @author Slawkens <slawkens@gmail.com> + * @author Lee + * @copyright 2020 MyAAC + * @link https://my-aac.org + */ +defined('MYAAC') or die('Direct access not allowed!'); +$title = 'MyAAC Changelog'; + +if (!file_exists(BASE . 'CHANGELOG.md')) { + echo 'File CHANGELOG.md doesn\'t exist.'; + return; +} + +require LIBS . 'Parsedown.php'; + +$changelog = file_get_contents(BASE . 'CHANGELOG.md'); + +$Parsedown = new Parsedown(); + +$changelog = $Parsedown->text($changelog); # prints: <p>Hello <em>Parsedown</em>!</p> + +echo '<div>' . $changelog . '</div>'; diff --git a/system/pages/admin/version.php b/system/pages/admin/version.php index ec9f4f64..e643e728 100644 --- a/system/pages/admin/version.php +++ b/system/pages/admin/version.php @@ -24,10 +24,10 @@ if (!$myaac_version) { $version_compare = version_compare($myaac_version, MYAAC_VERSION); if ($version_compare == 0) { success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version. - <br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here')); + <br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); } else if ($version_compare < 0) { success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '. - <br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here')); + <br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); } else { warning('You\'re using outdated version.<br/> Your version: <b>' . MYAAC_VERSION . '</b><br/> diff --git a/system/pages/changelog.php b/system/pages/changelog.php index 6b2adb86..541f9088 100644 --- a/system/pages/changelog.php +++ b/system/pages/changelog.php @@ -16,7 +16,9 @@ $limit = 30; $offset = $_page * $limit; $next_page = false; -$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog' . '` WHERE `hidden` = 0 ORDER BY `id` DESC LIMIT ' . ($limit + 1) . ' OFFSET ' . $offset)->fetchAll(); +$canEdit = hasFlag(FLAG_CONTENT_NEWS) || superAdmin(); + +$changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog` ' . ($canEdit ? '' : 'WHERE `hidden` = 0').' ORDER BY `id` DESC LIMIT ' . ($limit + 1) . ' OFFSET ' . $offset)->fetchAll(); $i = 0; foreach($changelogs as $key => &$log) @@ -39,33 +41,6 @@ $twig->display('changelog.html.twig', array( 'changelogs' => $changelogs, 'page' => $_page, 'next_page' => $next_page, + 'canEdit' => $canEdit, )); - -function getChangelogType($v) -{ - switch($v) { - case 1: - return 'added'; - case 2: - return 'removed'; - case 3: - return 'changed'; - case 4: - return 'fixed'; - } - - return 'unknown'; -} - -function getChangelogWhere($v) -{ - switch($v) { - case 1: - return 'server'; - case 2: - return 'website'; - } - - return 'unknown'; -} ?> diff --git a/system/templates/admin.changelog.form.html.twig b/system/templates/admin.changelog.form.html.twig new file mode 100644 index 00000000..e3ca5dab --- /dev/null +++ b/system/templates/admin.changelog.form.html.twig @@ -0,0 +1,59 @@ +{% if action %} + <div class="card card-info card-outline"> + <div class="card-header"> + <h5 class="m-0">{{ (action == 'edit') ? 'Edit' : 'Add' }}</h5> + </div> + <form role="form" method="post" action="{{ cl_link_form }}" id="cl-edit-form"> + <div class="card-body"> + {% if action == 'edit' %} + <input type="hidden" name="id" value="{{ cl_id }}"/> + {% endif %} + + <div class="form-group row"> + <label for="body">Content</label> + <textarea class="form-control" id="body" name="body" maxlength="600" cols="50" rows="5">{{ body|raw }}</textarea> + </div> + <div class="form-group row"> + <div class="col-12 col-sm-12 col-lg-6"> + <label for="createdate" class="control-label">Date:</label> + <input type="text" class="form-control" id="createdate" name="createdate" autocomplete="off" maxlength="20" value="{{ create_date|date("M d Y, H:i:s") }}"/> + </div> + <div class="col-sm-6 pl-0"> + <label for="player_id">Author</label> + <select class="form-control" name="player_id" id="player_id"> + {% for player in account_players %} + <option value="{{ player.getId() }}"{% if player_id is defined and player.getId() == player_id %} selected="selected"{% endif %}>{{ player.getName() }}</option> + {% endfor %} + </select> + </div> + </div> + <div class="form-group row"> + <div class="col-sm-6 pl-0"> + <label for="select-where">Where</label> + <select class="form-control" name="where" id="select-where"> + {% for id, cat in log_where %} + <option value="{{ cat.id }}" + {% if (where == 0 and id == 1) or (where == cat.id) %}selected="selected"{% endif %}>{{ cat.icon|capitalize }}</option> + {% endfor %} + </select> + </div> + <div class="col-sm-6 pl-0"> + <label for="select-type">Type</label> + <select class="form-control" name="type" id="select-type"> + {% for id, cat in log_type %} + <option value="{{ cat.id }}" + {% if (type == 0 and id == 1) or (type == cat.id) %}selected="selected"{% endif %}>{{ cat.icon|capitalize }}</option> + {% endfor %} + </select> + </div> + </div> + </div> + <div class="card-footer"> + <button type="submit" class="btn btn-info"><i class="fas fa-update"></i> {{ (action == 'edit') ? 'Update' : 'Add' }}</button> + <button type="button" onclick="window.location = '{{ constant('ADMIN_URL') }}?p=changelog';" + class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel + </button> + </div> + </form> + </div> +{% endif %} diff --git a/system/templates/admin.changelog.html.twig b/system/templates/admin.changelog.html.twig new file mode 100644 index 00000000..fe43982a --- /dev/null +++ b/system/templates/admin.changelog.html.twig @@ -0,0 +1,55 @@ +<div class="card card-info card-outline"> + <div class="card-header"> + <h5 class="m-0">News: + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=new" class="float-right"><span + class="btn btn-sm btn-success">New</span></a> + </h5> + </div> + + <div class="card-body"> + <table class="tb_datatable table table-striped table-bordered"> + <thead> + <tr> + <th width="5%">ID</th> + <th>Date</th> + <th>Description</th> + <th>Type</th> + <th>Where</th> + <th></th> + </tr> + </thead> + <tbody> + {% if changelogs|length > 0 %} + {% set i = 0 %} + {% for log in changelogs %} + <tr> + <td>{{ log.id }}</td> + <td>{{ log.date|date("j.m.Y") }}</td> + <td>{{ truncate(log.body|raw,20) }}</td> + <td><img src="{{ constant('BASE_URL') }}images/changelog/{{ log.type }}.png" title="{{ log.type|capitalize }}"/> {{ log.type|capitalize }}</td> + <td><img src="{{ constant('BASE_URL') }}images/changelog/{{ log.where }}.png" title="{{ log.where|capitalize }}"/> {{ log.where|capitalize }}</td> + <td> + <div class="btn-group"> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=edit&id={{ log.id }}" class="btn btn-success btn-sm" title="Edit"> + <i class="fas fa-pencil-alt"></i> + </a> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=delete&id={{ log.id }}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?');" title="Delete"> + <i class="fas fa-trash"></i> + </a> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=hide&id={{ log.id }}" class="btn btn-{{ (log.hidden != 1) ? 'info' : 'default' }} btn-sm" title="{% if log.hidden != 1 %}Hide{% else %}Show{% endif %}"> + <i class="fas fa-eye{{ (log.hidden != 1) ? '' : '-slash' }}"></i> + </a> + </div> + </td> + </tr> + {% set i = i + 1 %} + {% endfor %} + {% else %} + <tr> + <td colspan="6">There are no changelogs for the moment.</td> + </tr> + {% endif %} + </tbody> + </table> + </div> +</div> diff --git a/system/templates/changelog.html.twig b/system/templates/changelog.html.twig index 8ba6c627..d63a6a2a 100644 --- a/system/templates/changelog.html.twig +++ b/system/templates/changelog.html.twig @@ -1,23 +1,41 @@ -<br/> +{% if canEdit %} + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=new" class="btn btn-success btn-sm" title="Add New" target="_blank">Add New</a> +{% endif %} <table border="0" cellspacing="1" cellpadding="4" width="100%"> <tr bgcolor="{{ config.vdarkborder }}"> <td width="22"><span class="white"><b>Type</b></span></td> <td width="22"><span class="white"><b>Where</b></span></td> <td width="50"><span class="white"><b>Date</b></span></td> <td><span class="white"><b>Description</b></span></td> + {% if canEdit %} + <td></td> + {% endif %} </tr> {% if changelogs|length > 0%} {% set i = 0 %} {% for log in changelogs %} <tr bgcolor="{{ getStyle(i) }}"> <td align="center"> - <img src="images/changelog/{{ log.type }}.png" title="{{ log.type|capitalize }}"/> + <img src="{{ constant('BASE_URL') }}images/changelog/{{ log.type }}.png" title="{{ log.type|capitalize }}"/> </td> <td align="center"> - <img src="images/changelog/{{ log.where }}.png" title="{{ log.where|capitalize }}"/> + <img src="{{ constant('BASE_URL') }}images/changelog/{{ log.where }}.png" title="{{ log.where|capitalize }}"/> </td> <td>{{ log.date|date("j.m.Y") }}</td> - <td>{{ log.body|raw }}</td> + <td>{{ log.body|nl2br}}</td> + {% if canEdit %} + <td> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=edit&id={{ log.id }}" title="Edit in Admin Panel" target="_blank"> + <img src="images/edit.png"/>Edit + </a> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=delete&id={{ log.id }}" onclick="return confirm('Are you sure?');" title="Delete in Admin Panel" target="_blank"> + <img src="images/del.png"/>Delete + </a> + <a href="{{ constant('ADMIN_URL') }}?p=changelog&action=hide&id={{ log.id }}" title="{% if log.hidden != 1 %}Hide{% else %}Show{% endif %} in Admin Panel" target="_blank"> + <img src="images/{{ (log.hidden != 1 ? 'success' : 'error') }}.png"/>{{ (log.hidden != 1) ? 'Hide' : 'Show' }} + </a> + </td> + {% endif %} </tr> {% set i = i + 1 %} {% endfor %} @@ -35,4 +53,4 @@ <tr><td width="100%" align="right" valign="bottom"><a href="{{ getLink('changelog/' ~ (page + 1)) }}" class="size_xxs">Next Page</a></td></tr> {% endif %} </table> -</table> \ No newline at end of file +</table> diff --git a/system/twig.php b/system/twig.php index 3a258843..e847f356 100644 --- a/system/twig.php +++ b/system/twig.php @@ -54,6 +54,20 @@ $function = new TwigFunction('getGuildLink', function ($s, $p) { }); $twig->addFunction($function); +$function = new TwigFunction('truncate', function ($s, $n) { + return truncate($s, $n); +}); +$twig->addFunction($function); + +$function = new TwigFunction('getChangelogType', function ($n) { + return getChangelogType($n); +}); +$twig->addFunction($function); + +$function = new TwigFunction('getChangelogWhere', function ($n) { + return getChangelogWhere($n); +}); +$twig->addFunction($function); $function = new TwigFunction('hook', function ($hook) { global $hooks;