diff options
Diffstat (limited to 'layouts')
-rw-r--r-- | layouts/404.json | 4 | ||||
-rw-r--r-- | layouts/_default/list.json | 32 | ||||
-rw-r--r-- | layouts/affected/list.json | 37 | ||||
-rw-r--r-- | layouts/index.json | 62 | ||||
-rw-r--r-- | layouts/issues/single.html | 17 | ||||
-rw-r--r-- | layouts/issues/single.json | 8 | ||||
-rw-r--r-- | layouts/issues/small.html | 21 | ||||
-rw-r--r-- | layouts/partials/index/components.html | 64 | ||||
-rw-r--r-- | layouts/partials/index/summary.html | 4 | ||||
-rw-r--r-- | layouts/partials/js.html | 109 | ||||
-rw-r--r-- | layouts/partials/meta.html | 45 |
11 files changed, 287 insertions, 116 deletions
diff --git a/layouts/404.json b/layouts/404.json new file mode 100644 index 0000000..82681f1 --- /dev/null +++ b/layouts/404.json @@ -0,0 +1,4 @@ +{ + "is" : "404", + "title" : "Error - Not Found" +}
\ No newline at end of file diff --git a/layouts/_default/list.json b/layouts/_default/list.json new file mode 100644 index 0000000..f469523 --- /dev/null +++ b/layouts/_default/list.json @@ -0,0 +1,32 @@ +{{ $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" }}{ + "is": "{{ .Section }}", + "title": "{{ .Title }}", + "baseURL": "{{ .Site.BaseURL }}", + "description": "{{ if .Params.Description }}{{ .Params.description }}{{ else }}{{ end }}", + "pages": [{{ range $i, $e := .Pages }}{{ if $i }},{{ end }}{{ if eq .Section "issues" }} + { + "is": "issue", + "title": "{{ .Title }}", + "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", + "permalink": "{{ .Permalink }}", + "severity": "{{ .Params.severity }}", + "resolved": {{ if .Params.resolved }}true{{ else }}false{{ end }}, + "informational": {{ if .Params.informational }}true{{ else }}false{{ end }}, + "resolvedAt": "{{ .Params.resolvedWhen }}", + "affected": [{{ range $i, $e := .Params.Affected }}{{ if $i }}, {{ end }}"{{ . }}"{{ end }}], + "filename": "{{ .File.LogicalName }}" + } + {{ else }} + { + "is": "page", + "title": "{{ .Title }}", + "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", + "permalink": "{{ .Permalink }}", + "filename": "{{ .File.LogicalName }}", + "summary": {{ jsonify .Summary }} + } + {{ end }}{{ end }} + ], +} diff --git a/layouts/affected/list.json b/layouts/affected/list.json new file mode 100644 index 0000000..1fde8d1 --- /dev/null +++ b/layouts/affected/list.json @@ -0,0 +1,37 @@ +{{ $incidents := .Pages }}{{ $active := where $incidents "Params.resolved" "=" false }}{{ $isNotice := where $active "Params.severity" "=" "notice" }}{{ $isDisrupted := where $active "Params.severity" "=" "disrupted" }}{{ $isDown := where $active "Params.severity" "=" "down" }}{ + "is": "system", + "title": "{{ .Title }}", + "permalink": "{{ .Permalink }}", + "status": {{ if $isDown }}"down",{{ else }}{{ if $isDisrupted }}"disrupted",{{ else }}{{ if $isNotice }}"notice",{{ else }}"ok",{{ end }}{{ end }}{{ end }} + "pages": [{{ range $i, $e := .Pages }}{{ if $i }},{{ end }}{{ if eq .Section "issues" }} + { + "is": "issue", + "title": "{{ .Title }}", + "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", + "permalink": "{{ .Permalink }}", + "severity": "{{ .Params.severity }}", + "resolved": {{ if .Params.resolved }}true{{ else }}false{{ end }}, + "informational": {{ if .Params.informational }}true{{ else }}false{{ end }}, + "resolvedAt": "{{ .Params.resolvedWhen }}", + "affected": [{{ range $i, $e := .Params.Affected }}{{ if $i }}, {{ end }}"{{ . }}"{{ end }}], + "filename": "{{ .File.LogicalName }}" + } + {{ else }} + { + "is": "page", + "title": "{{ .Title }}", + "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", + "permalink": "{{ .Permalink }}", + "filename": "{{ .File.LogicalName }}", + "summary": {{ jsonify .Summary }} + } + {{ end }}{{ end }} + ], +} + + + + + diff --git a/layouts/index.json b/layouts/index.json index 5c47558..9834cec 100644 --- a/layouts/index.json +++ b/layouts/index.json @@ -1,20 +1,14 @@ -{{ $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" }} -{ +{{ $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" }}{ "is": "index", - "cStateVersion": "4.4", - "apiVersion": "1.0.0", + "cStateVersion": "5.0", + "apiVersion": "2.0", "title": "{{ .Site.Title }}", "languageCodeHTML": "{{ .Site.LanguageCode }}", "languageCode": "{{ T "languageCode" }}", "baseURL": "{{ .Site.BaseURL }}", "description": "{{ .Site.Params.Description }}", - "logo": "{{ .Site.Params.logo | absURL }}", - "categories": [ - {{ range $i, $e := .Site.Params.categories }}{{ if $i }},{{ end }} + "summaryStatus": {{ if $isDown }}"down",{{ else }}{{ if $isDisrupted }}"disrupted",{{ else }}{{ if $isNotice }}"notice",{{ else }}"ok",{{ end }}{{ end }}{{ end }} + "categories": [{{ range $i, $e := .Site.Params.categories }}{{ if $i }},{{ end }} { "name": "{{ .name }}",{{ if .description }} "description": "{{ .description }}",{{ end }} @@ -28,32 +22,48 @@ { "name": "{{ .name }}",{{ if .description }} "description": "{{ .description }}",{{ end }} - "category": "{{ .category }}" + "category": "{{ .category }}", + {{ $activeComponentIssues := where $active "Params.affected" "intersect" (slice .name) }}{{ $thisIsNotice := where $activeComponentIssues "Params.severity" "=" "notice" }}{{ $thisIsDisrupted := where $activeComponentIssues "Params.severity" "=" "disrupted" }}{{ $thisIsDown := where $activeComponentIssues "Params.severity" "=" "down" }} + "status": {{ if $thisIsDown }}"down"{{ else }}{{ if $thisIsDisrupted }}"disrupted"{{ else }}{{ if $thisIsNotice }}"notice"{{ else }}"ok"{{ end }}{{ end }}{{ end }}, + {{ if not $activeComponentIssues }} + "unresolvedIssues": [] + {{ else }} + "unresolvedIssues": [{{ range $i, $e := $activeComponentIssues }}{{ if $i }},{{ end }} + { + "is": "issue", + "title": "{{ .Title }}", + "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", + "permalink": "{{ .Permalink }}", + "severity": "{{ .Params.severity }}", + "resolved": {{ if .Params.resolved }}true{{ else }}false{{ end }}, + "informational": {{ if .Params.informational }}true{{ else }}false{{ end }}, + "resolvedAt": "{{ .Params.resolvedWhen }}", + "affected": [{{ range $i, $e := .Params.Affected }}{{ if $i }}, {{ end }}"{{ . }}"{{ end }}], + "filename": "{{ .File.LogicalName }}" + } + {{ end }} + ]{{ end }} + }{{ end }} + ], + {{ if .Site.Params.customTabs }} + "tabs": [{{ range $i, $e := .Site.Params.customTabs }}{{ if $i }},{{ end }} + { + "name": "{{ .name }}", + "link": "{{ .description }}" } {{ end }} - ], - + ],{{ end }} "buildDate": "{{ now.Format "2006-01-02" }}", "buildTime": "{{ now.Format "15:04" }}", "buildTimezone": "{{ now.Format "MST" }}", - "summaryStatus":{{ if $isDown }} - "down", - {{ else }} - {{ if $isDisrupted }} - "disrupted", - {{ else }} - {{ if $isNotice }} - "notice", - {{ else }} - "ok", - {{ end }}{{ end }}{{ end }} "colorBrand": "{{ .Site.Params.Brand }}", "colorOk": "{{ .Site.Params.Ok }}", "colorDisrupted": "{{ .Site.Params.Disrupted }}", "colorDown": "{{ .Site.Params.Down }}", "colorNotice": "{{ .Site.Params.Notice }}", "alwaysKeepBrandColor": "{{ .Site.Params.alwaysKeepBrandColor }}", - + "logo": "{{ .Site.Params.logo | absURL }}", "googleAnalytics": "{{ .Site.Params.googleAnalytics }}" } diff --git a/layouts/issues/single.html b/layouts/issues/single.html index 5761477..402c794 100644 --- a/layouts/issues/single.html +++ b/layouts/issues/single.html @@ -13,9 +13,24 @@ </div> <div class="contain"> - {{ .Render "issue" }} + {{ .Render "issue" }} </div> + + {{ if .Site.Params.enableLastMod }} + <div class="contain center"> + <p>{{ T "lastChecked" }}: + {{ if .Site.Params.dateFormat }} + {{ .Lastmod.UTC.Format .Site.Params.dateFormat }} + {{ else }} + {{ .Lastmod.Format "January 2, 2006 at 3:04 PM" }} + {{ end }} + </p> + </div> + {{ end }} + + + {{ partial "js" . }} {{ partial "footer" . }} diff --git a/layouts/issues/single.json b/layouts/issues/single.json index 36b0f67..fb78ee7 100644 --- a/layouts/issues/single.json +++ b/layouts/issues/single.json @@ -2,12 +2,12 @@ "is": "issue", "title": "{{ .Title }}", "createdAt": "{{ .Date }}", + "lastMod": "{{ .Lastmod }}", "permalink": "{{ .Permalink }}", "severity": "{{ .Params.severity }}", - "resolved": "{{ .Params.resolved }}", - "informational": "{{ .Params.informational }}", + "resolved": {{ if .Params.resolved }}true{{ else }}false{{ end }}, + "informational": {{ if .Params.informational }}true{{ else }}false{{ end }}, "resolvedAt": "{{ .Params.resolvedWhen }}", "affected": [{{ range $i, $e := .Params.Affected }}{{ if $i }}, {{ end }}"{{ . }}"{{ end }}], - "filename": "{{ .File.LogicalName }}", - "body": {{ jsonify .Content }} + "filename": "{{ .File.LogicalName }}" }
\ No newline at end of file diff --git a/layouts/issues/small.html b/layouts/issues/small.html index 6ed2cce..531b47b 100644 --- a/layouts/issues/small.html +++ b/layouts/issues/small.html @@ -7,8 +7,8 @@ <a href="{{ .Permalink }}" class="issue no-underline"> {{ if .Params.informational }} - - <small class="date float-right"> + + <small class="date float-right {{ cond .Site.Params.useRelativeTime "relative-time" "" }}" title="{{ .Date.Format "Jan 2 15:04:05 2006 UTC" }}"> {{ if .Site.Params.dateFormat }} {{ .Date.Format .Site.Params.dateFormat }} {{ else }} @@ -21,9 +21,9 @@ </h3> <span class="faded">{{ .Summary | truncate 200 }} </span> - + {{ else if .Params.Resolved }} - <small class="date float-right"> + <small class="date float-right {{ cond .Site.Params.useRelativeTime "relative-time" "" }}" title="{{ .Date.Format "Jan 2 15:04:05 2006" }}"> {{ if .Site.Params.dateFormat }} {{ .Date.Format .Site.Params.dateFormat }} {{ else }} @@ -65,9 +65,10 @@ </div> {{ end }} {{ end }} - {{ else }} - <small class="date float-right"> + {{ else }} + <!-- If not resolved --> + <small class="date float-right {{ cond .Site.Params.useRelativeTime "relative-time" "" }}" title="{{ .Date.Format "Jan 2 15:04:05 2006 UTC" }}"> {{ if .Site.Params.dateFormat }} {{ .Date.Format .Site.Params.dateFormat }} {{ else }} @@ -82,17 +83,17 @@ <!-- Marker --> {{ if eq .Params.severity "notice" }} <strong class="warning"> - ◆ + ◆ {{ T "downtimeOngoing" }} </strong> {{ else }} <strong class="error"> {{ if eq .Params.severity "down" }} - ■ + ■ {{ else if eq .Params.severity "disrupted" }} - ▲ + ▲ {{ else }} - ◆ + ◆ {{ end }} {{ T "downtimeOngoing" }} </strong> diff --git a/layouts/partials/index/components.html b/layouts/partials/index/components.html index 82964fe..acb1aa7 100644 --- a/layouts/partials/index/components.html +++ b/layouts/partials/index/components.html @@ -10,18 +10,8 @@ {{ $systems := .Site.Params.systems }} {{ $categories := .Site.Params.categories }} - <script> - function toggleCategoryHead(el) { - if (el.parentNode.className == 'category category--open') { - el.parentNode.className = 'category category--closed'; - } else { - el.parentNode.className = 'category category--open'; - } - } - </script> - {{ range $categories }} - <div class="category {{ if .closed }}category--closed{{ else }}category--open{{ end }}" id="{{ .name | urlize }}"> + <div class="category {{ if .closed }}category--closed{{ else }}category--open{{ end }}{{ if not .untitled }} category--titled{{ end }}" id="{{ .name | urlize }}"> {{ if not .untitled }} <div class="bold padding clicky category__head" onclick="toggleCategoryHead(this)"> <span class="hide-without-js"> @@ -42,6 +32,8 @@ </span> </span> {{ end }} + + <span class="category-status"></span> </div> {{ else }} @@ -94,8 +86,54 @@ {{ end }} </div> {{ end }} - </div> + </div> + + <!-- + Get category status + --> + <script> + // We will look at all components in one category + thisCategory = document.currentScript.parentNode + + componentsOfThisCategory = thisCategory.querySelectorAll('.component') + + // We will cycle through all components and show + // the worst status found + // + // By default, all is good but we change this value + // for progressively worse statuses + var highlestLevelStatus = ''; + + function checkStatus(element) { + var status = element.getAttribute('data-status'); + + if (status === 'down') { + highlestLevelStatus = 'down' + } else if (status === 'disrupted' && highlestLevelStatus !== 'down') { + highlestLevelStatus = 'disrupted' + } else if (status === 'notice' && highlestLevelStatus !== 'down' && highlestLevelStatus !== 'disrupted') { + highlestLevelStatus = 'notice' + } + } + + componentsOfThisCategory.forEach(element => checkStatus(element)); + + // Human readable (i18n) status name variable + var highlestLevelStatusReadable = highlestLevelStatus; + + if (highlestLevelStatus === 'ok') { highlestLevelStatusReadable = '{{ T "thisIsOk" }}' } + if (highlestLevelStatus === 'notice') { highlestLevelStatusReadable = '{{ T "thisIsNotice" }}' } + if (highlestLevelStatus === 'dsirupted') { highlestLevelStatusReadable = '{{ T "thisIsDisrupted" }}' } + if (highlestLevelStatus === 'down') { highlestLevelStatusReadable = '{{ T "thisIsDown" }}' } + + // Finally we can show the status + // (but only for categories with a name) + if (thisCategory.classList.contains('category--titled')) { + thisCategory.querySelector('.category__head').setAttribute('data-status', highlestLevelStatus); + thisCategory.querySelector('.category-status').innerHTML = highlestLevelStatusReadable; + } + </script> </div> {{ end }} -</div> +</div>
\ No newline at end of file diff --git a/layouts/partials/index/summary.html b/layouts/partials/index/summary.html index de6bceb..41f285b 100644 --- a/layouts/partials/index/summary.html +++ b/layouts/partials/index/summary.html @@ -20,5 +20,5 @@ {{ end }}{{ end }}{{ end }} </strong> - <div class="summary__date clicky float-right" onclick="location.reload()"></div> -</div>
\ No newline at end of file + <div class="summary__date clicky float-right relative-time" onclick="location.reload()" data-time-prefix="{{ T "lastChecked" }} "></div> +</div> diff --git a/layouts/partials/js.html b/layouts/partials/js.html index b398fbe..28ce0a1 100644 --- a/layouts/partials/js.html +++ b/layouts/partials/js.html @@ -3,11 +3,11 @@ * Dev toolset */ - console.log('cState v4.4 - https://github.com/cstate/cstate'); + console.log('cState v5.0 - https://github.com/cstate/cstate'); document.getElementsByTagName('html')[0].className = 'js'; /** - * Make theme color pretty + * Change header color based on status */ if (document.body.className === 'change-header-color') { @@ -40,65 +40,86 @@ document.location.pathname = '/admin'; } - /** - * Timer + /** + * Category logic */ - function hasClass(element, className) { - return (' ' + element.className + ' ').indexOf(' ' + className+ ' ') > -1; + function toggleCategoryHead(el) { + if (el.parentNode.className == 'category category--open category--titled') { + el.parentNode.className = 'category category--closed category--titled'; + } else { + el.parentNode.className = 'category category--open category--titled'; + } } - if (hasClass(document.querySelector('body'), 'status-homepage')) { - var lastUpdated = document.querySelector('.summary__date'); - lastUpdated.innerHTML = '{{ T "lastChecked" }} {{ T "justNow" }}'; - - var lastUpdate = new Date(); + /** + * Returns a relative date string for the given date. + */ + + function timeSince(date) { + var seconds = Math.floor((new Date() - date) / 1000); - function timeSince(date) { - var seconds = Math.floor((new Date() - date) / 1000); + var interval = Math.floor(seconds / 31536000); - var interval = Math.floor(seconds / 31536000); + if (interval > 1) { + return interval + ' {{ T "yearsAgo" }}'; + } + interval = Math.floor(seconds / 2592000); + if (interval > 1) { + return interval + ' {{ T "monthsAgo" }}'; + } + interval = Math.floor(seconds / 86400); + if (interval > 1) { + return interval + '{{ T "daysAgo" }}'; + } + interval = Math.floor(seconds / 3600); + if (interval > 1) { + return interval + '{{ T "hoursAgo" }}'; + } + interval = Math.floor(seconds / 60); + if (interval > 1) { + return interval + ' {{ T "minsAgo" }}'; + } + {{ if .Site.Params.skipSeconds }} + return '<1 {{ T "minsAgo" }}' + {{ else }} + return Math.floor(seconds) + '{{ T "secondsAgo" }}'; + {{ end }} + } - if (interval > 1) { - return interval + ' {{ T "yearsAgo" }}'; - } - interval = Math.floor(seconds / 2592000); - if (interval > 1) { - return interval + ' {{ T "monthsAgo" }}'; - } - interval = Math.floor(seconds / 86400); - if (interval > 1) { - return interval + '{{ T "daysAgo" }}'; - } - interval = Math.floor(seconds / 3600); - if (interval > 1) { - return interval + '{{ T "hoursAgo" }}'; - } - interval = Math.floor(seconds / 60); - if (interval > 1) { - return interval + ' {{ T "minsAgo" }}'; + /** + * Changes elements with the class 'relative-time' into relative times and + * moves the timestamp to a title attribute tooltip. + */ + + function updateRelativeTimes() { + var elements = document.querySelectorAll('.relative-time'); + for (var i = 0; i < elements.length; i++) { + var element = elements[i]; + var time = Date.parse(element.getAttribute('title')); + var html = element.getAttribute('data-time-prefix') || ''; + if (!time) { + time = element.innerText; + element.setAttribute('title', time || new Date); + html += '{{ T "justNow" }}'; + } else { + html += timeSince(time) + ' {{ T "someTimeAgo" }}'; } - return Math.floor(seconds) + '{{ T "secondsAgo" }}'; + html += element.getAttribute('data-time-suffix') || ''; + element.innerHTML = html.trim(); } - var aDay = 24*60*60*1000; } - window.setInterval(function() { - if (hasClass(document.querySelector('body'), 'status-homepage')) { - lastUpdated.innerHTML = '{{ T "lastChecked" }} ' + timeSince(lastUpdate) + ' {{ T "someTimeAgo" }}'; + updateRelativeTimes(); - // Refresh almost every 5m - if (lastUpdate > 290000) { - location.reload; - } - } - }, 5000) + // Update "time since" feature every 5s + setInterval(updateRelativeTimes, 5000); </script> {{ if ne .Site.Params.googleAnalytics "UA-00000000-1" }} <!-- Global site tag (gtag.js) - Google Analytics --> - <script type="text/javascript" defer src="https://www.googletagmanager.com/gtag/js?id=UA-109775664-1"></script> + <script type="text/javascript" defer src="https://www.googletagmanager.com/gtag/js?id={{ .Site.Params.googleAnalytics }}"></script> <script type="text/javascript" defer> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} diff --git a/layouts/partials/meta.html b/layouts/partials/meta.html index 77c66db..c46ee94 100644 --- a/layouts/partials/meta.html +++ b/layouts/partials/meta.html @@ -12,7 +12,7 @@ {{ range .AlternativeOutputFormats -}} {{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }} {{ end -}} - <meta name="generator" content="cState v4.4 - https://github.com/cstate/cstate"> + <meta name="generator" content="cState v5.0 - https://github.com/cstate/cstate"> <meta name="theme-color" content="{{ .Site.Params.brand }}"> <script> var themeBrandColor = '{{ .Site.Params.brand }}'; @@ -319,14 +319,23 @@ .status-notice .announcement-box { border-top: 0; } /** - * Dynamically show individual component statuses + * Dynamically show component statuses */ - .component-status { float: right; } - .component[data-status="ok"] .component-status { color: {{ .Site.Params.ok }}; } - .component[data-status="disrupted"] .component-status { color: {{ .Site.Params.disrupted }}; } - .component[data-status="down"] .component-status { color: {{ .Site.Params.down }}; } - .component[data-status="notice"] .component-status { color: {{ .Site.Params.notice }}; } + .category--open .category-status { display: none; } + .component-status, .category-status { float: right; } + .component[data-status="ok"] .component-status, + .category__head[data-status="ok"] .category-status + { color: {{ .Site.Params.ok }}; } + .component[data-status="disrupted"] .component-status, + .category__head[data-status="disrupted"] .category-status + { color: {{ .Site.Params.disrupted }}; } + .component[data-status="notice"] .component-status, + .category__head[data-status="notice"] .category-status + { color: {{ .Site.Params.notice }}; } + .component[data-status="down"] .component-status, + .category__head[data-status="down"] .category-status + { color: {{ .Site.Params.down }}; } /** * Responsiveness @@ -386,15 +395,19 @@ .error { color: #ff4242; } .warning {color: #ffde7f; } .ok { color: #7fff7f; } - - .component[data-status="ok"] - .component-status { color: #7fff7f; } - .component[data-status="disrupted"] - .component-status { color: #ffde7f; } - .component[data-status="notice"] - .component-status { color: #83a4e8; } - .component[data-status="down"] - .component-status { color: #ff8181; } + + .component[data-status="ok"] .component-status, + .category__head[data-status="ok"] .category-status + { color: #7fff7f; } + .component[data-status="disrupted"] .component-status, + .category__head[data-status="disrupted"] .category-status + { color: #ffde7f; } + .component[data-status="notice"] .component-status, + .category__head[data-status="notice"] .category-status + { color: #83a4e8; } + .component[data-status="down"] .component-status, + .category__head[data-status="down"] .category-status + { color: #ff8181; } } {{ end }} </style> |