aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CHANGELOG.md16
-rw-r--r--CODE_OF_CONDUCT.md2
-rw-r--r--LICENSE.md2
-rw-r--r--README.md128
-rw-r--r--archetypes/default.md2
-rw-r--r--config-example.yml67
-rw-r--r--exampleSite/config.yml181
-rw-r--r--exampleSite/content/issues/unavailable-guilds-connection-issues.md24
-rw-r--r--exampleSite/content/issues/us-east-conn-issues.md18
-rw-r--r--exampleSite/content/stats.html4
-rw-r--r--layouts/index.html98
-rw-r--r--layouts/issues/issue.html34
-rw-r--r--layouts/partials/footer.html4
-rw-r--r--layouts/partials/header-mini.html7
-rw-r--r--layouts/partials/header.html25
-rw-r--r--layouts/partials/js.html3
-rw-r--r--layouts/partials/meta.html93
-rw-r--r--layouts/shortcodes/track.html2
-rw-r--r--layouts/uptime/single.html65
-rw-r--r--static/admin/config.yml9
-rw-r--r--static/admin/index.html10
-rw-r--r--theme.toml2
23 files changed, 556 insertions, 242 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..05f0438
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+exampleSite/public/
+public/
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 6d8daaa..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# cState Updates
-
-## v1.0 (November 25, 2017)
-
-**cState is now ready for use in production! With a switch to the Hugo theming system, you can now independently manage incidents, content, settings, while seamlessly keeping cState up to date.**
-
-+ Whole new header design that lets you choose between a logo and just text
-+ Updated incident history section and post design
-+ Updated config file; added variables for changing the look and feel of your status page
-+ Ensured proper legacy browser support by making JavaScript optional
-+ Update incident view to include better mini header, clear issue type, and whether it is resolved
-+ Updated footer design, added copyright notice
-- Removed pinging, which was never properly implemented
-- Removed notifications, as they never worked in the first place
-- Fixed bug, where the main announcement box would clip, creating a small white 1px border
-- Generally removed a lot of leftover cruft and ensured cState is in pristine condition for a stable release
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 1e5a647..12075b1 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -1,6 +1,6 @@
# Code of Conduct
-> TL;DR is to be a good, sensible person. It does not matter who you are.
+> TL;DR is to be a good, sensible person. It does not matter who you are, this rule applies to _everybody_.
This community as a whole, much like others, is made up of a mixture of professionals and volunteers from all over the world, working on every aspect of the project at hand. Diversity can be a strength, but it can also lead to communication issues and unhappiness. To that end, we have a few ground rules that we ask people to adhere to. This code applies to all spaces managed by the project creators equally.
diff --git a/LICENSE.md b/LICENSE.md
index 470243e..8ec1cd6 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,7 +1,7 @@
The MIT License (MIT)
=====================
-Copyright (C) 2017 Mantas Vilčinskas
+Copyright (C) Mantas Vilčinskas
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
diff --git a/README.md b/README.md
index fa816f7..89bad94 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,20 @@
# cState
-[![GitHub last commit](https://img.shields.io/github/last-commit/mistermantas/cstate.svg?style=flat-square)](https://github.com/mistermantas/cstate/commits/master)
-[![GitHub repo size in bytes](https://img.shields.io/github/repo-size/mistermantas/cstate.svg?style=flat-square)](https://github.com/mistermantas/cstate/tree/master/)
-[![Discord](https://img.shields.io/badge/discord-join%20chat-7289DA.svg?style=flat-square)](http://discord.io/choraleapp) [![Twitter](https://img.shields.io/twitter/follow/mistermantas.svg?style=social&label=Follow)](https://twitter.com/mistermantas)
+[![GitHub release](https://img.shields.io/github/release/mistermantas/cstate.svg?style=flat-square)](https://github.com/mistermantas/cstate/releases) [![GitHub last commit](https://img.shields.io/github/last-commit/mistermantas/cstate.svg?style=flat-square)](https://github.com/mistermantas/cstate/commits/master) [![GitHub repo size in bytes](https://img.shields.io/github/repo-size/mistermantas/cstate.svg?style=flat-square)](https://github.com/mistermantas/cstate/tree/master/) [![Gitter](https://img.shields.io/badge/chat-gitter-ed1965.svg?style=flat-square)](https://gitter.im/cState/Lobby) [![Twitter](https://img.shields.io/twitter/follow/mistermantas.svg?style=social&label=Follow)](https://twitter.com/mistermantas)
-> The fastest and most efficient status page on the market, beating even paid solutions. cState has outstanding browser support (IE8+) and can easily be managed with GitHub Pages or Netlify. Ready for production.
+> Über fast, backwards compatible (IE8+), tiny, and simple status page built with Hugo. Compatible with Netlify & GitHub Pages.
-[**See real-world example**](https://rabbitnodestatus.netlify.com/)
+*This release is a developer preview.*
+
+[**Live demo**](https://cstate.netlify.com)
## Contents
+ [Features](#features)
-+ [Install](#install)
++ Getting started
+ + [Production](#production)
+ + [Development](#development)
+ + [Updating](#updating)
+ [FAQ](#faq)
+ [Contribute](#contribute)
+ [License](#license)
@@ -19,124 +22,120 @@
## Features
+ Built with [Hugo](https://gohugo.io), a hyperfast Golang generator
-+ Works not just on mobile browsers, but also on archaic browsers like Internet Explorer 8
++ Works not just on mobile, but also on the archaic Internet Explorer 8
+ Comes with a simple, focused, and extremely light design
-+ Edit your status page just from the config file
-+ Comes pre-equipped with Netlify CMS for quick updates
++ Edit your status page from a simple config file
++ Comes pre-equipped with Netlify CMS for quick admin updates
+ Easy to edit and deploy on Netlify or GitHub Pages
++ Secure, ready for HTTPS, thanks to [JAMstack](https://jamstack.org/)
+
+## Getting started
+
+For this tutorial, it is assumed that you have Hugo and Git installed (check with `hugo version` & `git --version`).
-## Install
+#### Production (with Netlify)
We encourage you to use [Netlify](https://www.netlify.com) for cState. These are the following options you need to change in deploy settings:
+ Build command: **hugo**
+ Publish directory: **public**
-+ Add one build enviroment variable
++ Add one build environment variable
+ Key: **HUGO_VERSION**
+ Value: **0.31**
-For this tutorial, it is assumed that you have Hugo and Git installed (check with `hugo version` & `git --version`).
-
-**This does not seem to work in one go on PowerShell, so enter each command individually.**
+1. Download the contents of the `exampleSite` directory in this repository. This will be your site guts, which will hold the content and configuration for the status page.
+2. Create a `themes` folder and navigate to it on the command line.
```bash
-# 1. First off, we initialize the Git repository
-# !: If you already have one, skip this step
-git init;
-
-# !: THIS ONLY WORKS ON BASH, USE THE 2ND COMMAND FOR POWERSHELL
-# 2. Then this creates all the necessary directories
-mkdir -p content/issues themes static;
-mkdir -p content/issues, themes, static;
-
-# 3. We get the config file
-curl -o config.yml https://cdn.rawgit.com/mistermantas/cstate/master/config-example.yml;
+mkdir themes; cd themes;
+```
-# 4. Download cState
-cd themes; git submodule add https://github.com/mistermantas/cstate;
+3. Now simply add a Git submodule pointing to this repository, like so:
-# 5. Last off, start the server locally
-cd ../; hugo serve;
+```bash
+git submodule add https://github.com/mistermantas/cstate
```
-And that is it; you have set up cState locally.
+4. Set up cState for your liking. It is now ready to be deployed
+
+#### Development
-Now is a good time to make cState look the way you want it to, so upload a favicon (and logo) to `/static/`. Edit `config.yml` to fit your needs. And so on, and so forth.
+1. Clone this repository in the command line:
-**Do not change any files in the `themes` directory or its subdirectories. Everything is handled automatically by Git. If the content or static directories are empty, create at least one file in them (such as `gitkeep.txt`) to make sure Git picks them up.**
+```bash
+git clone https://github.com/mistermantas/cstate.git
+```
-To make the status page public, you will need to connect to a remote GitHub repository much like this:
+2. Go to the `exampleSite` folder, like so:
```bash
-# Create a remote origin like this (if you have not already)
-git remote add origin https://github.com/username/example.git
+cd cstate-master/exampleSite
+```
-# Add all the files
-git add -A
+3. Uncomment this line in `config.yml`:
-# Then a message based on your changes
-git commit -m "Testing out cState"
+```yml
+# themesDir: ../..
+```
+
+3. Then try out the site! A link to it will be shown on screen.
-# All done
-git push -u origin master
+```bash
+hugo serve
```
-For an example of a working status page, see [rabbitnode/status](https://github.com/rabbitnode/status).
+The main directory is the theme itself (the cState guts, basically) and the `exampleSite` folder houses all content. Use this local setup to experiment before deploying to production!
+
+If you would like to commit/make a PR, make sure that `themesDir` is a comment before trying to merge upstream.
## Updating
-From your root directory, enter these 2 commands:
+Assuming the production install instructions were followed, keep cState updated by having an up to date Git submodule in the `themes` folder. containing this repository. Your content will stay separate, as to avoid any conflicts.
```bash
-# 1. Fetch submodules
-git submodule update --init --recursive;
-
-# 2. Now pull the changes
-git submodule foreach git pull origin master
+git submodule update
```
-You may also need to update the build enviroment variable **HUGO_VERSION** if you are using Netlify to [the latest equivelant](https://github.com/gohugoio/hugo/releases).
-
-You can [read more on git-scm.com](https://git-scm.com/book/en/v2/Git-Tools-Submodules) about submodules.
-
## FAQ
### Where do issues go? What is the frontmatter, how do I define metadata for issues?
-Create a file in `content/issues`. The name of the file will be the slug (what shows up in the URL bar). For example, this is what `i-am-an-issue.md` should look like:
+Create a file in `content/issues`. The name of the file will be the slug (what shows up in the URL bar). For example, this is what `major-outage-east-us.md` should look like:
```md
---
-Title: Give your issue a good title
-Description: This description is here merely for metadata purposes and may show up in search results. It may be used as a summary.
-Date: 2017-02-30 14:30
+Title: Major outage in East US
+Date: 2017-02-30 14:30:00
Resolved: true
+ResolvedWhen: 2017-02-30 16:00:00
Severity: down
Affected:
- - Client Area
+ - API
Section: post
---
-Content goes here.
+*Monitoring* - After hitting the ole reboot button Example Chat App is now recovering. We're going to continue to monitor as everyone reconnects. {{< track "2018-04-13 16:50:00" >}}
+
+*Investigating* - We're aware of users experiencing unavailable guilds and issues when attempting to connect. We're currently investigating. {{< track "2018-04-13 15:54:00" >}}
```
Time to break that down.
`Title`: This is the one of the most important parts of an incident. *(required)*
-`Description`: This description is here merely for metadata purposes and may show up in search results. It may be used as a summary.
-`Date`: An ISO-8601 formatted date. Does not include time zone. *(required)*
+`Date`: An ISO-8601 formatted date. Does not include time zone. This is when you first discovered the issue. *(required)*
`Resolved`: Whether issue should affect overall status. Either `true` or `false`. *(boolean, required)*
+`ResolvedWhen`: An ISO-8601 formatted date. Does not include time zone. This is when downtime stopped. You may set the time that downtime ended without completely resolving the issue (thus leaving time for monitoring).
`Severity`: If an issue is not resolved, it will have an applied severity. There are 3 levels of severity: `notice`, `disrupted`, and `down`. If there are multiple issues, the status page will take the appearance of the more drastic issue (such as `disrupted` instead of `notice`). *(required)*
`Affected`. Add the items that were present in the config file which should alter the status of each individual system (component). *(array, required)*
`Section`. This must be `issue`, so that Hugo treats it as one. *(required)*
### Is there an admin panel or some easy way to change the state of each issue?
-If you use [Netlify](https://www.netlify.com), you can expect to see Netlify CMS integration very soon. Otherwise, you could fall back to [prose.io](http://prose.io) or something similiar.
+If you use [Netlify](https://www.netlify.com), you can expect to see Netlify CMS integration very soon. Otherwise, you could fall back to [prose.io](http://prose.io) or something similar.
### How do I make this work on GitHub Pages?
-Compile locally, commit changes, and push them out. We do recommend using [Netlify](https://www.netlify.com), however.
+Compile locally (using production instructions), commit changes, and push them out. Using [Netlify](https://www.netlify.com) is recommended as it simplifies the process.
### My question was not answered!
@@ -146,8 +145,9 @@ This part of the documentation still needs to finished. [Questions](https://gith
+ Glance over the [Code of Conduct](/CODE_OF_CONDUCT.md).
+ Before submitting a pull request, create an issue to [discuss the implications of your proposal](https://github.com/mistermantas/cstate/issues).
-+ Write consistent, simple, and readable code. You can [join the Chorale Discord](http://discord.io/choraleapp) to discuss in `#cstate`.
++ Write consistent, simple, readable code and precise documentation.
++ [Join the Gitter chat](http://discord.io/choraleapp) for help or discussion.
## License
-MIT © Mantas Vilčinskas
+[MIT](https://github.com/mistermantas/cstate/blob/master/LICENSE.md) © Mantas Vilčinskas
diff --git a/archetypes/default.md b/archetypes/default.md
index 193e817..4908b8a 100644
--- a/archetypes/default.md
+++ b/archetypes/default.md
@@ -1,8 +1,8 @@
---
Title:
-Description:
Date:
Resolved:
+ResolvedWhen:
Severity:
Affected:
Section: issue
diff --git a/config-example.yml b/config-example.yml
deleted file mode 100644
index 39bae6e..0000000
--- a/config-example.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-# Welcome to the Hugo configuration file.
-# Hugo is used for building the status page,
-# so this file can be used to change how
-# your status page should behave or look.
-
-# What is your status page called?
-# Shows up in the browser bar and meta tags
-title: Example Inc. Status
-
-# What language is this page in?
-# Only alters the html[lang] attribute
-languageCode: en-US
-
-# What is the hostname or path to the root?
-# Where is the site hosted?
-# Example: https://status.example.com/
-baseURL: https://status.example.com/
-
-# Should posts, which have a publish date
-# from the future, be built? Useful for
-# sharing upcoming maintenance, etc.
-#
-# We recommend to keep this at `true`.
-# BOOLEAN; `true`, `false`
-buildFuture: true
-
-params:
- # These are your systems. Change them to
- # change the amount of components.
- systems:
- - Core
- - EU
- - US
-
- # Should we show the logo or the title
- # of the status page?
- useLogo: false
-
- # Where is the logo located, if one is
- # present at all?
- logo: /logo.png
-
- # This is the description that is shown
- # in the footer and meta tags.
- description: We continuously monitor the status of our services and if there are any interruptions, a note will be posted here.
-
- # Cplors throughout cState
- #
- # Defaults:
- #
- # ok: 228B22
- # warning: DC143C
- # down: FF8C00
- # notice: 708090
- # border: dfdfdf
- # faded: ccc
- ok: 228B22
- disrupted: FF8C00
- down: DC143C
- notice: 708090
- border: dfdfdf
- faded: ccc
-
-# These options affect the core of cState.
-# Please do not change them if you do not
-# know what you are doing.
-theme: cstate
diff --git a/exampleSite/config.yml b/exampleSite/config.yml
new file mode 100644
index 0000000..f731012
--- /dev/null
+++ b/exampleSite/config.yml
@@ -0,0 +1,181 @@
+############################################################
+# +------------------------------------------------------+ #
+# | Notes | #
+# +------------------------------------------------------+ #
+############################################################
+
+# Welcome to the cState configuration file!
+#
+# Hugo is used for building the status page,
+# so this file can be used to change how
+# your status page should behave or look.
+#
+# If you want to use special characters,
+# such as accented letters, you MUST save
+# the file as UTF-8, not ANSI.
+#
+# If cState does not load, ensure that:
+# - No tabs are present;
+# YAML only allows spaces
+# - Indents are correct
+# YAML hierarchy is based entirely on indentation
+# - You have "escaped" all apostrophes
+# in your text: If you want to write "don't",
+# for example, write "don''t" instead!
+# Note the doubled apostrophe.
+# - Text with symbols is enclosed in single
+# or double quotation marks.
+#
+# If you have problems, create an issue on GitHub:
+# https://github.com/mistermantas/cstate/issues
+
+############################################################
+# +------------------------------------------------------+ #
+# | Basic metadata | #
+# +------------------------------------------------------+ #
+############################################################
+
+# What is your status page called?
+# Shows up in the browser bar and meta tags
+title: Example Chat App Status
+
+# What language is this page in?
+# Only alters the html[lang] attribute
+languageCode: en-US
+
+# What is the hostname or path to the root?
+# Where is the site hosted?
+#
+# Slash enables relative links.
+#
+# Default: /
+# Example: https://status.example.com/
+baseURL: /
+
+############################################################
+# +------------------------------------------------------+ #
+# | Preferences | #
+# +------------------------------------------------------+ #
+############################################################
+
+# Should posts, which have a publish date
+# from the future, be built? Useful for
+# sharing upcoming maintenance, etc.
+#
+# We recommend to keep this at `true`.
+# BOOLEAN; `true`, `false`
+buildFuture: true
+
+params:
+ # These are your systems. Change them to
+ # change the amount of components.
+ systems:
+ #-
+ # name: Client Area
+ # codename: panel
+ #-
+ # name: Minecraft
+ # codename: mc
+ #-
+ # name: Web Hosting
+ # codename: web
+ - Gateway
+ - API
+ - Media Proxy
+
+ # What header design should we use?
+ # Default: true
+ # BOOLEAN; `true`, `false`
+ useLargeHeaderDesign: false
+
+ # Should we show the logo or the title
+ # of the status page?
+ useLogo: false
+
+ # Where is the logo located, if one is
+ # present at all?
+ #
+ # Recommended: png or jpg for best
+ # browser support!
+ # logo: /logo.png
+
+ # This is the description that is shown
+ # in the footer and meta tags.
+ description: We continuously monitor the status of our services and if there are any interruptions, a note will be posted here.
+
+ # Cplors throughout cState
+ #
+ # Defaults:
+ #
+ # brand: #181818
+ # ok: 228B22
+ # warning: DC143C
+ # down: FF8C00
+ # notice: 708090
+ brand: 181818
+ ok: 228B22
+ disrupted: FF8C00
+ down: DC143C
+ notice: 708090
+ border: dfdfdf
+ faded: ccc
+
+ # If the status page shows that
+ # there are disruptions or outages
+ # happening, should it keep the
+ # brand header color or drop it
+ # and use the status indication
+ # colors that were just defined?
+ #
+ # Default: true
+ # BOOLEAN; `true`, `false`
+ alwaysKeepBrandColor: true
+
+############################################################
+# +------------------------------------------------------+ #
+# | Developer | #
+# +------------------------------------------------------+ #
+############################################################
+
+ # Custom CSS file
+ # If you want to add any
+ # custom styling, you may
+ # link to one file with all
+ # your modifications here.
+ #
+ # This has *intentionally*
+ # been left uncommented,
+ # as it is not an advanced
+ # feature for developers.
+ #
+ # customCSS: /custom.css
+
+ # Custom JavaScript file
+ # If you want to add any
+ # custom scripting, you may
+ # link to one file with all
+ # your modifications here.
+ #
+ # This has *intentionally*
+ # been left uncommented,
+ # as it is not an advanced
+ # feature for developers.
+ #
+ # customJS: /custom.js
+
+############################################################
+# +------------------------------------------------------+ #
+# | For developers | #
+# +------------------------------------------------------+ #
+############################################################
+
+# These options affect the core of cState.
+# Please do not change them if you do not
+# know what you are doing.
+theme: cstate
+
+# If you are developing locally and want
+# to contribute to the cState Git repo,
+# please uncomment this option but do not
+# forget to re-comment it when
+# themesDir: ../..
diff --git a/exampleSite/content/issues/unavailable-guilds-connection-issues.md b/exampleSite/content/issues/unavailable-guilds-connection-issues.md
new file mode 100644
index 0000000..eba61b2
--- /dev/null
+++ b/exampleSite/content/issues/unavailable-guilds-connection-issues.md
@@ -0,0 +1,24 @@
+---
+Title: Unavailable Guilds & Connection Issues
+Date: 2018-04-13 15:54:00
+Resolved: true
+ResolvedWhen: 2018-04-13 17:30:00
+# down, disrupted, notice
+Severity: down
+Affected:
+ - API
+Section: issue
+---
+
+*Post-mortem*
+
+At approximately 14:01, a Redis instance acting as the primary for a highly-available cluster used by our API services was migrated automatically by Google’s Cloud Platform. This migration caused the node to incorrectly drop offline, forcing the cluster to rebalance and trigger known issues with the way our API instances handle Redis failover. After resolving this partial outage, unnoticed issues on other services caused a cascading failure through Example Chat App’s real time system. These issues caused enough critical impact that Example Chat App’s engineering team was forced to fully restart the service, reconnecting millions of clients over a period of 20 minutes.
+
+
+---
+
+*Update* - A fix has been implemented and we are monitoring the results. Looks like this has been fixed. {{< track "2018-04-13 17:30:00" >}}
+
+*Monitoring* - After hitting the ole reboot button Example Chat App is now recovering. We're going to continue to monitor as everyone reconnects. {{< track "2018-04-13 16:50:00" >}}
+
+*Investigating* - We're aware of users experiencing unavailable guilds and issues when attempting to connect. We're currently investigating. {{< track "2018-04-13 15:54:00" >}}
diff --git a/exampleSite/content/issues/us-east-conn-issues.md b/exampleSite/content/issues/us-east-conn-issues.md
new file mode 100644
index 0000000..5431bef
--- /dev/null
+++ b/exampleSite/content/issues/us-east-conn-issues.md
@@ -0,0 +1,18 @@
+---
+Title: US East Connection Issues
+Date: 2018-05-25 04:13:00
+Resolved: true
+ResolvedWhen: 2018-05-25 04:40:00
+# down, disrupted, notice
+Severity: disrupted
+Affected:
+ - API
+Section: issue
+---
+
+*Resolved* -
+We believe all users experiencing issues have been able to connect at this time. {{< track "2018-05-25 05:54:00" >}}
+
+*Monitoring* - We believe the connectivity issues are being caused by an isolated ISP issue. We've had reports that swapping to Google DNS servers (see here; https://developers.google.com/speed/public-dns/docs/using) resolves the problem for users. {{< track "2018-05-25 04:40:00" >}}
+
+*Investigating* - We're aware of reports that users are experiencing connection issues on the East coast of the United States. We're currently investigating these issues, and apologize for any inconvenience it may be causing you. {{< track "2018-05-25 04:13:00" >}}
diff --git a/exampleSite/content/stats.html b/exampleSite/content/stats.html
new file mode 100644
index 0000000..d4dd1aa
--- /dev/null
+++ b/exampleSite/content/stats.html
@@ -0,0 +1,4 @@
+---
+title: Uptime
+type: uptime
+---
diff --git a/layouts/index.html b/layouts/index.html
index a09d429..eedb08d 100644
--- a/layouts/index.html
+++ b/layouts/index.html
@@ -1,4 +1,5 @@
{{ partial "meta" . }}
+
{{ $incidents := where .Site.RegularPages "Params.section" "issue" }}
{{ $active := where $incidents "Params.resolved" "=" false }}
@@ -6,18 +7,8 @@
{{ $isDisrupted := where $active "Params.severity" "=" "disrupted" }}
{{ $isDown := where $active "Params.severity" "=" "down" }}
- <body class="status-{{ if $isDown }}down{{ else }}{{ if $isDisrupted}}disrupted{{ else }}{{ if $isNotice }}notice{{ else }}ok{{ end }}{{ end }}{{ end }}">
- <div class="header">
- <div class="contain contain--more center">
- <a href="/" class="logo">
- {{ if .Site.Params.useLogo }}
- <h1><img src="{{ .Site.Params.logo }}" alt="{{ .Site.Title }}"></h1>
- {{ else }}
- <h1>{{ .Site.Title }}</h1>
- {{ end }}
- </a>
- </div>
- </div>
+ <body class="status status-{{ if $isDown }}down{{ else }}{{ if $isDisrupted}}disrupted{{ else }}{{ if $isNotice }}notice{{ else }}ok{{ end }}{{ end }}{{ end }} {{ if not .Site.Params.alwaysKeepBrandColor }}change-header-color{{ end }}">
+ {{ partial "header" . }}
<!-- Main -->
<div class="contain">
@@ -32,7 +23,7 @@
{{ if $isDown }}
Experiencing major issues
{{ else }}
- {{ if $isDisrupted}}
+ {{ if $isDisrupted }}
Experiencing disruptions
{{ else }}
{{ if $isNotice }}
@@ -42,47 +33,80 @@
{{ end }}{{ end }}{{ end }}
</strong>
- <span class="status summary__date" onclick="location.reload()"></span>
+ <span class="status summary__date" onclick="location.reload()"></span>
+ </div>
+
+ {{ if $active }}
+ <div class="announcement-box">
+ {{ range $active }}
+ <div class="padding">
+ <p><strong>{{ .Title }}</strong></p>
+ {{ .Content }}
+ </div>
+ {{ else }}{{ end }}
</div>
+ {{ end }}
- {{ range $active }}
- <div class="padding"></div>
- <small class="date">{{ .Date.Format "January 02, 2006 at 3:04 PM" }}</small><br>
- <strong class="faded">{{ .Title }}</strong>
- {{ .Content }}
- <div class="padding"></div>
- {{ else }}{{ end }}
<!-- Individual info -->
- {{ if not $active }}
<div class="padding"></div>
<div class="components">
{{ $systems := .Site.Params.systems }}
{{ range $index, $systems }}
- <div class="component" data-status="ok">
+ {{ $activeComponentIssues := where $active "Params.affected" "intersect" (slice .) }}
+
+ {{ $thisIsNotice := where $activeComponentIssues "Params.severity" "=" "notice" }}
+ {{ $thisIsDisrupted := where $activeComponentIssues "Params.severity" "=" "disrupted" }}
+ {{ $thisIsDown := where $activeComponentIssues "Params.severity" "=" "down" }}
+
+ <div class="component" data-status="{{ if $thisIsDown }}down{{ else }}{{ if $thisIsDisrupted }}disrupted{{ else }}{{ if $thisIsNotice }}notice{{ else }}ok{{ end }}{{ end }}{{ end }}">
+ {{ $this := . }}
{{ . }}
- <span class="component-status">Operational</span>
+ <span class="component-status">
+ {{ if $thisIsDown }}
+ Down
+ {{ else }}
+ {{ if $thisIsDisrupted }}
+ Disrupted
+ {{ else }}
+ {{ if $thisIsNotice }}
+ Maintenance
+ {{ else }}
+ Operational
+ {{ end }}{{ end }}{{ end }}
+ </span>
</div>
{{ end }}
</div>
- {{ end }}
<!-- End main -->
- </div><div class="padding"></div><hr>
+ </div>
- <div class="contain">
- <h2 class="center">Incident history</h2>
- {{ if not .Data.Pages }}
- <p class="center">Looks like we do not have any incidents logged.</p>
- {{ else }}
- {{ range first 10 .Data.Pages }}
- {{ .Render "issue" }}
- {{ end }}
- {{ end }}
+ <div class="tabs">
+ <div class="contain tabs--inner">
+ <a href="#incidents" class="tab tab--current">
+ Incidents
+ </a>
+ <a href="/stats" class="tab tab--other">
+ Uptime
+ </a>
</div>
+ </div>
+
+
+ <div class="contain">
+ <div class="padding"></div>
+ {{ if not .Data.Pages }}
+ <p class="center">Looks like we do not have any incidents logged.</p>
+ {{ else }}
+ {{ range .Data.Pages }}
+ {{ .Render "issue" }}
+ {{ end }}
+ {{ end }}
+ </div>
- {{ partial "js" . }}
- {{ partial "footer" . }}
+ {{ partial "js" . }}
+ {{ partial "footer" . }}
</body>
</html>
diff --git a/layouts/issues/issue.html b/layouts/issues/issue.html
index 9b63b78..c4d5ab6 100644
--- a/layouts/issues/issue.html
+++ b/layouts/issues/issue.html
@@ -6,24 +6,38 @@
{{ $isDown := where $active "Params.severity" "=" "down" }}
<div class="article">
- <span class="marker">
- {{ .Params.severity }}
- </span>
- &nbsp;
- <small class="date">
- {{ .Date.Format "January 02, 2006 at 3:04 PM" }}
- </small>
- &nbsp;
{{ if .Params.Resolved }}
- <span class="ok">✓</span>
- {{ end }}
+ <span class="ok">✓ Resolved after
+
+ {{ $t := (time .Params.ResolvedWhen) }}
+ {{ $timeDiff := (sub $t.Unix .Date.Unix) }}
+ {{ $diffInMin := (div $timeDiff 60) }}
+
+ {{ if gt $timeDiff 3600 }}
+ {{ $minutesForCalc := (mod $diffInMin 60) }}
+ {{ div (sub $diffInMin $minutesForCalc) 60 }}h
+ {{ $minutesForCalc }}m of downtime
+ {{ else }}
+ {{ $secsForCalc := (mod $timeDiff 60) }}
+ {{ div (sub $timeDiff $secsForCalc) 60 }}m
+ <!-- {{ $secsForCalc }}s --> of downtime
+ {{ end }}
+ </span>
+ {{ else }}
+ <span class="error">Ongoing, services {{ .Params.severity }}</span>
+ {{ end }}
<h3>
<a href="{{ .Permalink }}">{{ .Title }}</a>
</h3>
+ <small class="date">
+ {{ .Date.Format "January 02, 2006 at 3:04 PM" }}
+ </small>
+
<hr>
{{ .Content }}
</div>
+<div class="padding"></div>
diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html
index e1314ce..085b814 100644
--- a/layouts/partials/footer.html
+++ b/layouts/partials/footer.html
@@ -1,6 +1,8 @@
<div class="footer">
<div class="contain">
- <p><strong>{{ now.Year }} &copy; {{ .Site.Title }}</strong></p>
+ <p><strong>{{ now.Year }} &copy; {{ .Site.Title }}</strong>
+ &nbsp; • &nbsp; <a href="#">Back to top</a>
+ </p>
<p>{{ .Site.Params.description }}</p>
diff --git a/layouts/partials/header-mini.html b/layouts/partials/header-mini.html
deleted file mode 100644
index 93a26c2..0000000
--- a/layouts/partials/header-mini.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<div class="header">
- <div class="contain">
- <a href="/" class="no-underline">←
- <strong>{{ .Site.Title }}</strong>
- </a>
- </div>
-</div>
diff --git a/layouts/partials/header.html b/layouts/partials/header.html
new file mode 100644
index 0000000..c378998
--- /dev/null
+++ b/layouts/partials/header.html
@@ -0,0 +1,25 @@
+{{ if .Site.Params.useLargeHeaderDesign }}
+<div class="header header--large">
+ <div class="contain contain--more center">
+ <a href="/" class="logo">
+ {{ if .Site.Params.useLogo }}
+ <img src="{{ .Site.Params.logo }}" alt="{{ .Site.Title }}">
+ {{ else }}
+ <h1>{{ .Site.Title }}</h1>
+ {{ end }}
+ </a>
+ </div>
+</div>
+{{ else }}
+<div class="header">
+ <div class="contain">
+ <a href="/" class="logo logo--small">
+ {{ if .Site.Params.useLogo }}
+ <img src="{{ .Site.Params.logo }}" alt="{{ .Site.Title }}">
+ {{ else }}
+ <h1>{{ .Site.Title }}</h1>
+ {{ end }}
+ </a>
+ </div>
+</div>
+{{ end }}
diff --git a/layouts/partials/js.html b/layouts/partials/js.html
index 1e62849..d47cd5d 100644
--- a/layouts/partials/js.html
+++ b/layouts/partials/js.html
@@ -60,3 +60,6 @@
lastUpdated.innerHTML = 'Last checked ' + timeSince(lastUpdate) + ' ago';
}, 1000);
</script>
+{{ with .Site.Params.customJS }}
+<script type="text/javascript" src="{{ . }}"></script>
+{{ end }}
diff --git a/layouts/partials/meta.html b/layouts/partials/meta.html
index e3ebbf1..2bef153 100644
--- a/layouts/partials/meta.html
+++ b/layouts/partials/meta.html
@@ -6,12 +6,13 @@
<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>
+ <meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Summary }}{{ end }}">
+ <title>{{ if eq .Title .Site.Title }}{{ .Title }}{{ else }}{{ .Title }} | {{ .Site.Title }}{{ end }}</title>
<link rel="canonical" href="{{ .Permalink }}">
{{ .Hugo.Generator }}
<meta name="theme-color" content="#{{ .Site.Params.ok }}">
<script>
+ var themeBrandColor = '#{{ .Site.Params.brand }}';
var themeOkColor = '#{{ .Site.Params.ok }}';
var themeNoticeColor = '#{{ .Site.Params.notice }}';
var themeDisruptedColor = '#{{ .Site.Params.disrupted }}';
@@ -22,7 +23,7 @@
/**
* Color palette
*
- * Default:
+ * Defaults:
* white: #fff;
* whitesmoke: #f5f5f5;
* forestgreen: #228B22;
@@ -36,7 +37,7 @@
margin: 0;
background: #fff;
color: #444;
- font: 100%/1.5 BlinkMacSystemFont, -apple-system, 'San Francisco Text', Helvetica, Arial, sans-serif;
+ font: 100%/1.5 BlinkMacSystemFont, -apple-system, "San Francisco Text", "Roboto", "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";;
box-sizing: border-box;
}
@@ -46,7 +47,7 @@
hr {
border: 0;
- border-bottom: 1px solid #dedede;
+ border-bottom: 1px solid #ccc;
margin: 24px 0;
}
@@ -65,6 +66,8 @@
h3 { font-size: 20px; }
h4 { font-size: 18px; }
+ .stat { font-size: 18px; }
+
h2, h4 {
font-weight: normal;
color: #000;
@@ -86,16 +89,21 @@
}
.header {
- padding: 16px;
+ padding: 8px 0;
+ background: #{{ .Site.Params.brand }};
}
.header a {
color: #fff;
- font-size: 24px;
+ font-size: 14px;
font-variant: small-caps;
}
+ .header--large { padding: 16px; }
+ .header--large a { font-size: 20px; }
+
img {
+ border: 0;
width: 100%;
height: auto;
}
@@ -147,8 +155,7 @@
.error { color: #{{ .Site.Params.down }}; }
.footer {
- margin-top: 64px;
- padding: 20px 0;
+ margin-top: 20px;
background: #f5f5f5;
}
@@ -162,39 +169,68 @@
}
.logo img {
- height: auto;
- width: 100%;
+ height: 128px;
+ width: auto;
}
.logo--small img {
- height: 32px;
+ height: 64px;
width: auto;
}
- .article h3 a { border: 0; }
+ .tabs { border-bottom: 1px solid #ccc; }
+ .tabs--inner { padding: 0 16px; margin: 0 auto; }
+ a.tab { display: inline-table; }
+ .tab--current {
+ border: 1px solid #ccc;
+ border-bottom-color: #fff;
+ padding: 12px 18px;
+ position: relative;
+ top: 1px;
+ }
- .marker {
- text-transform: uppercase;
- font-size: smaller;
- padding: 2px 8px;
- padding-right: 4px;
- border: 2px solid #{{ .Site.Params.border }};
+ .tab--other {
+ border: 0;
+ padding: 12px 18px;
+ position: relative;
+ top: 1px;
+ color: #aaa;
+ }
+ .tab--other:hover { color: #000; }
+
+ .article {
+ padding-bottom: 20px;
}
+ .article h3 { line-height: 1.25; }
+ .article h3 a { border: 0; }
+ .article h3 a:hover { border-bottom: 1px solid currentColor; }
+
/**
* Specific to the status
*/
- .status-ok .summary, .status-ok .header { background: #{{ .Site.Params.ok }}; }
- .status-disrupted .summary, .status-disrupted .header { background: #{{ .Site.Params.disrupted }}; }
- .status-down .summary, .status-down .header { background: #{{ .Site.Params.down }}; }
- .status-notice .summary, .status-notice .header { background: #{{ .Site.Params.notice }}; }
+ .status-ok .summary { background: #{{ .Site.Params.ok }}; }
+ .status-disrupted .summary, .change-header-color.status-disrupted .header { background: #{{ .Site.Params.disrupted }}; }
+ .status-down .summary, .change-header-color.status-down .header { background: #{{ .Site.Params.down }}; }
+ .status-notice .summary, .change-header-color.status-notice .header { background: #{{ .Site.Params.notice }}; }
+
+ .announcement-box .padding {
+ padding: 16px;
+ border-bottom: 1px solid currentColor;
+ }
+
+ .status-disrupted .announcement-box .padding { border-bottom-color: #{{ .Site.Params.disrupted }}; }
+ .status-down .announcement-box .padding { border-bottom-color: #{{ .Site.Params.down }}; }
+ .status-notice .announcement-box .padding { border-bottom-color: #{{ .Site.Params.notice }}; }
+
+ .status-ok .announcement-box { border: 2px solid #{{ .Site.Params.ok }}; }
+ .status-disrupted .announcement-box { border: 2px solid #{{ .Site.Params.disrupted }}; }
+ .status-down .announcement-box { border: 2px solid #{{ .Site.Params.down }}; }
+ .status-notice .announcement-box { border: 2px solid #{{ .Site.Params.notice }}; }
- .marker-ok { background: #{{ .Site.Params.ok }}; }
- .marker-disrupted { background: #{{ .Site.Params.disrupted }}; }
- .marker-down { background: #{{ .Site.Params.down }}; }
- .marker-notice { background: #{{ .Site.Params.notice }}; }
+ .status .announcement-box { border-bottom-width: 1px; }
/**
@@ -218,4 +254,7 @@
}
}
</style>
+ {{ with .Site.Params.customCSS }}
+ <link href="{{ . }}" rel="stylesheet">
+ {{ end }}
</head>
diff --git a/layouts/shortcodes/track.html b/layouts/shortcodes/track.html
index 0c0c67f..3a80221 100644
--- a/layouts/shortcodes/track.html
+++ b/layouts/shortcodes/track.html
@@ -1 +1 @@
-<p class="faded">{{ dateFormat "02 Jan 2006 15:04" (.Get 0) }}</p>
+<span class="faded">({{ dateFormat "Jan 02, 2006 - 15:04" (.Get 0) }})</span>
diff --git a/layouts/uptime/single.html b/layouts/uptime/single.html
new file mode 100644
index 0000000..957ca8f
--- /dev/null
+++ b/layouts/uptime/single.html
@@ -0,0 +1,65 @@
+{{ partial "meta" . }}
+
+{{ $incidents := where .Site.RegularPages "Params.section" "issue" }}
+{{ $active := where $incidents "Params.resolved" "=" false }}
+
+{{ $isNotice := where $active "Params.severity" "=" "notice" }}
+{{ $isDisrupted := where $active "Params.severity" "=" "disrupted" }}
+{{ $isDown := where $active "Params.severity" "=" "down" }}
+
+ <body class="uptime status-{{ if $isDown }}down{{ else }}{{ if $isDisrupted}}disrupted{{ else }}{{ if $isNotice }}notice{{ else }}ok{{ end }}{{ end }}{{ end }} {{ if not .Site.Params.alwaysKeepBrandColor }}change-header-color{{ end }}">
+ {{ partial "header" . }}
+
+ <div class="padding"></div>
+
+ <div class="tabs">
+ <div class="contain tabs--inner">
+ <a href="/" class="tab tab--other">
+ Incidents
+ </a>
+ <a href="/stats" class="tab tab--current">
+ Uptime
+ </a>
+ </div>
+ </div>
+
+ {{ if not $active }}
+ <div class="contain">
+ <!-- still counting ALL the things -->
+ {{ $inactive := where $incidents "Params.resolved" "=" true }}
+
+ {{ range $inactive }}
+ {{ $t := (time .Params.ResolvedWhen) }}
+ {{ $timeDiff := (sub $t.Unix .Date.Unix) }}
+ {{ $diffInMin := (div $timeDiff 60) }}
+
+ {{ $.Scratch.Add "rackedUpDowntime" $timeDiff }}
+ {{ end }}
+ {{ $scratchValue := $.Scratch.Get "rackedUpDowntime" }}
+ <div class="stat">
+ {{ if gt $scratchValue 3600 }}
+ {{ $minutesForCalc := (mod (div $scratchValue 60) 60) }}
+
+ {{ div (sub (div $scratchValue 60) $minutesForCalc) 60 }}h
+ {{ $minutesForCalc }}m
+ {{ else }}
+ {{ $secsForCalc := (mod $scratchValue 60) }}
+
+ {{ div (sub $scratchValue $secsForCalc) 60 }}m
+ {{ $secsForCalc }}s
+ {{ end }} of downtime so far
+ <hr>
+ </div>
+ <p>
+ There have been {{ len $incidents }} incidents in total so far.
+ In total, this added up to {{ $scratchValue }}s (or {{ div $scratchValue 60 }} min) of downtime. Please note that the uptime statistics only counts resolved incidents, ongoing incidents are not included in these calculations.
+ </p>
+ </div>
+ {{ else }}
+ <div class="contain">
+ <p>Uptime stats are not available during an outage. Sorry!</p>
+ </div>
+ {{ end }}
+
+{{ partial "js" . }}
+{{ partial "footer" . }}
diff --git a/static/admin/config.yml b/static/admin/config.yml
index 893f620..93ec4d5 100644
--- a/static/admin/config.yml
+++ b/static/admin/config.yml
@@ -12,7 +12,7 @@
backend:
name: git-gateway
branch: master
- media_folder: "/static/img"
+ media_folder: "static/img"
public_folder: "/img"
# Do not change this!
collections:
@@ -32,7 +32,8 @@ backend:
- {label: "Title", name: "Title", widget: "string"}
- {label: "Description", name: "Description", widget: "string"}
- {label: "Date", name: "Date", widget: "datetime"}
- - {label: "Resolved?", name: "Resolved", widget: "boolean"}
- - {label: "Severity", name: "Severity", widget: "string"}
- - {label: "Affected", name: "Affected", widget: "string"}
+ - {label: "Is this completely resolved?", name: "Resolved", widget: "boolean"}
+ - {label: "When did downtime end (if it did)?", name: "ResolvedWhen", widget: "date"}
+ - {label: "Severity (enter disrupted, down, or notice)", name: "Severity", widget: "string"}
+ - {label: "Affected (example: ['API', ['Media Proxy']])", name: "Affected", widget: "string"}
- {label: "Body", name: "body", widget: "markdown"}
diff --git a/static/admin/index.html b/static/admin/index.html
index ea5090b..5d0b4fe 100644
--- a/static/admin/index.html
+++ b/static/admin/index.html
@@ -1,10 +1,10 @@
-<!DOCTYPE html>
+<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>cState Admin</title>
- <link rel="stylesheet" href="https://unpkg.com/netlify-cms@^0.7.0/dist/cms.css" />
+ <title>{{ .Site.Title }} | cState Admin</title>
+ <link rel="stylesheet" href="https://unpkg.com/netlify-cms@~1.1/dist/cms.css" />
</head>
<body>
<!--
@@ -15,6 +15,8 @@
/admin/ directory.
-->
- <script src="https://unpkg.com/netlify-cms@^0.7.0/dist/cms.js"></script>
+ <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
+ <script src="https://unpkg.com/netlify-cms@~1.9/dist/cms.js"></script>
+
</body>
</html>
diff --git a/theme.toml b/theme.toml
index f6623e8..d59f008 100644
--- a/theme.toml
+++ b/theme.toml
@@ -1,7 +1,7 @@
name = "cstate"
license = "MIT"
licenselink = "https://github.com/mistermantas/cstate/blob/master/LICENSE.md"
-description = "The best free status page on the market."
+description = "The best static, free, and open source status page on the market."
homepage = "https://github.com/mistermantas/cstate"
tags = ['hugo', 'netlify', 'status', 'statuspage', 'fast', 'light', 'ie8', 'ie9', 'ie10', 'ie11', 'github', 'github-pages', 'gh-pages', 'serverside', 'serverless', 'no-javascript', 'github-page', 'netlify-cms', 'gh-pages']
min_version = "0.28"