diff options
author | Mantas <mantasevilcinskas+git@gmail.com> | 2017-05-01 19:40:08 +0300 |
---|---|---|
committer | Mantas <mantasevilcinskas+git@gmail.com> | 2017-05-01 19:40:08 +0300 |
commit | 9d6a10ffe260b36ef76a73e8d53c835e8d5562c6 (patch) | |
tree | d1d86fe338029c29c2e5b573ce343ab864d8acb6 /layouts |
Complete refactor: add beta of #2, fix #1
Diffstat (limited to 'layouts')
-rw-r--r-- | layouts/incident/post.html | 8 | ||||
-rw-r--r-- | layouts/incident/single.html | 13 | ||||
-rw-r--r-- | layouts/index.html | 278 | ||||
-rw-r--r-- | layouts/partials/footer.html | 11 | ||||
-rw-r--r-- | layouts/partials/meta.html | 206 |
5 files changed, 516 insertions, 0 deletions
diff --git a/layouts/incident/post.html b/layouts/incident/post.html new file mode 100644 index 0000000..593481a --- /dev/null +++ b/layouts/incident/post.html @@ -0,0 +1,8 @@ +<div class="article"> + <h3> + <a href="{{ .Permalink }}">{{ .Title }} {{ if .Draft }}[DRAFT]{{ end }}</a> + </h3> + <h4>Began on {{ .Date }} ({{ .ReadingTime }} min read)</h4> + + {{ .Content }} +</div> diff --git a/layouts/incident/single.html b/layouts/incident/single.html new file mode 100644 index 0000000..92ead19 --- /dev/null +++ b/layouts/incident/single.html @@ -0,0 +1,13 @@ +{{ partial "meta" . }} + + <body> + + <div class="contain"> + <a href="{{ .Site.BaseURL }}">← Go back</a> + + <br><br><hr> + + {{ .Render "post"}} + </div> + +{{ partial "footer" . }} diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..014892d --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,278 @@ +{{ partial "meta" . }} + + <body> + <div class="header notice"> + <div class="contain"> + <a href="{{ .Site.BaseURL }}" class="logo"> + <img src="{{ .Site.Params.logo }}" alt="{{ .Site.Title }}"> + </a> + + <button class="subscribe">Subscribe</button> + </div> + </div> + + <!-- Main --> + <div class="contain"> + <noscript> + <p class="error">Uh oh! It looks like you have disabled JavaScript or your browser is a piece of garbage. This means we cannot fetch the neccesary data to show you information about our services. Please <a href="//enable-javascript.com">enable scripting</a> and try again.</p> + </noscript> + + <div class="subscriber-box"> + <div class="subscriber-box--header"> + <div class="contain"> + <strong>Notifications</strong> + <span class="close"> + <img alt="Close" src="https://cdn4.iconfinder.com/data/icons/geomicons/32/672366-x-128.png"> + </span> + </div> + </div> + + <div class="contain"> + <p>Users of modern browsers such as Chrome and Firefox get access to web notifications, a feature that shows alerts for things such as Facebook mentions, new emails, or in our case, status updates. These updates can be seen even if the user is not actively looking at this status page, however, the tab has to stay open.</p> + + <p class="error">Only some users may be able to use this feature. This feature does not work on mobile devices and is not fully tested.</p> + + <div id="alert-init"> + <input type="checkbox" id="alerts"> + <label for="alerts">Ping me when the status changes</label> + </div> + + <p class="alert-status faded">You have not enabled notifications.</p> + </div> + </div> + + <!-- Main info --> + <div class="summary notice"> + <div class="tldr notice"> + <strong>Checking status…</strong> + + <span class="status"></span> + </div> + <div class="details contain"> + <p>{{ .Site.Params.announcement }}</p> + </div> + </div><br> + + <!-- Individual info --> + <div class="components"> + <div class="component" data-status="" data-id="forums"> + Forums <small class="ping testing">Pinging…</small> + </div> + <div class="component" data-status="" data-id="website"> + Website <small class="ping testing">Pinging…</small> + </div> + <div class="component" data-status="" data-id="gameserver"> + Minecraft server + </div> + </div> + + <br> + <small><a href="#disclaimer">Disclaimer</a></small> + + <!-- End main --> + </div> + + <div class="contain"> + <h2>Incident history</h2><hr><br> + + {{ range first 10 .Data.Pages }} + {{ .Render "post" }} + {{ end }} + + <aside id="meta"> </aside> + </div> + + <script async> + /** + * Dev toolset + */ + + console.log('Welcome to cState! https://github.com/onlinemantas/cstate'); + + /** + * Notifications + */ + + // Notification toggle + document.querySelector('#alerts').addEventListener('click', enableNotifications) + + // Toggling logic + function enableNotifications() { + if(window.Notification && Notification.permission !== "denied") { + Notification.requestPermission(function(status) { + // status is "granted", if accepted by user + var n = new Notification('Great, you just enabled alerts!', { + body: 'You are now going to receive notifications (like this one) whenever the status changes so long as this tab is open. This feature is still being tested.', + icon: '/favicon.ico' + }) + + // Looks like we DO have permission now + // So let's mark that checkbox + document.querySelector('#alert-init').setAttribute('hidden', 'hidden') + document.querySelector('.alert-status').innerHTML = '<strong>Notifications are enabled. </strong>' + document.querySelector('.alert-status').className = 'alert-status' + }) + } + } + + if (Notification.permission === 'granted') { + // Looks like we DO have permission + // So let's mark that checkbox + document.querySelector('#alert-init').setAttribute('hidden', 'hidden') + document.querySelector('.alert-status').innerHTML = '<strong>Notifications are enabled. </strong>' + document.querySelector('.alert-status').className = 'alert-status' + } + + /** + * Subscribe button + */ + + function hasClass(element, cls) { + return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; + } + + document.querySelector('.subscribe').addEventListener('click', pressSubscribeButton); + document.querySelector('.close').addEventListener('click', pressSubscribeButton); + + function pressSubscribeButton() { + if (document.querySelector('.subscriber-box').className === 'subscriber-box active') { + document.querySelector('.subscriber-box').className = 'subscriber-box'; + } else { + document.querySelector('.subscriber-box').className = 'subscriber-box active'; + } + } + + /** + * Apply data + */ + + document.querySelector('.component[data-id=forums]').setAttribute('data-status', 'ok'); + document.querySelector('.component[data-id=website]').setAttribute('data-status', 'ok'); + document.querySelector('.component[data-id=gameserver]').setAttribute('data-status', 'notice'); + + /** + * Get elements + */ + + const header = document.querySelector('.header'); + const summary = document.querySelector('.summary'); + const summaryDetails = document.querySelector('.details'); + const tldr = document.querySelector('.tldr'); + + var summaryText = document.querySelector('.summary strong'); + var lastUpdated = document.querySelector('.summary span'); + + /** + * Prelimenary logic + */ + + var online = navigator.onLine; + + function updateStatus() { + var lastUpdate = new Date; + } + + /** + * Check for internet + */ + + var lastUpdate = new Date(); + + function timeSince(date) { + var seconds = Math.floor((new Date() - date) / 1000); + + var interval = Math.floor(seconds / 31536000); + + if (interval > 1) { + return interval + ' years'; + } + interval = Math.floor(seconds / 2592000); + if (interval > 1) { + return interval + ' months'; + } + interval = Math.floor(seconds / 86400); + if (interval > 1) { + return interval + 'd'; + } + interval = Math.floor(seconds / 3600); + if (interval > 1) { + return interval + 'h'; + } + interval = Math.floor(seconds / 60); + if (interval > 1) { + return interval + 'min'; + } + return Math.floor(seconds) + 's'; + } + var aDay = 24*60*60*1000; + + // Show second by second updates + window.setInterval(function() { + lastUpdated.innerHTML = 'Last updated ' + timeSince(lastUpdate) + ' ago'; + }, 1000); + + + /** + * Adaptive TLDR + */ + + const status = document.querySelector('.component[data-id=forums]').getAttribute('data-status') === 'ok' && + document.querySelector('.component[data-id=website]').getAttribute('data-status') === 'ok' && + document.querySelector('.component[data-id=gameserver]').getAttribute('data-status') === 'ok' + + if (status) { + // Change text + summaryText.innerHTML = 'All systems operational'; + // Change design + summary.className = 'summary ok'; + tldr.className = 'tldr ok'; + summaryDetails.className = 'details contain ok'; + header.className = 'header ok'; + } else if (!status) { + // Change text + summaryText.innerHTML = 'Experiencing downtime'; + // Change design + summary.className = 'summary down'; + tldr.className = 'tldr down'; + summaryDetails.className = 'details contain down'; + header.className = 'header down'; + + new Notification ( + 'We are experiencing downtime!', { + body : 'Please view the status page for more information. This alert was automatically triggered to let you know of this change.', + icon : '/favicon.ico' + } + ) + } + + + /** + * Check ping + */ + + // Links + const forumPingURL = 'https://forums.polargalaxy.com'; + const websiteURL = 'https://www.polargalaxy.com'; + + // Lib + !function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof module&&module.exports?module.exports=b():a.ping=b()}(this,function(){function a(a){return new Promise(function(b,c){var d=new Image;d.onload=function(){b(d)},d.onerror=function(){c(a)},d.src=a+"?random-no-cache="+Math.floor(65536*(1+Math.random())).toString(16)})}function b(b,c){return new Promise(function(d,e){var f=(new Date).getTime(),g=function(){var a=(new Date).getTime()-f;a*=c||1,d(a)};a(b).then(g).catch(g),setTimeout(function(){e(Error("Timeout"))},5e3)})}return b}); + + // Check ping for everything + ping(forumPingURL).then(function(delta) { + document.querySelector('.component[data-id="forums"] .ping').innerHTML = String(delta) + 'ms'; + document.querySelector('.component[data-id="forums"] .ping').className = 'ping done'; + }).catch(function(err) { + document.querySelector('.component[data-id="forums"] .ping').innerHTML = 'Can’t ping'; + document.querySelector('.component[data-id="forums"] .ping').className = 'ping error'; + }) + + ping(websiteURL).then(function(delta) { + document.querySelector('.component[data-id="website"] .ping').innerHTML = String(delta) + 'ms'; + document.querySelector('.component[data-id="website"] .ping').className = 'ping done'; + }).catch(function(err) { + document.querySelector('.component[data-id="website"] .ping').innerHTML = 'Can’t ping'; + document.querySelector('.component[data-id="website"] .ping').className = 'ping error'; + }) + </script> + +{{ partial "footer" . }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..62ea1b5 --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1,11 @@ + <div class="footer"> + <div class="contain"> + + <p id="disclaimer">{{ .Site.Params.description }}</p> + + <small class="copyright">Powered by <a href="https://github.com/onlinemantas/cstate">cState</a></small> + + </div> + </div> + </body> +</html> diff --git a/layouts/partials/meta.html b/layouts/partials/meta.html new file mode 100644 index 0000000..8237757 --- /dev/null +++ b/layouts/partials/meta.html @@ -0,0 +1,206 @@ +<!DOCTYPE html> +<html lang="{{ .Site.LanguageCode }}" class="nojs"> + <head> + <!-- Basics --> + <meta charset="utf-8"> + <meta http-equiv="x-ua-compatible" content="ie=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- Data --> + <meta name="description" content="{{ if .Description }}{{ else }}{{ .Site.Params.description }}{{ end }}"> + <title>{{ .Site.Title }}</title> + <link rel="canonical" href="{{ .Permalink }}"> + <link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}"> + <meta name="theme-color" content="#000000"> + <!-- Sources --> + <style> + /** + * Color palette + * + * white: #fff; + * forestgreen: #228B22; + * crimson: #DC143C; + * darkorange: #FF8C00; + * slategray: #708090; + * + */ + + html, body { + margin: 0; + background: #fff; + color: #444; + font: 16px sans-serif; + } + + a { + text-decoration: none; + border-bottom: 0.2px dotted currentColor; + } + + a:hover { border-bottom-style: solid; } + + h1, h2, h4 { + font-weight: normal; + color: #000; + } + + h3 { + margin-bottom: 0; + color: #000; + } + + h4 { + margin-top: 0; + color: #999; + } + + .faded { + color: #999; + } + + .header { + padding: 16px; + color: #fff; + } + + img { + height: 16px; + padding: 4px; + } + + .contain { + max-width: 640px; + margin: 16px auto; + padding: 16px; + } + + .summary { + border: 2px solid #fff; + } + + .summary .tldr { + padding: 16px; + color: #fff; + } + + .components { + border: 2px solid #ccc; + border-bottom: 0; + } + + .component { + color: #000; + padding: 16px; + border-bottom: 2px solid #ccc; + } + + .ping.testing { + color: #dcdcdc; + font-style: italic; + } + + .ping.done { + color: #aaa; + } + + .error { + color: #DC143C; + } + + /* .component:before { + content: '[+]'; + opacity: 0.4; + cursor: pointer; + } */ + + .close { + float: right; + } + + .subscribe, .status { + display: block; + } + + .subscribe { + margin: 8px 0; + } + + button, .close { + cursor: pointer; + } + + .subscriber-box.active { + display: block; + } + + .subscriber-box { + display: none; + background: #fff; + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 1; + overflow-y: scroll; + } + + .subscriber-box--header { + color: #000; + border-bottom: 1px solid #aaa; + } + + .footer { + padding: 64px; + background: #F0F0F0; + text-align: center; + } + + .copyright { + display: block; + font-variant: small-caps; + text-align: center; + } + + .copyright a, a.logo { + border-bottom: 0; + } + + + /** + * Specific to the status + */ + + .header.ok, .tldr.ok { background: #228B22; } + .header.disrupted, .tldr.disrupted { background: #FF8C00; } + .header.down, .tldr.down { background: #DC143C; } + .header.notice, .tldr.notice { background: #708090; } + + .summary.ok { border-color: #228B22; } + .summary.disrupted { border-color: #FF8C00; } + .summary.down { border-color: #DC143C; } + .summary.notice { border-color: #708090; } + + + + /** + * Dynamically show individual component statuses + */ + + .component:after { float: right; } + .component[data-status="ok"]:after { content: "Operational"; color: #228B22; } + .component[data-status="disrupted"]:after { content: "Disrupted"; color: #FF8C00; } + .component[data-status="down"]:after { content: "Down"; color: #DC143C; } + .component[data-status="notice"]:after { content: "Maintenance"; color: #708090; } + + /** + * Extend to desktops + */ + + @media (min-width: 560px) { + .status, .subscribe { + float: right; + display: inline-block; + } + } + </style> + </head> |