mirror of
https://github.com/glanceapp/glance.git
synced 2024-12-14 17:13:11 +03:00
Allow widgets to handle HTTP requests
This commit is contained in:
parent
c041197f3f
commit
795caa5d9d
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -24,6 +25,7 @@ type Application struct {
|
||||
Version string
|
||||
Config Config
|
||||
slugToPage map[string]*Page
|
||||
widgetByID map[uint64]widget.Widget
|
||||
}
|
||||
|
||||
type Theme struct {
|
||||
@ -106,16 +108,24 @@ func NewApplication(config *Config) (*Application, error) {
|
||||
Version: buildVersion,
|
||||
Config: *config,
|
||||
slugToPage: make(map[string]*Page),
|
||||
widgetByID: make(map[uint64]widget.Widget),
|
||||
}
|
||||
|
||||
app.slugToPage[""] = &config.Pages[0]
|
||||
|
||||
for i := range config.Pages {
|
||||
if config.Pages[i].Slug == "" {
|
||||
config.Pages[i].Slug = titleToSlug(config.Pages[i].Title)
|
||||
for p := range config.Pages {
|
||||
if config.Pages[p].Slug == "" {
|
||||
config.Pages[p].Slug = titleToSlug(config.Pages[p].Title)
|
||||
}
|
||||
|
||||
app.slugToPage[config.Pages[i].Slug] = &config.Pages[i]
|
||||
app.slugToPage[config.Pages[p].Slug] = &config.Pages[p]
|
||||
|
||||
for c := range config.Pages[p].Columns {
|
||||
for w := range config.Pages[p].Columns[c].Widgets {
|
||||
widget := config.Pages[p].Columns[c].Widgets[w]
|
||||
app.widgetByID[widget.GetID()] = widget
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return app, nil
|
||||
@ -190,6 +200,26 @@ func FileServerWithCache(fs http.FileSystem, cacheDuration time.Duration) http.H
|
||||
})
|
||||
}
|
||||
|
||||
func (a *Application) HandleWidgetRequest(w http.ResponseWriter, r *http.Request) {
|
||||
widgetValue := r.PathValue("widget")
|
||||
|
||||
widgetID, err := strconv.ParseUint(widgetValue, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
a.HandleNotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
widget, exists := a.widgetByID[widgetID]
|
||||
|
||||
if !exists {
|
||||
a.HandleNotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
widget.HandleRequest(w, r)
|
||||
}
|
||||
|
||||
func (a *Application) AssetPath(asset string) string {
|
||||
return "/static/" + a.Config.Server.AssetsHash + "/" + asset
|
||||
}
|
||||
@ -203,7 +233,10 @@ func (a *Application) Serve() error {
|
||||
|
||||
mux.HandleFunc("GET /{$}", a.HandlePageRequest)
|
||||
mux.HandleFunc("GET /{page}", a.HandlePageRequest)
|
||||
|
||||
mux.HandleFunc("GET /api/pages/{page}/content/{$}", a.HandlePageContentRequest)
|
||||
mux.HandleFunc("/api/widgets/{widget}/{path...}", a.HandleWidgetRequest)
|
||||
|
||||
mux.Handle(
|
||||
fmt.Sprintf("GET /static/%s/{path...}", a.Config.Server.AssetsHash),
|
||||
http.StripPrefix("/static/"+a.Config.Server.AssetsHash, FileServerWithCache(http.FS(assets.PublicFS), 8*time.Hour)),
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/glanceapp/glance/internal/feed"
|
||||
@ -15,51 +17,59 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var uniqueID atomic.Uint64
|
||||
|
||||
func New(widgetType string) (Widget, error) {
|
||||
var widget Widget
|
||||
|
||||
switch widgetType {
|
||||
case "calendar":
|
||||
return &Calendar{}, nil
|
||||
widget = &Calendar{}
|
||||
case "clock":
|
||||
return &Clock{}, nil
|
||||
widget = &Clock{}
|
||||
case "weather":
|
||||
return &Weather{}, nil
|
||||
widget = &Weather{}
|
||||
case "bookmarks":
|
||||
return &Bookmarks{}, nil
|
||||
widget = &Bookmarks{}
|
||||
case "iframe":
|
||||
return &IFrame{}, nil
|
||||
widget = &IFrame{}
|
||||
case "html":
|
||||
return &HTML{}, nil
|
||||
widget = &HTML{}
|
||||
case "hacker-news":
|
||||
return &HackerNews{}, nil
|
||||
widget = &HackerNews{}
|
||||
case "releases":
|
||||
return &Releases{}, nil
|
||||
widget = &Releases{}
|
||||
case "videos":
|
||||
return &Videos{}, nil
|
||||
widget = &Videos{}
|
||||
case "markets", "stocks":
|
||||
return &Markets{}, nil
|
||||
widget = &Markets{}
|
||||
case "reddit":
|
||||
return &Reddit{}, nil
|
||||
widget = &Reddit{}
|
||||
case "rss":
|
||||
return &RSS{}, nil
|
||||
widget = &RSS{}
|
||||
case "monitor":
|
||||
return &Monitor{}, nil
|
||||
widget = &Monitor{}
|
||||
case "twitch-top-games":
|
||||
return &TwitchGames{}, nil
|
||||
widget = &TwitchGames{}
|
||||
case "twitch-channels":
|
||||
return &TwitchChannels{}, nil
|
||||
widget = &TwitchChannels{}
|
||||
case "lobsters":
|
||||
return &Lobsters{}, nil
|
||||
widget = &Lobsters{}
|
||||
case "change-detection":
|
||||
return &ChangeDetection{}, nil
|
||||
widget = &ChangeDetection{}
|
||||
case "repository":
|
||||
return &Repository{}, nil
|
||||
widget = &Repository{}
|
||||
case "search":
|
||||
return &Search{}, nil
|
||||
widget = &Search{}
|
||||
case "extension":
|
||||
return &Extension{}, nil
|
||||
widget = &Extension{}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown widget type: %s", widgetType)
|
||||
}
|
||||
|
||||
widget.SetID(uniqueID.Add(1))
|
||||
|
||||
return widget, nil
|
||||
}
|
||||
|
||||
type Widgets []Widget
|
||||
@ -90,7 +100,7 @@ func (w *Widgets) UnmarshalYAML(node *yaml.Node) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = widget.Initialize(); err != nil {
|
||||
if err := widget.Initialize(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -106,6 +116,9 @@ type Widget interface {
|
||||
Update(context.Context)
|
||||
Render() template.HTML
|
||||
GetType() string
|
||||
GetID() uint64
|
||||
SetID(uint64)
|
||||
HandleRequest(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
type cacheType int
|
||||
@ -117,6 +130,7 @@ const (
|
||||
)
|
||||
|
||||
type widgetBase struct {
|
||||
ID uint64 `yaml:"-"`
|
||||
Type string `yaml:"type"`
|
||||
Title string `yaml:"title"`
|
||||
TitleURL string `yaml:"title-url"`
|
||||
@ -148,6 +162,18 @@ func (w *widgetBase) Update(ctx context.Context) {
|
||||
|
||||
}
|
||||
|
||||
func (w *widgetBase) GetID() uint64 {
|
||||
return w.ID
|
||||
}
|
||||
|
||||
func (w *widgetBase) SetID(id uint64) {
|
||||
w.ID = id
|
||||
}
|
||||
|
||||
func (widget *widgetBase) HandleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "not implemented", http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
func (w *widgetBase) GetType() string {
|
||||
return w.Type
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user