Initial commit
This commit is contained in:
commit
8d64d01463
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
vendor
|
||||
composer.lock
|
||||
cache
|
5
composer.json
Normal file
5
composer.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"require": {
|
||||
"twig/twig": "^3.0"
|
||||
}
|
||||
}
|
3
config.inc.php
Normal file
3
config.inc.php
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
define("UPTIME_KUMA_URL", "http://uptime-kuma.local:3001");
|
16
public/index.php
Normal file
16
public/index.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
require_once("../config.inc.php");
|
||||
require_once("../vendor/autoload.php");
|
||||
|
||||
$loader = new \Twig\Loader\FilesystemLoader("../view/");
|
||||
$twig = new \Twig\Environment($loader, [
|
||||
'cache' => '../cache/twig/',
|
||||
]);
|
||||
|
||||
$page = json_decode(file_get_contents(UPTIME_KUMA_URL . "/api/status-page/public"), true);
|
||||
$monitors = json_decode(file_get_contents(UPTIME_KUMA_URL . "/api/status-page/heartbeat/public"), true);
|
||||
|
||||
$data = array_merge($page, $monitors);
|
||||
|
||||
echo $twig->render('index.twig', $data);
|
102
public/style.css
Normal file
102
public/style.css
Normal file
|
@ -0,0 +1,102 @@
|
|||
:root {
|
||||
--border-radius: .35rem;
|
||||
--green-color: #10b981;
|
||||
--red-color: #f87171;
|
||||
--yellow-color: #ffdd6d;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #fff;
|
||||
background-color: #0f121a;
|
||||
font-family: Cantarell, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
section {
|
||||
max-width: 750px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.group {
|
||||
background: #191c24;
|
||||
border: 1px solid rgb(33 36 45);
|
||||
margin: 10px 0;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
h3, h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.group .item {
|
||||
overflow: hidden;
|
||||
margin: 5px 0;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.group .item:hover {
|
||||
background-color: #fff1;
|
||||
}
|
||||
|
||||
.monitor {
|
||||
--color: #fff2;
|
||||
}
|
||||
|
||||
.monitor > .inner {
|
||||
display: flex;
|
||||
gap: 7px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.monitor header {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
grid-template-columns: 22px 1fr max-content;
|
||||
}
|
||||
|
||||
.monitor .heartbeats {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
height: 5px;
|
||||
transition: all .3s;
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
.monitor:hover .heartbeats {
|
||||
height: 25px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monitor .heartbeats > * {
|
||||
flex: 1;
|
||||
background-color: var(--color);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.monitor.status-1, .monitor .heartbeats .status-1 {
|
||||
--color: var(--green-color);
|
||||
}
|
||||
|
||||
.monitor.status-0, .monitor .heartbeats .status-0 {
|
||||
--color: var(--red-color);
|
||||
}
|
||||
|
||||
.monitor.status-2, .monitor .heartbeats .status-2 {
|
||||
--color: var(--red-color);
|
||||
}
|
||||
|
||||
:is(.group, .item) > .inner {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.monitor .icon {
|
||||
color: var(--color);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monitor .uptime {
|
||||
font-size: .9rem;
|
||||
color: var(--color);
|
||||
}
|
12
view/group.twig
Normal file
12
view/group.twig
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="group">
|
||||
<div class="inner">
|
||||
<header class="item">
|
||||
<div class="inner">
|
||||
<h3>{{ group.name }}</h3>
|
||||
</div>
|
||||
</header>
|
||||
{% for monitor in group.monitorList %}
|
||||
{{ include("./monitor.twig") }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
1
view/icon/error.svg
Normal file
1
view/icon/error.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1.75 1.75 20.5 20.5"><path fill="currentColor" d="m8.4 17l3.6-3.6l3.6 3.6l1.4-1.4l-3.6-3.6L17 8.4L15.6 7L12 10.6L8.4 7L7 8.4l3.6 3.6L7 15.6L8.4 17Zm3.6 5q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Z"/></svg>
|
After Width: | Height: | Size: 442 B |
1
view/icon/success.svg
Normal file
1
view/icon/success.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1.75 1.75 20.5 20.5"><path fill="currentColor" d="m10.6 16.6l7.05-7.05l-1.4-1.4l-5.65 5.65l-2.85-2.85l-1.4 1.4l4.25 4.25ZM12 22q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Z"/></svg>
|
After Width: | Height: | Size: 415 B |
1
view/icon/warning.svg
Normal file
1
view/icon/warning.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="1.75 1.75 20.5 20.5"><path fill="currentColor" d="M1 21L12 2l11 19H1Zm11-3q.425 0 .713-.288T13 17q0-.425-.288-.713T12 16q-.425 0-.713.288T11 17q0 .425.288.713T12 18Zm-1-3h2v-5h-2v5Z"/></svg>
|
After Width: | Height: | Size: 240 B |
17
view/index.twig
Normal file
17
view/index.twig
Normal file
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ config.title }}</title>
|
||||
<link rel="stylesheet" href="/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<section>
|
||||
<h1>{{ config.title }}</h1>
|
||||
{% for group in publicGroupList %}
|
||||
{{ include('./group.twig') }}
|
||||
{% endfor %}
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
28
view/monitor.twig
Normal file
28
view/monitor.twig
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% set heartbeats = heartbeatList[monitor.id] %}
|
||||
{% set status = (heartbeats|last).status %}
|
||||
<div class="item monitor status-{{ status }}">
|
||||
<div class="inner">
|
||||
<header>
|
||||
<div class="icon">
|
||||
{% if status == 0 %}
|
||||
{{ include("./icon/error.svg") }}
|
||||
{% elseif status == 1 %}
|
||||
{{ include("./icon/success.svg") }}
|
||||
{% elseif status == 2 %}
|
||||
{{ include("./icon/warning.svg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<h4>
|
||||
{{ monitor.name }}
|
||||
</h4>
|
||||
<div class="uptime">
|
||||
<b>{{ (attribute(uptimeList, "#{monitor.id}_24") * 100) | number_format(1, '.') }}%</b> uptime
|
||||
</div>
|
||||
</header>
|
||||
<div class="heartbeats">
|
||||
{% for heartbeat in heartbeats %}
|
||||
<div class="status-{{ heartbeat.status }}"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue