Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6cff15964f | |||
| be9baee799 | |||
| c94f166153 | |||
| 972c2e6520 | |||
| 428e383c91 | |||
| 8cf8a26821 | |||
| d4f1efe96a | |||
| 5e5fb356c7 | |||
| 9257912eb7 | |||
| 355df433c1 | |||
| d36099a8e3 | |||
| b8e3cd2466 | |||
| f45e0a03d8 | |||
| 84453234b4 | |||
| be2a2dc473 | |||
| cf990c8544 |
+1
-1
@@ -82,7 +82,7 @@ body {
|
|||||||
.nav-fix-scroll {
|
.nav-fix-scroll {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-height: 85vh;
|
max-height: 85vh;
|
||||||
align-items: unset;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ INSERT INTO `DBPREFIXconfig` (`identifier`, `type`, `value`, `user_editable`) VA
|
|||||||
('loginpokeclient', 'BOOL', 'true', 1),
|
('loginpokeclient', 'BOOL', 'true', 1),
|
||||||
('cache_logincode', 'INT', '120', 1),
|
('cache_logincode', 'INT', '120', 1),
|
||||||
('cache_adminstatus', 'INT', '60', 1),
|
('cache_adminstatus', 'INT', '60', 1),
|
||||||
|
('cache_languages', 'INT', '300', 1),
|
||||||
('adminstatus_groups', 'JSON', '[]', 1),
|
('adminstatus_groups', 'JSON', '[]', 1),
|
||||||
('adminstatus_mode', 'INT', '2', 1),
|
('adminstatus_mode', 'INT', '2', 1),
|
||||||
('adminstatus_enabled', 'BOOL', 'true', 1),
|
('adminstatus_enabled', 'BOOL', 'true', 1),
|
||||||
|
|||||||
+1619
-1389
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,9 @@ if (!file_exists(__PRIVATE_DIR . "/vendor/autoload.php")) {
|
|||||||
die(
|
die(
|
||||||
'<h2>Oops! We cannot find Composer\'s autoload file.</h2>' .
|
'<h2>Oops! We cannot find Composer\'s autoload file.</h2>' .
|
||||||
'<h3>In 2.0, the installation procedure is a little different. Go to the ' .
|
'<h3>In 2.0, the installation procedure is a little different. Go to the ' .
|
||||||
'<a href="https://github.com/Wruczek/ts-website/releases" target="_blank">releases</a> on GitHub, ' .
|
'<a href="https://github.com/Wruczek/ts-website/wiki/%5BEN%5D-Website-Installation" target="_blank">wiki</a> ' .
|
||||||
'download the latest version and upload in on your server.</h3>' .
|
'and follow the installation tutorial.</h3>' .
|
||||||
|
'<h2 style="color: red">Please do not contact us for help with that error. Read the wiki.</h2>' .
|
||||||
'Or, if you know what you are doing, run <code>composer update</code> in the ' .
|
'Or, if you know what you are doing, run <code>composer update</code> in the ' .
|
||||||
'<code>' . realpath(__BASE_DIR) . '</code> directory'
|
'<code>' . realpath(__BASE_DIR) . '</code> directory'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -43,7 +43,15 @@ if (!empty($_POST)) {
|
|||||||
// try to connect only if dbconfig is defined
|
// try to connect only if dbconfig is defined
|
||||||
if (isset($dbconfig)) {
|
if (isset($dbconfig)) {
|
||||||
try {
|
try {
|
||||||
$db = new Medoo($dbconfig);
|
$errmodeException = [
|
||||||
|
"option" => [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
// Enable DB exceptions instead of silent fails, only for the Medoo
|
||||||
|
// object and not for the dbConfig, we dont want to get it saved
|
||||||
|
$db = new Medoo($dbconfig + $errmodeException);
|
||||||
|
|
||||||
$sqlfiles = [];
|
$sqlfiles = [];
|
||||||
|
|
||||||
@@ -88,7 +96,7 @@ EOT;
|
|||||||
|
|
||||||
// Add all variables to the config
|
// Add all variables to the config
|
||||||
foreach ($dbconfig as $key => $value) {
|
foreach ($dbconfig as $key => $value) {
|
||||||
$confarray .= sprintf(' "%s" => "%s",' . PHP_EOL, addcslashes($key, '"'), addcslashes($value, '"'));
|
$confarray .= sprintf(" '%s' => '%s'," . PHP_EOL, addcslashes($key, '"'), addcslashes($value, '"'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove semicolon and new line from the end
|
// Remove semicolon and new line from the end
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ $(document).ready(function() {
|
|||||||
language: {
|
language: {
|
||||||
url: "https://cdn.datatables.net/plug-ins/1.10.19/i18n/" + DATATABLES_LANGUAGE_NAME + ".json"
|
url: "https://cdn.datatables.net/plug-ins/1.10.19/i18n/" + DATATABLES_LANGUAGE_NAME + ".json"
|
||||||
},
|
},
|
||||||
|
initComplete: function(settings, json) {
|
||||||
|
console.log("DataTables Loaded")
|
||||||
|
$("#banlist-loader").hide()
|
||||||
|
$("#banlist").show()
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
It looks better with the "search" text as an placeholder instead of the label
|
It looks better with the "search" text as an placeholder instead of the label
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class ServerIconCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function syncIcons() {
|
public static function syncIcons() {
|
||||||
if (!file_exists(self::$iconsCacheDir) && !mkdir(self::$iconsCacheDir, true)) {
|
if (!file_exists(self::$iconsCacheDir) && !mkdir(self::$iconsCacheDir)) {
|
||||||
throw new \Exception("Cannot create icons cache directory at " . self::$iconsCacheDir);
|
throw new \Exception("Cannot create icons cache directory at " . self::$iconsCacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Wruczek\TSWebsite\Utils;
|
namespace Wruczek\TSWebsite\Utils;
|
||||||
use Medoo\Medoo;
|
use Medoo\Medoo;
|
||||||
|
use PDO;
|
||||||
use Wruczek\TSWebsite\Config;
|
use Wruczek\TSWebsite\Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,7 +29,14 @@ class DatabaseUtils {
|
|||||||
public function getDb() {
|
public function getDb() {
|
||||||
if($this->db === null) {
|
if($this->db === null) {
|
||||||
try {
|
try {
|
||||||
$db = new Medoo($this->configUtils->getDatabaseConfig());
|
$config = $this->configUtils->getDatabaseConfig();
|
||||||
|
|
||||||
|
// Enable DB exceptions instead of silent fails
|
||||||
|
$config["option"] = [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
];
|
||||||
|
|
||||||
|
$db = new Medoo($config);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
TemplateUtils::i()->renderErrorTemplate("DB error", "Connection to database failed", $e->getMessage());
|
TemplateUtils::i()->renderErrorTemplate("DB error", "Connection to database failed", $e->getMessage());
|
||||||
exit;
|
exit;
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ namespace Wruczek\TSWebsite\Utils;
|
|||||||
use Wruczek\TSWebsite\Utils\Language\LanguageUtils;
|
use Wruczek\TSWebsite\Utils\Language\LanguageUtils;
|
||||||
|
|
||||||
class DateUtils {
|
class DateUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current date format based on current user language. If it cannot
|
* Returns current date format based on current user language. If it cannot
|
||||||
* be retrieved, default value is returned
|
* be retrieved, default value is returned
|
||||||
* @return string date format
|
* @return string date format
|
||||||
*/
|
*/
|
||||||
public function getDateFormat() {
|
public static function getDateFormat() {
|
||||||
try {
|
try {
|
||||||
return LanguageUtils::i()->translate("DATE_FORMAT");
|
return LanguageUtils::i()->translate("DATE_FORMAT");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@@ -23,7 +24,7 @@ class DateUtils {
|
|||||||
* be retrieved, default value is returned
|
* be retrieved, default value is returned
|
||||||
* @return string time format
|
* @return string time format
|
||||||
*/
|
*/
|
||||||
public function getTimeFormat() {
|
public static function getTimeFormat() {
|
||||||
try {
|
try {
|
||||||
return LanguageUtils::i()->translate("TIME_FORMAT");
|
return LanguageUtils::i()->translate("TIME_FORMAT");
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@@ -36,8 +37,8 @@ class DateUtils {
|
|||||||
* @param $timestamp
|
* @param $timestamp
|
||||||
* @return false|string
|
* @return false|string
|
||||||
*/
|
*/
|
||||||
public function formatToDate($timestamp) {
|
public static function formatDate($timestamp) {
|
||||||
return date($this->getDateFormat(), $timestamp);
|
return date(self::getDateFormat(), $timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,8 +46,8 @@ class DateUtils {
|
|||||||
* @param $timestamp
|
* @param $timestamp
|
||||||
* @return false|string
|
* @return false|string
|
||||||
*/
|
*/
|
||||||
public function formatToTime($timestamp) {
|
public static function foramtTime($timestamp) {
|
||||||
return date($this->getTimeFormat(), $timestamp);
|
return date(self::getTimeFormat(), $timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,63 +56,8 @@ class DateUtils {
|
|||||||
* @param string $additional additional date format
|
* @param string $additional additional date format
|
||||||
* @return false|string
|
* @return false|string
|
||||||
*/
|
*/
|
||||||
public function formatToDateTime($timestamp, $additional = "") {
|
public static function formatDatetime($timestamp, $additional = "") {
|
||||||
return date("{$this->getDateFormat()} {$this->getTimeFormat()} $additional", $timestamp);
|
return date(trim(self::getDateFormat() . ", " . self::getTimeFormat() . " " . $additional), $timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats timestamp into "time ago" string
|
|
||||||
* For example, timestamp set to 60 seconds ago will return "1 minute ago"
|
|
||||||
*
|
|
||||||
* Taken from StackOverflow: https://stackoverflow.com/a/18602474
|
|
||||||
* @param $timestamp int timestamp with past date
|
|
||||||
* @param bool $full if true, full date will be returned. For example "5 hours, 2 minutes, 8 seconds"
|
|
||||||
* @return string timestamp formatted to fuzzy date. Marf.
|
|
||||||
*/
|
|
||||||
public function fuzzyDate($timestamp, $full = false) {
|
|
||||||
$now = new \DateTime;
|
|
||||||
$ago = (new \DateTime)->setTimestamp($timestamp);
|
|
||||||
|
|
||||||
$diff = $now->diff($ago);
|
|
||||||
|
|
||||||
$diff->w = floor($diff->d / 7);
|
|
||||||
$diff->d -= $diff->w * 7;
|
|
||||||
|
|
||||||
$string = [
|
|
||||||
'y' => 'year',
|
|
||||||
'm' => 'month',
|
|
||||||
'w' => 'week',
|
|
||||||
'd' => 'day',
|
|
||||||
'h' => 'hour',
|
|
||||||
'i' => 'minute',
|
|
||||||
's' => 'second'
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($string as $k => &$v) {
|
|
||||||
if ($diff->$k) {
|
|
||||||
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
|
|
||||||
} else {
|
|
||||||
unset($string[$k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$full) $string = array_slice($string, 0, 1);
|
|
||||||
return $string ? implode(', ', $string) . ' ago' : 'just now';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns fuzzy date with abbreviation showing precise date
|
|
||||||
* @see fuzzyDate
|
|
||||||
* @param $timestamp
|
|
||||||
* @param bool $full
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function fuzzyDateHTML($timestamp, $full = false) {
|
|
||||||
$fuzzyDate = $this->fuzzyDate($timestamp, $full);
|
|
||||||
$fullDate = $this->formatToDateTime($timestamp, "T");
|
|
||||||
|
|
||||||
return '<abbr data-fuzzydate="' . $timestamp . '"></abbr>';
|
|
||||||
// return '<abbr data-toggle="tooltip" title="' . htmlentities($fullDate) . '">' . htmlentities($fuzzyDate) . '</abbr>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Wruczek\TSWebsite\Utils\Language;
|
namespace Wruczek\TSWebsite\Utils\Language;
|
||||||
|
|
||||||
use Wruczek\PhpFileCache\PhpFileCache;
|
use Wruczek\PhpFileCache\PhpFileCache;
|
||||||
|
use Wruczek\TSWebsite\Config;
|
||||||
use Wruczek\TSWebsite\Utils\DatabaseUtils;
|
use Wruczek\TSWebsite\Utils\DatabaseUtils;
|
||||||
use Wruczek\TSWebsite\Utils\SingletonTait;
|
use Wruczek\TSWebsite\Utils\SingletonTait;
|
||||||
|
|
||||||
@@ -147,10 +148,18 @@ class LanguageUtils {
|
|||||||
$langs[] = new Language($langid, $englishname, $nativename, $langcode, $isdefault, $languageItems);
|
$langs[] = new Language($langid, $englishname, $nativename, $langcode, $isdefault, $languageItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uasort($langs, function ($a, $b) {
|
||||||
|
if ($a->getLanguageId() === $b->getLanguageId()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strnatcmp($a->getLanguageNameNative(), $b->getLanguageNameNative());
|
||||||
|
});
|
||||||
|
|
||||||
$this->languages = $langs;
|
$this->languages = $langs;
|
||||||
|
|
||||||
if($updateCache)
|
if($updateCache)
|
||||||
$this->cache->store("languages", $langs, 300);
|
$this->cache->store("languages", $langs, Config::get("cache_languages", 300));
|
||||||
|
|
||||||
return $langs;
|
return $langs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,13 @@ class TemplateUtils {
|
|||||||
// Add custom filters...
|
// Add custom filters...
|
||||||
|
|
||||||
$this->getLatte()->addFilter("fuzzyDateAbbr", function ($s) {
|
$this->getLatte()->addFilter("fuzzyDateAbbr", function ($s) {
|
||||||
return new Html('<span data-relativetime="fuzzydate" data-timestamp="' . $s . '">{cannot convert ' . $s . '}</span>');
|
$default = DateUtils::formatDatetime($s);
|
||||||
|
return new Html('<span data-relativetime="fuzzydate" data-timestamp="' . $s . '">' . $default . '</span>');
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->getLatte()->addFilter("fullDate", function ($s) {
|
$this->getLatte()->addFilter("fullDate", function ($s) {
|
||||||
return new Html('<span data-relativetime="fulldate" data-timestamp="' . $s . '">{cannot convert ' . $s . '}</span>');
|
$default = DateUtils::formatDatetime($s);
|
||||||
|
return new Html('<span data-relativetime="fulldate" data-timestamp="' . $s . '">' . $default . '</span>');
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->getLatte()->addFilter("translate", function ($s, ...$args) {
|
$this->getLatte()->addFilter("translate", function ($s, ...$args) {
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ EOD;
|
|||||||
$html = "";
|
$html = "";
|
||||||
|
|
||||||
if($client["client_is_priority_speaker"]) {
|
if($client["client_is_priority_speaker"]) {
|
||||||
$html .= $this->getIcon("microphone.svg", __get("VIEWER_CLIENT_PRIORITY_SPEAKER"));
|
$html .= $this->getIcon("capture.svg", __get("VIEWER_CLIENT_PRIORITY_SPEAKER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($client["client_is_channel_commander"]) {
|
if($client["client_is_channel_commander"]) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
define("__TSWEBSITE_VERSION", "dev-2.0.1");
|
define("__TSWEBSITE_VERSION", "dev-2.0.2");
|
||||||
define("__TSWEBSITE_COMMIT", "no-commit");
|
define("__TSWEBSITE_COMMIT", "no-commit");
|
||||||
define("__BASE_DIR", __DIR__ . "/../..");
|
define("__BASE_DIR", __DIR__ . "/../..");
|
||||||
define("__PRIVATE_DIR", __BASE_DIR . "/private");
|
define("__PRIVATE_DIR", __BASE_DIR . "/private");
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<i class="fas fa-info-circle"></i>{_"BANS_EMPTY"}
|
<i class="fas fa-info-circle"></i>{_"BANS_EMPTY"}
|
||||||
</div>
|
</div>
|
||||||
{else}
|
{else}
|
||||||
|
<!-- Tip shown when the table shrinks, telling you that you can tap a row to view more -->
|
||||||
<div id="responsive-table-details-tip" class="alert alert-info alert-dismissible fade show" style="display: none" role="alert">
|
<div id="responsive-table-details-tip" class="alert alert-info alert-dismissible fade show" style="display: none" role="alert">
|
||||||
<i class="fas fa-info-circle"></i>{_"BANS_VIEW_MORE_TIP"}
|
<i class="fas fa-info-circle"></i>{_"BANS_VIEW_MORE_TIP"}
|
||||||
<button type="button" class="close" data-dismiss="alert" aria-label="{_"ARIA_CLOSE"}">
|
<button type="button" class="close" data-dismiss="alert" aria-label="{_"ARIA_CLOSE"}">
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{if $ipbanned !== false}
|
{if $ipbanned !== false}
|
||||||
|
<!-- IP ban alert -->
|
||||||
<div class="alert alert-danger ban-alert banned" role="alert">
|
<div class="alert alert-danger ban-alert banned" role="alert">
|
||||||
<i class="fas fa-exclamation-circle fa-2x"></i>
|
<i class="fas fa-exclamation-circle fa-2x"></i>
|
||||||
<div>
|
<div>
|
||||||
@@ -35,7 +37,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<table id="banlist" class="table display dt-responsive no-wrap" width="100%">
|
<!-- Loader shown when DataTables is initialising the table -->
|
||||||
|
<div id="banlist-loader" class="position-relative p-3">
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table id="banlist" class="table display dt-responsive no-wrap" width="100%" style="display: none">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th data-priority="1">{_"BANS_HEADER_TARGET"}</th>
|
<th data-priority="1">{_"BANS_HEADER_TARGET"}</th>
|
||||||
|
|||||||
Reference in New Issue
Block a user