Compare commits

...

3 Commits

Author SHA1 Message Date
c490d38457 develop (#24)
Reviewed-on: https://git.eckertplayground.de/taarly/PHP_AdminTool_Projekt/pulls/24
Co-authored-by: blaerf <blaerf@gmx.de>
Co-committed-by: blaerf <blaerf@gmx.de>
2025-12-05 09:20:21 +00:00
11aec278e8 public/views/login.php aktualisiert
Hinweistext geändert
2025-12-04 11:38:51 +00:00
5aac9b6f26 develop (#15)
Reviewed-on: https://git.eckertplayground.de/taarly/PHP_AdminTool_Projekt/pulls/15
2025-12-04 11:37:42 +00:00
34 changed files with 1765 additions and 7641 deletions

297
CHANGELOG.md Normal file
View File

@ -0,0 +1,297 @@
# CHANGELOG
## 2025-12-03 — SNMP Live-Dashboard (Architektur: Service + API)
### Übersicht
Implementierung eines **dualen SNMP-Status-Systems**:
1. **Server-seitig (Initial Load):** `DashboardController``SnmpServerStatusService`
2. **Client-seitig (Live-Updates):** Browser-JavaScript → API-Endpunkt (`snmp_status.php`)
Ergebnis: **Beste User Experience** (sofortige Daten beim Laden) + **Redundanz** (Live-Polling läuft weiter, auch wenn Service fehlt).
---
## Komponente 1: Service (`app/Services/Snmp/SnmpServerStatusService.php`) — modernisiert
### Was wurde geändert?
Die alte Version ist zu streng gewesen (wirft Exception wenn "Physical Memory" nicht exakt gefunden wird).
Neue Version hat **intelligente Fallback-Logik**:
**RAM-Erkennung (in dieser Reihenfolge):**
1. Heuristik: Suche nach "Physical Memory" (exakt)
2. Fallback 1: Suche nach "physical" ODER "memory" ODER "ram" (Case-insensitive)
3. Fallback 2: Nimm den **kleinsten Storage-Eintrag** (wahrscheinlich RAM)
4. Falls alles fehlschlägt: Exception → abgefangen im Controller → 0% angezeigt
**Disk-Erkennung (in dieser Reihenfolge):**
1. Heuristik: Suche nach "C:\\" (Windows, exakt)
2. Fallback 1: Suche nach "C:" ODER "root" ODER "/" (Case-insensitive)
3. Fallback 2: Nimm den **größten Storage-Eintrag > 1 GB** (wahrscheinlich Hauptlaufwerk)
4. Falls alles fehlschlägt: Exception → abgefangen im Controller → 0% angezeigt
### Featureset
- ✅ Robuste Fehlerbehandlung (aussagekräftige `RuntimeException` für Debugging)
- ✅ Intelligente Fallbacks bei unerwarteten OID-Beschreibungen
- ✅ Unterstützung Windows + Linux
- ✅ Prüfung auf SNMP-Erweiterung und Konfiguration
- ✅ Uptime in lesbares Format konvertieren (z. B. "1 Tage, 10:17:36")
- ✅ CPU-Durchschnitt über alle Kerne
---
## Komponente 2: Controller (`app/Controllers/DashboardController.php`) — neu strukturiert
### Was wurde geändert?
Der Controller hatte nur eine Zeile geändert; jetzt **fehlertolerante Abfrage**:
```php
try {
$serverStatus = $this->snmpService->getServerStatus();
} catch (\RuntimeException $e) {
error_log('SNMP-Fehler beim initialen Laden - ' . $e->getMessage());
// Fallback-Werte werden verwendet (siehe oben)
}
```
**Effekt:**
- Wenn Service fehlschlägt: Dashboard wird trotzdem geladen (mit 0% oder 'n/a')
- Fehler wird geloggt (PHP Error-Log)
- Live-Polling (API) läuft trotzdem weiter und kann Daten liefern
- Bessere User Experience statt "Error 500"
---
## Komponente 3: API (`public/api/snmp_status.php`)
Siehe vorherige CHANGELOG-Einträge. Wichtig:
- **Identische Fallback-Logik** wie der Service
- **Session-Validierung** (nur Admins)
- **Caching** (10 Sekunden)
- **Detailliertes Logging** in `public/logs/snmp_api.log`
---
## Komponente 4: View & JavaScript (`public/views/dashboard.php`)
Siehe vorherige CHANGELOG-Einträge.
---
## Architektur: Dual-Layer System
### Layer 1: Initial Load (Server-seitig)
```
Nutzer öffnet Dashboard
DashboardController::show()
SnmpServerStatusService::getServerStatus()
SNMP-Abfrage (mit Fallbacks)
Daten sofort in View angezeigt
(Bei Fehler: Fallback-Werte wie 0%, 'n/a')
Logging in PHP Error-Log
```
**Vorteile:**
- ✅ Daten sind **sofort** sichtbar (gute UX)
- ✅ Fallbacks verhindern "Error 500"
- ✅ Service wird nur 1x pro Seitenladung aufgerufen (sparsam)
---
### Layer 2: Live-Updates (Client-seitig)
```
Browser lädt Dashboard
JavaScript addEventListener('DOMContentLoaded')
Sofort erste Abfrage: fetch('api/snmp_status.php')
Antwort: JSON mit aktuellen Daten
updateUI() aktualisiert die Karten
Alle 5 Sekunden wiederholt (setInterval)
Logging in public/logs/snmp_api.log (Server-seitig)
```
**Vorteile:**
- ✅ **Live-Updates** ohne Seite zu reload-en
- ✅ **Session-Schutz** (nur Admins können Endpunkt aufrufen)
- ✅ **Caching** reduziert SNMP-Last (10s TTL)
- ✅ **Fallback-Logik** im API unabhängig vom Service
- ✅ **Redundanz:** Wenn Service fehlt, läuft API trotzdem
---
## Logging
### PHP Error-Log (Service-Fehler)
- **Ort:** Abhängig von PHP-Konfiguration (meist `/var/log/php-errors.log` oder Windows Event-Log)
- **Format:** Standard PHP Error-Log
- **Inhalt:** SNMP-Fehler beim initialen Laden (z. B. "SNMP-Konfiguration ist unvollständig")
- **Trigger:** Nur wenn Service-Abfrage fehlschlägt
**Beispiel:**
```
[03-Dec-2025 12:05:00 UTC] DashboardController: SNMP-Fehler beim initialen Laden - SNMP-Konfiguration ist unvollständig (host fehlt).
```
### SNMP API Log (`public/logs/snmp_api.log`)
- **Ort:** `public/logs/snmp_api.log` (wird automatisch angelegt)
- **Format:** `[YYYY-MM-DD HH:MM:SS] Nachricht`
- **Inhalt:**
- Cache-Hits/Misses
- SNMP-Konfiguration
- Alle Storage-Einträge
- Erkannte Disk/RAM mit Prozentsätzen
- Fallback-Aktionen
- Finale Werte
- Fehler
**Beispiel:**
```
[2025-12-03 12:05:00] --- SNMP-Abfrage gestartet ---
[2025-12-03 12:05:00] SNMP-Host: 127.0.0.1, Community: public_ro, Timeout: 2s
[2025-12-03 12:05:00] Uptime OID: 1.3.6.1.2.1.1.3.0, Raw: "Timeticks: (1234567) 14 days, 6:14:27.67"
[2025-12-03 12:05:00] Storage[1]: Desc='Physical Memory', Size=16777216, Used=8388608, Units=1024
[2025-12-03 12:05:00] Speicher erkannt (Index 1): Physical Memory → 50.00%
[2025-12-03 12:05:00] Storage[2]: Desc='C:\\ ', Size=536870912, Used=268435456, Units=512
[2025-12-03 12:05:00] Datenträger erkannt (Index 2): C:\\ → 50.00%
[2025-12-03 12:05:00] RESULT: CPU=25, Mem=50.00, Disk=50.00
[2025-12-03 12:05:00] Cache geschrieben, TTL: 10s
```
---
## Fehlerszenarien & Behavior
### Szenario 1: SNMP läuft, alles OK
```
Service: ✅ Daten sofort angezeigt
API: ✅ Live-Updates alle 5s
Logs: ✅ Beide Logs ganz normal
```
### Szenario 2: SNMP-Erweiterung fehlt
```
Service: ❌ Exception → abgefangen → 0%, 'n/a' angezeigt
API: ❌ Exception → abgefangen → {"error": "snmp_extension_missing"}
Logs: ⚠️ Beide Logs zeigen Fehler
User-View: "Metriken werden angezeigt (0%), aber nicht aktualisiert"
Aktion: Admin sieht Fehler im Log und installiert SNMP
```
### Szenario 3: SNMP antwortet, aber Beschreibungen sind unbekannt
```
Service: ✅ Fallback-Logik findet RAM/Disk trotzdem
API: ✅ Fallback-Logik findet RAM/Disk trotzdem
Logs: `Fallback RAM gefunden` / `Fallback Disk gefunden`
User-View: ✅ Daten werden angezeigt
```
### Szenario 4: Service fehlt, API läuft
```
Service: ❌ Exception beim Laden
API: ✅ Live-Updates funktionieren normal
User-View: "Beim Laden: 0%, nach 5s: aktuelle Werte"
Gut genug!
```
---
## Testing-Anleitung
### 1. Initialer Load testen
```bash
# Browser öffnen, als Admin einloggen
# Dashboard öffnen
# → Sollten Werte sichtbar sein (entweder echte oder 0%)
```
### 2. Service-Fehler simulieren
```php
// In DashboardController.php: Service-Aufruf kommentieren
// $serverStatus = [... Fallback-Werte ...];
// → Dashboard sollte trotzdem laden (mit 0%)
```
### 3. API testen
```bash
# Browser DevTools → Network → api/snmp_status.php
# → Sollte JSON zurückgeben
# Bei 401 → Session fehlt (erwartet wenn nicht angemeldet)
# Sollte aber funktionieren wenn angemeldet
```
### 4. Logs prüfen
```bash
# PHP Error-Log
error_log() Output ansehen
# SNMP API Log
cat public/logs/snmp_api.log
# Sollte Einträge zeigen (mit Timestamps)
```
### 5. Cache prüfen
```bash
# Temp-Datei prüfen
# Windows: %TEMP%\snmp_status_cache.json
# Linux: /tmp/snmp_status_cache.json
# → Sollte JSON enthalten
```
---
## Known Issues & Limitations
1. **Disk/RAM-Heuristik:** Bei sehr ungewöhnlichen Storage-Labels können Fallbacks greifen, die nicht ideal sind
- **Lösung:** Log prüfen (`Storage[X]:` Einträge) und ggf. Heuristiken anpassen
2. **Cache-Speicher:** Erfordert Schreibzugriff auf `sys_get_temp_dir()`
- **Lösung:** Falls nicht verfügbar → Cache-Code entfernen oder APCu/Redis nutzen
3. **OS-Feld:** Hardcoded auf "Windows Server" (TODO: Dynamisch per OID 1.3.6.1.2.1.1.1.0)
---
## Performance
- **Service-Abfrage:** 1x pro Seitenladung (~100-500ms je nach SNMP-Timeout)
- **API-Abfrage:** Alle 5s, aber gecacht für 10s → effektiv alle 10s eine echte SNMP-Abfrage
- **JavaScript Polling:** 5s Intervall (Browser-seitig, keine Last auf Server)
- **Gesamt:** Sehr effizient, auch bei vielen gleichzeitigen Nutzern
---
## Summary für Kollegen
✅ **Live-Dashboard mit zwei Ebenen:**
1. Initial Load via Service (sofortige Daten)
2. Live-Polling via API (kontinuierliche Updates)
**Robuste Fallback-Logik** für RAM und Disk (findet die Werte auch bei unbekannten Labels)
✅ **Dual Logging:**
- PHP Error-Log für Service-Fehler
- `public/logs/snmp_api.log` für API-Aktivitäten
**Session-Geschützt:** Nur Admins können Status abrufen
**Gecacht:** 10 Sekunden TTL reduziert SNMP-Load
**Error-tolerant:** Dashboard funktioniert auch wenn SNMP fehlt (zeigt 0%, wartet auf Live-Updates)

View File

@ -6,12 +6,18 @@ declare(strict_types=1);
namespace App\Controllers;
use App\Services\Ldap\LdapAuthService;
use App\Services\Logging\LoggingService;
/**
* Zuständig für alles rund um den Login:
* - Login-Formular anzeigen
* - Login-Daten verarbeiten (Authentifizierung gegen LDAP/AD)
* - Logout durchführen
*
* NEU:
* - Statt direkt HTML auszugeben oder header()-Redirects zu setzen,
* liefert der Controller "View-Results" zurück, die von index.php
* und einem zentralen Layout verarbeitet werden.
*/
class AuthController
{
@ -21,6 +27,9 @@ class AuthController
/** @var LdapAuthService Service, der die eigentliche LDAP/AD-Authentifizierung übernimmt */
private LdapAuthService $ldapAuthService;
/** @var LoggingService Logger für technische Fehler */
private LoggingService $logger;
/**
* Übergibt die Konfiguration an den Controller und initialisiert den LDAP-Authentifizierungsservice.
*
@ -34,38 +43,45 @@ class AuthController
// LdapAuthService mit dem Teilbereich "ldap" aus der Konfiguration initialisieren.
// Wenn 'ldap' nicht gesetzt ist, wird ein leeres Array übergeben (Fail fast erfolgt dann im Service).
$this->ldapAuthService = new LdapAuthService($config['ldap'] ?? []);
// LoggingService mit dem Teilbereich "logging" aus der Konfiguration initialisieren.
$this->logger = new LoggingService($config['logging'] ?? []);
}
/**
* Zeigt das Login-Formular an.
* Optional kann eine Fehlermeldung übergeben werden, die in der View dargestellt wird.
*
* @return array<string, mixed> View-Result für das zentrale Layout
*/
public function showLoginForm(?string $errorMessage = null): void
public function showLoginForm(?string $errorMessage = null): array
{
// Pfad zur Login-View (Template-Datei) ermitteln.
$viewPath = __DIR__ . '/../../public/views/login.php';
// Variable für die View vorbereiten (wird in der eingebundenen Datei verwendet).
$error = $errorMessage;
// Falls die View-Datei (noch) nicht existiert, einen Fallback-HTML-Output verwenden.
if (file_exists($viewPath) === false) {
$this->renderInlineLogin($error);
return;
}
// View-Datei einbinden. Variablen aus dieser Methode (z. B. $error) sind dort verfügbar.
require $viewPath;
// Wichtig: Die View erwartet aktuell die Variable $error.
return [
'view' => $viewPath,
'data' => [
'error' => $errorMessage,
'loginPage' => true,
],
'pageTitle' => 'Login',
// Beim Login ist typischerweise kein Menüpunkt aktiv.
'activeMenu' => null,
];
}
/**
* Verarbeitet das Login-Formular:
* - Liest Benutzername und Passwort aus $_POST
* - Ruft den LdapAuthService zur Authentifizierung auf
* - Setzt bei Erfolg die Session und leitet zum Dashboard weiter
* - Zeigt bei Fehlern erneut das Login-Formular mit Fehlermeldung an
* - Liefert bei Erfolg ein Redirect-Result zum Dashboard
* - Liefert bei Fehlern ein View-Result für das Login-Formular mit Fehlermeldung
*
* @return array<string, mixed> View-Result ODER Redirect-Result
*/
public function processLogin(): void
public function processLogin(): array
{
// Formulardaten aus dem POST-Request lesen.
$username = trim($_POST['username'] ?? '');
@ -77,16 +93,31 @@ class AuthController
// false = Anmeldedaten fachlich ungültig (Benutzer/Passwort falsch)
$authenticated = $this->ldapAuthService->authenticate($username, $password);
} catch (\Throwable $exception) {
// Technischer Fehler (z. B. LDAP-Server nicht erreichbar, falsche Konfiguration).
// In diesem Fall wird eine technische Fehlermeldung im Login-Formular angezeigt.
$this->showLoginForm('Technischer Fehler bei der Anmeldung: ' . $exception->getMessage());
return;
// HIER ist vorher dein Fehler entstanden:
// - showLoginForm() wurde nur aufgerufen, das Ergebnis aber ignoriert
// - danach kam ein "return;" ohne Rückgabewert → Rückgabetyp array wurde verletzt
// Technischen Fehler ausführlich ins Log schreiben
$this->logger->logException(
'Technischer Fehler bei der Anmeldung.',
$exception,
[
'route' => 'login.submit',
'username' => $username,
'remote_addr'=> $_SERVER['REMOTE_ADDR'] ?? null,
]
);
// Für den Benutzer nur eine allgemeine, aber verständliche Meldung anzeigen
return $this->showLoginForm(
'Technischer Fehler bei der Anmeldung. Bitte versuchen Sie es später erneut '
. 'oder wenden Sie sich an den Administrator.'
);
}
// Fachlich fehlgeschlagene Anmeldung (z. B. falsches Passwort).
if ($authenticated === false) {
$this->showLoginForm('Benutzername oder Passwort ist ungültig.');
return;
return $this->showLoginForm('Benutzername oder Passwort ist ungültig.');
}
// Ab hier ist die Anmeldung erfolgreich.
@ -96,22 +127,27 @@ class AuthController
$sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';
// Benutzerinformationen in der Session hinterlegen.
// Diese Daten werden später von requireLogin() ausgewertet.
// Diese Daten werden später von requireLogin() bzw. im Layout ausgewertet.
$_SESSION[$sessionKey] = [
'username' => $username,
'login_at' => date('c'), // ISO-8601 Datum/Zeit der Anmeldung
];
// Nach erfolgreicher Anmeldung zum Dashboard weiterleiten.
header('Location: index.php?route=dashboard');
exit;
// Kein direkter header()-Aufruf, sondern ein Redirect-Result
// für die zentrale Steuerung in index.php.
return [
'redirect' => 'index.php?route=dashboard',
];
}
/**
* Meldet den aktuell eingeloggten Benutzer ab, indem der entsprechende Session-Eintrag entfernt wird,
* und leitet anschließend zurück auf die Login-Seite.
* und liefert anschließend ein Redirect-Result zurück auf die Login-Seite.
*
* @return array<string, mixed> Redirect-Result
*/
public function logout(): void
public function logout(): array
{
// Session-Key für den eingeloggten Benutzer aus der Konfiguration lesen.
$sessionKey = $this->config['security']['session_key_user'] ?? 'admin_user';
@ -119,49 +155,9 @@ class AuthController
// Eintrag aus der Session entfernen → Benutzer gilt als ausgeloggt.
unset($_SESSION[$sessionKey]);
// Zur Login-Seite zurückleiten.
header('Location: index.php?route=login');
exit;
}
/**
* Fallback-Ausgabe für das Login-Formular, falls noch keine separate View-Datei existiert.
* Gibt direkt HTML aus (inline-Template).
*/
private function renderInlineLogin(?string $errorMessage): void
{
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>AD Admin Tool Login</title>
</head>
<body>
<h1>AD Admin Tool Login</h1>
<?php if ($errorMessage !== null): ?>
<!-- Fehlermeldung ausgeben, HTML-Ausgabe wird dabei sicher maskiert -->
<p style="color: red;"><?php echo htmlspecialchars($errorMessage, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></p>
<?php endif; ?>
<!-- Einfaches Login-Formular, das per POST an die Route "login.submit" gesendet wird -->
<form action="index.php?route=login.submit" method="post">
<div>
<label for="username">Benutzername:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="password">Passwort:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Anmelden</button>
</form>
</body>
</html>
<?php
// Redirect-Result zur Login-Seite.
return [
'redirect' => 'index.php?route=login',
];
}
}

View File

@ -1,6 +1,4 @@
<?php
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);
namespace App\Controllers;
@ -9,112 +7,57 @@ use App\Services\Snmp\SnmpServerStatusService;
/**
* Controller für das Dashboard.
* Zuständig für:
* - Abrufen des Serverstatus (über SnmpServerStatusService)
* - Auswählen und Rendern der Dashboard-View
*
* Zeigt Serverstatus-Metriken über SNMP an:
* - Initial Load: Server-seitiger Service-Aufruf (sofortige Daten)
* - Live-Updates: Client-seitiges JavaScript-Polling alle 5s
*/
class DashboardController
{
/** @var array<string, mixed> Vollständige Anwendungskonfiguration (aus config.php) */
private array $config;
/** @var SnmpServerStatusService Service, der den Serverstatus (später per SNMP) liefert */
private SnmpServerStatusService $snmpService;
/**
* Übergibt die Konfiguration an den Controller und initialisiert den SNMP-Statusservice.
*
* @param array<string, mixed> $config Vollständige Konfiguration aus config.php
*/
public function __construct(array $config)
{
// Komplette Config lokal speichern (falls später weitere Werte benötigt werden).
$this->config = $config;
// Teilbereich "snmp" aus der Konfiguration ziehen.
// Wenn nicht vorhanden, wird ein leeres Array übergeben (der Service prüft das selbst).
$snmpConfig = $config['snmp'] ?? [];
// SNMP-Service initialisieren, der den Serverstatus liefert.
$this->snmpService = new SnmpServerStatusService($snmpConfig);
}
/**
* Zeigt das Dashboard an.
* Holt die Serverstatus-Daten aus dem SnmpServerStatusService und übergibt sie an die View.
*
* Beim initialen Laden wird der Service aufgerufen, um sofort Daten anzuzeigen.
* Live-Updates erfolgen anschließend via JavaScript-Polling (api/snmp_status.php alle 5s).
*/
public function show(): void
public function show(): array
{
// Serverstatus über den SNMP-Service ermitteln.
// In der aktuellen Version liefert der Service noch Demo-Daten.
$serverStatus = $this->snmpService->getServerStatus();
$serverStatus = [
'hostname' => 'n/a',
'os' => 'n/a',
'uptime' => 'n/a',
'cpu_usage' => 0,
'memory_usage' => 0,
'disk_usage_c' => 0,
'last_update' => date('d.m.Y H:i:s'),
];
try {
$serverStatus = $this->snmpService->getServerStatus();
} catch (\RuntimeException $e) {
error_log('DashboardController: SNMP-Fehler beim initialen Laden - ' . $e->getMessage());
}
// Pfad zur Dashboard-View (Template-Datei) ermitteln.
$viewPath = __DIR__ . '/../../public/views/dashboard.php';
// Falls die View-Datei (noch) nicht existiert, Fallback-HTML direkt aus dem Controller ausgeben.
if (file_exists($viewPath) === false) {
$this->renderInlineDashboard($serverStatus);
return;
}
// View-Datei einbinden. Die Variable $serverStatus steht in der View zur Verfügung.
require $viewPath;
}
/**
* Fallback-Dashboard-Ausgabe direkt aus dem Controller (ohne separate View-Datei).
* Nur als Notlösung gedacht, falls die eigentliche View noch nicht vorhanden ist.
*
* @param array<string, mixed> $serverStatus Serverstatus-Daten (Hostname, CPU%, RAM%, etc.)
*/
private function renderInlineDashboard(array $serverStatus): void
{
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>AD Admin Tool Dashboard</title>
</head>
<body>
<h1>Dashboard</h1>
<h2>Serverstatus</h2>
<ul>
<li>
Hostname:
<?php echo htmlspecialchars((string)$serverStatus['hostname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</li>
<li>
Betriebssystem:
<?php echo htmlspecialchars((string)$serverStatus['os'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</li>
<li>
Uptime:
<?php echo htmlspecialchars((string)$serverStatus['uptime'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</li>
<li>
CPU-Auslastung:
<?php echo (int)$serverStatus['cpu_usage']; ?>%
</li>
<li>
RAM-Auslastung:
<?php echo (int)$serverStatus['memory_usage']; ?>%
</li>
<li>
Datenträger C:
<?php echo (int)$serverStatus['disk_usage_c']; ?>%
</li>
<li>
Letzte Aktualisierung:
<?php echo htmlspecialchars((string)$serverStatus['last_update'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</li>
</ul>
<p><a href="index.php?route=logout">Logout</a></p>
</body>
</html>
<?php
return [
'view' => $viewPath,
'data' => [
'serverStatus' => $serverStatus,
'loginPage' => false,
],
'pageTitle' => 'Dashboard',
'activeMenu' => 'dashboard',
];
}
}

View File

@ -6,6 +6,7 @@ declare(strict_types=1);
namespace App\Controllers;
use App\Services\Ldap\LdapDirectoryService;
use App\Services\Logging\LoggingService;
/**
* Controller für die Benutzer- und Gruppenanzeige.
@ -18,6 +19,9 @@ use App\Services\Ldap\LdapDirectoryService;
* WICHTIG:
* - Es werden aktuell nur Daten angezeigt (Read-only).
* - Es findet keine Änderung im Active Directory statt.
*
* NEU:
* - Gibt ein View-Result-Array zurück, das von index.php + Layout gerendert wird.
*/
class UserManagementController
{
@ -27,6 +31,9 @@ class UserManagementController
/** @var LdapDirectoryService Service für das Lesen von Benutzern und Gruppen aus dem LDAP/AD */
private LdapDirectoryService $directoryService;
/** @var LoggingService Logger für technische Fehler */
private LoggingService $logger;
/**
* @param array<string, mixed> $config Vollständige Konfiguration aus config.php
*/
@ -40,13 +47,18 @@ class UserManagementController
// Directory-Service initialisieren, der die eigentliche LDAP-Arbeit übernimmt.
$this->directoryService = new LdapDirectoryService($ldapConfig);
// Logging-Service initialisieren.
$this->logger = new LoggingService($config['logging'] ?? []);
}
/**
* Zeigt Benutzer- und Gruppenliste an.
* Wird typischerweise über die Route "users" (index.php?route=users) aufgerufen.
*
* @return array<string, mixed> View-Result für das zentrale Layout
*/
public function show(): void
public function show(): array
{
// Standardwerte für die View-Variablen vorbereiten.
$error = null;
@ -58,96 +70,34 @@ class UserManagementController
$users = $this->directoryService->getUsers();
$groups = $this->directoryService->getGroups();
} catch (\Throwable $exception) {
// Sämtliche technischen Fehler (z. B. Verbindungs- oder Konfigurationsprobleme)
// werden hier in eine für den Benutzer lesbare Fehlermeldung übersetzt.
$error = 'Fehler beim Laden von Benutzern/Gruppen: ' . $exception->getMessage();
// Technische Details ins Log, für den Benutzer eine allgemeine Meldung.
$this->logger->logException(
'Fehler beim Laden von Benutzern/Gruppen.',
$exception,
[
'route' => 'users',
'remote_addr' => $_SERVER['REMOTE_ADDR'] ?? null,
]
);
$error = 'Fehler beim Laden von Benutzern/Gruppen. '
. 'Bitte versuchen Sie es später erneut oder wenden Sie sich an den Administrator.';
}
// Pfad zur eigentlichen View-Datei bestimmen.
$viewPath = __DIR__ . '/../../public/views/users.php';
// Falls die View-Datei (noch) nicht existiert, Fallback-Ausgabe verwenden.
if (file_exists($viewPath) === false) {
$this->renderInline($users, $groups, $error);
return;
}
// Variablen $users, $groups, $error stehen in der View zur Verfügung,
// weil sie im aktuellen Scope definiert sind.
require $viewPath;
}
/**
* Fallback-Ausgabe, falls noch keine View-Datei existiert.
*
* @param array<int, array<string, string>> $users Liste der Benutzer-Datensätze
* @param array<int, array<string, string>> $groups Liste der Gruppen-Datensätze
* @param string|null $error Fehlermeldung (falls vorhanden)
*/
private function renderInline(array $users, array $groups, ?string $error): void
{
?>
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>AD Admin Tool Benutzer &amp; Gruppen</title>
</head>
<body>
<h1>Benutzer &amp; Gruppen</h1>
<?php if ($error !== null): ?>
<!-- Fehlermeldung ausgeben, HTML-sicher maskiert -->
<p style="color: red;"><?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></p>
<?php endif; ?>
<h2>Benutzer</h2>
<table border="1" cellpadding="4" cellspacing="0">
<thead>
<tr>
<th>Benutzername (sAMAccountName)</th>
<th>Anzeigename</th>
<th>E-Mail</th>
</tr>
</thead>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo htmlspecialchars($user['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($user['displayname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($user['mail'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<h2>Gruppen</h2>
<table border="1" cellpadding="4" cellspacing="0">
<thead>
<tr>
<th>Gruppenname (sAMAccountName)</th>
<th>CN</th>
<th>Beschreibung</th>
</tr>
</thead>
<tbody>
<?php foreach ($groups as $group): ?>
<tr>
<td><?php echo htmlspecialchars($group['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($group['cn'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($group['description'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p>
<a href="index.php?route=dashboard">Zurück zum Dashboard</a> |
<a href="index.php?route=logout">Logout</a>
</p>
</body>
</html>
<?php
return [
'view' => $viewPath,
'data' => [
// Die View erwartet aktuell $users, $groups, $error.
'users' => $users,
'groups' => $groups,
'error' => $error,
'loginPage' => false,
],
'pageTitle' => 'Benutzer & Gruppen',
'activeMenu' => 'users',
];
}
}

View File

@ -1,11 +0,0 @@
<?php
session_start();
if (empty($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
header("Location: login.php");
exit();
}
$username = $_SESSION['username'];
?>

View File

@ -58,7 +58,8 @@ class LdapConnectionHelper
// Verbindung zum LDAP/AD-Server herstellen.
// ldap_connect liefert entweder ein Verbindungs-Handle (Resource) oder false.
$connection = ldap_connect($server, $port);
$uri = "ldap://".$server . ':' . $port;
$connection = ldap_connect($uri);
// Wenn keine Verbindung aufgebaut werden konnte, Exception werfen.
if ($connection === false) {

View File

@ -0,0 +1,133 @@
<?php
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);
namespace App\Services\Logging;
use DateTimeImmutable;
/**
* Einfacher File-Logger für die AdminTool-Anwendung.
*
* Ziele:
* - Technische Details werden in eine Log-Datei unter public/logs/ geschrieben.
* - In der Weboberfläche erscheinen nur verständliche, fachliche Fehlermeldungen.
*/
class LoggingService
{
/** @var string Vollständiger Pfad zum Log-Verzeichnis */
private string $logDir;
/** @var string Dateiname der Log-Datei */
private string $logFile;
/** @var int Minimale Log-Stufe, ab der geschrieben wird. */
private int $minLevel;
/**
* Zuordnung der Log-Level zu numerischen Werten zur Filterung.
*
* @var array<string, int>
*/
private const LEVEL_MAP = [
'debug' => 100,
'info' => 200,
'warning' => 300,
'error' => 400,
];
/**
* @param array<string, mixed> $config Teilkonfiguration "logging" aus config.php
*/
public function __construct(array $config)
{
// Standard: public/logs relativ zum Projektroot
$baseDir = $config['log_dir'] ?? (__DIR__ . '/../../../public/logs');
$fileName = $config['log_file'] ?? 'app.log';
$level = strtolower((string)($config['min_level'] ?? 'info'));
$this->logDir = rtrim($baseDir, DIRECTORY_SEPARATOR);
$this->logFile = $fileName;
$this->minLevel = self::LEVEL_MAP[$level] ?? self::LEVEL_MAP['info'];
$this->ensureLogDirectoryExists();
}
/**
* Stellt sicher, dass das Log-Verzeichnis existiert.
*/
private function ensureLogDirectoryExists(): void
{
if (is_dir($this->logDir) === true) {
return;
}
if (@mkdir($this->logDir, 0775, true) === false && is_dir($this->logDir) === false) {
// Wenn das Anlegen fehlschlägt, wenigstens einen Eintrag im PHP-Error-Log hinterlassen.
error_log(sprintf('LoggingService: Konnte Log-Verzeichnis "%s" nicht anlegen.', $this->logDir));
}
}
/**
* Allgemeiner Log-Eintrag.
*
* @param string $level Log-Level (debug|info|warning|error)
* @param string $message Nachrichtentext
* @param array<string, mixed> $context Zusätzliche Kontextinformationen
*/
public function log(string $level, string $message, array $context = []): void
{
$level = strtolower($level);
$numericLevel = self::LEVEL_MAP[$level] ?? self::LEVEL_MAP['error'];
// Alles unterhalb der minimalen Stufe ignorieren.
if ($numericLevel < $this->minLevel) {
return;
}
$timestamp = (new DateTimeImmutable())->format('Y-m-d H:i:s');
$contextJson = $context === []
? '{}'
: (string)json_encode($context, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$line = sprintf(
"[%s] %-7s %s %s%s",
$timestamp,
strtoupper($level),
$message,
$contextJson,
PHP_EOL
);
$filePath = $this->logDir . DIRECTORY_SEPARATOR . $this->logFile;
if (@file_put_contents($filePath, $line, FILE_APPEND | LOCK_EX) === false) {
// Fallback, damit Fehler beim Logging selbst nicht die App zerschießen.
error_log(sprintf('LoggingService: Konnte in Log-Datei "%s" nicht schreiben.', $filePath));
}
}
/**
* Komfortmethode, um Exceptions strukturiert zu loggen.
*
* @param string $message Kurzer Kontexttext zur Exception
* @param \Throwable $exception Die geworfene Exception
* @param array<string, mixed> $context Zusätzlicher Kontext (Route, Benutzername, Remote-IP, ...)
*/
public function logException(string $message, \Throwable $exception, array $context = []): void
{
$exceptionContext = [
'exception_class' => get_class($exception),
'exception_message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTraceAsString(),
];
$mergedContext = array_merge($context, $exceptionContext);
$this->log('error', $message, $mergedContext);
}
}

View File

@ -1,6 +1,5 @@
<?php
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);
namespace App\Services\Snmp;
@ -8,15 +7,20 @@ namespace App\Services\Snmp;
use RuntimeException;
/**
* Service zur Ermittlung des Serverstatus.
* Service zur Ermittlung des Serverstatus per SNMP.
*
* In dieser ersten Version werden noch statische Demo-Daten zurückgegeben.
* Später können hier echte SNMP-Abfragen eingebaut werden, ohne dass sich
* der DashboardController oder die Views ändern müssen.
* Features:
* - Robuste Fehlerbehandlung mit aussagekräftigen Exceptions
* - Intelligente Fallback-Logik bei fehlenden oder unerwarteten OID-Beschreibungen
* - Unterstützung für Windows (C:\) und Linux (/) Systeme
* - Detailliertes Logging über Exceptions
*
* Wird vom DashboardController beim initialen Laden aufgerufen.
* Das Live-Polling erfolgt über das API-Endpunkt (public/api/snmp_status.php).
*/
class SnmpServerStatusService
{
/** @var array<string, mixed> SNMP-spezifische Konfiguration (Host, Community, Timeout, OIDs, etc.) */
/** @var array<string, mixed> SNMP-Konfiguration (Host, Community, Timeout, OIDs, etc.) */
private array $config;
/**
@ -26,9 +30,9 @@ class SnmpServerStatusService
*/
public function __construct(array $snmpConfig)
{
// SNMP-Konfiguration in der Instanz speichern.
$this->config = $snmpConfig;
}
/**
* Liefert den aktuellen Serverstatus zurück.
*
@ -56,106 +60,166 @@ class SnmpServerStatusService
throw new RuntimeException('SNMP-Konfiguration ist unvollständig (oids fehlen).');
}
// Helper-Funktion zum Bereinigen von SNMP-Antworten (z.B. "INTEGER: 123" -> 123)
if (!function_exists('snmpget')) {
throw new RuntimeException('PHP-SNMP-Erweiterung ist nicht installiert.');
}
// Hilfsfunktion: SNMP-Werte bereinigen (z.B. "INTEGER: 123" -> 123)
$cleanSnmpValue = fn($v) => (int)filter_var($v, FILTER_SANITIZE_NUMBER_INT);
// --- 2. Uptime abfragen (war vorher nicht implementiert) ---
$uptimeResult = snmpget($host, $community, $oids['uptime'], $timeout, $retries);
// --- 2. Uptime abfragen ---
$uptimeOid = $oids['uptime'] ?? '1.3.6.1.2.1.1.3.0';
$uptimeResult = @snmpget($host, $community, $uptimeOid, $timeout, $retries);
if ($uptimeResult === false) {
throw new RuntimeException("SNMP Uptime GET fehlgeschlagen.");
}
// Uptime (timeticks) in ein lesbares Format umwandeln (optional, hier als String)
// Format ist oft "Timeticks: (12345678) 1 day, 10:17:36.78"
// Wir extrahieren den Teil in Klammern (Hundertstelsekunden)
// Uptime aus TimeTicks (Hundertstel-Sekunden) in lesbar konvertieren
preg_match('/\((.*?)\)/', $uptimeResult, $matches);
$uptimeTicks = (int)($matches[1] ?? 0);
$uptimeSeconds = $uptimeTicks / 100;
$uptimeFormatted = sprintf(
'%d Tage, %02d:%02d:%02d',
floor($uptimeSeconds / 86400),
floor(($uptimeSeconds % 86400) / 3600),
floor(($uptimeSeconds % 3600) / 60),
$uptimeSeconds % 60
(int)floor($uptimeSeconds / 86400),
(int)floor(($uptimeSeconds % 86400) / 3600),
(int)floor(($uptimeSeconds % 3600) / 60),
(int)($uptimeSeconds % 60)
);
// --- 3. CPU ---
$cpuValues = snmpwalk($host, $community, $oids['cpu_table'], $timeout, $retries);
// --- 3. CPU (Durchschnitt über alle Kerne) ---
$cpuTable = $oids['cpu_table'] ?? '1.3.6.1.2.1.25.3.3.1.2';
$cpuValues = @snmpwalk($host, $community, $cpuTable, $timeout, $retries);
if (!is_array($cpuValues) || empty($cpuValues)) {
throw new RuntimeException("SNMP CPU WALK fehlgeschlagen.");
}
$cpuValues = array_map($cleanSnmpValue, $cpuValues);
$cpuAvg = array_sum($cpuValues) / count($cpuValues);
$cpuAvg = (int)round(array_sum($cpuValues) / count($cpuValues));
// --- 4. Storage-Tabellen (RAM + Disks) ---
$descrOid = $oids['storage_descr'] ?? '1.3.6.1.2.1.25.2.3.1.3';
$unitsOid = $oids['storage_units'] ?? '1.3.6.1.2.1.25.2.3.1.4';
$sizeOid = $oids['storage_size'] ?? '1.3.6.1.2.1.25.2.3.1.5';
$usedOid = $oids['storage_used'] ?? '1.3.6.1.2.1.25.2.3.1.6';
// --- 4. Memory ---
$memTotalResult = snmpget($host, $community, $oids['mem_size'], $timeout, $retries);
if($memTotalResult === false) {
throw new RuntimeException("SNMP MemTotal GET fehlgeschlagen.");
}
$descr = @snmpwalk($host, $community, $descrOid, $timeout, $retries);
$units = @snmpwalk($host, $community, $unitsOid, $timeout, $retries);
$size = @snmpwalk($host, $community, $sizeOid, $timeout, $retries);
$used = @snmpwalk($host, $community, $usedOid, $timeout, $retries);
// memTotal in Bytes berechnen (korrigierte Reihenfolge von filter/cast)
$memTotal = $cleanSnmpValue($memTotalResult) * 1024; // KB -> Bytes
// Storage-Tabelle (RAM + Disks)
$descr = snmpwalk($host, $community, $oids['storage_descr'], $timeout, $retries);
$units = snmpwalk($host, $community, $oids['storage_units'], $timeout, $retries);
$size = snmpwalk($host, $community, $oids['storage_size'], $timeout, $retries);
$used = snmpwalk($host, $community, $oids['storage_used'], $timeout, $retries);
if ($descr === false || $units === false || $size === false || $used === false) {
if (!is_array($descr) || !is_array($units) || !is_array($size) || !is_array($used)) {
throw new RuntimeException("SNMP Storage WALK fehlgeschlagen.");
}
// Werte bereinigen
// Die SNMP-Antwort enthält "STRING: " und Anführungszeichen, die wir entfernen müssen.
$descr = array_map(fn($v) => trim(str_ireplace('STRING:', '', $v), ' "'), $descr);
$units = array_map($cleanSnmpValue, $units);
$size = array_map($cleanSnmpValue, $size);
$used = array_map($cleanSnmpValue, $used);
$units = array_map($cleanSnmpValue, $units); // Ints
$size = array_map($cleanSnmpValue, $size); // Ints
$used = array_map($cleanSnmpValue, $used); // Ints
// --- 5. RAM mit Fallback-Logik ---
$ramPercent = null;
$memTotalBytes = null;
// RAM
// Heuristik 1: Suche nach "Physical Memory"
$ramIndex = array_search("Physical Memory", $descr);
if ($ramIndex === false) {
if ($ramIndex !== false) {
$memTotalBytes = $units[$ramIndex] * $size[$ramIndex];
$ramUsedBytes = $units[$ramIndex] * $used[$ramIndex];
$ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0;
}
// Fallback 1: Wenn nicht gefunden, suche nach ähnlichen Labels
if ($ramPercent === null) {
foreach ($descr as $index => $description) {
$lower = strtolower($description);
if (strpos($lower, 'physical') !== false || strpos($lower, 'memory') !== false || strpos($lower, 'ram') !== false) {
$memTotalBytes = $units[$index] * $size[$index];
$ramUsedBytes = $units[$index] * $used[$index];
$ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0;
break;
}
}
}
// Fallback 2: Wenn immer noch nicht gefunden, nimm den kleinsten Eintrag (i.d.R. RAM)
if ($ramPercent === null && count($descr) > 0) {
$minIndex = 0;
$minSize = PHP_INT_MAX;
foreach ($size as $index => $s) {
if ($s > 0 && $s < $minSize) {
$minSize = $s;
$minIndex = $index;
}
}
$memTotalBytes = $units[$minIndex] * $size[$minIndex];
$ramUsedBytes = $units[$minIndex] * $used[$minIndex];
$ramPercent = ($memTotalBytes > 0) ? ($ramUsedBytes / $memTotalBytes) * 100 : 0;
}
// Fallback 3: Wenn gar nichts geht, Exception
if ($ramPercent === null) {
throw new RuntimeException("Konnte 'Physical Memory' in der SNMP Storage-Tabelle nicht finden.");
}
$ramUsedBytes = $units[$ramIndex] * $used[$ramIndex];
$ramPercent = ($memTotal > 0) ? ($ramUsedBytes / $memTotal) * 100 : 0;
// --- 6. Disk C: / Root mit Fallback-Logik ---
$diskCPercent = null;
// --- 5. Disk C: ---
$cIndex = false;
// Heuristik 1: Suche nach C:\
foreach ($descr as $index => $description) {
// str_starts_with prüft, ob der String mit C:\ beginnt
if (str_starts_with($description, 'C:\\')) {
$cIndex = $index;
$cTotal = $units[$index] * $size[$index];
$cUsed = $units[$index] * $used[$index];
$diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0;
break;
}
}
if ($cIndex === false) {
throw new RuntimeException("Konnte Laufwerk 'C:\' in der SNMP Storage-Tabelle nicht finden.");
// Fallback 1: Suche nach "C:" oder "root" oder "/"
if ($diskCPercent === null) {
foreach ($descr as $index => $description) {
$lower = strtolower($description);
if (strpos($lower, 'c:') !== false || $lower === '/' || strpos($lower, 'root') !== false) {
$cTotal = $units[$index] * $size[$index];
$cUsed = $units[$index] * $used[$index];
$diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0;
break;
}
}
}
$cUsed = $units[$cIndex] * $used[$cIndex];
$cTotal = $units[$cIndex] * $size[$cIndex];
// Fallback 2: Nimm den größten Eintrag > 1GB (wahrscheinlich der Hauptdatenträger)
if ($diskCPercent === null) {
$maxIndex = 0;
$maxSize = 0;
foreach ($size as $index => $s) {
$sizeGB = ($s * $units[$index]) / (1024 ** 3);
if ($sizeGB > 1 && $s > $maxSize) {
$maxSize = $s;
$maxIndex = $index;
}
}
if ($maxSize > 0) {
$cTotal = $units[$maxIndex] * $size[$maxIndex];
$cUsed = $units[$maxIndex] * $used[$maxIndex];
$diskCPercent = ($cTotal > 0) ? ($cUsed / $cTotal) * 100 : 0;
}
}
// --- 6. Status-Array zusammenbauen ---
// Fallback 3: Wenn immer noch nichts, Exception
if ($diskCPercent === null) {
throw new RuntimeException("Konnte Laufwerk 'C:\\' oder Root-Partition in der SNMP Storage-Tabelle nicht finden.");
}
// --- 7. Status-Array zusammenbauen ---
$status = [
'hostname' => $host,
'os' => 'Windows Server 2025 Datacenter', // TODO: OS dynamisch abfragen
'uptime' => $uptimeFormatted, // Fehlende Variable hinzugefügt
'cpu_usage' => round($cpuAvg),
'memory_usage' => round($ramPercent),
'disk_usage_c' => round($diskCPercent),
'os' => 'Windows Server', // TODO: OS dynamisch per SNMP abfragen (OID 1.3.6.1.2.1.1.1.0)
'uptime' => $uptimeFormatted,
'cpu_usage' => $cpuAvg,
'memory_usage' => (int)round($ramPercent),
'disk_usage_c' => (int)round($diskCPercent),
'last_update' => date('d.m.Y H:i:s'),
];

View File

@ -49,4 +49,14 @@ return [
'storage_used' => '1.3.6.1.2.1.25.2.3.1.6',
],
],
// Logging-Konfiguration
'logging' => [
// Standard: public/logs relativ zum Projekt-Root
'log_dir' => __DIR__ . '/../public/logs',
// Name der Logdatei
'log_file' => 'app.log',
// Minimale Stufe: debug, info, warning, error
'min_level' => 'info',
],
];

View File

@ -1,430 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - 404</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span>
</a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true"
aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse show" aria-labelledby="headingPages"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item active" href="404.html">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- 404 Error Text -->
<div class="text-center">
<div class="error mx-auto" data-text="404">404</div>
<p class="lead text-gray-800 mb-5">Page Not Found</p>
<p class="text-gray-500 mb-0">It looks like you found a glitch in the matrix...</p>
<a href="views/dashboard.php">&larr; Back to Dashboard</a>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

292
public/api/snmp_status.php Normal file
View File

@ -0,0 +1,292 @@
<?php
declare(strict_types=1);
/**
* SNMP-Status-API für das Dashboard.
*
* Nur authentifizierte Admins dürfen auf diesen Endpunkt zugreifen.
* Wird alle 5s vom JavaScript im Dashboard aufgerufen.
*
* Sicherheit: Session-Validierung + Admin-Rollenprüfung.
* Performance: Datei-basiertes Caching (10 Sekunden) um SNMP-Last zu reduzieren.
* Logging: Alle Fehler und wichtigen Daten werden in `public/logs/snmp_api.log` geschrieben.
*/
session_start();
// === Authentifizierung + Autorisierung ===
$sessionKeyUser = 'admin_user'; // aus config
if (!isset($_SESSION[$sessionKeyUser])) {
http_response_code(401);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['error' => 'unauthorized']);
exit;
}
header('Content-Type: application/json; charset=utf-8');
// === Logging-Setup ===
$logDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'logs';
if (!is_dir($logDir)) {
@mkdir($logDir, 0755, true);
}
$logFile = $logDir . DIRECTORY_SEPARATOR . 'snmp_api.log';
function log_msg(string $msg): void {
global $logFile;
$timestamp = date('Y-m-d H:i:s');
@file_put_contents($logFile, "[$timestamp] $msg\n", FILE_APPEND);
}
function rotate_log_if_needed(): void {
global $logFile;
$maxSize = 500 * 1024; // 500 KB (anpassbar)
if (file_exists($logFile) && filesize($logFile) > $maxSize) {
$backupFile = $logFile . '.old';
@rename($logFile, $backupFile);
log_msg('=== Log rotiert (alte Datei: .old) ===');
}
}
$configPath = __DIR__ . '/../../config/config.php';
if (!is_readable($configPath)) {
log_msg('ERROR: config.php nicht lesbar');
echo json_encode(['error' => 'config_not_found']);
exit;
}
$config = require $configPath;
$snmp = $config['snmp'] ?? [];
rotate_log_if_needed();
log_msg('--- SNMP-Abfrage gestartet ---');
// === Cache-Logik (Datei) ===
// Cache-Datei wird nach 10 Sekunden als ungültig betrachtet
$cacheDir = sys_get_temp_dir();
$cacheFile = $cacheDir . DIRECTORY_SEPARATOR . 'snmp_status_cache.json';
$cacheTTL = 10; // Sekunden
if (file_exists($cacheFile)) {
$cacheAge = time() - filemtime($cacheFile);
if ($cacheAge < $cacheTTL) {
// Cache ist noch gültig
$cached = file_get_contents($cacheFile);
if ($cached !== false) {
log_msg("Cache HIT (Alter: {$cacheAge}s)");
echo $cached;
exit;
}
} else {
log_msg("Cache abgelaufen (Alter: {$cacheAge}s), neue Abfrage");
}
}
$host = $snmp['host'] ?? '127.0.0.1';
$community = $snmp['community'] ?? 'public';
$timeout = (int)($snmp['timeout'] ?? 2);
$retries = (int)($snmp['retries'] ?? 1);
log_msg("SNMP-Host: $host, Community: $community, Timeout: {$timeout}s");
if (!function_exists('snmpget')) {
log_msg('ERROR: SNMP-Erweiterung nicht installiert');
echo json_encode(['error' => 'snmp_extension_missing']);
exit;
}
snmp_set_quick_print(true);
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);
// Hilfsfunktion: sichere snmpget-Rückgabe (numeric oder null)
function sget(string $host, string $community, string $oid, int $timeout, int $retries)
{
$v = @snmpget($host, $community, $oid, $timeout, $retries);
if ($v === false || $v === null) return null;
return is_string($v) ? trim($v) : $v;
}
// System-Uptime (TimeTicks)
$uptimeOid = $snmp['oids']['uptime'] ?? '1.3.6.1.2.1.1.3.0';
$upticksRaw = @sget($host, $community, $uptimeOid, $timeout, $retries);
$upticks = $upticksRaw !== null ? (int)preg_replace('/[^0-9]/', '', (string)$upticksRaw) : null;
log_msg("Uptime OID: $uptimeOid, Raw: " . ($upticksRaw ?? 'null'));
function format_uptime(?int $ticks): ?string
{
if ($ticks === null) return null;
// ticks sind Hundertstel-Sekunden
$seconds = (int)floor($ticks / 100);
$days = intdiv($seconds, 86400);
$seconds -= $days * 86400;
$hours = intdiv($seconds, 3600);
$seconds -= $hours * 3600;
$minutes = intdiv($seconds, 60);
$seconds -= $minutes * 60;
$parts = [];
if ($days) $parts[] = $days . ' Tage';
if ($hours) $parts[] = $hours . ' Std';
if ($minutes) $parts[] = $minutes . ' Min';
$parts[] = $seconds . ' Sek';
return implode(' ', $parts);
}
$uptimeStr = format_uptime($upticks);
// CPU: ersten Eintrag aus der CPU-Tabelle lesen
$cpuTable = $snmp['oids']['cpu_table'] ?? '1.3.6.1.2.1.25.3.3.1.2';
$cpuOid = $cpuTable . '.1';
$cpuRaw = @sget($host, $community, $cpuOid, $timeout, $retries);
$cpu = $cpuRaw !== null ? (float)preg_replace('/[^0-9.]/', '', (string)$cpuRaw) : null;
log_msg("CPU OID: $cpuOid, Raw: " . ($cpuRaw ?? 'null') . ", Parsed: " . ($cpu ?? 'null'));
// Storage-Tabellen: Versuche, C: (Windows) oder Root ("/") zu finden
$descrOid = $snmp['oids']['storage_descr'] ?? '1.3.6.1.2.1.25.2.3.1.3';
$unitsOid = $snmp['oids']['storage_units'] ?? '1.3.6.1.2.1.25.2.3.1.4';
$sizeOid = $snmp['oids']['storage_size'] ?? '1.3.6.1.2.1.25.2.3.1.5';
$usedOid = $snmp['oids']['storage_used'] ?? '1.3.6.1.2.1.25.2.3.1.6';
log_msg("Starte Storage-Walk - Descr: $descrOid, Units: $unitsOid, Size: $sizeOid, Used: $usedOid");
$descrWalk = @snmprealwalk($host, $community, $descrOid);
$unitsWalk = @snmprealwalk($host, $community, $unitsOid);
$sizeWalk = @snmprealwalk($host, $community, $sizeOid);
$usedWalk = @snmprealwalk($host, $community, $usedOid);
if (!is_array($descrWalk)) {
log_msg('WARNING: snmprealwalk für Beschreibungen fehlgeschlagen');
$descrWalk = [];
}
if (!is_array($unitsWalk)) {
log_msg('WARNING: snmprealwalk für Units fehlgeschlagen');
$unitsWalk = [];
}
if (!is_array($sizeWalk)) {
log_msg('WARNING: snmprealwalk für Größe fehlgeschlagen');
$sizeWalk = [];
}
if (!is_array($usedWalk)) {
log_msg('WARNING: snmprealwalk für Used fehlgeschlagen');
$usedWalk = [];
}
log_msg('Storage-Einträge gefunden: ' . count($descrWalk));
$diskPercent = null;
$memPercent = null;
$storageEntries = [];
// Sammeln aller Storage-Einträge für Debug-Logging
if (is_array($descrWalk) && count($descrWalk) > 0) {
foreach ($descrWalk as $descrOidFull => $descrRaw) {
// Index extrahieren
if (!preg_match('/\.(\d+)$/', $descrOidFull, $m)) continue;
$idx = $m[1];
$descr = trim((string)$descrRaw, ' "');
// Suche nach passenden Einträgen in anderen Walks mit gleichem Index
$units = null;
$size = null;
$used = null;
foreach ($unitsWalk as $oid => $val) {
if (preg_match('/\.(\d+)$/', $oid, $m2) && $m2[1] === $idx) {
$units = (int)preg_replace('/[^0-9]/', '', (string)$val);
break;
}
}
foreach ($sizeWalk as $oid => $val) {
if (preg_match('/\.(\d+)$/', $oid, $m2) && $m2[1] === $idx) {
$size = (int)preg_replace('/[^0-9]/', '', (string)$val);
break;
}
}
foreach ($usedWalk as $oid => $val) {
if (preg_match('/\.(\d+)$/', $oid, $m2) && $m2[1] === $idx) {
$used = (int)preg_replace('/[^0-9]/', '', (string)$val);
break;
}
}
log_msg("Storage[$idx]: Desc='$descr', Size=$size, Used=$used, Units=$units");
if ($size === null || $units === null || $used === null || $size === 0 || $units === 0) {
log_msg("Storage[$idx]: SKIP (fehlende oder ungültige Daten)");
continue;
}
$totalBytes = $size * $units;
$usedBytes = $used * $units;
$percent = $totalBytes > 0 ? ($usedBytes / $totalBytes) * 100 : 0;
$storageEntries[] = [
'idx' => $idx,
'descr' => $descr,
'percent' => $percent,
'totalGB' => $totalBytes / (1024 ** 3),
'usedGB' => $usedBytes / (1024 ** 3),
];
// Heuristik 1: Suche nach C: oder Root
$lower = strtolower($descr);
if ($diskPercent === null && (strpos($lower, 'c:') !== false || strpos($lower, 'c:\\') !== false || strpos($lower, 'c:/') !== false || $lower === '/' || strpos($lower, 'root') !== false)) {
$diskPercent = $percent;
log_msg("Datenträger erkannt (Index $idx): $descr$percent%");
}
// Heuristik 2: Suche nach Physical Memory
if ($memPercent === null && ((strpos($lower, 'physical') !== false && strpos($lower, 'memory') !== false) || strpos($lower, 'ram') !== false || strpos($lower, 'physical memory') !== false)) {
$memPercent = $percent;
log_msg("Speicher erkannt (Index $idx): $descr$percent%");
}
}
}
// Fallback 1: Wenn keine Disk gefunden, nimm den größten Storage-Eintrag > 1GB
if ($diskPercent === null && count($storageEntries) > 0) {
log_msg('Fallback: Suche Disk (größter Eintrag > 1GB)');
usort($storageEntries, fn($a, $b) => $b['totalGB'] <=> $a['totalGB']);
foreach ($storageEntries as $entry) {
if ($entry['totalGB'] > 1) {
$diskPercent = $entry['percent'];
log_msg('Fallback Disk gefunden (Index ' . $entry['idx'] . '): ' . $entry['descr'] . ' → ' . $diskPercent . '%');
break;
}
}
}
// Fallback 2: Wenn kein Speicher gefunden, nimm den kleinsten Eintrag (meist Physical Memory)
if ($memPercent === null && count($storageEntries) > 0) {
log_msg('Fallback: Suche Memory (kleinster Eintrag)');
usort($storageEntries, fn($a, $b) => $a['totalGB'] <=> $b['totalGB']);
$memPercent = $storageEntries[0]['percent'];
log_msg('Fallback Memory gefunden (Index ' . $storageEntries[0]['idx'] . '): ' . $storageEntries[0]['descr'] . ' → ' . $memPercent . '%');
}
$result = [
'hostname' => @sget($host, $community, '1.3.6.1.2.1.1.5.0', $timeout, $retries) ?? null,
'uptime' => $uptimeStr,
'upticks' => $upticks,
'cpu_usage' => $cpu,
'memory_usage' => $memPercent !== null ? round($memPercent, 2) : null,
'disk_usage_c' => $diskPercent !== null ? round($diskPercent, 2) : null,
'last_update' => time(),
];
log_msg('RESULT: CPU=' . $result['cpu_usage'] . ', Mem=' . $result['memory_usage'] . ', Disk=' . $result['disk_usage_c']);
$resultJson = json_encode($result);
// === Cache schreiben ===
@file_put_contents($cacheFile, $resultJson);
log_msg('Cache geschrieben, TTL: ' . $cacheTTL . 's');
echo $resultJson;
exit;

View File

@ -1,429 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Blank</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapsePages" aria-expanded="true"
aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse show" aria-labelledby="headingPages"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item active" href="blank.html">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-4 text-gray-800">Blank Page</h1>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,604 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Buttons</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true"
aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item active" href="buttons.html">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-4 text-gray-800">Buttons</h1>
<div class="row">
<div class="col-lg-6">
<!-- Circle Buttons -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Circle Buttons</h6>
</div>
<div class="card-body">
<p>Use Font Awesome Icons (included with this theme package) along with the circle
buttons as shown in the examples below!</p>
<!-- Circle Buttons (Default) -->
<div class="mb-2">
<code>.btn-circle</code>
</div>
<a href="#" class="btn btn-primary btn-circle">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="btn btn-success btn-circle">
<i class="fas fa-check"></i>
</a>
<a href="#" class="btn btn-info btn-circle">
<i class="fas fa-info-circle"></i>
</a>
<a href="#" class="btn btn-warning btn-circle">
<i class="fas fa-exclamation-triangle"></i>
</a>
<a href="#" class="btn btn-danger btn-circle">
<i class="fas fa-trash"></i>
</a>
<!-- Circle Buttons (Small) -->
<div class="mt-4 mb-2">
<code>.btn-circle .btn-sm</code>
</div>
<a href="#" class="btn btn-primary btn-circle btn-sm">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="btn btn-success btn-circle btn-sm">
<i class="fas fa-check"></i>
</a>
<a href="#" class="btn btn-info btn-circle btn-sm">
<i class="fas fa-info-circle"></i>
</a>
<a href="#" class="btn btn-warning btn-circle btn-sm">
<i class="fas fa-exclamation-triangle"></i>
</a>
<a href="#" class="btn btn-danger btn-circle btn-sm">
<i class="fas fa-trash"></i>
</a>
<!-- Circle Buttons (Large) -->
<div class="mt-4 mb-2">
<code>.btn-circle .btn-lg</code>
</div>
<a href="#" class="btn btn-primary btn-circle btn-lg">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="btn btn-success btn-circle btn-lg">
<i class="fas fa-check"></i>
</a>
<a href="#" class="btn btn-info btn-circle btn-lg">
<i class="fas fa-info-circle"></i>
</a>
<a href="#" class="btn btn-warning btn-circle btn-lg">
<i class="fas fa-exclamation-triangle"></i>
</a>
<a href="#" class="btn btn-danger btn-circle btn-lg">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
<!-- Brand Buttons -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Brand Buttons</h6>
</div>
<div class="card-body">
<p>Google and Facebook buttons are available featuring each company's respective
brand color. They are used on the user login and registration pages.</p>
<p>You can create more custom buttons by adding a new color variable in the
<code>_variables.scss</code> file and then using the Bootstrap button variant
mixin to create a new style, as demonstrated in the <code>_buttons.scss</code>
file.</p>
<a href="#" class="btn btn-google btn-block"><i class="fab fa-google fa-fw"></i>
.btn-google</a>
<a href="#" class="btn btn-facebook btn-block"><i
class="fab fa-facebook-f fa-fw"></i> .btn-facebook</a>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Split Buttons with Icon</h6>
</div>
<div class="card-body">
<p>Works with any button colors, just use the <code>.btn-icon-split</code> class and
the markup in the examples below. The examples below also use the
<code>.text-white-50</code> helper class on the icons for additional styling,
but it is not required.</p>
<a href="#" class="btn btn-primary btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-flag"></i>
</span>
<span class="text">Split Button Primary</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-success btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-check"></i>
</span>
<span class="text">Split Button Success</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-info btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-info-circle"></i>
</span>
<span class="text">Split Button Info</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-warning btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-exclamation-triangle"></i>
</span>
<span class="text">Split Button Warning</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-danger btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-trash"></i>
</span>
<span class="text">Split Button Danger</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-secondary btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-arrow-right"></i>
</span>
<span class="text">Split Button Secondary</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-light btn-icon-split">
<span class="icon text-gray-600">
<i class="fas fa-arrow-right"></i>
</span>
<span class="text">Split Button Light</span>
</a>
<div class="mb-4"></div>
<p>Also works with small and large button classes!</p>
<a href="#" class="btn btn-primary btn-icon-split btn-sm">
<span class="icon text-white-50">
<i class="fas fa-flag"></i>
</span>
<span class="text">Split Button Small</span>
</a>
<div class="my-2"></div>
<a href="#" class="btn btn-primary btn-icon-split btn-lg">
<span class="icon text-white-50">
<i class="fas fa-flag"></i>
</span>
<span class="text">Split Button Large</span>
</a>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,598 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Cards</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="true"
aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse show" aria-labelledby="headingTwo"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item active" href="cards.html">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Cards</h1>
</div>
<div class="row">
<!-- Earnings (Monthly) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Earnings (Monthly)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">$40,000</div>
</div>
<div class="col-auto">
<i class="fas fa-calendar fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Earnings (Annual) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Earnings (Annual)</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">$215,000</div>
</div>
<div class="col-auto">
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Tasks Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tasks
</div>
<div class="row no-gutters align-items-center">
<div class="col-auto">
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800">50%</div>
</div>
<div class="col">
<div class="progress progress-sm mr-2">
<div class="progress-bar bg-info" role="progressbar"
style="width: 50%" aria-valuenow="50" aria-valuemin="0"
aria-valuemax="100"></div>
</div>
</div>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Pending Requests Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Pending Requests</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">18</div>
</div>
<div class="col-auto">
<i class="fas fa-comments fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<!-- Default Card Example -->
<div class="card mb-4">
<div class="card-header">
Default Card Example
</div>
<div class="card-body">
This card uses Bootstrap's default styling with no utility classes added. Global
styles are the only things modifying the look and feel of this default card example.
</div>
</div>
<!-- Basic Card Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Basic Card Example</h6>
</div>
<div class="card-body">
The styling for this basic card example is created by using default Bootstrap
utility classes. By using utility classes, the style of the card component can be
easily modified with no need for any custom CSS!
</div>
</div>
</div>
<div class="col-lg-6">
<!-- Dropdown Card Example -->
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div
class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Dropdown Card Example</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- Card Body -->
<div class="card-body">
Dropdown menus can be placed in the card header in order to extend the functionality
of a basic card. In this dropdown card example, the Font Awesome vertical ellipsis
icon in the card header can be clicked on in order to toggle a dropdown menu.
</div>
</div>
<!-- Collapsable Card Example -->
<div class="card shadow mb-4">
<!-- Card Header - Accordion -->
<a href="#collapseCardExample" class="d-block card-header py-3" data-toggle="collapse"
role="button" aria-expanded="true" aria-controls="collapseCardExample">
<h6 class="m-0 font-weight-bold text-primary">Collapsable Card Example</h6>
</a>
<!-- Card Content - Collapse -->
<div class="collapse show" id="collapseCardExample">
<div class="card-body">
This is a collapsable card example using Bootstrap's built in collapse
functionality. <strong>Click on the card header</strong> to see the card body
collapse and expand!
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,497 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Charts</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item active">
<a class="nav-link" href="charts.html">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-2 text-gray-800">Charts</h1>
<p class="mb-4">Chart.js is a third party plugin that is used to generate the charts in this theme.
The charts below have been customized - for further customization options, please visit the <a
target="_blank" href="https://www.chartjs.org/docs/latest/">official Chart.js
documentation</a>.</p>
<!-- Content Row -->
<div class="row">
<div class="col-xl-8 col-lg-7">
<!-- Area Chart -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Area Chart</h6>
</div>
<div class="card-body">
<div class="chart-area">
<canvas id="myAreaChart"></canvas>
</div>
<hr>
Styling for the area chart can be found in the
<code>/js/demo/chart-area-demo.js</code> file.
</div>
</div>
<!-- Bar Chart -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Bar Chart</h6>
</div>
<div class="card-body">
<div class="chart-bar">
<canvas id="myBarChart"></canvas>
</div>
<hr>
Styling for the bar chart can be found in the
<code>/js/demo/chart-bar-demo.js</code> file.
</div>
</div>
</div>
<!-- Donut Chart -->
<div class="col-xl-4 col-lg-5">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Donut Chart</h6>
</div>
<!-- Card Body -->
<div class="card-body">
<div class="chart-pie pt-4">
<canvas id="myPieChart"></canvas>
</div>
<hr>
Styling for the donut chart can be found in the
<code>/js/demo/chart-pie-demo.js</code> file.
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="js/demo/chart-area-demo.js"></script>
<script src="js/demo/chart-pie-demo.js"></script>
<script src="js/demo/chart-bar-demo.js"></script>
</body>
</html>

View File

@ -1,87 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Forgot Password</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-password-image"></div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-2">Forgot Your Password?</h1>
<p class="mb-4">We get it, stuff happens. Just enter your email address below
and we'll send you a link to reset your password!</p>
</div>
<form class="user">
<div class="form-group">
<input type="email" class="form-control form-control-user"
id="exampleInputEmail" aria-describedby="emailHelp"
placeholder="Enter Email Address...">
</div>
<a href="login.php" class="btn btn-primary btn-user btn-block">
Reset Password
</a>
</form>
<hr>
<div class="text-center">
<a class="small" href="register.php">Create an Account!</a>
</div>
<div class="text-center">
<a class="small" href="login.php">Already have an account? Login!</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -3,9 +3,31 @@
// Strenge Typprüfung für Parameter- und Rückgabetypen aktivieren.
declare(strict_types=1);
// Eine neue Session wird gestartet und die entsprechende Variable ($_SESSION) angelegt oder eine bestehende wird fortgesetzt.
/**
* Front-Controller der Webanwendung.
*
* Aufgaben:
* - Startet die Session und initialisiert den Autoloader für den App-Namespace.
* - Lädt die zentrale Konfiguration aus config/config.php.
* - Instanziiert die Hauptcontroller (Auth, Dashboard, User-Management).
* - Steuert das Routing anhand des GET-Parameters "route".
* - Leitet View-Result-Arrays an das zentrale Layout (renderLayout) weiter
* oder führt Redirects aus.
*
* WICHTIG:
* - Diese Datei ist der einzige öffentliche Einstiegspunkt (Entry Point) der App.
* - Alle neuen Routen sollten über den Switch-Block am Ende ergänzt werden.
*/
// Eine neue Session wird gestartet und die entsprechende Variable ($_SESSION) angelegt
// oder eine bestehende wird fortgesetzt.
session_start();
// PHP-Fehler erfassen, aber veraltete Hinweise (E_DEPRECATED) ignorieren,
// weil sie sonst im Zusammenspiel mit IIS/fastcgi zu 500-Fehlern führen können.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
ini_set('display_errors', '0');
/*
* Registriert eine Autoload-Funktion für Klassen mit dem Namespace-Präfix "App\".
* Statt jede Klasse manuell über "require pfad_zur_klasse.php" einzubinden,
@ -13,7 +35,6 @@ session_start();
* im Namespace "App\..." verwendet wird.
*/
spl_autoload_register(
// Anonyme Funktion, die den Klassennamen prüft und den Dateipfad zur Klasse ermittelt.
static function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/../app/';
@ -32,7 +53,11 @@ spl_autoload_register(
}
);
// Pfad zur Konfigurationsdatei prüfen und Konfiguration laden
// Layout-Funktion einbinden (renderLayout)
require __DIR__ . '/views/layout.php';
// Die Konfigurationsdatei liefert ein assoziatives Array mit den Teilbereichen
// "ldap", "snmp", "security" und "logging" (u. a. Session-Keys, Timeout-Einstellungen, OIDs, Log-Pfade).
$configPath = __DIR__ . '/../config/config.php';
if (file_exists($configPath) === false) {
// Fail fast: ohne Konfiguration macht die App keinen Sinn
@ -48,8 +73,68 @@ $config = require $configPath;
use App\Controllers\AuthController;
use App\Controllers\DashboardController;
use App\Controllers\UserManagementController;
use App\Services\Logging\LoggingService;
// Hilfsfunktion für geschützte Routen
// Globalen Logger initialisieren, damit auch Fehler außerhalb der Controller
// (z. B. in index.php selbst) sauber protokolliert werden.
$globalLogger = new LoggingService($config['logging'] ?? []);
/**
* Globale Fehlerbehandlung:
* - PHP-Fehler (Warnings, Notices, ...) werden in den Logger geschrieben.
* - Unbehandelte Exceptions werden ebenfalls geloggt und führen zu einer generischen 500er-Meldung.
*/
set_error_handler(
static function (
int $severity,
string $message,
string $file = '',
int $line = 0
) use ($globalLogger): bool {
// Fehler nur loggen, wenn sie durch error_reporting() nicht unterdrückt sind.
if ((error_reporting() & $severity) === 0) {
return false;
}
$globalLogger->log(
'error',
'PHP-Fehler: ' . $message,
[
'severity' => $severity,
'file' => $file,
'line' => $line,
]
);
// false zurückgeben = PHP darf seinen Standard-Handler zusätzlich verwenden
// (der Browser sieht wegen display_errors=0 trotzdem nichts).
return false;
}
);
set_exception_handler(
static function (\Throwable $exception) use ($globalLogger): void {
$globalLogger->logException(
'Unbehandelte Exception in der Anwendung.',
$exception,
[
'request_uri' => $_SERVER['REQUEST_URI'] ?? null,
'route' => $_GET['route'] ?? null,
]
);
http_response_code(500);
echo 'Es ist ein unerwarteter Fehler aufgetreten. '
. 'Bitte versuchen Sie es später erneut oder wenden Sie sich an den Administrator.';
}
);
/**
* Hilfsfunktion: Prüft, ob ein Benutzer eingeloggt ist.
* Wenn nicht, wird auf die Login-Seite umgeleitet.
*
* @param array<string, mixed> $config
*/
function requireLogin(array $config): void
{
// session_key_user aus dem Config-Array lesen. Wenn nicht gesetzt oder null, Standard "admin_user" verwenden.
@ -63,44 +148,96 @@ function requireLogin(array $config): void
}
}
// Route aus dem GET-Parameter lesen. Wenn nicht gesetzt, Standardroute "login" verwenden.
$route = $_GET['route'] ?? 'login';
/**
* Verarbeitet ein View-Result oder Redirect-Result.
*
* @param array<string, mixed>|null $result
*/
function handleResult(?array $result): void
{
if ($result === null) {
return;
}
// Neue Instanz der Klasse AuthController erstellen (wird bei Bedarf über den Autoloader geladen).
// Redirect-Result
if (isset($result['redirect']) === true) {
header('Location: ' . (string)$result['redirect']);
exit;
}
// View-Result
$contentView = (string)($result['view'] ?? '');
$viewData = (array)($result['data'] ?? []);
// Standard: Wir gehen davon aus, dass es KEINE Loginseite ist,
// außer der Controller sagt explizit etwas anderes.
if (array_key_exists('loginPage', $viewData) === false) {
$viewData['loginPage'] = false;
}
$pageTitle = (string)($result['pageTitle'] ?? '');
$activeMenu = $result['activeMenu'] ?? null;
if ($contentView === '' || file_exists($contentView) === false) {
http_response_code(500);
echo 'Interner Fehler: Content-View wurde nicht gefunden.';
exit;
}
// Hier rufen wir jetzt die Layout-Funktion aus layout.php auf
renderLayout(
$contentView,
$viewData,
$pageTitle,
is_string($activeMenu) ? $activeMenu : null
);
}
// Zentrale Controller der Anwendung initialisieren und ihnen die vollständige Konfiguration übergeben.
// Die Controller holen sich daraus bei Bedarf ihre spezifischen Teilkonfigurationen (z. B. "ldap" oder "snmp").
// Jeder Controller erzeugt intern seinen eigenen LoggingService aus $config['logging'].
$authController = new AuthController($config);
// Neue Instanz der Klasse DashboardController erstellen (wird bei Bedarf über den Autoloader geladen).
$dashboardController = new DashboardController($config);
// Neue Instanz der Klasse UserManagmentController erstellen (wird bei Bedarf über den Autoloader geladen).
$userManagementController = new UserManagementController($config);
// Anhand des Routing-Ziels (route) entscheiden, welcher Code ausgeführt wird.
// Route aus dem Query-Parameter lesen. Standardroute ist "login",
// sodass nicht angemeldete Benutzer automatisch auf die Login-Seite geführt werden.
$route = $_GET['route'] ?? 'login';
// Einfache Router-Logik: Jede Route ruft eine Controller-Methode auf und
// übergibt deren View-Result an handleResult(). Neue Seiten werden hier ergänzt.
switch ($route) {
case 'login':
$authController->showLoginForm();
// Login-Formular anzeigen (ggf. mit Fehlermeldung)
$result = $authController->showLoginForm();
handleResult($result);
break;
case 'login.submit':
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
// Falscher HTTP-Verb: einfach zurück zum Login
header('Location: index.php?route=login');
exit;
}
$authController->processLogin();
$result = $authController->processLogin();
handleResult($result);
break;
case 'logout':
$authController->logout();
$result = $authController->logout();
handleResult($result);
break;
case 'dashboard':
requireLogin($config);
$dashboardController->show();
$result = $dashboardController->show();
handleResult($result);
break;
case 'users':
requireLogin($config);
$userManagementController->show();
$result = $userManagementController->show();
handleResult($result);
break;
default:

View File

@ -1,109 +0,0 @@
<?php
declare(strict_types=1);
/**
* @var string|null $error
*/
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Login</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<?php if ($error !== null): ?>
<div class="alert alert-danger" role="alert">
<?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</div>
<?php endif; ?>
<form class="user" method="post" action="index.php?route=login.submit">
<div class="form-group">
<input type="text" name="username" class="form-control form-control-user"
id="username" aria-describedby="usernameHelp"
placeholder="Enter Username...">
</div>
<div class="form-group">
<input type="password" name="password" class="form-control form-control-user"
id="password" placeholder="Password">
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember
Me</label>
</div>
</div>
<button type="submit" class="btn btn-primary btn-user btn-block">
Anmelden
</button>
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.php">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="register.php">Create an Account!</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,102 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Register</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-5 d-none d-lg-block bg-register-image"></div>
<div class="col-lg-7">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Create an Account!</h1>
</div>
<form class="user">
<div class="form-group row">
<div class="col-sm-6 mb-3 mb-sm-0">
<input type="text" class="form-control form-control-user" id="exampleFirstName"
placeholder="First Name">
</div>
<div class="col-sm-6">
<input type="text" class="form-control form-control-user" id="exampleLastName"
placeholder="Last Name">
</div>
</div>
<div class="form-group">
<input type="email" class="form-control form-control-user" id="exampleInputEmail"
placeholder="Email Address">
</div>
<div class="form-group row">
<div class="col-sm-6 mb-3 mb-sm-0">
<input type="password" class="form-control form-control-user"
id="exampleInputPassword" placeholder="Password">
</div>
<div class="col-sm-6">
<input type="password" class="form-control form-control-user"
id="exampleRepeatPassword" placeholder="Repeat Password">
</div>
</div>
<a href="login.php" class="btn btn-primary btn-user btn-block">
Register Account
</a>
<hr>
<a href="views/dashboard.php" class="btn btn-google btn-user btn-block">
<i class="fab fa-google fa-fw"></i> Register with Google
</a>
<a href="views/dashboard.php" class="btn btn-facebook btn-user btn-block">
<i class="fab fa-facebook-f fa-fw"></i> Register with Facebook
</a>
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.php">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="login.php">Already have an account? Login!</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,49 +0,0 @@
<?php
// dashboard.php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
// SNMP-Konfiguration
$community = 'public_ro';
$host = '127.0.0.1';
snmp_set_quick_print(true);
snmp_set_oid_output_format(SNMP_OID_OUTPUT_NUMERIC);
// CPU-Last (erster Kern, Beispiel)
$cpu_oid = '.1.3.6.1.2.1.25.3.3.1.2.1';
$cpu_load = @snmpget($host, $community, $cpu_oid, 1000000, 2);
// System Uptime
$uptime_oid = '.1.3.6.1.2.1.25.1.1.0';
$uptime_raw = @snmpget($host, $community, $uptime_oid);
$uptime = $uptime_raw ? ($uptime_raw / (100 * 60 * 60 * 24)) . " Tage" : "Fehler";
// RAM (statisches Beispiel mit Index 5)
$ram_total_oid = '.1.3.6.1.2.1.25.2.3.1.5.5';
$ram_used_oid = '.1.3.6.1.2.1.25.2.3.1.6.5';
$ram_alloc_units_oid = '.1.3.6.1.2.1.25.2.3.1.4.5';
$ram_total_raw = @snmpget($host, $community, $ram_total_oid);
$ram_used_raw = @snmpget($host, $community, $ram_used_oid);
$ram_units = @snmpget($host, $community, $ram_alloc_units_oid);
if ($ram_total_raw && $ram_used_raw && $ram_units) {
$ram_total_gb = ($ram_total_raw * $ram_units) / (1024 ** 3);
$ram_used_gb = ($ram_used_raw * $ram_units) / (1024 ** 3);
$ram_percent = ($ram_used_gb / $ram_total_gb) * 100;
}
?>
<h2>Admin Dashboard</h2>
<p>Angemeldet als: <?php echo htmlspecialchars($_SESSION['username']); ?></p>
<h3>Server-Status (SNMP)</h3>
<p>CPU-Last (Kern 1): <?php echo $cpu_load ?: "Fehler bei Abfrage"; ?>%</p>
<p>System Uptime: <?php echo $uptime; ?></p>
<p>RAM-Auslastung:
<?php echo isset($ram_percent) ? number_format($ram_percent, 2) . "%" : "Fehler bei Abfrage"; ?>
</p>
<hr>
<p><a href="create_single_user.php">Einzelnen Benutzer erstellen</a></p>
<p><a href="bulk_create_users.php">Benutzer per CSV importieren</a></p>

View File

@ -1,934 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Tables</title>
<!-- Custom fonts for this template -->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template -->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
<!-- Custom styles for this page -->
<link href="vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item active">
<a class="nav-link" href="tables.html">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<form class="form-inline">
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
</form>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-2 text-gray-800">Tables</h1>
<p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below.
For more information about DataTables, please visit the <a target="_blank"
href="https://datatables.net">official DataTables documentation</a>.</p>
<!-- DataTales Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">DataTables Example</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
<tr>
<td>Garrett Winters</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>63</td>
<td>2011/07/25</td>
<td>$170,750</td>
</tr>
<tr>
<td>Ashton Cox</td>
<td>Junior Technical Author</td>
<td>San Francisco</td>
<td>66</td>
<td>2009/01/12</td>
<td>$86,000</td>
</tr>
<tr>
<td>Cedric Kelly</td>
<td>Senior Javascript Developer</td>
<td>Edinburgh</td>
<td>22</td>
<td>2012/03/29</td>
<td>$433,060</td>
</tr>
<tr>
<td>Airi Satou</td>
<td>Accountant</td>
<td>Tokyo</td>
<td>33</td>
<td>2008/11/28</td>
<td>$162,700</td>
</tr>
<tr>
<td>Brielle Williamson</td>
<td>Integration Specialist</td>
<td>New York</td>
<td>61</td>
<td>2012/12/02</td>
<td>$372,000</td>
</tr>
<tr>
<td>Herrod Chandler</td>
<td>Sales Assistant</td>
<td>San Francisco</td>
<td>59</td>
<td>2012/08/06</td>
<td>$137,500</td>
</tr>
<tr>
<td>Rhona Davidson</td>
<td>Integration Specialist</td>
<td>Tokyo</td>
<td>55</td>
<td>2010/10/14</td>
<td>$327,900</td>
</tr>
<tr>
<td>Colleen Hurst</td>
<td>Javascript Developer</td>
<td>San Francisco</td>
<td>39</td>
<td>2009/09/15</td>
<td>$205,500</td>
</tr>
<tr>
<td>Sonya Frost</td>
<td>Software Engineer</td>
<td>Edinburgh</td>
<td>23</td>
<td>2008/12/13</td>
<td>$103,600</td>
</tr>
<tr>
<td>Jena Gaines</td>
<td>Office Manager</td>
<td>London</td>
<td>30</td>
<td>2008/12/19</td>
<td>$90,560</td>
</tr>
<tr>
<td>Quinn Flynn</td>
<td>Support Lead</td>
<td>Edinburgh</td>
<td>22</td>
<td>2013/03/03</td>
<td>$342,000</td>
</tr>
<tr>
<td>Charde Marshall</td>
<td>Regional Director</td>
<td>San Francisco</td>
<td>36</td>
<td>2008/10/16</td>
<td>$470,600</td>
</tr>
<tr>
<td>Haley Kennedy</td>
<td>Senior Marketing Designer</td>
<td>London</td>
<td>43</td>
<td>2012/12/18</td>
<td>$313,500</td>
</tr>
<tr>
<td>Tatyana Fitzpatrick</td>
<td>Regional Director</td>
<td>London</td>
<td>19</td>
<td>2010/03/17</td>
<td>$385,750</td>
</tr>
<tr>
<td>Michael Silva</td>
<td>Marketing Designer</td>
<td>London</td>
<td>66</td>
<td>2012/11/27</td>
<td>$198,500</td>
</tr>
<tr>
<td>Paul Byrd</td>
<td>Chief Financial Officer (CFO)</td>
<td>New York</td>
<td>64</td>
<td>2010/06/09</td>
<td>$725,000</td>
</tr>
<tr>
<td>Gloria Little</td>
<td>Systems Administrator</td>
<td>New York</td>
<td>59</td>
<td>2009/04/10</td>
<td>$237,500</td>
</tr>
<tr>
<td>Bradley Greer</td>
<td>Software Engineer</td>
<td>London</td>
<td>41</td>
<td>2012/10/13</td>
<td>$132,000</td>
</tr>
<tr>
<td>Dai Rios</td>
<td>Personnel Lead</td>
<td>Edinburgh</td>
<td>35</td>
<td>2012/09/26</td>
<td>$217,500</td>
</tr>
<tr>
<td>Jenette Caldwell</td>
<td>Development Lead</td>
<td>New York</td>
<td>30</td>
<td>2011/09/03</td>
<td>$345,000</td>
</tr>
<tr>
<td>Yuri Berry</td>
<td>Chief Marketing Officer (CMO)</td>
<td>New York</td>
<td>40</td>
<td>2009/06/25</td>
<td>$675,000</td>
</tr>
<tr>
<td>Caesar Vance</td>
<td>Pre-Sales Support</td>
<td>New York</td>
<td>21</td>
<td>2011/12/12</td>
<td>$106,450</td>
</tr>
<tr>
<td>Doris Wilder</td>
<td>Sales Assistant</td>
<td>Sidney</td>
<td>23</td>
<td>2010/09/20</td>
<td>$85,600</td>
</tr>
<tr>
<td>Angelica Ramos</td>
<td>Chief Executive Officer (CEO)</td>
<td>London</td>
<td>47</td>
<td>2009/10/09</td>
<td>$1,200,000</td>
</tr>
<tr>
<td>Gavin Joyce</td>
<td>Developer</td>
<td>Edinburgh</td>
<td>42</td>
<td>2010/12/22</td>
<td>$92,575</td>
</tr>
<tr>
<td>Jennifer Chang</td>
<td>Regional Director</td>
<td>Singapore</td>
<td>28</td>
<td>2010/11/14</td>
<td>$357,650</td>
</tr>
<tr>
<td>Brenden Wagner</td>
<td>Software Engineer</td>
<td>San Francisco</td>
<td>28</td>
<td>2011/06/07</td>
<td>$206,850</td>
</tr>
<tr>
<td>Fiona Green</td>
<td>Chief Operating Officer (COO)</td>
<td>San Francisco</td>
<td>48</td>
<td>2010/03/11</td>
<td>$850,000</td>
</tr>
<tr>
<td>Shou Itou</td>
<td>Regional Marketing</td>
<td>Tokyo</td>
<td>20</td>
<td>2011/08/14</td>
<td>$163,000</td>
</tr>
<tr>
<td>Michelle House</td>
<td>Integration Specialist</td>
<td>Sidney</td>
<td>37</td>
<td>2011/06/02</td>
<td>$95,400</td>
</tr>
<tr>
<td>Suki Burks</td>
<td>Developer</td>
<td>London</td>
<td>53</td>
<td>2009/10/22</td>
<td>$114,500</td>
</tr>
<tr>
<td>Prescott Bartlett</td>
<td>Technical Author</td>
<td>London</td>
<td>27</td>
<td>2011/05/07</td>
<td>$145,000</td>
</tr>
<tr>
<td>Gavin Cortez</td>
<td>Team Leader</td>
<td>San Francisco</td>
<td>22</td>
<td>2008/10/26</td>
<td>$235,500</td>
</tr>
<tr>
<td>Martena Mccray</td>
<td>Post-Sales support</td>
<td>Edinburgh</td>
<td>46</td>
<td>2011/03/09</td>
<td>$324,050</td>
</tr>
<tr>
<td>Unity Butler</td>
<td>Marketing Designer</td>
<td>San Francisco</td>
<td>47</td>
<td>2009/12/09</td>
<td>$85,675</td>
</tr>
<tr>
<td>Howard Hatfield</td>
<td>Office Manager</td>
<td>San Francisco</td>
<td>51</td>
<td>2008/12/16</td>
<td>$164,500</td>
</tr>
<tr>
<td>Hope Fuentes</td>
<td>Secretary</td>
<td>San Francisco</td>
<td>41</td>
<td>2010/02/12</td>
<td>$109,850</td>
</tr>
<tr>
<td>Vivian Harrell</td>
<td>Financial Controller</td>
<td>San Francisco</td>
<td>62</td>
<td>2009/02/14</td>
<td>$452,500</td>
</tr>
<tr>
<td>Timothy Mooney</td>
<td>Office Manager</td>
<td>London</td>
<td>37</td>
<td>2008/12/11</td>
<td>$136,200</td>
</tr>
<tr>
<td>Jackson Bradshaw</td>
<td>Director</td>
<td>New York</td>
<td>65</td>
<td>2008/09/26</td>
<td>$645,750</td>
</tr>
<tr>
<td>Olivia Liang</td>
<td>Support Engineer</td>
<td>Singapore</td>
<td>64</td>
<td>2011/02/03</td>
<td>$234,500</td>
</tr>
<tr>
<td>Bruno Nash</td>
<td>Software Engineer</td>
<td>London</td>
<td>38</td>
<td>2011/05/03</td>
<td>$163,500</td>
</tr>
<tr>
<td>Sakura Yamamoto</td>
<td>Support Engineer</td>
<td>Tokyo</td>
<td>37</td>
<td>2009/08/19</td>
<td>$139,575</td>
</tr>
<tr>
<td>Thor Walton</td>
<td>Developer</td>
<td>New York</td>
<td>61</td>
<td>2013/08/11</td>
<td>$98,540</td>
</tr>
<tr>
<td>Finn Camacho</td>
<td>Support Engineer</td>
<td>San Francisco</td>
<td>47</td>
<td>2009/07/07</td>
<td>$87,500</td>
</tr>
<tr>
<td>Serge Baldwin</td>
<td>Data Coordinator</td>
<td>Singapore</td>
<td>64</td>
<td>2012/04/09</td>
<td>$138,575</td>
</tr>
<tr>
<td>Zenaida Frank</td>
<td>Software Engineer</td>
<td>New York</td>
<td>63</td>
<td>2010/01/04</td>
<td>$125,250</td>
</tr>
<tr>
<td>Zorita Serrano</td>
<td>Software Engineer</td>
<td>San Francisco</td>
<td>56</td>
<td>2012/06/01</td>
<td>$115,000</td>
</tr>
<tr>
<td>Jennifer Acosta</td>
<td>Junior Javascript Developer</td>
<td>Edinburgh</td>
<td>43</td>
<td>2013/02/01</td>
<td>$75,650</td>
</tr>
<tr>
<td>Cara Stevens</td>
<td>Sales Assistant</td>
<td>New York</td>
<td>46</td>
<td>2011/12/06</td>
<td>$145,600</td>
</tr>
<tr>
<td>Hermione Butler</td>
<td>Regional Director</td>
<td>London</td>
<td>47</td>
<td>2011/03/21</td>
<td>$356,250</td>
</tr>
<tr>
<td>Lael Greer</td>
<td>Systems Administrator</td>
<td>London</td>
<td>21</td>
<td>2009/02/27</td>
<td>$103,500</td>
</tr>
<tr>
<td>Jonas Alexander</td>
<td>Developer</td>
<td>San Francisco</td>
<td>30</td>
<td>2010/07/14</td>
<td>$86,500</td>
</tr>
<tr>
<td>Shad Decker</td>
<td>Regional Director</td>
<td>Edinburgh</td>
<td>51</td>
<td>2008/11/13</td>
<td>$183,000</td>
</tr>
<tr>
<td>Michael Bruce</td>
<td>Javascript Developer</td>
<td>Singapore</td>
<td>29</td>
<td>2011/06/27</td>
<td>$183,000</td>
</tr>
<tr>
<td>Donna Snider</td>
<td>Customer Support</td>
<td>New York</td>
<td>27</td>
<td>2011/01/25</td>
<td>$112,000</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="js/demo/datatables-demo.js"></script>
</body>
</html>

View File

@ -1,529 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Animation Utilities</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item active" href="utilities-animation.html">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-1 text-gray-800">Animation Utilities</h1>
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
below were created to extend this theme past the default utility classes built into Bootstrap's
framework.</p>
<!-- Content Row -->
<div class="row">
<!-- Grow In Utility -->
<div class="col-lg-6">
<div class="card position-relative">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Grow In Animation Utilty</h6>
</div>
<div class="card-body">
<div class="mb-3">
<code>.animated--grow-in</code>
</div>
<div class="small mb-1">Navbar Dropdown Example:</div>
<nav class="navbar navbar-expand navbar-light bg-light mb-4">
<a class="navbar-brand" href="#">Navbar</a>
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu dropdown-menu-right animated--grow-in"
aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</nav>
<p class="mb-0 small">Note: This utility animates the CSS transform property,
meaning it will override any existing transforms on an element being animated!
In this theme, the grow in animation is only being used on dropdowns within the
navbar.</p>
</div>
</div>
</div>
<!-- Fade In Utility -->
<div class="col-lg-6">
<div class="card position-relative">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Fade In Animation Utilty</h6>
</div>
<div class="card-body">
<div class="mb-3">
<code>.animated--fade-in</code>
</div>
<div class="small mb-1">Navbar Dropdown Example:</div>
<nav class="navbar navbar-expand navbar-light bg-light mb-4">
<a class="navbar-brand" href="#">Navbar</a>
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown"
role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu dropdown-menu-right animated--fade-in"
aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</nav>
<div class="small mb-1">Dropdown Button Example:</div>
<div class="dropdown mb-4">
<button class="btn btn-primary dropdown-toggle" type="button"
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Dropdown
</button>
<div class="dropdown-menu animated--fade-in"
aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
<p class="mb-0 small">Note: This utility animates the CSS opacity property, meaning
it will override any existing opacity on an element being animated!</p>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,531 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Border Utilities</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item active" href="utilities-border.html">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-1 text-gray-800">Border Utilities</h1>
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
below were created to extend this theme past the default utility classes built into Bootstrap's
framework.</p>
<!-- Content Row -->
<div class="row">
<!-- Border Left Utilities -->
<div class="col-lg-6">
<div class="card mb-4 py-3 border-left-primary">
<div class="card-body">
.border-left-primary
</div>
</div>
<div class="card mb-4 py-3 border-left-secondary">
<div class="card-body">
.border-left-secondary
</div>
</div>
<div class="card mb-4 py-3 border-left-success">
<div class="card-body">
.border-left-success
</div>
</div>
<div class="card mb-4 py-3 border-left-info">
<div class="card-body">
.border-left-info
</div>
</div>
<div class="card mb-4 py-3 border-left-warning">
<div class="card-body">
.border-left-warning
</div>
</div>
<div class="card mb-4 py-3 border-left-danger">
<div class="card-body">
.border-left-danger
</div>
</div>
<div class="card mb-4 py-3 border-left-dark">
<div class="card-body">
.border-left-dark
</div>
</div>
</div>
<!-- Border Bottom Utilities -->
<div class="col-lg-6">
<div class="card mb-4 py-3 border-bottom-primary">
<div class="card-body">
.border-bottom-primary
</div>
</div>
<div class="card mb-4 py-3 border-bottom-secondary">
<div class="card-body">
.border-bottom-secondary
</div>
</div>
<div class="card mb-4 py-3 border-bottom-success">
<div class="card-body">
.border-bottom-success
</div>
</div>
<div class="card mb-4 py-3 border-bottom-info">
<div class="card-body">
.border-bottom-info
</div>
</div>
<div class="card mb-4 py-3 border-bottom-warning">
<div class="card-body">
.border-bottom-warning
</div>
</div>
<div class="card mb-4 py-3 border-bottom-danger">
<div class="card-body">
.border-bottom-danger
</div>
</div>
<div class="card mb-4 py-3 border-bottom-dark">
<div class="card-body">
.border-bottom-dark
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,517 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Color Utilities</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item active" href="utilities-color.html">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item" href="utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-1 text-gray-800">Color Utilities</h1>
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
below were created to extend this theme past the default utility classes built into Bootstrap's
framework.</p>
<!-- Content Row -->
<div class="row">
<!-- First Column -->
<div class="col-lg-4">
<!-- Custom Text Color Utilities -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Custom Text Color Utilities</h6>
</div>
<div class="card-body">
<p class="text-gray-100 p-3 bg-dark m-0">.text-gray-100</p>
<p class="text-gray-200 p-3 bg-dark m-0">.text-gray-200</p>
<p class="text-gray-300 p-3 bg-dark m-0">.text-gray-300</p>
<p class="text-gray-400 p-3 bg-dark m-0">.text-gray-400</p>
<p class="text-gray-500 p-3 m-0">.text-gray-500</p>
<p class="text-gray-600 p-3 m-0">.text-gray-600</p>
<p class="text-gray-700 p-3 m-0">.text-gray-700</p>
<p class="text-gray-800 p-3 m-0">.text-gray-800</p>
<p class="text-gray-900 p-3 m-0">.text-gray-900</p>
</div>
</div>
<!-- Custom Font Size Utilities -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Custom Font Size Utilities</h6>
</div>
<div class="card-body">
<p class="text-xs">.text-xs</p>
<p class="text-lg mb-0">.text-lg</p>
</div>
</div>
</div>
<!-- Second Column -->
<div class="col-lg-4">
<!-- Background Gradient Utilities -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Custom Background Gradient Utilities
</h6>
</div>
<div class="card-body">
<div class="px-3 py-5 bg-gradient-primary text-white">.bg-gradient-primary</div>
<div class="px-3 py-5 bg-gradient-secondary text-white">.bg-gradient-secondary</div>
<div class="px-3 py-5 bg-gradient-success text-white">.bg-gradient-success</div>
<div class="px-3 py-5 bg-gradient-info text-white">.bg-gradient-info</div>
<div class="px-3 py-5 bg-gradient-warning text-white">.bg-gradient-warning</div>
<div class="px-3 py-5 bg-gradient-danger text-white">.bg-gradient-danger</div>
<div class="px-3 py-5 bg-gradient-light text-white">.bg-gradient-light</div>
<div class="px-3 py-5 bg-gradient-dark text-white">.bg-gradient-dark</div>
</div>
</div>
</div>
<!-- Third Column -->
<div class="col-lg-4">
<!-- Grayscale Utilities -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Custom Grayscale Background Utilities
</h6>
</div>
<div class="card-body">
<div class="p-3 bg-gray-100">.bg-gray-100</div>
<div class="p-3 bg-gray-200">.bg-gray-200</div>
<div class="p-3 bg-gray-300">.bg-gray-300</div>
<div class="p-3 bg-gray-400">.bg-gray-400</div>
<div class="p-3 bg-gray-500 text-white">.bg-gray-500</div>
<div class="p-3 bg-gray-600 text-white">.bg-gray-600</div>
<div class="p-3 bg-gray-700 text-white">.bg-gray-700</div>
<div class="p-3 bg-gray-800 text-white">.bg-gray-800</div>
<div class="p-3 bg-gray-900 text-white">.bg-gray-900</div>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,511 +0,0 @@
<?php
require_once __DIR__ . '/../app/Helpers/AuthenticatedUserHelper.php';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Other Utilities</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="buttons.php">Buttons</a>
<a class="collapse-item" href="cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item active">
<a class="nav-link" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse show" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="utilities-color.php">Colors</a>
<a class="collapse-item" href="utilities-border.php">Borders</a>
<a class="collapse-item" href="utilities-animation.php">Animations</a>
<a class="collapse-item active" href="utilities-other.html">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="register.php">Register</a>
<a class="collapse-item" href="forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="404.php">404 Page</a>
<a class="collapse-item" href="blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-1 text-gray-800">Other Utilities</h1>
<p class="mb-4">Bootstrap's default utility classes can be found on the official <a
href="https://getbootstrap.com/docs">Bootstrap Documentation</a> page. The custom utilities
below were created to extend this theme past the default utility classes built into Bootstrap's
framework.</p>
<!-- Content Row -->
<div class="row">
<div class="col-lg-6">
<!-- Overflow Hidden -->
<div class="card mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Overflow Hidden Utilty</h6>
</div>
<div class="card-body">
Use <code>.o-hidden</code> to set the overflow property of any element to hidden.
</div>
</div>
<!-- Progress Small -->
<div class="card mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Progress Small Utility</h6>
</div>
<div class="card-body">
<div class="mb-1 small">Normal Progress Bar</div>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" style="width: 75%"
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<div class="mb-1 small">Small Progress Bar</div>
<div class="progress progress-sm mb-2">
<div class="progress-bar" role="progressbar" style="width: 75%"
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
</div>
Use the <code>.progress-sm</code> class along with <code>.progress</code>
</div>
</div>
<!-- Dropdown No Arrow -->
<div class="card mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Dropdown - No Arrow</h6>
</div>
<div class="card-body">
<div class="dropdown no-arrow mb-4">
<button class="btn btn-secondary dropdown-toggle" type="button"
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
Dropdown (no arrow)
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
Add the <code>.no-arrow</code> class alongside the <code>.dropdown</code>
</div>
</div>
</div>
<div class="col-lg-6">
<!-- Roitation Utilities -->
<div class="card">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Rotation Utilities</h6>
</div>
<div class="card-body text-center">
<div class="bg-primary text-white p-3 rotate-15 d-inline-block my-4">.rotate-15
</div>
<hr>
<div class="bg-primary text-white p-3 rotate-n-15 d-inline-block my-4">.rotate-n-15
</div>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>

View File

@ -1,792 +1,185 @@
<?php
declare(strict_types=1);
/**
* Server-Dashboard (Ansicht).
*
* Zeigt Server-Kennzahlen an (Hostname, Uptime, CPU, RAM, Datenträger).
* Erwartetes Array: `$serverStatus` mit Schlüsseln: hostname, uptime, cpu_usage,
* memory_usage, disk_usage_c, last_update.
*/
/** @var array<string, mixed> $serverStatus */
?>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Content Row -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Server-Dashboard</h1>
</div>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Dashboard</title>
<!-- Custom fonts for this template-->
<link href="../vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="../css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="../index.php?route=dashboard">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item active">
<a class="nav-link" href="../index.php?route=dashboard">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../index.php?route=users">
<i class="fas fa-fw fa-users"></i>
<span>Users</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="../buttons.php">Buttons</a>
<a class="collapse-item" href="../cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="../utilities-color.php">Colors</a>
<a class="collapse-item" href="../utilities-border.php">Borders</a>
<a class="collapse-item" href="../utilities-animation.php">Animations</a>
<a class="collapse-item" href="../utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="../register.php">Register</a>
<a class="collapse-item" href="../forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="../404.php">404 Page</a>
<a class="collapse-item" href="../blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="../charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item">
<a class="nav-link" href="../tables.php">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
<!-- Sidebar Message -->
<div class="sidebar-card d-none d-lg-flex">
<img class="sidebar-card-illustration mb-2" src="../images/undraw_rocket.svg" alt="...">
<p class="text-center mb-2"><strong>SB Admin Pro</strong> is packed with premium features, components, and more!</p>
<a class="btn btn-success btn-sm" href="https://startbootstrap.com/theme/sb-admin-pro">Upgrade to Pro!</a>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="../images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Dashboard</h1>
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i
class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>
</div>
<!-- Content Row -->
<div class="row">
<!-- Earnings (Monthly) Card Example -->
<div class="row">
<!-- Hostname -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card border-left-primary shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">CPU
</div>
<div class="row no-gutters align-items-center">
<div class="col-auto">
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800"><?php echo (int)$serverStatus['cpu_usage']; ?>%</div>
</div>
<div class="col">
<div class="progress progress-sm mr-2">
<div class="progress-bar bg-info" role="progressbar"
style=<?php echo"\"width:". (int)$serverStatus['cpu_usage'] . "%\""; ?> aria-valuenow=<?php echo"\"". (int)$serverStatus['cpu_usage'] . "\""; ?> aria-valuemin="0"
aria-valuemax="100"></div>
</div>
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Hostname
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo htmlspecialchars((string)($serverStatus['hostname'] ?? 'n/a'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
<i class="fas fa-server fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Earnings (Monthly) Card Example -->
<!-- Betriebssystem -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">RAM
</div>
<div class="row no-gutters align-items-center">
<div class="col-auto">
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800"><?php echo (int)$serverStatus['memory_usage']; ?>%</div>
</div>
<div class="col">
<div class="progress progress-sm mr-2">
<div class="progress-bar bg-info" role="progressbar"
style=<?php echo"\"width:". (int)$serverStatus['memory_usage'] . "%\""; ?> aria-valuenow=<?php echo"\"". (int)$serverStatus['memory_usage'] . "\""; ?> aria-valuemin="0"
aria-valuemax="100"></div>
</div>
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Betriebssystem
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<?php echo htmlspecialchars((string)($serverStatus['os'] ?? 'n/a'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
<i class="fas fa-desktop fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Earnings (Monthly) Card Example -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">HDD (C:)
</div>
<div class="row no-gutters align-items-center">
<div class="col-auto">
<div class="h5 mb-0 mr-3 font-weight-bold text-gray-800"><?php echo (int)$serverStatus['disk_usage_c']; ?>%</div>
</div>
<div class="col">
<div class="progress progress-sm mr-2">
<div class="progress-bar bg-info" role="progressbar"
style=<?php echo"\"width:". (int)$serverStatus['disk_usage_c'] . "%\""; ?> aria-valuenow=<?php echo"\"". (int)$serverStatus['disk_usage_c'] . "\""; ?> aria-valuemin="0"
aria-valuemax="100"></div>
</div>
</div>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Pending Requests Card Example -->
<!-- CPU-Auslastung -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-warning shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Pending Requests</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">18</div>
CPU-Auslastung
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span id="cpu_card_value"><?php echo (int)($serverStatus['cpu_usage'] ?? 0); ?></span> %
</div>
</div>
<div class="col-auto">
<i class="fas fa-comments fa-2x text-gray-300"></i>
</div>
<i class="fas fa-microchip fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Content Row -->
<div class="row">
<!-- Area Chart -->
<div class="col-xl-8 col-lg-7">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div
class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Earnings Overview</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- Card Body -->
<!-- RAM-Auslastung -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-info shadow h-100 py-2">
<div class="card-body">
<div class="chart-area">
<canvas id="myAreaChart"></canvas>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
RAM-Auslastung
</div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span id="mem_card_value"><?php echo (int)($serverStatus['memory_usage'] ?? 0); ?></span> %
</div>
</div>
<div class="col-auto">
<i class="fas fa-memory fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Pie Chart -->
<div class="col-xl-4 col-lg-5">
<div class="card shadow mb-4">
<!-- Card Header - Dropdown -->
<div
class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-primary">Revenue Sources</h6>
<div class="dropdown no-arrow">
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i>
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
aria-labelledby="dropdownMenuLink">
<div class="dropdown-header">Dropdown Header:</div>
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</div>
</div>
<!-- Card Body -->
<div class="row">
<!-- Disk C: / Root -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-secondary shadow h-100 py-2">
<div class="card-body">
<div class="chart-pie pt-4 pb-2">
<canvas id="myPieChart"></canvas>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-secondary text-uppercase mb-1">
Datenträger C: / Root
</div>
<div class="mt-4 text-center small">
<span class="mr-2">
<i class="fas fa-circle text-primary"></i> Direct
</span>
<span class="mr-2">
<i class="fas fa-circle text-success"></i> Social
</span>
<span class="mr-2">
<i class="fas fa-circle text-info"></i> Referral
</span>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span id="disk_usage_text"><?php echo isset($serverStatus['disk_usage_c']) ? (int)$serverStatus['disk_usage_c'] : 'n/a'; ?></span> %
</div>
</div>
<div class="col-auto">
<i class="fas fa-hdd fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Content Row -->
<div class="row">
<!-- Content Column -->
<div class="col-lg-6 mb-4">
<!-- Project Card Example -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Projects</h6>
</div>
<!-- Uptime -->
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-dark shadow h-100 py-2">
<div class="card-body">
<h4 class="small font-weight-bold">Server Migration <span
class="float-right">20%</span></h4>
<div class="progress mb-4">
<div class="progress-bar bg-danger" role="progressbar" style="width: 20%"
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-dark text-uppercase mb-1">
System Uptime
</div>
<h4 class="small font-weight-bold">Sales Tracking <span
class="float-right">40%</span></h4>
<div class="progress mb-4">
<div class="progress-bar bg-warning" role="progressbar" style="width: 40%"
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<h4 class="small font-weight-bold">Customer Database <span
class="float-right">60%</span></h4>
<div class="progress mb-4">
<div class="progress-bar" role="progressbar" style="width: 60%"
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<h4 class="small font-weight-bold">Payout Details <span
class="float-right">80%</span></h4>
<div class="progress mb-4">
<div class="progress-bar bg-info" role="progressbar" style="width: 80%"
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<h4 class="small font-weight-bold">Account Setup <span
class="float-right">Complete!</span></h4>
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" style="width: 100%"
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
<div class="h5 mb-0 font-weight-bold text-gray-800">
<span id="uptime_text"><?php echo htmlspecialchars((string)($serverStatus['uptime'] ?? 'n/a'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></span>
</div>
</div>
<div class="col-auto">
<i class="fas fa-clock fa-2x text-gray-300"></i>
</div>
<!-- Color System -->
<div class="row">
<div class="col-lg-6 mb-4">
<div class="card bg-primary text-white shadow">
<div class="card-body">
Primary
<div class="text-white-50 small">#4e73df</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-success text-white shadow">
<div class="card-body">
Success
<div class="text-white-50 small">#1cc88a</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-info text-white shadow">
<div class="card-body">
Info
<div class="text-white-50 small">#36b9cc</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-warning text-white shadow">
<div class="card-body">
Warning
<div class="text-white-50 small">#f6c23e</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-danger text-white shadow">
<div class="card-body">
Danger
<div class="text-white-50 small">#e74a3b</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-secondary text-white shadow">
<div class="card-body">
Secondary
<div class="text-white-50 small">#858796</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-light text-black shadow">
<div class="card-body">
Light
<div class="text-black-50 small">#f8f9fc</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="card bg-dark text-white shadow">
<div class="card-body">
Dark
<div class="text-white-50 small">#5a5c69</div>
</div>
</div>
</div>
</div>
<div class="col-12 mb-2">
<div class="small text-gray-600">Letztes Update: <span id="snmp_last_update"></span></div>
</div>
</div>
<div class="col-lg-6 mb-4">
<script>
document.addEventListener('DOMContentLoaded', function(){
const diskEl = document.getElementById('disk_usage_text');
const uptimeEl = document.getElementById('uptime_text');
const cpuEl = document.getElementById('cpu_card_value');
const memEl = document.getElementById('mem_card_value');
const lastEl = document.getElementById('snmp_last_update');
<!-- Illustrations -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Illustrations</h6>
</div>
<div class="card-body">
<div class="text-center">
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;"
src="../images/undraw_posting_photo.svg" alt="...">
</div>
<p>Add some quality, svg illustrations to your project courtesy of <a
target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a
constantly updated collection of beautiful svg images that you can use
completely free and without attribution!</p>
<a target="_blank" rel="nofollow" href="https://undraw.co/">Browse Illustrations on
unDraw &rarr;</a>
</div>
</div>
function updateUI(data){
if(!data) return;
if(diskEl) diskEl.textContent = (data.disk_usage_c !== null && data.disk_usage_c !== undefined) ? Math.round(data.disk_usage_c) : 'n/a';
if(uptimeEl) uptimeEl.textContent = data.uptime || 'n/a';
if(cpuEl) cpuEl.textContent = (data.cpu_usage !== null && data.cpu_usage !== undefined) ? Math.round(data.cpu_usage) : 0;
if(memEl) memEl.textContent = (data.memory_usage !== null && data.memory_usage !== undefined) ? Math.round(data.memory_usage) : 0;
if(lastEl) lastEl.textContent = data.last_update ? new Date(data.last_update * 1000).toLocaleTimeString() : '';
}
<!-- Approach -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Development Approach</h6>
</div>
<div class="card-body">
<p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce
CSS bloat and poor page performance. Custom CSS classes are used to create
custom components and custom utility classes.</p>
<p class="mb-0">Before working with this theme, you should become familiar with the
Bootstrap framework, especially the utility classes.</p>
</div>
</div>
async function fetchStatus(){
try{
const res = await fetch('api/snmp_status.php');
if(!res.ok) throw new Error('Network response not ok');
const json = await res.json();
updateUI(json);
} catch(e){
console.error('Abruf SNMP fehlgeschlagen', e);
}
}
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2021</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="../vendor/jquery/jquery.min.js"></script>
<script src="../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="../vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="../js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="../vendor/chart.js/Chart.min.js"></script>
<!-- Page level custom scripts -->
<script src="../js/demo/chart-area-demo.js"></script>
<script src="../js/demo/chart-pie-demo.js"></script>
</body>
</html>
fetchStatus();
setInterval(fetchStatus, 5000);
});
</script>

76
public/views/layout.php Normal file
View File

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/**
* Zentrales Layout für das AD Admin Tool.
*
* Erwartet (aus index.php übergeben):
* - string $contentView Pfad zur Content-View (z. B. public/views/dashboard.php)
* - array<string, mixed> $viewData Daten-Array für die View
* - string $pageTitle Seitentitel
* - string|null $activeMenu Kennung für die Sidebar (z. B. 'dashboard' oder 'users')
*/
// Daten-Array in einzelne Variablen entpacken,
// sodass die Content-Views direkt mit $users, $groups, $serverStatus, $error etc. arbeiten können.
function renderLayout(string $contentView, array $viewData, string $pageTitle, ?string $activeMenu): void
{
// Daten-Array in einzelne Variablen entpacken
foreach ($viewData as $key => $value) {
if (is_string($key) && $key !== '') {
$cleanKey = preg_replace('/[^a-zA-Z0-9_]/', '', $key);
if ($cleanKey !== '') {
$$cleanKey = $value;
}
}
}
// Basispfad für alle Layout-Teilansichten (Head, Sidebar, Topbar, Footer, Scripts).
$partialsPath = __DIR__ . '/partials';
$isLoginPage = !empty($viewData['loginPage']);
?>
<!DOCTYPE html>
<html lang="de">
<!-- Begin Head -->
<?php require $partialsPath . '/head.php'; ?>
<!-- End of Head -->
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Begin Sidebar -->
<?php if ($isLoginPage === false):
require __DIR__ . '/partials/sidebar.php';
endif;?>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Begin Topbar -->
<?php if ($isLoginPage === false):
require __DIR__ . '/partials/topbar.php';
endif; ?>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<?php require $contentView; ?>
</div>
<!-- End of Page Content -->
</div>
<!-- End of Main Content -->
<!-- Begin Footer -->
<?php require $partialsPath . '/footer.php'; ?>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<?php require $partialsPath . '/scripts.php'; ?>
</body>
</html>
<?php
}

View File

@ -1,86 +1,75 @@
<?php
declare(strict_types=1);
/**
* @var string|null $error
* View-Template für die Login-Seite des AD Admin Tools.
*
* Aufgaben:
* - Stellt das Anmeldeformular für Administratoren dar.
* - Zeigt bei Bedarf eine Fehlermeldung aus der Authentifizierung an.
* - Kennzeichnet sich selbst über die Konstante LOGIN_PAGE, damit das Layout
* Sidebar und Topbar ausblenden kann.
*
* Erwartete View-Daten:
* - string|null $error Fehlermeldung aus dem AuthController (oder null bei Erfolg).
*/
/** @var string|null $error */
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Login</title>
<!-- Custom fonts for this template-->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template-->
<link href="css/sb-admin-2.min.css" rel="stylesheet">
</head>
<body class="bg-gradient-primary">
<div class="container">
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="row justify-content-center">
<div class="col-xl-6 col-lg-7 col-md-8">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<!-- Nested Row within Card Body -->
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
<div class="col-lg-6">
<div class="col-lg-12">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
<div class="text-center mb-4">
<h1 class="h4 text-gray-900">Willkommen beim AD Admin Tool</h1>
<p class="text-muted mb-0">
Dies ist unser Testserver für den <code>develop</code> Branch.
</p>
</div>
<?php if ($error !== null): ?>
<div class="alert alert-danger" role="alert">
<?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</div>
<?php endif; ?>
<form class="user" method="post" action="index.php?route=login.submit">
<form class="user" action="../index.php?route=login.submit" method="post" novalidate>
<div class="form-group">
<input type="text" name="username" class="form-control form-control-user"
id="username" aria-describedby="usernameHelp"
placeholder="Enter Username...">
<label for="username">Benutzername</label>
<input type="text"
class="form-control form-control-user"
id="username"
name="username"
placeholder="z. B. admin"
required>
</div>
<div class="form-group">
<input type="password" name="password" class="form-control form-control-user"
id="password" placeholder="Password">
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember
Me</label>
</div>
<label for="password">Passwort</label>
<input type="password"
class="form-control form-control-user"
id="password"
name="password"
placeholder="Passwort"
required>
</div>
<button type="submit" class="btn btn-primary btn-user btn-block">
Anmelden
</button>
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.php">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="register.php">Create an Account!</a>
<p class="small text-muted mb-0">
Die Zugangsdaten werden nicht gespeichert.
</p>
</div>
</div>
</div>
@ -88,22 +77,4 @@ declare(strict_types=1);
</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="vendor/jquery/jquery.min.js"></script>
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="js/sb-admin-2.min.js"></script>
</body>
</html>
</div>

View File

@ -0,0 +1,23 @@
<?php
/**
* Partielle View für den Footer-Bereich und das Schließen der Layout-Container.
*
* Aufgaben:
* - Schließt die Container für den Hauptinhalt und den Content-Wrapper.
* - Rendert den Sticky-Footer mit einfachem Copyright-Hinweis.
* - Schließt die äußeren Wrapper-Elemente des SB-Admin-2-Layouts.
*
* Hinweis:
* - Die JavaScript-Ressourcen werden separat in scripts.php eingebunden.
*/
?>
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>&copy; AD Admin Tool <?= date('Y') ?></span>
</div>
</div>
</footer>

View File

@ -0,0 +1,30 @@
<?php
/**
* Partielle View für den <head>-Bereich und den Beginn des HTML-Body.
*
* Aufgaben:
* - Setzt Zeichensatz und Dokumenttitel (inkl. optionalem Seitentitel).
* - Bindet die CSS-Ressourcen des SB-Admin-2-Templates sowie DataTables ein.
* - Öffnet das <body>-Element und den Wrapper für das Layout.
*
* WICHTIG:
* - Diese Datei wird ausschließlich über das zentrale Layout (layout.php) eingebunden.
*/
?>
<head>
<meta charset="utf-8">
<title>AD Admin Tool<?= isset($pageTitle) ? ' ' . htmlspecialchars($pageTitle, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') : '' ?></title>
<!-- Custom fonts for this template-->
<link href="../../vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<!-- Google Fonts oder lokal, je nach Setup -->
<link href="../../css/sb-admin-2.min.css" rel="stylesheet">
<!-- DataTables CSS (falls benötigt) -->
<link href="../../vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>

View File

@ -0,0 +1,43 @@
<?php
/**
* Partielle View für alle JavaScript-Assets.
*
* Aufgaben:
* - Stellt den "Scroll to Top"-Button bereit.
* - Bindet die JavaScript-Abhängigkeiten des SB-Admin-2-Templates ein
* (jQuery, Bootstrap, jQuery-Easing).
* - Lädt optionale Plugins wie Chart.js und DataTables.
* - Lädt die Demo-Skripte für Charts und Tabellen (js/demo/...).
*
* Hinweis:
* - Diese Datei sollte am Ende des Body-Bereichs über das Layout eingebunden werden,
* damit die Seite schnell gerendert wird.
*/
?>
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Bootstrap core JavaScript-->
<script src="../../vendor/jquery/jquery.min.js"></script>
<script src="../../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="../../vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="../../js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="../../vendor/chart.js/Chart.min.js"></script>
<script src="../../vendor/datatables/jquery.dataTables.min.js"></script>
<script src="../../vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="../../js/demo/datatables-demo.js"></script>
<script src="../../js/demo/chart-area-demo.js"></script>
<script src="../../js/demo/chart-pie-demo.js"></script>

View File

@ -0,0 +1,60 @@
<?php
/**
* Partielle View für die linke Sidebar-Navigation.
*
* Aufgaben:
* - Zeigt das Branding (Logo + Titel "AD Admin Tool") im oberen Bereich.
* - Enthält die Navigationspunkte "Dashboard" und "Benutzer & Gruppen".
* - Markiert den aktuell aktiven Menüpunkt anhand der Variable $activeMenu.
* - Stellt den Sidebar-Toggler für schmalere Viewports bereit.
*
* Erwartete View-Daten:
* - string|null $activeMenu Kennzeichnung für den aktuell aktiven Eintrag (z. B. 'dashboard' oder 'users').
*/
?>
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="../../index.php?route=dashboard">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-tools"></i>
</div>
<div class="sidebar-brand-text mx-3">AD Admin Tool</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item<?= (isset($activeMenu) && $activeMenu === 'dashboard') ? ' active' : '' ?>">
<a class="nav-link" href="../../index.php?route=dashboard">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Verzeichnis
</div>
<!-- Nav Item - Benutzer & Gruppen -->
<li class="nav-item<?= (isset($activeMenu) && $activeMenu === 'users') ? ' active' : '' ?>">
<a class="nav-link" href="../../index.php?route=users">
<i class="fas fa-fw fa-users-cog"></i>
<span>Benutzer &amp; Gruppen</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>

View File

@ -0,0 +1,51 @@
<?php
/**
* Partielle View für die obere Navigationsleiste (Topbar).
*
* Aufgaben:
* - Stellt den Button zum Ein- und Ausklappen der Sidebar auf mobilen Geräten bereit.
* - Zeigt im rechten Bereich die Benutzerinformationen an (Anzeigename + Profilbild).
* - Bietet im Benutzer-Dropdown einen Logout-Link an, der die Route "logout" aufruft.
*
* Erwartete View-Daten:
* - string|null $currentUsername Anzeigename des aktuell angemeldeten Benutzers (optional).
*/
?>
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">
<?= isset($currentUsername)
? htmlspecialchars($currentUsername, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
: 'Administrator' ?>
</span>
<img class="img-profile rounded-circle"
src="../../images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="../../index.php?route=logout">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>

View File

@ -1,520 +1,112 @@
<?php
declare(strict_types=1);
/** @var array<int, array<string, string>> $users */
/** @var array<int, array<string, string>> $groups */
/** @var string|null $error */
/**
* View-Template für die Anzeige von Benutzern und Gruppen.
*
* Aufgaben:
* - Stellt zwei Tabellen dar: eine Benutzerliste und eine Gruppenliste.
* - Nutzt Daten aus dem LdapDirectoryService (über den UserManagementController).
* - Behandelt optionale Fehlermeldungen durch Ausgabe eines Alert-Elements.
*
* Erwartete View-Daten:
* - array<int, array<string, string>> $users Liste von Benutzerobjekten (z. B. sAMAccountName, displayName, mail).
* - array<int, array<string, string>> $groups Liste von Gruppenobjekten (z. B. sAMAccountName, cn, description).
* - string|null $error Fehlermeldung bei Problemen mit dem LDAP-Zugriff.
*/
/**
* @var array<int, array<string, string>> $users
* @var array<int, array<string, string>> $groups
* @var string|null $error
*/
?>
<!DOCTYPE html>
<html lang="en">
<head>
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">Benutzer &amp; Gruppen</h1>
</div>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>SB Admin 2 - Tables</title>
<!-- Custom fonts for this template -->
<link href="../vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link
href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
rel="stylesheet">
<!-- Custom styles for this template -->
<link href="../css/sb-admin-2.min.css" rel="stylesheet">
<!-- Custom styles for this page -->
<link href="../vendor/datatables/dataTables.bootstrap4.min.css" rel="stylesheet">
</head>
<body id="page-top">
<!-- Page Wrapper -->
<div id="wrapper">
<!-- Sidebar -->
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="../views/dashboard.php">
<div class="sidebar-brand-icon rotate-n-15">
<i class="fas fa-laugh-wink"></i>
</div>
<div class="sidebar-brand-text mx-3">SB Admin <sup>2</sup></div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item">
<a class="nav-link" href="../views/dashboard.php">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Interface
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>Components</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Components:</h6>
<a class="collapse-item" href="../buttons.php">Buttons</a>
<a class="collapse-item" href="../cards.php">Cards</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Utilities</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Custom Utilities:</h6>
<a class="collapse-item" href="../utilities-color.php">Colors</a>
<a class="collapse-item" href="../utilities-border.php">Borders</a>
<a class="collapse-item" href="../utilities-animation.php">Animations</a>
<a class="collapse-item" href="../utilities-other.php">Other</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Addons
</div>
<!-- Nav Item - Pages Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapsePages"
aria-expanded="true" aria-controls="collapsePages">
<i class="fas fa-fw fa-folder"></i>
<span>Pages</span>
</a>
<div id="collapsePages" class="collapse" aria-labelledby="headingPages" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Login Screens:</h6>
<a class="collapse-item" href="login.php">Login</a>
<a class="collapse-item" href="../register.php">Register</a>
<a class="collapse-item" href="../forgot-password.php">Forgot Password</a>
<div class="collapse-divider"></div>
<h6 class="collapse-header">Other Pages:</h6>
<a class="collapse-item" href="../404.php">404 Page</a>
<a class="collapse-item" href="../blank.php">Blank Page</a>
</div>
</div>
</li>
<!-- Nav Item - Charts -->
<li class="nav-item">
<a class="nav-link" href="../charts.php">
<i class="fas fa-fw fa-chart-area"></i>
<span>Charts</span></a>
</li>
<!-- Nav Item - Tables -->
<li class="nav-item active">
<a class="nav-link" href="../tables.html">
<i class="fas fa-fw fa-table"></i>
<span>Tables</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider d-none d-md-block">
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
</ul>
<!-- End of Sidebar -->
<!-- Content Wrapper -->
<div id="content-wrapper" class="d-flex flex-column">
<!-- Main Content -->
<div id="content">
<!-- Topbar -->
<nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow">
<!-- Sidebar Toggle (Topbar) -->
<form class="form-inline">
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
</form>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="alertsDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-bell fa-fw"></i>
<!-- Counter - Alerts -->
<span class="badge badge-danger badge-counter">3+</span>
</a>
<!-- Dropdown - Alerts -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="alertsDropdown">
<h6 class="dropdown-header">
Alerts Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-primary">
<i class="fas fa-file-alt text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 12, 2019</div>
<span class="font-weight-bold">A new monthly report is ready to download!</span>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-success">
<i class="fas fa-donate text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 7, 2019</div>
$290.29 has been deposited into your account!
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="mr-3">
<div class="icon-circle bg-warning">
<i class="fas fa-exclamation-triangle text-white"></i>
</div>
</div>
<div>
<div class="small text-gray-500">December 2, 2019</div>
Spending Alert: We've noticed unusually high spending for your account.
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Show All Alerts</a>
</div>
</li>
<!-- Nav Item - Messages -->
<li class="nav-item dropdown no-arrow mx-1">
<a class="nav-link dropdown-toggle" href="#" id="messagesDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-envelope fa-fw"></i>
<!-- Counter - Messages -->
<span class="badge badge-danger badge-counter">7</span>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-list dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="messagesDropdown">
<h6 class="dropdown-header">
Message Center
</h6>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_1.svg"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div class="font-weight-bold">
<div class="text-truncate">Hi there! I am wondering if you can help me with a
problem I've been having.</div>
<div class="small text-gray-500">Emily Fowler · 58m</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_2.svg"
alt="...">
<div class="status-indicator"></div>
</div>
<div>
<div class="text-truncate">I have the photos that you ordered last month, how
would you like them sent to you?</div>
<div class="small text-gray-500">Jae Chun · 1d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="../images/undraw_profile_3.svg"
alt="...">
<div class="status-indicator bg-warning"></div>
</div>
<div>
<div class="text-truncate">Last month's report looks great, I am very happy with
the progress so far, keep up the good work!</div>
<div class="small text-gray-500">Morgan Alvarez · 2d</div>
</div>
</a>
<a class="dropdown-item d-flex align-items-center" href="#">
<div class="dropdown-list-image mr-3">
<img class="rounded-circle" src="https://source.unsplash.com/Mv9hjnEUHR4/60x60"
alt="...">
<div class="status-indicator bg-success"></div>
</div>
<div>
<div class="text-truncate">Am I a good boy? The reason I ask is because someone
told me that people say this to all dogs, even if they aren't good...</div>
<div class="small text-gray-500">Chicken the Dog · 2w</div>
</div>
</a>
<a class="dropdown-item text-center small text-gray-500" href="#">Read More Messages</a>
</div>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Douglas McGee</span>
<img class="img-profile rounded-circle"
src="../images/undraw_profile.svg">
</a>
<!-- Dropdown - User Information -->
<div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
aria-labelledby="userDropdown">
<a class="dropdown-item" href="#">
<i class="fas fa-user fa-sm fa-fw mr-2 text-gray-400"></i>
Profile
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-cogs fa-sm fa-fw mr-2 text-gray-400"></i>
Settings
</a>
<a class="dropdown-item" href="#">
<i class="fas fa-list fa-sm fa-fw mr-2 text-gray-400"></i>
Activity Log
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal">
<i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"></i>
Logout
</a>
</div>
</li>
</ul>
</nav>
<!-- End of Topbar -->
<!-- Begin Page Content -->
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-2 text-gray-800">Benutzer & Gruppen</h1>
<?php if ($error !== null): ?>
<p class="error">
<?php if ($error !== null): ?>
<div class="alert alert-danger" role="alert">
<?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</p>
<?php endif; ?>
<p class="mb-4">DataTables is a third party plugin that is used to generate the demo table below.
For more information about DataTables, please visit the <a target="_blank"
href="https://datatables.net">official DataTables documentation</a>.</p>
</div>
<?php endif; ?>
<!-- DataTales Example -->
<div class="card shadow mb-4">
<p class="mb-4">
Die folgenden Tabellen zeigen Benutzern und Gruppen, die über LDAP/LDAPS aus dem Active Directory gelesen wurden.
</p>
<!-- Benutzer-Tabelle -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Benutzer</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="usersTable" width="100%" cellspacing="0">
<table class="table table-bordered" id="usersTable">
<thead>
<tr>
<th>Anmeldename</th>
<th><input type="checkbox" name="selectAllUsers"></th>
<th>Anmeldename (sAMAccountName)</th>
<th>Anzeigename</th>
<th>E-Mail</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Anmeldename</th>
<th>Anzeigename</th>
<th>E-Mail</th>
</tr>
</tfoot>
<tbody>
<?php foreach ($users as $user): ?>
<tr>
<td><?php echo htmlspecialchars($user['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($user['displayname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($user['mail'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td>
<input type="checkbox" name="selectUser<?php echo htmlspecialchars($user['samaccountname'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>">
</td>
<td>
<?php echo htmlspecialchars($user['samaccountname'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
<td>
<?php echo htmlspecialchars($user['displayname'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
<td>
<?php echo htmlspecialchars($user['mail'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<div class="card shadow mb-4">
</div>
<!-- Gruppen-Tabelle -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Gruppen</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="groupsTable" width="100%" cellspacing="0">
<table class="table table-bordered" id="groupsTable">
<thead>
<tr>
<th>Gruppenname</th>
<th>Gruppenname (sAMAccountName)</th>
<th>CN</th>
<th>Beschreibung</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Gruppenname</th>
<th>CN</th>
<th>Beschreibung</th>
</tr>
</tfoot>
<tbody>
<?php foreach ($groups as $group): ?>
<tr>
<td><?php echo htmlspecialchars($group['samaccountname'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($group['cn'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td><?php echo htmlspecialchars($group['description'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></td>
<td>
<?php echo htmlspecialchars($group['samaccountname'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
<td>
<?php echo htmlspecialchars($group['cn'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
<td>
<?php echo htmlspecialchars($group['description'] ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- End of Main Content -->
<!-- Footer -->
<footer class="sticky-footer bg-white">
<div class="container my-auto">
<div class="copyright text-center my-auto">
<span>Copyright &copy; Your Website 2020</span>
</div>
</div>
</footer>
<!-- End of Footer -->
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Page Wrapper -->
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fas fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<div class="modal fade" id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
<a class="btn btn-primary" href="login.php">Logout</a>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript-->
<script src="../vendor/jquery/jquery.min.js"></script>
<script src="../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="../vendor/jquery-easing/jquery.easing.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="../js/sb-admin-2.min.js"></script>
<!-- Page level plugins -->
<script src="../vendor/datatables/jquery.dataTables.min.js"></script>
<script src="../vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src="../js/demo/datatables-demo.js"></script>
</body>
</html>