Fetch statuspage.io info next to bookmarks
This commit is contained in:
parent
f5427310e8
commit
58ffe6e55f
4 changed files with 147 additions and 12 deletions
|
@ -397,7 +397,8 @@ body {
|
|||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.notice-icon-major {
|
||||
.notice-icon-major,
|
||||
.notice-icon-critical {
|
||||
background: var(--color-negative);
|
||||
}
|
||||
|
||||
|
@ -405,6 +406,10 @@ body {
|
|||
border: 1px solid var(--color-negative);
|
||||
}
|
||||
|
||||
.notice-icon-none {
|
||||
border: 1px solid var(--color-positive);
|
||||
}
|
||||
|
||||
kbd {
|
||||
font: inherit;
|
||||
padding: 0.1rem 0.8rem;
|
||||
|
@ -1427,6 +1432,7 @@ kbd:active {
|
|||
.inline-block { display: inline-block; }
|
||||
.overflow-hidden { overflow: hidden; }
|
||||
.relative { position: relative; }
|
||||
.hidden { display: none; }
|
||||
.flex { display: flex; }
|
||||
.flex-wrap { flex-wrap: wrap; }
|
||||
.flex-nowrap { flex-wrap: nowrap; }
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
</div>
|
||||
{{ end }}
|
||||
<a href="{{ .URL }}" class="bookmarks-link {{ if .HideArrow }}bookmarks-link-no-arrow {{ end }}color-highlight size-h4" {{ if not .SameTab }}target="_blank"{{ end }} rel="noreferrer">{{ .Title }}</a>
|
||||
{{ if .StatusPage }}
|
||||
<div class="notice-icon notice-icon-{{ .StatusPage.StatusPageInfo.StatusResponse.Indicator }} {{ if not .StatusPage.ShowIfOperational }} hidden {{ end }}" title="{{ .StatusPage.StatusPageInfo.StatusResponse.Description }}"></div>
|
||||
{{ end}}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
|
66
internal/feed/bookmarks.go
Normal file
66
internal/feed/bookmarks.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package feed
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StatusPage struct {
|
||||
URL string `yaml:"url"`
|
||||
ShowIfOperational bool `yaml:"show-if-operational" default:"false"`
|
||||
StatusPageInfo StatusPageInfo `yaml:"-"`
|
||||
}
|
||||
|
||||
type StatusPageInfo struct {
|
||||
StatusResponse StatusResponse `json:"status"`
|
||||
Error error
|
||||
}
|
||||
|
||||
type StatusResponse struct {
|
||||
Indicator string `json:"indicator"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
const summaryEndpointPath = "/api/v2/summary.json"
|
||||
|
||||
func getStatusPageTask(statusRequest *StatusPage) (StatusPageInfo, error) {
|
||||
request, err := http.NewRequest(http.MethodGet, statusRequest.URL+summaryEndpointPath, nil)
|
||||
|
||||
if err != nil {
|
||||
return StatusPageInfo{
|
||||
Error: err,
|
||||
}, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
|
||||
defer cancel()
|
||||
request = request.WithContext(ctx)
|
||||
|
||||
var response *http.Response
|
||||
response, err = defaultClient.Do(request)
|
||||
|
||||
var status StatusPageInfo
|
||||
if err != nil {
|
||||
status.Error = err
|
||||
return status, nil
|
||||
}
|
||||
|
||||
err = json.NewDecoder(response.Body).Decode(&status)
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
||||
func FetchStatusPages(requests []*StatusPage) ([]StatusPageInfo, error) {
|
||||
job := newJob(getStatusPageTask, requests).withWorkers(20)
|
||||
results, _, err := workerPoolDo(job)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
|
@ -1,34 +1,41 @@
|
|||
package widget
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/glanceapp/glance/internal/feed"
|
||||
"html/template"
|
||||
"time"
|
||||
|
||||
"github.com/glanceapp/glance/internal/assets"
|
||||
)
|
||||
|
||||
type Bookmarks struct {
|
||||
widgetBase `yaml:",inline"`
|
||||
cachedHTML template.HTML `yaml:"-"`
|
||||
Groups []struct {
|
||||
Title string `yaml:"title"`
|
||||
Color *HSLColorField `yaml:"color"`
|
||||
Links []struct {
|
||||
Title string `yaml:"title"`
|
||||
URL string `yaml:"url"`
|
||||
Icon string `yaml:"icon"`
|
||||
IsSimpleIcon bool `yaml:"-"`
|
||||
SameTab bool `yaml:"same-tab"`
|
||||
HideArrow bool `yaml:"hide-arrow"`
|
||||
Title string `yaml:"title"`
|
||||
URL string `yaml:"url"`
|
||||
Icon string `yaml:"icon"`
|
||||
IsSimpleIcon bool `yaml:"-"`
|
||||
SameTab bool `yaml:"same-tab"`
|
||||
HideArrow bool `yaml:"hide-arrow"`
|
||||
StatusPage *feed.StatusPage `yaml:"status-page"`
|
||||
} `yaml:"links"`
|
||||
} `yaml:"groups"`
|
||||
Style string `yaml:"style"`
|
||||
}
|
||||
|
||||
func (widget *Bookmarks) Initialize() error {
|
||||
widget.withTitle("Bookmarks").withError(nil)
|
||||
countStatusPages := 0
|
||||
|
||||
for g := range widget.Groups {
|
||||
for l := range widget.Groups[g].Links {
|
||||
if widget.Groups[g].Links[l].StatusPage != nil {
|
||||
countStatusPages++
|
||||
}
|
||||
|
||||
if widget.Groups[g].Links[l].Icon == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -38,11 +45,64 @@ func (widget *Bookmarks) Initialize() error {
|
|||
}
|
||||
}
|
||||
|
||||
widget.cachedHTML = widget.render(widget, assets.BookmarksTemplate)
|
||||
w := widget.withTitle("Bookmarks")
|
||||
if countStatusPages > 0 {
|
||||
w.withCacheDuration(30 * time.Minute)
|
||||
} else {
|
||||
w.withError(nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (widget *Bookmarks) Render() template.HTML {
|
||||
return widget.cachedHTML
|
||||
func (widget *Bookmarks) Update(ctx context.Context) {
|
||||
countStatusPages := 0
|
||||
for g := range widget.Groups {
|
||||
for l := range widget.Groups[g].Links {
|
||||
if widget.Groups[g].Links[l].StatusPage != nil {
|
||||
if widget.Groups[g].Links[l].StatusPage.URL != "" {
|
||||
countStatusPages++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if countStatusPages == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
requests := make([]*feed.StatusPage, countStatusPages)
|
||||
|
||||
countStatusPages = 0
|
||||
for g := range widget.Groups {
|
||||
for l := range widget.Groups[g].Links {
|
||||
if widget.Groups[g].Links[l].StatusPage != nil {
|
||||
if widget.Groups[g].Links[l].StatusPage.URL != "" {
|
||||
requests[countStatusPages] = widget.Groups[g].Links[l].StatusPage
|
||||
countStatusPages++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statuses, err := feed.FetchStatusPages(requests)
|
||||
|
||||
if !widget.canContinueUpdateAfterHandlingErr(err) {
|
||||
return
|
||||
}
|
||||
|
||||
for g := range widget.Groups {
|
||||
for l := range widget.Groups[g].Links {
|
||||
if widget.Groups[g].Links[l].StatusPage != nil {
|
||||
if widget.Groups[g].Links[l].StatusPage.URL != "" {
|
||||
widget.Groups[g].Links[l].StatusPage.StatusPageInfo = statuses[0]
|
||||
statuses = statuses[1:]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (widget *Bookmarks) Render() template.HTML {
|
||||
return widget.render(widget, assets.BookmarksTemplate)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue