Ver código fonte

Fetch statuspage.io info next to bookmarks

dvdandroid 11 meses atrás
pai
commit
58ffe6e55f

+ 7 - 1
internal/assets/static/main.css

@@ -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; }

+ 3 - 0
internal/assets/templates/bookmarks.html

@@ -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 - 0
internal/feed/bookmarks.go

@@ -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
+}

+ 70 - 10
internal/widget/bookmarks.go

@@ -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) 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.cachedHTML
+	return widget.render(widget, assets.BookmarksTemplate)
 }