mirror of
https://github.com/sablierapp/sablier.git
synced 2025-12-27 07:31:42 +01:00
feat(strategy): add dynamic theme listing endpoint /strategies/dynamic/themes
This commit is contained in:
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
//go:embed themes/*
|
||||
var themes embed.FS
|
||||
var Themes embed.FS
|
||||
|
||||
type RenderOptionsInstanceState struct {
|
||||
Name string
|
||||
@@ -54,7 +54,7 @@ func Render(options RenderOptions, writer io.Writer) error {
|
||||
tpl, err = template.ParseFS(options.CustomThemes, fmt.Sprintf("%s.html", options.Theme))
|
||||
} else {
|
||||
// Load from the embedded FS
|
||||
tpl, err = template.ParseFS(themes, fmt.Sprintf("themes/%s.html", options.Theme))
|
||||
tpl, err = template.ParseFS(Themes, fmt.Sprintf("themes/%s.html", options.Theme))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -40,7 +40,7 @@ func NewServeStrategy(sessionsManager sessions.Manager, conf config.Strategy) *S
|
||||
if conf.Dynamic.CustomThemesPath != "" {
|
||||
customThemesFs := osDirFS(conf.Dynamic.CustomThemesPath)
|
||||
serveStrategy.customThemesFS = customThemesFs
|
||||
serveStrategy.customThemes = loadAllowedThemes(customThemesFs)
|
||||
serveStrategy.customThemes = listThemes(customThemesFs)
|
||||
}
|
||||
|
||||
return serveStrategy
|
||||
@@ -84,6 +84,26 @@ func (s *ServeStrategy) ServeDynamic(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ServeStrategy) ServeDynamicThemes(c *gin.Context) {
|
||||
|
||||
customThemes := []string{}
|
||||
for theme := range s.customThemes {
|
||||
customThemes = append(customThemes, theme)
|
||||
}
|
||||
sort.Strings(customThemes)
|
||||
|
||||
embeddedThemes := []string{}
|
||||
for theme := range listThemes(pages.Themes) {
|
||||
embeddedThemes = append(embeddedThemes, strings.TrimPrefix(theme, "themes/"))
|
||||
}
|
||||
sort.Strings(embeddedThemes)
|
||||
|
||||
c.JSON(http.StatusOK, map[string]interface{}{
|
||||
"custom": customThemes,
|
||||
"embedded": embeddedThemes,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ServeStrategy) ServeBlocking(c *gin.Context) {
|
||||
request := models.BlockingRequest{
|
||||
Timeout: s.StrategyConfig.Blocking.DefaultTimeout,
|
||||
@@ -142,7 +162,8 @@ func instanceStateToRenderOptionsRequestState(instanceState *instance.State) pag
|
||||
}
|
||||
}
|
||||
|
||||
func loadAllowedThemes(dir fs.FS) (allowedThemes map[string]bool) {
|
||||
func listThemes(dir fs.FS) (themes map[string]bool) {
|
||||
themes = make(map[string]bool)
|
||||
fs.WalkDir(dir, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -154,7 +175,7 @@ func loadAllowedThemes(dir fs.FS) (allowedThemes map[string]bool) {
|
||||
|
||||
if strings.HasSuffix(d.Name(), ".html") {
|
||||
log.Debugf("found theme at \"%s\" can be loaded using \"%s\"", path, strings.TrimSuffix(path, ".html"))
|
||||
allowedThemes[strings.TrimSuffix(path, ".html")] = true
|
||||
themes[strings.TrimSuffix(path, ".html")] = true
|
||||
} else {
|
||||
log.Tracef("ignoring file \"%s\" because it has no .html suffix", path)
|
||||
}
|
||||
|
||||
@@ -278,3 +278,94 @@ func TestNewServeStrategy(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeStrategy_ServeDynamicThemes(t *testing.T) {
|
||||
type fields struct {
|
||||
StrategyConfig config.Strategy
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
osDirFS fs.FS
|
||||
expected map[string]any
|
||||
}{
|
||||
{
|
||||
name: "load custom themes",
|
||||
fields: fields{StrategyConfig: config.Strategy{
|
||||
Dynamic: config.DynamicStrategy{
|
||||
CustomThemesPath: "my/path/to/themes",
|
||||
},
|
||||
}},
|
||||
osDirFS: fstest.MapFS{
|
||||
"my/path/to/superman.html": {Data: []byte("superman")},
|
||||
"my/path/to/themes/marvel.html": {Data: []byte("thor")},
|
||||
"my/path/to/themes/dc-comics.html": {Data: []byte("batman")},
|
||||
"my/path/to/themes/inner/dc-comics.html": {Data: []byte("batman")},
|
||||
},
|
||||
expected: map[string]any{
|
||||
"custom": []any{
|
||||
"dc-comics",
|
||||
"inner/dc-comics",
|
||||
"marvel",
|
||||
},
|
||||
"embedded": []any{
|
||||
"ghost",
|
||||
"hacker-terminal",
|
||||
"matrix",
|
||||
"shuffle",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "load without custom themes",
|
||||
expected: map[string]any{
|
||||
"custom": []any{},
|
||||
"embedded": []any{
|
||||
"ghost",
|
||||
"hacker-terminal",
|
||||
"matrix",
|
||||
"shuffle",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
oldosDirFS := osDirFS
|
||||
defer func() { osDirFS = oldosDirFS }()
|
||||
|
||||
myOsDirFS := func(dir string) fs.FS {
|
||||
fs, err := fs.Sub(tt.osDirFS, dir)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return fs
|
||||
}
|
||||
|
||||
osDirFS = myOsDirFS
|
||||
|
||||
s := NewServeStrategy(nil, tt.fields.StrategyConfig)
|
||||
|
||||
recorder := httptest.NewRecorder()
|
||||
c := GetTestGinContext(recorder)
|
||||
|
||||
s.ServeDynamicThemes(c)
|
||||
|
||||
res := recorder.Result()
|
||||
defer res.Body.Close()
|
||||
|
||||
jsonRes := make(map[string]interface{})
|
||||
err := json.NewDecoder(res.Body).Decode(&jsonRes)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, jsonRes, tt.expected)
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ func Start(serverConf config.Server, strategyConf config.Strategy, sessionManage
|
||||
{
|
||||
strategy := routes.NewServeStrategy(sessionManager, strategyConf)
|
||||
api.GET("/strategies/dynamic", strategy.ServeDynamic)
|
||||
api.GET("/strategies/dynamic/themes", strategy.ServeDynamicThemes)
|
||||
api.GET("/strategies/blocking", strategy.ServeBlocking)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user