🌅
Signed-off-by: David Calavera <david.calavera@gmail.com>
7
.babelrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"presets": ["es2015"],
|
||||||
|
"plugins": [
|
||||||
|
"syntax-object-rest-spread",
|
||||||
|
"transform-object-rest-spread"
|
||||||
|
]
|
||||||
|
}
|
101
.eslintrc
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
env:
|
||||||
|
browser: true
|
||||||
|
|
||||||
|
parser: babel-eslint
|
||||||
|
|
||||||
|
plugins: [ "import" ]
|
||||||
|
|
||||||
|
# enable ECMAScript features
|
||||||
|
ecmaFeatures:
|
||||||
|
arrowFunctions: true
|
||||||
|
binaryLiterals: true
|
||||||
|
blockBindings: true
|
||||||
|
classes: true
|
||||||
|
defaultParams: true
|
||||||
|
destructuring: true
|
||||||
|
forOf: true
|
||||||
|
generators: true
|
||||||
|
jsx: true
|
||||||
|
modules: true
|
||||||
|
objectLiteralShorthandMethods: true
|
||||||
|
objectLiteralShorthandProperties: true
|
||||||
|
octalLiterals: true
|
||||||
|
spread: true
|
||||||
|
templateStrings: true
|
||||||
|
|
||||||
|
rules:
|
||||||
|
# Possible Errors
|
||||||
|
# https://github.com/eslint/eslint/tree/master/docs/rules#possible-errors
|
||||||
|
no-control-regex: 2
|
||||||
|
no-console: 1
|
||||||
|
no-debugger: 2
|
||||||
|
no-dupe-args: 2
|
||||||
|
no-dupe-keys: 2
|
||||||
|
no-duplicate-case: 2
|
||||||
|
no-empty-character-class: 2
|
||||||
|
no-ex-assign: 2
|
||||||
|
no-extra-boolean-cast : 2
|
||||||
|
no-extra-semi: 2
|
||||||
|
no-invalid-regexp: 2
|
||||||
|
no-irregular-whitespace: 1
|
||||||
|
no-proto: 2
|
||||||
|
no-unexpected-multiline: 2
|
||||||
|
no-unreachable: 2
|
||||||
|
valid-typeof: 2
|
||||||
|
|
||||||
|
# Best Practices
|
||||||
|
# https://github.com/eslint/eslint/tree/master/docs/rules#best-practices
|
||||||
|
no-fallthrough: 2
|
||||||
|
no-redeclare: 2
|
||||||
|
|
||||||
|
# Stylistic Issues
|
||||||
|
# https://github.com/eslint/eslint/tree/master/docs/rules#stylistic-issues
|
||||||
|
comma-spacing: 2
|
||||||
|
eol-last: 2
|
||||||
|
eqeqeq: ["error", "smart"]
|
||||||
|
indent: [2, 2, {SwitchCase: 1}]
|
||||||
|
keyword-spacing: 2
|
||||||
|
max-len: [1, 160, 2]
|
||||||
|
new-parens: 2
|
||||||
|
no-mixed-spaces-and-tabs: 2
|
||||||
|
no-multiple-empty-lines: [2, {max: 2}]
|
||||||
|
no-trailing-spaces: 2
|
||||||
|
object-curly-spacing: [2, "never"]
|
||||||
|
quotes: [2, "double", "avoid-escape"]
|
||||||
|
semi: 2
|
||||||
|
space-before-blocks: [2, "always"]
|
||||||
|
space-before-function-paren: [2, "never"]
|
||||||
|
space-in-parens: [2, "never"]
|
||||||
|
space-infix-ops: 2
|
||||||
|
space-unary-ops: 2
|
||||||
|
|
||||||
|
# ECMAScript 6
|
||||||
|
# http://eslint.org/docs/rules/#ecmascript-6
|
||||||
|
arrow-parens: [2, "always"]
|
||||||
|
arrow-spacing: [2, {"before": true, "after": true}]
|
||||||
|
no-confusing-arrow: 2
|
||||||
|
prefer-const: 2
|
||||||
|
|
||||||
|
# JSX
|
||||||
|
jsx-quotes: [2, "prefer-double"]
|
||||||
|
|
||||||
|
# Import
|
||||||
|
import/no-unresolved: [1, {"commonjs": true, "amd": true}]
|
||||||
|
import/export: 2
|
||||||
|
|
||||||
|
# Strict Mode
|
||||||
|
# https://github.com/eslint/eslint/tree/master/docs/rules#strict-mode
|
||||||
|
strict: [2, "global"]
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
# https://github.com/eslint/eslint/tree/master/docs/rules#variables
|
||||||
|
no-undef: 2
|
||||||
|
no-unused-vars: [2, {"args": "none"}]
|
||||||
|
|
||||||
|
# Global scoped method and vars
|
||||||
|
globals:
|
||||||
|
__dirname: true
|
||||||
|
require: true
|
||||||
|
process: true
|
||||||
|
ENV: true
|
||||||
|
module: true
|
27
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<!--
|
||||||
|
If you are reporting a new issue, make sure that we do not have any duplicates
|
||||||
|
already open. You can ensure this by searching the issue list for this
|
||||||
|
repository. If there is a duplicate, please close your issue and add a comment
|
||||||
|
to the existing issue instead.
|
||||||
|
|
||||||
|
If you suspect your issue is a bug, please edit your issue description to
|
||||||
|
include the BUG REPORT INFORMATION shown below. If you fail to provide this
|
||||||
|
information within 7 days, we cannot debug your issue and will close it. We
|
||||||
|
will, however, reopen it if you later provide the information.
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
BUG REPORT INFORMATION
|
||||||
|
---------------------------------------------------
|
||||||
|
Use the commands below to provide key information from your environment:
|
||||||
|
You do NOT have to include this information if this is a FEATURE REQUEST
|
||||||
|
-->
|
||||||
|
|
||||||
|
**- Do you want to request a *feature* or report a *bug*?**
|
||||||
|
|
||||||
|
**- What is the current behavior?**
|
||||||
|
|
||||||
|
**- If the current behavior is a bug, please provide the steps to reproduce.**
|
||||||
|
|
||||||
|
**- What is the expected behavior?**
|
||||||
|
|
||||||
|
**- Please mention your node.js, and operating system version.**
|
35
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<!--
|
||||||
|
Thanks for submitting a pull request!
|
||||||
|
|
||||||
|
Please make sure you've read and understood our contributing guidelines;
|
||||||
|
https://github.com/netlify/netlify-statuskit/blob/master/CONTRIBUTING.md
|
||||||
|
|
||||||
|
If this is a bug fix, make sure your description includes "fixes #xxxx", or
|
||||||
|
"closes #xxxx", where #xxxx is the issue number.
|
||||||
|
|
||||||
|
Please provide enough information so that others can review your pull request.
|
||||||
|
The first three fields are mandatory:
|
||||||
|
-->
|
||||||
|
|
||||||
|
**- Summary**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Explain the **motivation** for making this change.
|
||||||
|
What existing problem does the pull request solve?
|
||||||
|
-->
|
||||||
|
|
||||||
|
**- Test plan**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Demonstrate the code is solid.
|
||||||
|
Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI.
|
||||||
|
-->
|
||||||
|
|
||||||
|
**- Description for the changelog**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Write a short (one line) summary that describes the changes in this
|
||||||
|
pull request for inclusion in the changelog:
|
||||||
|
-->
|
||||||
|
|
||||||
|
**- A picture of a cute animal (not mandatory but encouraged)**
|
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
npm-debug.log
|
74
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to making participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity and
|
||||||
|
orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community. Examples of
|
||||||
|
representing a project or community include using an official project e-mail
|
||||||
|
address, posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event. Representation of a project may be
|
||||||
|
further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at david@netlify.com. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
47
CONTRIBUTING.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# CONTRIBUTING
|
||||||
|
|
||||||
|
Contributions are always welcome, no matter how large or small. Before contributing,
|
||||||
|
please read the [code of conduct](CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
> Install yarn on your system: https://yarnpkg.com/en/docs/install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ git clone https://github.com/netlify/netlify-statuskit
|
||||||
|
$ cd netlify-statuskit
|
||||||
|
$ yarn
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Runing the server
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm run start
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
|
||||||
|
We actively welcome your pull requests.
|
||||||
|
|
||||||
|
1. Fork the repo and create your branch from `master`.
|
||||||
|
2. If you've added code that should be tested, add tests.
|
||||||
|
3. If you've changed APIs, update the documentation.
|
||||||
|
4. Ensure the test suite passes.
|
||||||
|
5. Make sure your code lints.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
By contributing to Netlify StatusKit, you agree that your contributions will be licensed
|
||||||
|
under its [MIT license](LICENSE).
|
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Copyright (c) 2016 Netlify <hello@netlify.com>
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
58
README.md
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# Introduction
|
||||||
|
|
||||||
|
Netlify StatusKit is a template to deploy your own Status pages on Netlify.
|
||||||
|
|
||||||
|
Netlify StatusKit is released under the [MIT License](LICENSE).
|
||||||
|
Please make sure you understand its [implications and guarantees](https://writing.kemitchell.com/2016/09/21/MIT-License-Line-by-Line.html).
|
||||||
|
|
||||||
|
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-statuskit)
|
||||||
|
|
||||||
|
## Initial configuration
|
||||||
|
|
||||||
|
Click in the Deploy to Netlify button above to create your own site directly and push this repository to your own account.
|
||||||
|
Before creating the site, Netlify will ask you to fill required environment variables listed here:
|
||||||
|
|
||||||
|
- `STATUSKIT_PAGE_TITLE` - Title to show in the browser for your status site.
|
||||||
|
- `STATUSKIT_COMPANY_LOGO` - URL to your company's logo.
|
||||||
|
- `STATUSKIT_SUPPORT_CONTACT_LINK` - URL to a support page for your users to talk with you.
|
||||||
|
- `STATUSKIT_RESOURCES_LINK` - URL to documentation for your users.
|
||||||
|
- `STATUSKIT_FAVICONS_PATH` - Path where the favicons for different statuses are. By default, we use `/images/favicon/favicon-ok.ico` when there are no incidents, `/images/favicon/favicon-warning.ico` when there are no major incidents, and `/images/favicon/favicon-danger.ico` when there are major incidents. This path can be an external URL, like `https://my-favourite-cdn/images/status-favicons`. The names for the different statuses must be `favicon-ok.ico`, favicon-warning.ico` and `favicon-danger.ico`.
|
||||||
|
|
||||||
|
## Extra configuration
|
||||||
|
|
||||||
|
After the site is created, you can modify the code as much as you want and push it to your GitHub repository. Netlify will pick up changes from there.
|
||||||
|
|
||||||
|
### Reporting systems
|
||||||
|
|
||||||
|
You can add systems you want to report about to your Status page. For instance, you might want to tell your users about a status change in your CDN infrastructure but not in your API.
|
||||||
|
|
||||||
|
Go to `site/config.toml` and change the global `systems` variables. Once that's done, you'll be able to change the status of each one of those systems individually when you open or modify an incident.
|
||||||
|
|
||||||
|
### Full customization
|
||||||
|
|
||||||
|
This template is based in [Netlify's Victor-Hugo](https://github.com/netlify/victor-hugo) boilerplate.
|
||||||
|
To work on it you'll need NPM installed. To download dependencies type `npm run dependencies`, that will check if you have Hugo installed and will download it for you if you don't. It will also run `npm install` for the first time to download extra dependencies. After that, you can run `npm install` every time you want to install packages.
|
||||||
|
|
||||||
|
## Creating incidents
|
||||||
|
|
||||||
|
Adding incidents to your status page is as simple as adding a new document to the incidents collection.
|
||||||
|
Create a new incident using Hugo with a command like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
hugo -s site new -k incidents incidents/oh-no-something-went-wrong.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Hugo will create a new Markdown file for you with title and date based on the file name and a few predefined settings in the header. To learn more about the different states and report, you can see more detailed examples in `site/archetypes/incidents.md`.
|
||||||
|
|
||||||
|
After explaining the current situation in the incident, you can just push the file to GitHub. Netlify will deploy the indicent announcement for you in a matter of seconds.
|
||||||
|
|
||||||
|
## Resolving incidents
|
||||||
|
|
||||||
|
Everything will be operational again when all incidents are marked with `resolved = true`.
|
||||||
|
|
||||||
|
# Development
|
||||||
|
|
||||||
|
Netlify StatusKit uses NPM to manage dependencies. It also bundles a version of Hugo to work out of the box.
|
||||||
|
|
||||||
|
1. Use `npm install` to download dependencies.
|
||||||
|
2. Use `npm start` to start the development server.
|
BIN
bin/hugo_0.17_darwin_amd64
Executable file
BIN
bin/hugo_0.17_linux_amd64
Executable file
BIN
bin/hugo_0.17_windows_amd64.exe
Executable file
65
gulpfile.babel.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import gulp from "gulp";
|
||||||
|
import cp from "child_process";
|
||||||
|
import gutil from "gulp-util";
|
||||||
|
import postcss from "gulp-postcss";
|
||||||
|
import cssImport from "postcss-import";
|
||||||
|
import cssnext from "postcss-cssnext";
|
||||||
|
import BrowserSync from "browser-sync";
|
||||||
|
import webpack from "webpack";
|
||||||
|
import webpackConfig from "./webpack.conf";
|
||||||
|
|
||||||
|
const browserSync = BrowserSync.create();
|
||||||
|
const hugoBin = `./bin/hugo_0.17_${process.platform}_amd64${process.platform === "windows" ? ".exe" : ""}`;
|
||||||
|
const defaultArgs = ["-d", "../dist", "-s", "site", "-v"];
|
||||||
|
|
||||||
|
gulp.task("hugo", (cb) => buildSite(cb));
|
||||||
|
gulp.task("hugo-preview", (cb) => buildSite(cb, ["--buildDrafts", "--buildFuture"]));
|
||||||
|
|
||||||
|
gulp.task("build", ["css", "js", "hugo"]);
|
||||||
|
gulp.task("build-preview", ["css", "js", "hugo-preview"]);
|
||||||
|
|
||||||
|
gulp.task("css", () => (
|
||||||
|
gulp.src("./src/css/*.css")
|
||||||
|
.pipe(postcss([cssnext(), cssImport({from: "./src/css/main.css"})]))
|
||||||
|
.pipe(gulp.dest("./dist/css"))
|
||||||
|
.pipe(browserSync.stream())
|
||||||
|
));
|
||||||
|
|
||||||
|
gulp.task("js", (cb) => {
|
||||||
|
const myConfig = Object.assign({}, webpackConfig);
|
||||||
|
|
||||||
|
webpack(myConfig, (err, stats) => {
|
||||||
|
if (err) throw new gutil.PluginError("webpack", err);
|
||||||
|
gutil.log("[webpack]", stats.toString({
|
||||||
|
colors: true,
|
||||||
|
progress: true
|
||||||
|
}));
|
||||||
|
browserSync.reload();
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task("server", ["hugo", "css", "js"], () => {
|
||||||
|
browserSync.init({
|
||||||
|
server: {
|
||||||
|
baseDir: "./dist"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gulp.watch("./src/js/**/*.js", ["js"]);
|
||||||
|
gulp.watch("./src/css/**/*.css", ["css"]);
|
||||||
|
gulp.watch("./site/**/*", ["hugo"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildSite(cb, options) {
|
||||||
|
const args = options ? defaultArgs.concat(options) : defaultArgs;
|
||||||
|
|
||||||
|
return cp.spawn(hugoBin, args, {stdio: "inherit"}).on("close", (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
browserSync.reload();
|
||||||
|
cb();
|
||||||
|
} else {
|
||||||
|
browserSync.notify("Hugo build failed :(");
|
||||||
|
cb("Hugo build failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
13
netlify.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[build]
|
||||||
|
command = "npm run build"
|
||||||
|
publish = "dist"
|
||||||
|
|
||||||
|
[context.deploy-preview]
|
||||||
|
command = "npm run build-preview"
|
||||||
|
|
||||||
|
[template.environment]
|
||||||
|
STATUSKIT_PAGE_TITLE = "title for the page"
|
||||||
|
STATUSKIT_COMPANY_LOGO = "url to your company's logo"
|
||||||
|
STATUSKIT_SUPPORT_CONTACT_LINK = "url to your support page"
|
||||||
|
STATUSKIT_RESOURCES_LINK = "url to your knowledge base page"
|
||||||
|
STATUSKIT_FAVICONS_PATH = "/images/favicons/"
|
47
package.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "netlify-statusKit",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "StatusKit is a template to build Status pages for your business",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"hugo": "gulp hugo",
|
||||||
|
"webpack": "gulp webpack",
|
||||||
|
"build": "gulp build",
|
||||||
|
"build-preview": "gulp build-preview",
|
||||||
|
"start": "gulp server",
|
||||||
|
"lint": "eslint src"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"autoprefixer": "^6.3.7",
|
||||||
|
"babel-eslint": "^6.1.2",
|
||||||
|
"babel-loader": "^6.2.4",
|
||||||
|
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
||||||
|
"babel-plugin-transform-class-properties": "^6.10.2",
|
||||||
|
"babel-plugin-transform-object-assign": "^6.8.0",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.8.0",
|
||||||
|
"babel-preset-es2015": "^6.9.0",
|
||||||
|
"babel-register": "^6.11.6",
|
||||||
|
"browser-sync": "^2.13.0",
|
||||||
|
"css-loader": "^0.23.1",
|
||||||
|
"eslint": "^3.1.1",
|
||||||
|
"eslint-plugin-import": "^1.11.1",
|
||||||
|
"exports-loader": "^0.6.3",
|
||||||
|
"file-loader": "^0.9.0",
|
||||||
|
"gulp": "^3.9.1",
|
||||||
|
"gulp-babel": "^6.1.2",
|
||||||
|
"gulp-postcss": "^6.1.1",
|
||||||
|
"gulp-util": "^3.0.7",
|
||||||
|
"imports-loader": "^0.6.5",
|
||||||
|
"postcss-cssnext": "^2.7.0",
|
||||||
|
"postcss-import": "^8.1.2",
|
||||||
|
"postcss-loader": "^0.9.1",
|
||||||
|
"url-loader": "^0.5.7",
|
||||||
|
"webpack": "^1.13.1",
|
||||||
|
"whatwg-fetch": "^1.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "^1.0.15"
|
||||||
|
}
|
||||||
|
}
|
30
site/archetypes/incidents.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
+++
|
||||||
|
# default attributes for an incident.
|
||||||
|
#
|
||||||
|
# Hugo adds `title` and `date` by default
|
||||||
|
# when running `hugo new incidents/new-incident.md`,
|
||||||
|
# so we don't have to specify them here.
|
||||||
|
|
||||||
|
# state: represents the global state of
|
||||||
|
# your system due to the current incident.
|
||||||
|
# This is the list of supported states:
|
||||||
|
#
|
||||||
|
# - under-maintenance
|
||||||
|
# - degraded-performance
|
||||||
|
# - partial-outage
|
||||||
|
# - major-outage
|
||||||
|
#
|
||||||
|
state = "degraded-performance"
|
||||||
|
|
||||||
|
# affectedsystem: is a list of systems affected
|
||||||
|
# by the incident.
|
||||||
|
# Example:
|
||||||
|
# affectedsytems = ["API", "Build servers"]
|
||||||
|
#
|
||||||
|
affectedsytems = ["API", "Build servers"]
|
||||||
|
|
||||||
|
# resolved: marks an incident as resolved.
|
||||||
|
# It can be either true or false.
|
||||||
|
#
|
||||||
|
resolved = false
|
||||||
|
+++
|
17
site/config.toml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
baseurl = "/"
|
||||||
|
languageCode = "en-us"
|
||||||
|
title = "StatusKit"
|
||||||
|
|
||||||
|
[permalinks]
|
||||||
|
incidents = "/incidents/:year/:month/:day/:slug/"
|
||||||
|
|
||||||
|
[params]
|
||||||
|
defaultLogo = "https://www.netlify.com/img/press/logos/logomark.svg"
|
||||||
|
faviconsPath = "/images/favicon/"
|
||||||
|
|
||||||
|
# List of systems monitored in this status page.
|
||||||
|
# You'll be able to change their status every time
|
||||||
|
# you open or update an incident.
|
||||||
|
# Example:
|
||||||
|
# systems = ["API", "CDN", "DNS", "Site delivery"]
|
||||||
|
systems = []
|
0
site/content/.keep
Normal file
0
site/content/incidents/.keep
Normal file
0
site/data/.keep
Normal file
13
site/data/states.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[descriptions]
|
||||||
|
ok = "Up and running"
|
||||||
|
under-maintenance = "Under maintenance"
|
||||||
|
degraded-performance = "Degraded performance"
|
||||||
|
partial-outage = "Partial outage"
|
||||||
|
major-outage = "Major outage"
|
||||||
|
|
||||||
|
[alerts]
|
||||||
|
ok = "ok"
|
||||||
|
under-maintenance = "warning"
|
||||||
|
degraded-performance = "warning"
|
||||||
|
partial-outage = "warning"
|
||||||
|
major-outage = "danger"
|
4
site/layouts/incidents/single.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{{ partial "header" . }}
|
||||||
|
|
||||||
|
{{ partial "incident" . }}
|
||||||
|
</div>
|
31
site/layouts/index.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{{ partial "header" . }}
|
||||||
|
|
||||||
|
{{ $incidents := where .Site.Pages.ByDate.Reverse "Section" "incidents" }}
|
||||||
|
{{ $active := where $incidents "Params.resolved" "!=" true }}
|
||||||
|
|
||||||
|
{{ partial "systems" (dict "content" . "incidents" $active) }}
|
||||||
|
|
||||||
|
{{ with $active }}
|
||||||
|
<div class="section-title">Active Incidents</div>
|
||||||
|
{{ range $active }}
|
||||||
|
{{ partial "incident" . }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ $latest := index $incidents 0 }}
|
||||||
|
{{ partial "all-clear" $latest }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ $recents := first 3 (where $incidents "Params.resolved" "==" true) }}
|
||||||
|
{{ with $recents }}
|
||||||
|
<div class="history">
|
||||||
|
<div class="section-title">Past Incidents</div>
|
||||||
|
{{ range $recents }}
|
||||||
|
{{ partial "incident" . }}
|
||||||
|
{{ end }}
|
||||||
|
<a href="/incidents" class="see-more">See all incidents</a>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ partial "footer" . }}
|
||||||
|
|
||||||
|
<script src="/app.js"></script>
|
10
site/layouts/partials/all-clear.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div class="system-check-ok">
|
||||||
|
<img src="/images/icon-large-ok.svg" />
|
||||||
|
{{ with .Date }}
|
||||||
|
{{ $latestDate := dateFormat "2006-01-02T15:04:05" .Date}}
|
||||||
|
<p id="days-since-latest" data-latest-incident-date="{{ $latestDate }}">48+ days since last incident</p>
|
||||||
|
{{ else }}
|
||||||
|
<p>No incidents so far, all is good</p>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
|
5
site/layouts/partials/footer.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div class="footer">
|
||||||
|
<a href="http://netlify.com">
|
||||||
|
Powered by Netlify
|
||||||
|
</a>
|
||||||
|
</div>
|
37
site/layouts/partials/header.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<!doctype html>
|
||||||
|
{{ $logo := getenv "STATUSKIT_COMPANY_LOGO" | default .Site.Params.defaultLogo }}
|
||||||
|
{{ $title := getenv "STATUSKIT_PAGE_TITLE" | default .Site.Title }}
|
||||||
|
{{ $resources := getenv "STATUSKIT_RESOURCES_LINK" | default .Site.Params.resourcesLink }}
|
||||||
|
{{ $contact := getenv "STATUSKIT_SUPPORT_CONTACT_LINK" | default .Site.Params.contactLink }}
|
||||||
|
{{ $favicons := getenv "STATUSKIT_FAVICONS_PATH" | default .Site.Params.faviconsPath }}
|
||||||
|
|
||||||
|
{{ $incidents := where .Site.Pages.ByDate.Reverse "Section" "incidents" }}
|
||||||
|
{{ $active := where $incidents "Params.resolved" "!=" true }}
|
||||||
|
{{ $major := where $active "Params.state" "major-outage" }}
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ $title }}</title>
|
||||||
|
<link rel="stylesheet" href="/css/main.css"/>
|
||||||
|
{{ if $major }}
|
||||||
|
<link rel="icon" href="{{ absURL $favicons }}favicon-danger.ico">
|
||||||
|
{{ else if $active }}
|
||||||
|
<link rel="icon" href="{{ absURL $favicons }}favicon-warning.ico">
|
||||||
|
{{ else }}
|
||||||
|
<link rel="icon" href="{{ absURL $favicons }}favicon-ok.ico">
|
||||||
|
{{ end }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="gangsta-wrap">
|
||||||
|
<div class="header">
|
||||||
|
<img src="{{ $logo }}" class="logo"/>
|
||||||
|
<span class="title"><a href="/">{{ $title }}</a></span>
|
||||||
|
<div class="right-links">
|
||||||
|
{{ with $resources }}
|
||||||
|
<a href="{{ . }}" class="button resources-link">Resources</a>
|
||||||
|
{{ end }}
|
||||||
|
{{ with $contact }}
|
||||||
|
<a href="{{ . }}" class="button contact-link">Contact</a>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
14
site/layouts/partials/incident.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<div class="incident card">
|
||||||
|
<div class="incident-header">
|
||||||
|
<p class="incident-title">{{ .Title }}</p>
|
||||||
|
<p class="incident-date">{{ dateFormat "02 Jan 2006 15:04 -0700 MST" .Date }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="incident-description">
|
||||||
|
{{- .Content -}}
|
||||||
|
</div>
|
||||||
|
{{- $alert := index .Site.Data.states.alerts .Params.state -}}
|
||||||
|
|
||||||
|
<p class="incident-status color-{{ $alert }}">
|
||||||
|
{{ index .Site.Data.states.descriptions .Params.state }}
|
||||||
|
</p>
|
||||||
|
</div>
|
31
site/layouts/partials/paginator.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{{ $pag := $.Paginator }}
|
||||||
|
{{ if gt $pag.TotalPages 1 }}
|
||||||
|
<ul class="pagination">
|
||||||
|
{{ if gt $pag.TotalPages 5 }}
|
||||||
|
{{ with $pag.First }}
|
||||||
|
<li>
|
||||||
|
<a href="{{ .URL }}" aria-label="First"><span aria-hidden="true">««</span></a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
<li
|
||||||
|
{{ if not $pag.HasPrev }}class="disabled"{{ end }}>
|
||||||
|
<a href="{{ if $pag.HasPrev }}{{ $pag.Prev.URL }}{{ end }}" aria-label="Previous"><span aria-hidden="true">«</span></a>
|
||||||
|
</li>
|
||||||
|
{{ range $pag.Pagers }}
|
||||||
|
<li
|
||||||
|
{{ if eq . $pag }}class="active"{{ end }}><a href="{{ .URL }}">{{ .PageNumber }}</a></li>
|
||||||
|
{{ end }}
|
||||||
|
<li
|
||||||
|
{{ if not $pag.HasNext }}class="disabled"{{ end }}>
|
||||||
|
<a href="{{ if $pag.HasNext }}{{ $pag.Next.URL }}{{ end }}" aria-label="Next"><span aria-hidden="true">»</span></a>
|
||||||
|
</li>
|
||||||
|
{{ if gt $pag.TotalPages 5 }}
|
||||||
|
{{ with $pag.Last }}
|
||||||
|
<li>
|
||||||
|
<a href="{{ .URL }}" aria-label="Last"><span aria-hidden="true">»»</span></a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
5
site/layouts/partials/status-badge.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<div class="system-status-badge color-{{ .alert }}">
|
||||||
|
<!-- Depends on status -->
|
||||||
|
<img src="/images/icon-{{ .alert }}.svg" />
|
||||||
|
{{ .description }}
|
||||||
|
</div>
|
29
site/layouts/partials/systems.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{{ $okAlert := index .content.Site.Data.states.alerts "ok"}}
|
||||||
|
{{ $okDesc := index .content.Site.Data.states.descriptions "ok" }}
|
||||||
|
|
||||||
|
{{ with .content.Site.Params.systems }}
|
||||||
|
<div class="systems">
|
||||||
|
{{ range . }}
|
||||||
|
{{ $name := . }}
|
||||||
|
<div class="system-operational">
|
||||||
|
<div class="card">
|
||||||
|
{{ $name }}
|
||||||
|
|
||||||
|
{{ if $.incidents }}
|
||||||
|
{{ range $.incidents }}
|
||||||
|
{{ if in .Params.affectedsystems $name }}
|
||||||
|
{{ $alert := index .Site.Data.states.alerts .Params.state }}
|
||||||
|
{{ $desc := index .Site.Data.states.descriptions .Params.state }}
|
||||||
|
{{ partial "status-badge" (dict "alert" $alert "description" $desc) }}
|
||||||
|
{{ else }}
|
||||||
|
{{ partial "status-badge" (dict "alert" $okAlert "description" $okDesc) }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
{{ else }}
|
||||||
|
{{ partial "status-badge" (dict "alert" $okAlert "description" $okDesc) }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
16
site/layouts/section/incidents.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{{ partial "header" . }}
|
||||||
|
|
||||||
|
<div class="incidents">
|
||||||
|
{{ range (.Paginate .Data.Pages.ByPublishDate 15 ).Pages }}
|
||||||
|
<div class="incident-summary">
|
||||||
|
<a href="{{ .Permalink }}" class="article article-title">
|
||||||
|
{{ .Title }}
|
||||||
|
</a>
|
||||||
|
<span class="article-date">
|
||||||
|
{{ dateFormat "02 Jan 2006 15:04 -0700 MST" .Date }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ partial "paginator" . }}
|
||||||
|
</div>
|
0
site/static/.keep
Normal file
BIN
site/static/images/favicon/favicon-danger.ico
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
site/static/images/favicon/favicon-ok.ico
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
site/static/images/favicon/favicon-warning.ico
Normal file
After Width: | Height: | Size: 6.4 KiB |
3
site/static/images/icon-danger.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path fill="#BD1F1A" fill-rule="evenodd" d="M31.9518167,60 L39.6352947,52.316522 C40.121127,51.8306897 40.1214237,51.045068 39.63705,50.5606943 L37.4393057,48.36295 C36.9556324,47.8792767 36.1688211,47.8793622 35.683478,48.3647053 L28,56.0481833 L20.316522,48.3647053 C19.8306897,47.878873 19.045068,47.8785763 18.5606943,48.36295 L16.36295,50.5606943 C15.8792767,51.0443676 15.8793622,51.8311789 16.3647053,52.316522 L24.0481833,60 L16.3647053,67.683478 C15.878873,68.1693103 15.8785763,68.954932 16.36295,69.4393057 L18.5606943,71.63705 C19.0443676,72.1207233 19.8311789,72.1206378 20.316522,71.6352947 L28,63.9518167 L35.683478,71.6352947 C36.1693103,72.121127 36.954932,72.1214237 37.4393057,71.63705 L39.63705,69.4393057 C40.1207233,68.9556324 40.1206378,68.1688211 39.6352947,67.683478 L31.9518167,60 L31.9518167,60 Z" transform="translate(-16 -48)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 951 B |
12
site/static/images/icon-large-ok.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="141" height="141" viewBox="0 0 141 141" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<circle id="a" cx="70.5" cy="70.5" r="70.5"/>
|
||||||
|
<mask id="b" width="141" height="141" x="0" y="0" fill="white">
|
||||||
|
<use xlink:href="#a"/>
|
||||||
|
</mask>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path fill="#009A8D" d="M96.2371576,45.8858211 C95.0357448,44.7047263 93.0652397,44.7047263 91.8630436,45.8858211 L63.0661795,74.0040203 C61.8639835,75.1851151 59.8942616,75.1851151 58.6920655,74.0040203 L49.136369,64.6168175 C47.9341729,63.4357227 45.964451,63.4357227 44.762255,64.6168175 L38.901647,70.3776361 C37.699451,71.5587309 37.699451,73.4938797 38.901647,74.6749745 L58.6920655,94.1141789 C59.8942616,95.2952737 61.8639835,95.2952737 63.0661795,94.1141789 L102.097766,55.9409004 C103.300745,54.7590361 103.300745,52.8246568 102.097766,51.6427926 L96.2371576,45.8858211 Z"/>
|
||||||
|
<use stroke="#009A8D" stroke-width="20" mask="url(#b)" xlink:href="#a"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
3
site/static/images/icon-ok.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="31" height="24" viewBox="0 0 31 24">
|
||||||
|
<path fill="#009A8D" fill-rule="evenodd" d="M43.7746444,48.4251941 C43.2016629,47.8582686 42.2618835,47.8582686 41.6885285,48.4251941 L27.9546395,61.9219298 C27.3812844,62.4888553 26.4418786,62.4888553 25.8685235,61.9219298 L21.3111914,57.4160724 C20.7378363,56.8491469 19.7984305,56.8491469 19.2250754,57.4160724 L16.4300163,60.1812653 C15.8566612,60.7481908 15.8566612,61.6770623 16.4300163,62.2439878 L25.8685235,71.5748059 C26.4418786,72.1417314 27.3812844,72.1417314 27.9546395,71.5748059 L46.5697036,53.2516322 C47.1434321,52.6843373 47.1434321,51.7558353 46.5697036,51.1885404 L43.7746444,48.4251941 Z" transform="translate(-16 -48)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 736 B |
6
site/static/images/icon-warning.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="27" height="24" viewBox="0 0 27 24">
|
||||||
|
<g fill="#DFAA00" fill-rule="evenodd">
|
||||||
|
<path d="M23.8964786,23.9045455 L3.04807208,23.9045455 C1.82549221,23.9045455 0.841330519,23.4182727 0.348013636,22.5692727 C-0.145028571,21.7216364 -0.0774584416,20.6318182 0.533968831,19.581 L10.9578974,1.65381818 C11.569874,0.602727273 12.4861909,0 13.47255,0 C14.4591838,0 15.3755006,0.603 15.9866532,1.65409091 L26.4100325,19.5815455 C27.0217344,20.6326364 27.0895792,21.7219091 26.596537,22.5698182 C26.1032201,23.4182727 25.1190584,23.9045455 23.8964786,23.9045455 Z M13.47255,2.17581818 C13.3294442,2.17581818 13.0833351,2.35090909 12.8559039,2.74227273 L2.43170065,20.6691818 C2.20399481,21.0602727 2.17432987,21.3594545 2.24574545,21.4824545 C2.31716104,21.6046364 2.59293506,21.7287273 3.04807208,21.7287273 L23.8964786,21.7287273 C24.3516156,21.7287273 24.6271149,21.6046364 24.6988052,21.4819091 C24.7702208,21.3594545 24.7400065,21.0605455 24.5125753,20.6691818 L14.0886468,2.742 C13.8614903,2.35090909 13.6151065,2.17581818 13.47255,2.17581818 Z"/>
|
||||||
|
<path d="M12.1716877 14.2895455C12.2293695 14.8838182 12.3263299 15.3207273 12.4686117 15.6259091 12.6471506 16.0099091 12.9784091 16.2128182 13.4272286 16.2128182 13.8664344 16.2128182 14.1998903 16.0071818 14.392163 15.6182727 14.5484532 15.3008182 14.6470617 14.8699091 14.6921084 14.3042727L15.0783019 9.90790909C15.1208766 9.49636364 15.142576 9.08290909 15.142576 8.67954545 15.142576 7.95872727 15.0472636 7.41354545 14.8503214 7.01236364 14.6921084 6.69027273 14.3353052 6.30681818 13.5354506 6.30681818 13.0212584 6.30681818 12.5979838 6.47945455 12.2774377 6.81981818 11.9618357 7.155 11.8017 7.61509091 11.8017 8.18890909 11.8017 8.55872727 11.8291675 9.16881818 11.8832786 10.0039091L12.1716877 14.2895455zM13.4634857 17.1531818C13.0012071 17.1531818 12.6048506 17.3154545 12.2845792 17.6326364 11.9640331 17.9506364 11.8017 18.342 11.8017 18.7941818 11.8017 19.3093636 11.9755695 19.7203636 12.318639 20.0157273 12.648524 20.3007273 13.0396617 20.4441818 13.4813396 20.4441818 13.9180734 20.4441818 14.3056403 20.2982727 14.6333279 20.0089091 14.9709039 19.7102727 15.142576 19.3022727 15.142576 18.7939091 15.142576 18.3400909 14.9766721 17.9481818 14.6481604 17.6296364 14.3223955 17.3138182 13.9235669 17.1531818 13.4634857 17.1531818z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
4
src/css/imports/reset.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
body {
|
||||||
|
font-size: 16px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
290
src/css/main.css
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
@import "imports/reset.css";
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
color: #202020;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #3A71B0;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
a:focus,
|
||||||
|
a:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.gangsta-wrap {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 16px;
|
||||||
|
padding-bottom: 104px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding: 16px 0 24px 0;
|
||||||
|
border-bottom: 2px solid #F7F7F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
position: relative;
|
||||||
|
top: 4px;
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 21px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title a {
|
||||||
|
color: #202020;
|
||||||
|
}
|
||||||
|
.title a:hover,
|
||||||
|
.title a:focus, {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-links {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
.right-links {
|
||||||
|
float: left;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding-bottom: 68px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
position: relative;
|
||||||
|
top: 4px;
|
||||||
|
padding: 8px 16px 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #202020;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 24px;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 2px solid #202020;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover,
|
||||||
|
.button:active,
|
||||||
|
.button:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
background: #202020;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-link {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.systems {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0px 8px 20px 0px rgba(19, 39, 48, .08);
|
||||||
|
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #202020;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-operational {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-operational:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-status-badge {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-status-badge img {
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
margin-right: 4px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident {
|
||||||
|
color: #202020;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-title {
|
||||||
|
float: left;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-date {
|
||||||
|
float: right;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 450px) {
|
||||||
|
.incident-date {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-description {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-status {
|
||||||
|
margin: 24px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-check-ok {
|
||||||
|
margin: 80px auto 104px auto;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #009A8D; /*Switch to appropriate color*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.system-check-ok img {
|
||||||
|
margin: auto;
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
margin-top: 40px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
border-bottom: 2px solid #F7F7F8;
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.see-more {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 40px;
|
||||||
|
padding-top: 24px;
|
||||||
|
border-top: 2px solid #F7F7F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.history {
|
||||||
|
margin-top: 104px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-ok {
|
||||||
|
color: #009A8D;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-warning {
|
||||||
|
color: #DFAA00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-danger {
|
||||||
|
color: #BD1F1A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incident-summary {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-title {
|
||||||
|
width: 70%;
|
||||||
|
float: left;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-date {
|
||||||
|
width: 29%;
|
||||||
|
float: right;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination,
|
||||||
|
.pagination li {
|
||||||
|
list-style: none;
|
||||||
|
display: inline;
|
||||||
|
-webkit-padding-start: 0px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
display: block;
|
||||||
|
margin-top: 40px;
|
||||||
|
padding-top: 24px;
|
||||||
|
border-top: 2px solid #F7F7F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination .active a {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #3A71B0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination li a {
|
||||||
|
color: #202020;
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination li a:hover {
|
||||||
|
color: #3A71B0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 104px;
|
||||||
|
padding-top: 24px;
|
||||||
|
border-top: 2px solid #F7F7F8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #202020;
|
||||||
|
opacity: 0.3;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a:hover {
|
||||||
|
color: #3A71B0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
13
src/js/app.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// JS Goes here - ES6 supported
|
||||||
|
const daysSince = document.getElementById("days-since-latest");
|
||||||
|
console.log(daysSince);
|
||||||
|
if (daysSince) {
|
||||||
|
const aDay = 1000*60*60*24;
|
||||||
|
const dateSince = daysSince.getAttribute("data-latest-incident-date");
|
||||||
|
|
||||||
|
const timeSince = new Date() - new Date(dateSince);
|
||||||
|
const endDays = Math.floor(timeSince / aDay);
|
||||||
|
|
||||||
|
console.log(endDays);
|
||||||
|
daysSince.innerHTML = `${endDays} days since last incident`
|
||||||
|
}
|
37
webpack.conf.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import webpack from "webpack";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.((png)|(eot)|(woff)|(woff2)|(ttf)|(svg)|(gif))(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
|
loader: "file?name=/[hash].[ext]"
|
||||||
|
},
|
||||||
|
{test: /\.json$/, loader: "json-loader"},
|
||||||
|
{
|
||||||
|
loader: "babel",
|
||||||
|
test: /\.js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
query: {cacheDirectory: true}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
new webpack.ProvidePlugin({
|
||||||
|
"fetch": "imports?this=>global!exports?global.fetch!whatwg-fetch"
|
||||||
|
})
|
||||||
|
],
|
||||||
|
|
||||||
|
context: path.join(__dirname, "src"),
|
||||||
|
entry: {
|
||||||
|
app: ["./js/app"]
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, "dist"),
|
||||||
|
publicPath: "/",
|
||||||
|
filename: "[name].js"
|
||||||
|
},
|
||||||
|
externals: [/^vendor\/.+\.js$/]
|
||||||
|
};
|