From 401bd08d8b29225ab6626b2e277c3a3cd5286809 Mon Sep 17 00:00:00 2001 From: Xantios Krugor Date: Sat, 10 Jul 2021 15:27:36 +0200 Subject: [PATCH] Improved frontend a bit, elements should all scale normally now --- src/HttpServer.php | 28 +++-- src/ui/app.css | 12 +++ src/ui/app.js | 168 +++++++++++++++++++++++++++++ src/ui/index.html | 256 +++++---------------------------------------- 4 files changed, 231 insertions(+), 233 deletions(-) diff --git a/src/HttpServer.php b/src/HttpServer.php index d3d45b7..bc74cea 100644 --- a/src/HttpServer.php +++ b/src/HttpServer.php @@ -18,7 +18,7 @@ class HttpServer { private Server $server; private OutputInterface $output; - public function __construct(array $config,LoopInterface $loop,OutputInterface $output) { + public function __construct(array $config,LoopInterface $loop,OutputInterface $output,ProcessStateManager $psm) { $this->port = $config['port'] ?? '8100'; $this->host = $config['host'] ?? '127.0.0.1'; @@ -26,17 +26,33 @@ public function __construct(array $config,LoopInterface $loop,OutputInterface $o $this->loop = $loop; $this->output = $output; - $psm = ProcessStateManager::getInstance($output,$loop); - $this->server = new Server($this->loop,function(ServerRequestInterface $request) use($psm) { $route = $request->getUri()->getPath(); // Serve out dashboard - if($route === "/") { + if($route === "/" || $route==="/app.css" || $route==="/app.js") { + + $route = ($route==="/") ? "/index.html" : $route; + + switch ($route) { + case '/index.html': + $mime = 'text/html'; + break; + case '/app.js': + $mime = 'text/javascript'; + break; + case '/app.css': + $mime = 'text/css'; + break; + default: + $mime = "text/json"; + break; + } + return new Response(200,[ - 'Content-Type' => 'text/html' - ],file_get_contents(__DIR__.'/ui/index.html')); + 'Content-Type' => $mime + ],file_get_contents(__DIR__.'/ui'.$route)); } if($route === "/api/processes") { diff --git a/src/ui/app.css b/src/ui/app.css index e69de29..3e396c3 100644 --- a/src/ui/app.css +++ b/src/ui/app.css @@ -0,0 +1,12 @@ +body { + font-family: Nunito, sans-serif; + font-size: .95rem; + font-weight: 400; + line-height: 1.5; +} + +.truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/ui/app.js b/src/ui/app.js index e69de29..d9ebd6e 100644 --- a/src/ui/app.js +++ b/src/ui/app.js @@ -0,0 +1,168 @@ +function main() { + setInterval(() => { + axios.get('/api/processes') + .then(resp => { + + // Format desktop/tablet + let data = ''; + + let icon = "\ + \ + "; + + resp.data.forEach((item, i) => { + + let logButton = "
"+icon+"
"; + + data += ""; + data += " "+ item.name + ""; + data += "
" + item.command + "
"; + data += " "+logButton+""; + data += " " + statusPill(item.status) + ""; + data += " " + fuzzyTime(item.started_at) + ""; + data += " "+formattedAttempt(item)+""; + data += ""; + }); + + document.querySelector('#tablecontent').innerHTML = data; + + let mobile = ''; + + // Format Mobile + resp.data.forEach((item,i) => { + + mobile += "
"; + mobile += '
'; + mobile += '

'+item.name+'

'; + mobile += '
'+statusPill(item.status)+'
'; + mobile += '
'; + // mobile += '
'; + // mobile += "
"+item.command+"
"; + // mobile += '
'; + mobile += '
'; + mobile += ' '+formattedAttempt(item)+""; + mobile += ' '+fuzzyTime(item.started_at)+""; + mobile += '
'; + mobile += '
'; + }) + + document.querySelector('#mobile').innerHTML = mobile; + }) + .catch(e => console.error(e.message)); + },1000); +} + +function classes(...items) { return items.join(' ') } + +function formattedAttempt(item) { + + if(item.retries===0 && item.currentRetry===0) { + return ' 0 / 0 '; + } + + let max = (item.retries===-1) ? '∞' : item.retries; + + return ''+item.currentRetry+" / "+max+''; +} + +function statusPill(label) { + + if (label === "Finished") { + return "
Finished
"; + } + + if (label === "Running") { + return "
Running
"; + } + + if (label === "Crashed") { + return "
Crashed
"; + } + + if (label === "Created") { + return "
Created
"; + } + + return label; +} + +function fuzzyTime(data) { + + // let data = "2021-01-18T20:30:00"; + // const ts = Date.parse(data); + // console.log(ts,data); + + return '' + timeDifference(data, 'en') + ''; +} + +function timeDifference(timestamp, locale) { + + const msPerMinute = 60 * 1000; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + + const current = Date.now(); + const elapsed = current - timestamp; + + const rtf = new Intl.RelativeTimeFormat(locale, {numeric: "auto"}); + + if (elapsed < msPerMinute) { + return rtf.format(-Math.floor(elapsed / 1000), 'seconds'); + } else if (elapsed < msPerHour) { + return rtf.format(-Math.floor(elapsed / msPerMinute), 'minutes'); + } else if (elapsed < msPerDay) { + return rtf.format(-Math.floor(elapsed / msPerHour), 'hours'); + } else { + return new Date(timestamp).toLocaleDateString(locale); + } +} + +function openLogModal(title) { + document.querySelector('#modal-title').innerHTML = "Recent evens for "+title; + document.querySelector('#modal-content').innerHTML = ""; + + document.querySelector('#modal').style.display = "block"; + + // Add listener + logWatcher = setInterval(() => { + + const url = '/api/log/'+title; + axios.get(url) + .then(resp => { + let lines = resp.data.log + .map(line => { + if(line.msg !== "") { + let channel = line.channel.replace('std',''); + + let prefix; + if(channel=="out") { + prefix = '[Out]'; + } else { + prefix = '[Err]'; + } + + return prefix+" "+line.msg+""; + + } else { + return ""; + } + }) + .filter(line => line!=="") + .join('
'); + + document.querySelector('#modal-content').innerHTML = lines; + }) + .catch(e => { + console.error(e); + }) + + },250); +} + +function closeLogModal() { + + document.querySelector('#modal').style.display = 'none'; + + // Remove Listener + clearInterval(logWatcher); +} diff --git a/src/ui/index.html b/src/ui/index.html index 6144ae5..d0370a3 100644 --- a/src/ui/index.html +++ b/src/ui/index.html @@ -9,25 +9,11 @@ Maple :: Dashboard + - - - + - function main() { - - setInterval(() => { - axios.get('/api/processes') - .then(resp => { - - // Fortmat desktop/tablet - let data = ''; - - let icon = "\ - \ - "; - - resp.data.forEach((item, i) => { - - let logButton = "
"+icon+"
"; - - data += ""; - data += " " + i + ""; - data += " " + item.name + ""; - data += "
" + item.command + "
"; - data += " "+logButton+""; - data += " " + statusPill(item.status) + ""; - data += " " + fuzzyTime(item.started_at) + ""; - data += " "+formattedAttempt(item)+""; - data += ""; - }); - - document.querySelector('#tablecontent').innerHTML = data; - - let mobile = ''; - - // Format Mobile - resp.data.forEach((item,i) => { - - mobile += "
"; - mobile += '
'; - mobile += '

'+item.name+'

'; - mobile += '
'+statusPill(item.status)+'
'; - mobile += '
'; - // mobile += '
'; - // mobile += "
"+item.command+"
"; - // mobile += '
'; - mobile += '
'; - mobile += ' '+formattedAttempt(item)+""; - mobile += ' '+fuzzyTime(item.started_at)+""; - mobile += '
'; - mobile += '
'; - }) - - document.querySelector('#mobile').innerHTML = mobile; - }) - .catch(e => console.error(e.message)); - },1000); - } - - function formattedAttempt(item) { - - if(item.retries===0 && item.currentRetry===0) { - return ' 0 / 0 '; - } - - let max = (item.retries===-1) ? '∞' : item.retries; - - return ''+item.currentRetry+" / "+max+''; - } - - function statusPill(label) { - - if (label === "Finished") { - return "
Finished
"; - } - - if (label === "Running") { - return "
Running
"; - } - - if (label === "Crashed") { - return "
Crashed
"; - } - - if (label === "Created") { - return "
Created
"; - } - - return label; - } - - function fuzzyTime(data) { - - // let data = "2021-01-18T20:30:00"; - // const ts = Date.parse(data); - // console.log(ts,data); - - return '' + timeDifference(data, 'en') + ''; - } - - function timeDifference(timestamp, locale) { - - const msPerMinute = 60 * 1000; - const msPerHour = msPerMinute * 60; - const msPerDay = msPerHour * 24; - - const current = Date.now(); - const elapsed = current - timestamp; - - const rtf = new Intl.RelativeTimeFormat(locale, {numeric: "auto"}); - - if (elapsed < msPerMinute) { - return rtf.format(-Math.floor(elapsed / 1000), 'seconds'); - } else if (elapsed < msPerHour) { - return rtf.format(-Math.floor(elapsed / msPerMinute), 'minutes'); - } else if (elapsed < msPerDay) { - return rtf.format(-Math.floor(elapsed / msPerHour), 'hours'); - } else { - return new Date(timestamp).toLocaleDateString(locale); - } - } - - function openLogModal(title) { - document.querySelector('#modal-title').innerHTML = "Recent evens for "+title; - document.querySelector('#modal-content').innerHTML = ""; - - document.querySelector('#modal').style.display = "block"; - - // Add listener - logWatcher = setInterval(() => { - - const url = '/api/log/'+title; - axios.get(url) - .then(resp => { - let lines = resp.data.log - .map(line => { - if(line.msg !== "") { - let channel = line.channel.replace('std',''); - - let prefix; - if(channel=="out") { - prefix = '[Out]'; - } else { - prefix = '[Err]'; - } - - return prefix+" "+line.msg+""; - - } else { - return ""; - } - }) - .filter(line => line!=="") - .join('
'); - - document.querySelector('#modal-content').innerHTML = lines; - }) - .catch(e => { - console.error(e); - }) - - },250); - } - - function closeLogModal() { - - document.querySelector('#modal').style.display = 'none'; - - // Remove Listener - clearInterval(logWatcher); - } + - - +
+ SM + + + + +
@@ -229,8 +54,6 @@

Maple

-
-

Processes

@@ -241,7 +64,7 @@

Processes

-
-
-