Frontend stuff

This commit is contained in:
Roman Hergenreder 2020-04-03 22:10:21 +02:00
parent d9a20ae62e
commit efe3ada470
23 changed files with 515 additions and 650 deletions

@ -5,4 +5,4 @@ RedirectMatch 404 /\.git
RewriteEngine On RewriteEngine On
RewriteRule ^api/(.*)?$ index.php?api=$1&$2 [L,QSA] RewriteRule ^api/(.*)?$ index.php?api=$1&$2 [L,QSA]
RewriteRule ^((?!((js|css|img|fonts|api)($|\/)))(.*)?)$ index.php?site=$1&$2 [L,QSA] RewriteRule ^((?!((js|css|img|fonts|api|docs)($|/)))(.*)?)$ index.php?site=$1&$2 [L,QSA]

@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="webbase">
<words>
<w>adminlte</w>
<w>navbar</w>
</words>
</dictionary>
</component>

@ -9,7 +9,7 @@ class Fetch extends Request {
public function __construct($user, $externalCall = false) { public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array()); parent::__construct($user, $externalCall, array());
$this->loginRequired = true; $this->loginRequired = true;
// $this->requiredGroup = USER_GROUP_ADMIN; $this->requiredGroup = USER_GROUP_ADMIN;
} }
public function execute($values = array()) { public function execute($values = array()) {

@ -2,25 +2,25 @@
namespace Documents { namespace Documents {
use Documents\Admin\AdminBody;
use Documents\Admin\AdminHead; use Documents\Admin\AdminHead;
use Elements\Document; use Elements\Document;
use Objects\User;
use Views\AdminDashboard;
use Views\LoginBody;
class Admin extends Document { class Admin extends Document {
public function __construct($user) { public function __construct(User $user) {
parent::__construct($user, AdminHead::class, AdminBody::class); $body = $user->isLoggedIn() ? AdminDashboard::class : LoginBody::class;
parent::__construct($user, AdminHead::class, $body);
} }
} }
} }
namespace Documents\Admin { namespace Documents\Admin {
use Elements\Body;
use Elements\Head; use Elements\Head;
use Elements\Link; use Elements\Link;
use Elements\Script; use Elements\Script;
use Views\Admin;
use Views\Login;
class AdminHead extends Head { class AdminHead extends Head {
@ -30,7 +30,6 @@ namespace Documents\Admin {
protected function initSources() { protected function initSources() {
$this->loadJQuery(); $this->loadJQuery();
$this->loadBootstrap();
$this->loadFontawesome(); $this->loadFontawesome();
$this->addJS(Script::CORE); $this->addJS(Script::CORE);
$this->addCSS(Link::CORE); $this->addCSS(Link::CORE);
@ -56,24 +55,4 @@ namespace Documents\Admin {
return "WebBase - Administration"; return "WebBase - Administration";
} }
} }
class AdminBody extends Body {
public function __construct($document) {
parent::__construct($document);
}
public function getCode() {
$html = parent::getCode();
$document = $this->getDocument();
if(!$document->getUser()->isLoggedIn()) {
$html .= new Login($document);
} else {
$html .= new Admin($document);
}
return $html;
}
}
} }

@ -794,7 +794,7 @@ namespace Documents\Install {
</div> </div>
<div class=\"col-md-8 order-md-1\"> <div class=\"col-md-8 order-md-1\">
$progressMainview $progressMainview
<div class=\"alert$errorClass margin-top-m\" id=\"status\"$errorStyle>$this->errorString</div> <div class=\"alert$errorClass mt-4\" id=\"status\"$errorStyle>$this->errorString</div>
</div> </div>
</div> </div>
</div> </div>

@ -161,7 +161,7 @@ abstract class SQL {
$params = array(); $params = array();
if (!$tables) { if (!$tables) {
return "SELECT $columns"; return $this->execute("SELECT $columns", $params, true);
} }
$tables = $this->tableName($tables); $tables = $this->tableName($tables);

@ -69,6 +69,11 @@ abstract class Head extends View {
$this->addJS(Script::BOOTSTRAP); $this->addJS(Script::BOOTSTRAP);
} }
public function loadAdminlte() {
$this->addCSS(Link::ADMINLTE);
$this->addJS(Script::ADMINLTE);
}
public function getCode() { public function getCode() {
$header = "<head>"; $header = "<head>";

@ -24,6 +24,7 @@ class Link extends View {
// const REVEALJS = "/css/reveal.css"; // const REVEALJS = "/css/reveal.css";
// const REVEALJS_THEME_MOON = "/css/reveal_moon.css"; // const REVEALJS_THEME_MOON = "/css/reveal_moon.css";
// const REVEALJS_THEME_BLACK = "/css/reveal_black.css"; // const REVEALJS_THEME_BLACK = "/css/reveal_black.css";
const ADMINLTE = "/css/adminlte.min.css";
private string $type; private string $type;
private string $rel; private string $rel;

@ -20,7 +20,7 @@ class Script extends \View {
// const SYNTAX_HIGHLIGHTER = "/js/syntaxhighlighter.js"; // const SYNTAX_HIGHLIGHTER = "/js/syntaxhighlighter.js";
// const HIGHLIGHT = "/js/highlight.pack.js"; // const HIGHLIGHT = "/js/highlight.pack.js";
// const GOOGLE_CHARTS = "/js/loader.js"; // const GOOGLE_CHARTS = "/js/loader.js";
const BOOTSTRAP = "/js/bootstrap.min.js"; // const BOOTSTRAP = "/js/bootstrap.min.js";
// const BOOTSTRAP_DATEPICKER_JS = "/js/bootstrap-datepicker.min.js"; // const BOOTSTRAP_DATEPICKER_JS = "/js/bootstrap-datepicker.min.js";
// const POPPER = "/js/popper.min.js"; // const POPPER = "/js/popper.min.js";
// const JSMPEG = "/js/jsmpeg.min.js"; // const JSMPEG = "/js/jsmpeg.min.js";
@ -29,8 +29,10 @@ class Script extends \View {
// const REVEALJS = "/js/reveal.js"; // const REVEALJS = "/js/reveal.js";
// const REVEALJS_PLUGIN_NOTES = "/js/reveal_notes.js"; // const REVEALJS_PLUGIN_NOTES = "/js/reveal_notes.js";
const INSTALL = "/js/install.js"; const INSTALL = "/js/install.js";
const BOOTSTRAP = "/js/bootstrap.bundle.min.js";
const HIGHLIGHT_JS_LOADER = "\$(document).ready(function(){\$('code').each(function(i, block) { hljs.highlightBlock(block); }); })"; const HIGHLIGHT_JS_LOADER = "\$(document).ready(function(){\$('code').each(function(i, block) { hljs.highlightBlock(block); }); })";
const ADMINLTE = "/js/adminlte.min.js";
private string $type; private string $type;
private string $content; private string $content;

@ -2,6 +2,8 @@
namespace Elements; namespace Elements;
use View;
class Style extends View { class Style extends View {
private string $style; private string $style;

@ -50,31 +50,6 @@ abstract class View {
} }
// UI Functions // UI Functions
// TODO: do we need this in our general web-base?
public function createFileIcon($mimeType) {
$mimeType = htmlspecialchars($mimeType);
return "<img src=\"/img/icons/admin/getIcon.php?mimeType=$mimeType\" class=\"file-icon\" alt=\"[$mimeType icon]\">";
}
public function createParagraph($title, $id, $content) {
$id = replaceCssSelector($id);
$iconId = urlencode("$id-icon");
return "
<div class=\"row\">
<div class=\"col-12\">
<i class=\"fas fa-link\" style=\"display:none;position:absolute\" id=\"$iconId\"></i>
<h2 id=\"$id\" data-target=\"$iconId\" class=\"inlineLink\">$title</h2>
<div class=\"margin-bottom-xl\"><hr>$content</div>
</div>
</div>";
}
public function createSimpleParagraph($content, $class="") {
if($class) $class = " class=\"$class\"";
return "<p$class>$content</p>";
}
private function createList($items, $tag) { private function createList($items, $tag) {
if(count($items) === 0) if(count($items) === 0)
return "<$tag></$tag>"; return "<$tag></$tag>";
@ -90,19 +65,6 @@ abstract class View {
return $this->createList($items, "ul"); return $this->createList($items, "ul");
} }
public function createJumbotron($content, $lastModified=false) {
$lastModified = ($lastModified ? "<span class=\"float-right text-xxs margin-top-xxxl\">Last modified: $lastModified</span>" : "");
return "
<div class=\"row\">
<div class=\"col-12\">
<div class=\"jumbotron\">
$content
$lastModified
</div>
</div>
</div>";
}
protected function createLink($link, $title=null) { protected function createLink($link, $title=null) {
if(is_null($title)) $title=$link; if(is_null($title)) $title=$link;
return "<a href=\"$link\">$title</a>"; return "<a href=\"$link\">$title</a>";
@ -113,91 +75,16 @@ abstract class View {
return "<a href=\"$link\" target=\"_blank\" class=\"external\">$title</a>"; return "<a href=\"$link\" target=\"_blank\" class=\"external\">$title</a>";
} }
protected function createCodeBlock($code, $lang="") { protected function createIcon($icon, $type = "fas", $classes = "") {
if($lang) $lang = " class=\"$lang\""; $iconClass = "$type fa-$icon";
$html = "<pre><code$lang>";
$html .= intendCode($code);
$html .= "</code></pre>";
return $html;
}
protected function createIcon($icon, $margin = NULL) {
$marginStr = (is_null($margin) ? "" : " margin-$margin");
$iconClass = $this->getIconClass($icon);
return "<i class=\"$iconClass$marginStr\"></i>";
}
protected function getIconClass($icon) {
$mappings = array(
"sign-out" => "sign-out-alt",
"bank" => "university",
"line-chart" => "chart-line",
"circle-right" => "arrow-alt-circle-right",
"refresh" => "sync"
);
if(isset($mappings[$icon]))
$icon = $mappings[$icon];
if($icon === "spinner") if($icon === "spinner")
$icon .= " fa-spin"; $iconClass .= " fa-spin";
return "fas fa-$icon"; if($classes)
} $iconClass .= " $classes";
protected function createBootstrapTable($data) { return "<i class=\"$iconClass\"></i>";
$code = "<div class=\"container\">";
foreach($data as $row) {
$code .= "<div class=\"row margin-top-xs margin-bottom-xs\">";
$columnCount = count($row);
if($columnCount > 0) {
$remainingSize = 12;
$columnSize = 12 / $columnCount;
foreach($row as $col) {
$size = ($columnSize <= $remainingSize ? $columnSize : $remainingSize);
$content = $col;
$class = "";
$code .= "<div";
if(is_array($col)) {
foreach($col as $key => $val) {
if(strcmp($key, "content") === 0) {
$content = $val;
} else if(strcmp($key, "class") === 0) {
$class = " " . $col["class"];
} else if(strcmp($key, "cols") === 0 && is_numeric($val)) {
$size = intval($val);
} else {
$code .= " $key=\"$val\"";
}
}
$content = (isset($col["content"]) ? $col["content"] : "");
if(isset($col["class"])) $class = " " . $col["class"];
}
if($size <= 6) $class .= " col-md-" . intval($size * 2);
$code .= " class=\"col-lg-$size$class\">$content</div>";
$remainingSize -= $size;
}
}
$code .= "</div>";
}
$code .= "</div>";
return $code;
}
protected function createBash($command, $output="", $prefix="") {
$command = htmlspecialchars($command);
$output = htmlspecialchars($output);
$output = str_replace("\n", "<br>", $output);
return "<div class=\"bash\">
<span>$prefix$</span>&nbsp;
<span>$command</span><br>
<span>$output</span>
</div>";
} }
protected function createErrorText($text, $id="", $hidden=false) { protected function createErrorText($text, $id="", $hidden=false) {

@ -1,47 +0,0 @@
<?php
namespace Views;
// Source: https://adminlte.io/themes/v3/
class Admin extends \View {
public function __construct($document) {
parent::__construct($document);
}
private function getMainHeader() {
$home = L("Home");
$search = L("Search");
$iconMenu = $this->createIcon("bars");
$iconSearch = $this->createIcon("search");
$iconNotifications = $this->createIcon("bell");
$header = "";
return $header;
}
private function getMainContent() {
return "";
}
private function getSideBar() {
return "";
}
public function getCode() {
$html = parent::getCode();
$html .= "<div class=\"main-wrapper\">";
$html .= $this->getMainHeader();
$html .= "<div id=\"content\">";
$html .= $this->getSideBar();
$html .= $this->getMainContent();
$html .= "</div>
</div>";
return $html;
}
}
?>

@ -0,0 +1,230 @@
<?php
namespace Views;
// Source: https://adminlte.io/themes/v3/
use Elements\Body;
use Elements\Script;
class AdminDashboard extends Body {
private array $errorMessages;
public function __construct($document) {
parent::__construct($document);
$this->errorMessages = array();
}
private function getNotifications() : array {
$req = new \Api\Notifications\Fetch($this->getDocument()->getUser());
if(!$req->execute()) {
$this->errorMessages[] = $req->getLastError();
return array();
} else {
return $req->getResult()['notifications'];
}
}
private function getUsers() : array {
$req = new \Api\User\Fetch($this->getDocument()->getUser());
if(!$req->execute()) {
$this->errorMessages[] = $req->getLastError();
return array();
} else {
return $req->getResult()['users'];
}
}
private function getHeader() {
// Locale
$home = L("Home");
$search = L("Search");
// Icons
$iconMenu = $this->createIcon("bars");
$iconNotification = $this->createIcon("bell", "far");
$iconSearch = $this->createIcon("search");
$iconMail = $this->createIcon("envelope", "fas");
// Notifications
$notifications = $this->getNotifications();
$numNotifications = count($notifications);
if ($numNotifications === 0) {
$notificationText = L("No new notifications");
} else if($numNotifications === 1) {
$notificationText = L("1 new notification");
} else {
$notificationText = sprintf(L("%d new notification"), $numNotifications);
}
$html =
"<nav class=\"main-header navbar navbar-expand navbar-white navbar-light\">
<!-- Left navbar links -->
<ul class=\"navbar-nav\">
<li class=\"nav-item\">
<a class=\"nav-link\" data-widget=\"pushmenu\" href=\"#\" role=\"button\">$iconMenu</a>
</li>
<li class=\"nav-item d-none d-sm-inline-block\">
<a href=\"/\" class=\"nav-link\">$home</a>
</li>
</ul>
<!-- SEARCH FORM -->
<form class=\"form-inline ml-3\">
<div class=\"input-group input-group-sm\">
<input class=\"form-control form-control-navbar\" type=\"search\" placeholder=\"$search\" aria-label=\"$search\">
<div class=\"input-group-append\">
<button class=\"btn btn-navbar\" type=\"submit\">
$iconSearch
</button>
</div>
</div>
</form>
<!-- Right navbar links -->
<ul class=\"navbar-nav ml-auto\">
<!-- Notifications Dropdown Menu -->
<li class=\"nav-item dropdown\">
<a class=\"nav-link\" data-toggle=\"dropdown\" href=\"#\">
$iconNotification
<span class=\"badge badge-warning navbar-badge\">$numNotifications</span>
</a>
<div class=\"dropdown-menu dropdown-menu-lg dropdown-menu-right\">
<span class=\"dropdown-item dropdown-header\">$notificationText</span>
<div class=\"dropdown-divider\"></div>";
// Notifications
$i = 0;
foreach($notifications as $notification) {
$title = $notification["title"];
$notificationId = $notification["uid"];
$createdAt = getPeriodString($notification["created_at"]);
if ($i > 0) {
$html .= "<div class=\"dropdown-divider\"></div>";
}
$html .=
"<a href=\"#\" class=\"dropdown-item\" data-id=\"$notificationId\">
$iconMail<span class=\"ml-2\">$title</span>
<span class=\"float-right text-muted text-sm\">$createdAt</span>
</a>";
$i++;
if ($i >= 5) {
break;
}
}
$html .= "<a href=\"#\" class=\"dropdown-item dropdown-footer\">See All Notifications</a>
</div>
</li>
</ul>
</nav>";
return $html;
}
private function getSidebar() {
$menuEntries = array(
"dashboard" => array(
"name" => "Dashboard",
"icon" => "tachometer-alt"
),
"users" => array(
"name" => "Users",
"icon" => "users"
),
"settings" => array(
"name" => "Settings",
"icon" => "tools"
),
"help" => array(
"name" => "Help",
"icon" => "question-circle"
),
);
$currentView = $_GET["view"] ?? "dashboard";
$html =
"<aside class=\"main-sidebar sidebar-dark-primary elevation-4\">
<!-- Brand Logo -->
<a href=\"index3.html\" class=\"brand-link\">
<img src=\"/img/web_base_logo.png\" alt=\"WebBase Logo\" class=\"brand-image img-circle elevation-3\"
style=\"opacity: .8\">
<span class=\"brand-text font-weight-light\">WebBase</span>
</a>
<!-- Sidebar -->
<div class=\"sidebar\">
<!-- Sidebar Menu -->
<nav class=\"mt-2\">
<ul class=\"nav nav-pills nav-sidebar flex-column\" data-widget=\"treeview\" role=\"menu\" data-accordion=\"false\">";
foreach($menuEntries as $view => $menuEntry) {
$name = L($menuEntry["name"]);
$icon = $this->createIcon($menuEntry["icon"], "fas", "nav-icon");
$active = ($currentView === $view) ? " active" : "";
$html .=
"<li class=\"nav-item\">
<a href=\"?view=$view\" class=\"nav-link$active\">
$icon
<p>$name </p>
</a>
</li>";
}
$html .=
"</ul>
</nav>
</div>
</aside>";
return $html;
}
private function getContent() {
$this->getUsers();
$html = "<div class=\"content-wrapper p-2\">";
foreach($this->errorMessages as $errorMessage) {
$html .= $this->createErrorText($errorMessage);
}
$html .= "</div>";
return $html;
}
public function getCode() {
$head = $this->getDocument()->getHead();
$head->addJS(Script::BOOTSTRAP);
$head->loadAdminlte();
$header = $this->getHeader();
$sidebar = $this->getSidebar();
$content = $this->getContent();
$html =
"<!-- LICENSE: /docs/LICENSE_ADMINLTE -->
<body class=\"hold-transition sidebar-mini layout-fixed\">
<div class=\"wrapper\">
$header
$sidebar
$content
</div>
</body>";
return $html;
}
}

@ -2,6 +2,8 @@
namespace Views; namespace Views;
use Api\GetLanguages;
class LanguageFlags extends \View { class LanguageFlags extends \View {
public function __construct($document) { public function __construct($document) {
@ -14,7 +16,7 @@ class LanguageFlags extends \View {
$queryString = $_SERVER['QUERY_STRING']; $queryString = $_SERVER['QUERY_STRING'];
$flags = array(); $flags = array();
$request = new \Api\GetLanguages($this->getDocument()->getUser()); $request = new GetLanguages($this->getDocument()->getUser());
$params = explode("&", $queryString); $params = explode("&", $queryString);
$query = array(); $query = array();
foreach($params as $param) { foreach($params as $param) {
@ -40,7 +42,7 @@ class LanguageFlags extends \View {
$flags[] = $this->createLink( $flags[] = $this->createLink(
"$url$queryString", "$url$queryString",
"<img src=\"/img/icons/lang/$langCode.gif\" alt=\"$langName\" title=\"$langName\">" "<img class=\"p-1\" src=\"/img/icons/lang/$langCode.gif\" alt=\"$langName\" title=\"$langName\">"
); );
} }
} else { } else {

@ -2,53 +2,65 @@
namespace Views; namespace Views;
use View; use Elements\Body;
class LoginBody extends Body {
class Login extends View {
public function __construct($document) { public function __construct($document) {
parent::__construct($document); parent::__construct($document);
} }
public function getCode() { public function getCode() {
$html = parent::getCode();
$this->getDocument()->getHead()->loadBootstrap();
$username = L("Username"); $username = L("Username");
$password = L("Password"); $password = L("Password");
$rememberMe = L("Remember me");
$login = L("Login"); $login = L("Login");
$backToStartPage = L("Back to Start Page"); $backToStartPage = L("Back to Start Page");
$stayLoggedIn = L("Stay logged in");
$flags = new LanguageFlags($this->getDocument()); $flags = new LanguageFlags($this->getDocument());
$iconBack = $this->createIcon("arrow-circle-left", "right"); $iconBack = $this->createIcon("arrow-circle-left");
$domain = $_SERVER['HTTP_HOST']; $domain = $_SERVER['HTTP_HOST'];
$protocol = getProtocol(); $protocol = getProtocol();
$html = "<body>";
$accountCreated = ""; $accountCreated = "";
if(isset($_GET["accountCreated"])) { if(isset($_GET["accountCreated"])) {
$accountCreated .= ' $accountCreated =
<div class="alert alert-success margin-top-xs" id="accountCreated"> '<div class="alert alert-success mt-3" id="accountCreated">
Your account was successfully created, you may now login with your credentials Your account was successfully created, you may now login with your credentials
</div>'; </div>';
} }
$html .= " $html .= "
<div class=\"container margin-top-xxl\"> <div class=\"container mt-4\">
<div class=\"title text-center\"> <div class=\"title text-center\">
<h2>Admin Control Panel</h2> <h2>Admin Control Panel</h2>
</div> </div>
<div class=\"loginContainer margin-center\"> <div class=\"loginContainer m-auto\">
<form class=\"loginForm\"> <form class=\"loginForm\">
<label for=\"username\">$username</label> <label for=\"username\">$username</label>
<input type=\"text\" class=\"form-control\" name=\"username\" id=\"username\" placeholder=\"$username\" required autofocus /> <input type=\"text\" class=\"form-control\" name=\"username\" id=\"username\" placeholder=\"$username\" required autofocus />
<label for=\"password\">$password</label> <label for=\"password\">$password</label>
<input type=\"password\" class=\"form-control\" name=\"password\" id=\"password\" placeholder=\"$password\" required /> <input type=\"password\" class=\"form-control\" name=\"password\" id=\"password\" placeholder=\"$password\" required />
<div class=\"form-check\">
<input type=\"checkbox\" class=\"form-check-input\" id=\"stayLoggedIn\" name=\"stayLoggedIn\">
<label class=\"form-check-label\" for=\"stayLoggedIn\">$stayLoggedIn</label>
</div>
<button class=\"btn btn-lg btn-primary btn-block\" id=\"btnLogin\" type=\"button\">$login</button> <button class=\"btn btn-lg btn-primary btn-block\" id=\"btnLogin\" type=\"button\">$login</button>
<div class=\"alert alert-danger hidden\" role=\"alert\" id=\"loginError\"></div> <div class=\"alert alert-danger hidden\" role=\"alert\" id=\"loginError\"></div>
<span class=\"flags position-absolute\">$flags</span>
</form> </form>
<span class=\"subtitle flags-container\"><span class=\"flags\">$flags</span></span> <div class=\"p-1\">
<span class=\"subtitle\"><a class=\"link\" href=\"$protocol://$domain\">$iconBack&nbsp;$backToStartPage</a></span> <a href=\"$protocol://$domain\">$iconBack&nbsp;$backToStartPage</a>
</div>
$accountCreated $accountCreated
</div> </div>
</div>"; </div>
</body>";
return $html; return $html;
} }

@ -10,6 +10,7 @@
border-radius: 5px; border-radius: 5px;
background-color: #bbb; background-color: #bbb;
color: black; color: black;
position: relative;
} }
.loginForm input { .loginForm input {
@ -27,8 +28,38 @@
vertical-align: bottom; vertical-align: bottom;
} }
.flags {
background-color: #999;
padding: 6px 3px 3px 3px;
border-radius: 4px;
bottom: -27px;
right: 5px;
z-index: -99;
}
.main-header { .main-header {
transition: all 0.3s;
margin-left: 75px;
border-bottom: 1px solid #dee2e6; border-bottom: 1px solid #dee2e6;
padding: 0.7rem;
}
.navbar-badge {
font-size: .6rem;
font-weight: 300;
padding: 2px 4px;
position: absolute;
right: 3px;
top: 7px;
}
.navbar-white {
background-color: #fff;
}
.main-wrapper:not(.sidebar-collapsed) .main-header {
transition: all 0.3s;
margin-left: 250px;
} }
.main-sidebar { .main-sidebar {
@ -43,11 +74,40 @@
transition: all 0.3s; transition: all 0.3s;
} }
.content-wrapper { .main-sidebar.collapsed {
background: #f4f6f9; margin-left: 0;
width: 4.6rem;
}
.hide-collapsed {
transition: all 0.2s linear;
opacity: 1;
}
.main-sidebar.collapsed .hide-collapsed {
opacity: 0;
font-size: 0;
margin-left: 0;
}
.main-content {
/* background-color: red; */
height: 100%;
} }
.main-wrapper { .main-wrapper {
display: flex; height: 100%;
width: 100%; }
.dropdown-menu-lg {
max-width: 300px;
min-width: 280px;
padding: 0;
}
.brand-link {
display: block;
font-size: 1.5rem;
line-height: 2;
padding: 1rem;
} }

12
css/adminlte.min.css vendored Executable file

File diff suppressed because one or more lines are too long

@ -2,138 +2,11 @@ html, body {
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: "Verdana"; font-family: "Verdana", serif;
color: #555; color: #555;
} }
.syntaxhighlighter { margin-left: -25px; }
.no-underline:hover { text-decoration: none; }
.background { background-color: #fefefe; }
.background-gray { background-color: gray; }
.background-lightgray { background-color: lightgray; }
.background-light-blue { background-color: rgb(88, 160, 224); }
.background-jumbotron { background-color: #e9ecef; }
/* TEXT COLOR */
.text-white, .text-white:hover { color: white }
.text-black, .text-black:hover { color: black; }
.text-gray, .text-gray:hover { color: gray; }
.text-default, .text-default:hover { color: #555; }
.text-title, .text-title:hover { color: #333; text-decoration: underline; font-weight: bold; font-size: 1.7em; }
.text-red, .text-red:hover { color: red; }
.text-inherit, .text-inherit:hover { color: inherit; }
.text-green-attr { color: #50a14f; }
.text-cyan { color: cyan; }
.highlight { background-color: yellow; }
.code-box { background-color: #e0e0e0;
color: rgba(0,0,0,.87);
border-radius: 1px;
padding: 2px;
border: 1px solid #ddd;
word-break: break-all;
overflow-wrap: anywhere;
}
/* TEXT TRANSFORM */
.underline { text-decoration: underline; }
.italic { font-style: italic; }
.bold { font-weight: bold; }
.text-super { vertical-align : super; }
/* TEXT SIZE */
.text-xxs { font-size: 13px; }
.text-xs { font-size: 15px; }
.text-m { font-size: 20px; }
.text-xl { font-size: 22px; }
.text-xxl { font-size: 25px; }
.text-xxxl { font-size: 30px; }
/* MARGINS */
.margin-xs { margin: 5px; }
.margin-m { margin: 10px; }
.margin-xl { margin: 15px; }
.margin-top-xxs { margin-top: 10px; }
.margin-top-xs { margin-top: 15px; }
.margin-top-m { margin-top: 20px; }
.margin-top-xl { margin-top: 25px; }
.margin-top-xxl { margin-top: 30px; }
.margin-top-xxxl { margin-top: 40px; }
.margin-bottom-xxs { margin-bottom: 10px; }
.margin-bottom-xs { margin-bottom: 15px; }
.margin-bottom-m { margin-bottom: 20px; }
.margin-bottom-xl { margin-bottom: 25px; }
.margin-bottom-xxl { margin-bottom: 30px; }
.margin-bottom-xxxl { margin-bottom: 40px; }
.margin-left-xxs { margin-left: 10px; }
.margin-left-xs { margin-left: 15px; }
.margin-left-m { margin-left: 20px; }
.margin-left-xl { margin-left: 25px; }
.margin-left-xxl { margin-left: 30px; }
.margin-center { margin-left: auto; margin-right: auto; }
.margin-none { margin: 0 !important; }
/* PADDINGS */
.padding-xs { padding: 5px; }
.padding-m { padding: 10px; }
.padding-xl { padding: 15px; }
.padding-xxl { padding: 20px; }
.padding-xxxl { padding: 25px; }
.padding-top-m { padding-top: 10px; }
.padding-top-xl { padding-top: 15px; }
.padding-top-xxl { padding-top: 20px; }
.padding-bottom-m { padding-bottom: 10px; }
.padding-bottom-xxl { padding-bottom: 20px; }
.padding-left-xs { padding-left: 5px; }
.padding-left-xl { padding-left: 15px; }
.padding-none { padding: 0; }
/* BORDER */
.round { border-radius: 50%; }
.border-white { border-color: white; }
.border-grey { border-color: grey; }
.border-xxs { border: 1px solid; }
.border-xs { border: 2px solid; }
.border-m { border: 3px solid; }
.border-bottom-xss { border-bottom: 1px solid; }
.round-border-xs { border-radius: 2px; }
.round-border { border-radius: 5px; }
.round-border-xl { border-radius: 10px; }
.self-center { align-self: center; }
/* LAYOUT */
.fullheight { height: 100%; }
.fullwidth { width: 100%; }
.max-full-width { max-width: 100%; }
.restwidth { width: auto; }
.width-75 { width: 75%; }
.relative { position: relative; }
.absolute { position: absolute; }
.bottom { bottom: 0; }
.hide-overflow { overflow: hidden; }
.hidden { display: none; } .hidden { display: none; }
.clickable { cursor: pointer; }
/* SCROLLBARS */
.vertical-scroll { overflow-y: auto; }
.mainContent {
margin-top: 40px;
margin-bottom: 100px;
}
.sidebar-toggle {
position: absolute;
top: 15px;
left: 15px;
}
.sidebar-toggle:hover {
background-color: rgb(69, 150, 240);
}
.external::after { .external::after {
font-family: "Font Awesome 5 Free"; font-family: "Font Awesome 5 Free";
@ -142,85 +15,3 @@ html, body {
font-size: 10px; font-size: 10px;
vertical-align: super; vertical-align: super;
} }
.navigation {
padding-left: 15px;
}
.fullscreen-container {
margin: auto;
position: fixed;
top: 0; left: 0; bottom: 0; right: 0;
z-index: 9999;
overflow-y: auto;
overflow-x: hidden;
background-color: transparent;
background-color: #000;
background-color: rgba(0, 0, 0, 0.6);
}
.thumbnail {
border: 3px solid gray;
}
.fullscreen-container > img {
position: fixed;
z-index: 1000;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 95%;
max-height: 95%;
height: auto;
border: 3px solid gray;
}
.closeButton {
position: fixed;
top: 30px;
right: 30px;
padding: 5px 9px 5px 9px;
background-color: #ddd;
border: 1px solid black;
font-size: 20px;
font-weight: bold;
cursor: pointer;
}
.flags {
padding: 3px;
}
.flags > a {
margin: 5px;
}
span > .hljs {
display: inline;
padding: .2em;
}
.inlineLink:hover {
text-decoration: underline;
cursor: pointer;
}
.bash {
background-color: #2E3436;
padding: 3px 5px 3px 5px;
}
.bash > span {
color: #D3D7CF;
overflow-wrap: anywhere;
word-break: break-all;
}
.bash > span:first-child {
display: inline;
color: #4E9A06;
}
.file-icon {
padding-bottom: 5px;
}

20
docs/LICENSE_ADMINLTE Normal file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014-2018 almasaeed2010
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@ -2,16 +2,17 @@ $(document).ready(function() {
$("#username").keypress(function(e) { if(e.which == 13) $("#password").focus(); }); $("#username").keypress(function(e) { if(e.which == 13) $("#password").focus(); });
$("#password").keypress(function(e) { if(e.which == 13) $("#btnLogin").click(); }); $("#password").keypress(function(e) { if(e.which == 13) $("#btnLogin").click(); });
$("#btnLogin").click(function() { $("#btnLogin").click(function() {
var username = $("#username").val(); const username = $("#username").val();
var password = $("#password").val(); const password = $("#password").val();
var errorDiv = $("#loginError"); const errorDiv = $("#loginError");
var createdDiv = $("#accountCreated"); const createdDiv = $("#accountCreated");
var btn = $(this); const stayLoggedIn = $("#stayLoggedIn").is(":checked");
const btn = $(this);
errorDiv.hide(); errorDiv.hide();
btn.prop("disabled", true); btn.prop("disabled", true);
btn.html("Logging in… <i class=\"fa fa-spin fa-circle-notch\"></i>"); btn.html("Logging in… <i class=\"fa fa-spin fa-circle-notch\"></i>");
jsCore.apiCall("user/login", {"username": username, "password": password}, function(data) { jsCore.apiCall("/user/login", {"username": username, "password": password, "stayLoggedIn": stayLoggedIn }, function(data) {
window.location.reload(); window.location.reload();
}, function(err) { }, function(err) {
btn.html("Login"); btn.html("Login");
@ -22,4 +23,9 @@ $(document).ready(function() {
errorDiv.show(); errorDiv.show();
}); });
}); });
$("#toggleSidebar").click(function() {
$(".main-wrapper").toggleClass("sidebar-collapsed");
$(".main-sidebar").toggleClass("collapsed");
});
}); });

7
js/adminlte.min.js vendored Normal file

File diff suppressed because one or more lines are too long

7
js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

@ -1,108 +1,79 @@
var Core = function() { let Core = function () {
this.__construct = function() { this.__construct = function () {
this.url = document.location.href; this.url = document.location.href;
this.parseParameters(); this.parseParameters();
this.langEntries = {}; this.langEntries = {};
}; };
this.apiCall = function(func, aParams, callback, onerror) { this.apiCall = function (func, aParams, callback, onerror) {
aParams = typeof aParams !== 'undefined' ? aParams : { }; aParams = typeof aParams !== 'undefined' ? aParams : {};
callback = typeof callback !== 'undefined' ? callback : function(data) { }; callback = typeof callback !== 'undefined' ? callback : function (data) {};
onerror = typeof onerror !== 'undefined' ? onerror : function(msg) { bootbox.alert("Ein Fehler ist aufgetreten: " + msg); };
$.post('/api/' + func, aParams, function(data) { onerror = typeof onerror !== 'undefined' ? onerror : function (msg) {
bootbox.alert("An error occurred: " + msg);
};
const path = '/api' + (func.startsWith('/') ? '' : '/') + func;
$.post(path, aParams, function (data) {
console.log(func + "(): success=" + data.success + " msg=" + data.msg); console.log(func + "(): success=" + data.success + " msg=" + data.msg);
if(data.hasOwnProperty('logoutIn') && $("#logoutTimer").length > 0) { if (data.hasOwnProperty('logoutIn') && $("#logoutTimer").length > 0) {
$("#logoutTimer").attr("data-time", data.logoutIn); $("#logoutTimer").attr("data-time", data.logoutIn);
} }
if(!data.success) { if (!data.success) {
onerror.call(this, data.msg); onerror.call(this, data.msg);
} else { } else {
callback.call(this, data); callback.call(this, data);
} }
}, "json").fail(function(jqXHR, textStatus, errorThrown) { }, "json").fail(function (jqXHR, textStatus, errorThrown) {
console.log("API-Function Error: " + func + " Status: " + textStatus + " error thrown: " + errorThrown); console.log("API-Function Error: " + func + " Status: " + textStatus + " error thrown: " + errorThrown);
onerror.call(this, "An error occurred. API-Function: " + func + " Status: " + textStatus + " - " + errorThrown); onerror.call(this, "An error occurred. API-Function: " + func + " Status: " + textStatus + " - " + errorThrown);
}); });
}; };
this.getCookie = function(cname) { this.getCookie = function (cname) {
var name = cname + "="; var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie); var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(";"); var ca = decodedCookie.split(";");
for(var i = 0; i < ca.length; i++) { for (var i = 0; i < ca.length; i++) {
var c = ca[i]; var c = ca[i];
while (c.charAt(0) == ' ') { while (c.charAt(0) === ' ') {
c = c.substring(1); c = c.substring(1);
} }
if (c.indexOf(name) == 0) { if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length); return c.substring(name.length, c.length);
} }
} }
return ""; return "";
}; };
this.requestData = function(api, dest, src, callback) { this.addLangEntry = function (key, val) {
if(typeof dest != "undefined" && Object.keys(dest).length > 0) this.langEntries[key] = val;
return true;
callback = typeof callback !== 'undefined' ? callback : function() { };
var core = this;
var dialog = bootbox.dialog({
message: 'Loading ' + src + '... <i class="fa fa-spin fa-spinner"></i>',
closeButton: false
}).bind('shown.bs.modal',function(){
core.apiCall(api, { }, function(data) {
for(var id in data[src])
dest[id] = data[src][id];
dialog.modal('hide');
callback.call(this);
}, function(msg) {
bootbox.alert("Ein Fehler ist aufgetreten: " + msg);
dialog.modal('hide');
});
});
return false;
}; };
this.requestTags = function(callback) { this.getLangEntry = function (key) {
this.aTags = typeof this.aTags == "undefined" ? { } : this.aTags; if (typeof this.langEntries[key] !== 'undefined' && this.langEntries.hasOwnProperty(key)) {
return this.requestData('tags/getTags', this.aTags, 'tags', callback);
};
this.requestAccounts = function(callback) {
this.aAccounts = typeof this.aAccounts == "undefined" ? { } : this.aAccounts;
return this.requestData('accounts/getAccounts', this.aAccounts, 'accounts', callback);
};
this.requestPartners = function(callback) {
this.aPartners = typeof this.aPartners == "undefined" ? { } : this.aPartners;
return this.requestData('accounts/getPartners', this.aPartners, 'partners', callback);
};
this.addLangEntry = function(key, val) { this.langEntries[key] = val; };
this.getLangEntry = function(key) {
if(typeof this.langEntries[key] !== 'undefined' && this.langEntries.hasOwnProperty(key)) {
return this.langEntries[key]; return this.langEntries[key];
} }
return key; return key;
}; };
this.getUrl = function() { return this.url; }; this.getUrl = function () {
this.getParameters = function() { return this.aParameters; }; return this.url;
};
this.setTitle = function(title) { this.getParameters = function () {
return this.aParameters;
};
this.setTitle = function (title) {
document.title = title; document.title = title;
}; };
this.changeURL = function(history) { this.changeURL = function (history) {
if(history) { if (history) {
window.history.pushState({ window.history.pushState({
"html": document.getElementsByTagName("body")[0].innerHTML, "html": document.getElementsByTagName("body")[0].innerHTML,
"pageTitle": document.title "pageTitle": document.title
@ -115,37 +86,37 @@ var Core = function() {
} }
}; };
this.redirect = function() { this.redirect = function () {
window.location = this.url; window.location = this.url;
}; };
this.reload = function() { this.reload = function () {
window.location.reload(); window.location.reload();
}; };
this.removeParameter = function(param) { this.removeParameter = function (param) {
if (typeof this.aParameters[param] !== 'undefined' && this.aParameters.hasOwnProperty(param)) { if (typeof this.aParameters[param] !== 'undefined' && this.aParameters.hasOwnProperty(param)) {
delete this.aParameters[param]; delete this.aParameters[param];
} }
this.updateUrl(); this.updateUrl();
}; };
this.getParameter = function(param) { this.getParameter = function (param) {
if (typeof this.aParameters[param] !== 'undefined' && this.aParameters.hasOwnProperty(param)) if (typeof this.aParameters[param] !== 'undefined' && this.aParameters.hasOwnProperty(param))
return this.aParameters[param]; return this.aParameters[param];
else else
return null; return null;
}; };
this.setParameter = function(param, newvalue) { this.setParameter = function (param, newvalue) {
newvalue = typeof newvalue !== 'undefined' ? newvalue : ''; newvalue = typeof newvalue !== 'undefined' ? newvalue : '';
this.aParameters[param] = newvalue; this.aParameters[param] = newvalue;
this.updateUrl(); this.updateUrl();
}; };
this.parseParameters = function() { this.parseParameters = function () {
this.aParameters = []; this.aParameters = [];
if(this.url.indexOf('?') === -1) if (this.url.indexOf('?') === -1)
return; return;
var paramString = this.url.substring(this.url.indexOf('?') + 1); var paramString = this.url.substring(this.url.indexOf('?') + 1);
@ -153,7 +124,7 @@ var Core = function() {
for (var i = 0; i < split.length; i++) { for (var i = 0; i < split.length; i++) {
var param = split[i]; var param = split[i];
var index = param.indexOf('='); var index = param.indexOf('=');
if(index !== -1) { if (index !== -1) {
var key = param.substr(0, index); var key = param.substr(0, index);
var val = param.substr(index + 1); var val = param.substr(index + 1);
this.aParameters[key] = val; this.aParameters[key] = val;
@ -162,9 +133,9 @@ var Core = function() {
} }
}; };
this.updateUrl = function() { this.updateUrl = function () {
this.clearUrl(); this.clearUrl();
var i = 0; let i = 0;
for (var parameter in this.aParameters) { for (var parameter in this.aParameters) {
this.url += (i === 0 ? "?" : "&") + parameter; this.url += (i === 0 ? "?" : "&") + parameter;
if (this.aParameters.hasOwnProperty(parameter) && this.aParameters[parameter].toString().length > 0) { if (this.aParameters.hasOwnProperty(parameter) && this.aParameters[parameter].toString().length > 0) {
@ -174,107 +145,109 @@ var Core = function() {
} }
}; };
this.clearParameters = function() { this.clearParameters = function () {
this.aParameters = []; this.aParameters = [];
this.updateUrl(); this.updateUrl();
}; };
this.clearUrl = function() { this.clearUrl = function () {
if(this.url.indexOf('?') !== -1) if (this.url.indexOf('?') !== -1)
this.url = this.url.substring(0, this.url.indexOf('?')); this.url = this.url.substring(0, this.url.indexOf('?'));
}; };
this.logout = function() { this.logout = function () {
this.apiCall('user/logout'); this.apiCall('user/logout');
}; };
this.getJsonDateTime = function(date) { this.getJsonDateTime = function (date) {
return date.getFullYear() + "-" + return date.getFullYear() + "-" +
((date.getMonth() + 1 < 10) ? "0" : "") + (date.getMonth() + 1) + "-" + ((date.getMonth() + 1 < 10) ? "0" : "") + (date.getMonth() + 1) + "-" +
(date.getDate() < 10 ? "0" : "") + date.getDate() + " " + (date.getDate() < 10 ? "0" : "") + date.getDate() + " " +
(date.getHours() < 10 ? "0" : "") + date.getHours() + "-" + (date.getHours() < 10 ? "0" : "") + date.getHours() + "-" +
(date.getMinutes() < 10 ? "0" : "") + date.getMinutes() + "-" + (date.getMinutes() < 10 ? "0" : "") + date.getMinutes() + "-" +
(date.getSeconds() < 10 ? "0" : "") + date.getSeconds(); (date.getSeconds() < 10 ? "0" : "") + date.getSeconds();
}; };
this.getJsonDate = function(date) { this.getJsonDate = function (date) {
return this.getJsonDateTime(date).split(' ')[0]; return this.getJsonDateTime(date).split(' ')[0];
}; };
this.getJsonTime = function(date) { this.getJsonTime = function (date) {
return this.getJsonDateTime(date).split(' ')[1]; return this.getJsonDateTime(date).split(' ')[1];
}; };
this.showInputDialog = function(title, aInputs, callback, element, onCreated) { this.showInputDialog = function (title, aInputs, callback, element, onCreated) {
title = typeof title !== "undefined" ? title : ""; title = typeof title !== "undefined" ? title : "";
aInputs = typeof aInputs !== "undefined" ? aInputs : {}; aInputs = typeof aInputs !== "undefined" ? aInputs : {};
callback = typeof callback !== "undefined" ? callback : function(aResult, element) {}; callback = typeof callback !== "undefined" ? callback : function (aResult, element) {
onCreated = typeof onCreated !== "undefined" ? onCreated : function() {}; };
onCreated = typeof onCreated !== "undefined" ? onCreated : function () {
};
var html = '<div class="modal-header"><h4 class="modal-title">' + title + '</h4></div>' + var html = '<div class="modal-header"><h4 class="modal-title">' + title + '</h4></div>' +
'<form class="bootbox-form">'; '<form class="bootbox-form">';
for (var i in aInputs) { for (var i in aInputs) {
var input = aInputs[i]; var input = aInputs[i];
if(input.type !== "hidden" && input.type !== "checkbox") if (input.type !== "hidden" && input.type !== "checkbox")
html += '<label for="' + input.name + '">' + input.name + ':</label>'; html += '<label for="' + input.name + '">' + input.name + ':</label>';
if(input.type === "select") { if (input.type === "select") {
html += '<select id="' + input.id + '" class="bootbox-input bootbox-input-select form-control">'; html += '<select id="' + input.id + '" class="bootbox-input bootbox-input-select form-control">';
var aValues = (input.hasOwnProperty("aValues") && typeof input.aValues !== "undefined") ? input.aValues : {}; var aValues = (input.hasOwnProperty("aValues") && typeof input.aValues !== "undefined") ? input.aValues : {};
for (var value in aValues) { for (var value in aValues) {
var name = aValues[value]; var name = aValues[value];
var selected = (input.value == value) ? " selected" : ""; var selected = (input.value === value) ? " selected" : "";
html += '<option value="' + value + '"' + selected + '>' + name + '</option>'; html += '<option value="' + value + '"' + selected + '>' + name + '</option>';
} }
html += '</select>'; html += '</select>';
input.type = "select"; input.type = "select";
} else if(input.type === "checkbox") { } else if (input.type === "checkbox") {
html += '<div class="checkbox">' + html += '<div class="checkbox">' +
'<label><table><tr>' + '<label><table><tr>' +
'<td style="vertical-align:top;padding-top:3px;">' + '<td style="vertical-align:top;padding-top:3px;">' +
'<input class="bootbox-input bootbox-input-checkbox" id="' + input.id + '" value="1" type="checkbox"'+ (input.value ? " checked" : "") + '>' + '<input class="bootbox-input bootbox-input-checkbox" id="' + input.id + '" value="1" type="checkbox"' + (input.value ? " checked" : "") + '>' +
'</td>' + '</td>' +
'<td style="padding-left: 5px;">' + input.text + '</td>' + '<td style="padding-left: 5px;">' + input.text + '</td>' +
'</tr></table></label>' + '</tr></table></label>' +
'</div>'; '</div>';
} else if(input.type === "date") { } else if (input.type === "date") {
html += '<input class="bootbox-input form-control customDatePicker" autocomplete="off" ' + html += '<input class="bootbox-input form-control customDatePicker" autocomplete="off" ' +
'type="text" ' + 'type="text" ' +
'name="' + input.name + '" ' + 'name="' + input.name + '" ' +
'id="' + input.id + '" ' + 'id="' + input.id + '" ' +
'value="' + (input.value ? input.value : "") + '"' + (input.readonly ? " readonly" : "") + 'value="' + (input.value ? input.value : "") + '"' + (input.readonly ? " readonly" : "") +
(input.maxlength ? ' maxlength="' + input.maxlength + '"' : '') + '>'; (input.maxlength ? ' maxlength="' + input.maxlength + '"' : '') + '>';
} else if(input.type === "time") { } else if (input.type === "time") {
html += '<div class="input-group">' + html += '<div class="input-group">' +
'<input class="bootbox-input" autocomplete="off" value="0" pattern="[0-9][0-9]" type="number" name="' + input.name + '" id="' + input.id + 'Hour" style="width:60px;text-align: center">' + '<input class="bootbox-input" autocomplete="off" value="0" pattern="[0-9][0-9]" type="number" name="' + input.name + '" id="' + input.id + 'Hour" style="width:60px;text-align: center">' +
'<span>:</span>' + '<span>:</span>' +
'<input class="bootbox-input" autocomplete="off" type="number" name="' + input.name + '" id="' + input.id + 'Minute" value="00" style="width:60px;text-align: center">' + '<input class="bootbox-input" autocomplete="off" type="number" name="' + input.name + '" id="' + input.id + 'Minute" value="00" style="width:60px;text-align: center">' +
'</div>'; '</div>';
} else { } else {
html += '<input class="bootbox-input form-control" autocomplete="off" ' + html += '<input class="bootbox-input form-control" autocomplete="off" ' +
'type="' + input.type + '" ' + 'type="' + input.type + '" ' +
'name="' + input.name + '" ' + 'name="' + input.name + '" ' +
'id="' + input.id + '" ' + 'id="' + input.id + '" ' +
'value="' + (input.value ? input.value : "") + '"' + (input.readonly ? " readonly" : "") + 'value="' + (input.value ? input.value : "") + '"' + (input.readonly ? " readonly" : "") +
(input.maxlength ? ' maxlength="' + input.maxlength + '"' : '') + '>'; (input.maxlength ? ' maxlength="' + input.maxlength + '"' : '') + '>';
} }
} }
html += '</form>'; html += '</form>';
var dialog = bootbox.confirm(html, function(result) { var dialog = bootbox.confirm(html, function (result) {
if(result) { if (result) {
var aResult = []; var aResult = [];
for (var i in aInputs) { for (var i in aInputs) {
var input = aInputs[i]; var input = aInputs[i];
var value = $("#" + input.id).val(); var value = $("#" + input.id).val();
if(input.type === "select") if (input.type === "select")
value = $("#" + input.id).find(":selected").val(); value = $("#" + input.id).find(":selected").val();
else if(input.type === "checkbox") else if (input.type === "checkbox")
value = $("#" + input.id).prop("checked"); value = $("#" + input.id).prop("checked");
aResult[input.id] = value; aResult[input.id] = value;
@ -283,9 +256,9 @@ var Core = function() {
} }
}); });
dialog.init(function() { dialog.init(function () {
$(".modal-body").on("keypress", "input", function(e) { $(".modal-body").on("keypress", "input", function (e) {
if(e.keyCode == 13) { if (e.keyCode === 13) {
e.preventDefault(); e.preventDefault();
$(".modal-footer .btn-primary").click(); $(".modal-footer .btn-primary").click();
} }
@ -297,99 +270,7 @@ var Core = function() {
this.__construct(); this.__construct();
}; };
let jsCore = new Core();
function findGetParameter(parameterName) {
var result = null, tmp = [];
location.search.substr(1).split("&").forEach(function (item) {
tmp = item.split("=");
if (tmp[0] === parameterName) {
result = decodeURIComponent(tmp[1]);
}
});
return result;
}
var jsCore = new Core();
$(document).ready(function() { $(document).ready(function() {
$(".nav-toggle-menu").click(function(e) {
e.preventDefault();
var ul = $(this).parents('li').find('ul');
if(ul.hasClass('closed')) {
$(this).removeClass('fa-caret-down');
$(this).addClass('fa-caret-up');
ul.animate({
"max-height": (ul.find('li').length * 38) + "px"
}, {
duration: 350,
easing: "swing",
complete: function() { ul.removeClass('closed'); }
});
} else {
$(this).removeClass('fa-caret-up');
$(this).addClass('fa-caret-down');
ul.animate({
"max-height": "0"
}, {
duration: 350,
easing: "swing",
complete: function() { ul.addClass('closed'); }
});
}
});
$(".copy").click(function() {
var text = $(this).text();
if(navigator.clipboard) {
navigator.clipboard.writeText(text).then(function() { }, function(err) {
console.error('Async: Could not copy text: ', err);
});
}
});
function toggleLinkIcon(icon, show, parent) {
if(show) {
icon.show();
if(parent) {
icon.position({
my: "right-5",
at: "left",
of: parent
});
}
} else {
icon.hide();
}
}
$(".inlineLink").mouseenter(function() {
var target = $(this).data("target");
if(target) {
var icon = $("#" + target);
toggleLinkIcon(icon, true, $(this));
}
});
$(".inlineLink").mouseleave(function() {
var target = $(this).data("target");
if(target) {
var icon = $("#" + target);
toggleLinkIcon(icon, false);
}
});
$(".inlineLink").click(function() {
var id = $(this).attr('id');
if(id) {
var url = window.location.href;
var index = url.indexOf("#");
if(index !== -1) {
url = url.substring(0, index);
}
window.location.href = url + "#" + id;
}
});
}); });