detached 5ae0ddf

Refactor the templating renderer, add manager page

commit
5ae0ddfb6ea65df4cd8b17cbd14aeebf4f44cd68
author
bnema · · 2023-09-20 10:47 UTC
parent
19b7643
signature
unsigned
9 files · +82 -12
M cmd/main.go +0 -1
@@ -28,7 +28,6 @@ func main() {
2828 if err != nil {
2929 log.Fatal(err)
3030 }
31-
3231 // Pass memDb to the app with the rest of the configs
3332 a.DB = memDb
3433
@@ -28,7 +28,6 @@ func main() {
28 if err != nil {28 if err != nil {
29 log.Fatal(err)29 log.Fatal(err)
30 }30 }
31-
32 // Pass memDb to the app with the rest of the configs31 // Pass memDb to the app with the rest of the configs
33 a.DB = memDb32 a.DB = memDb
34 33
M internal/app/app.go +1 -1
@@ -22,7 +22,7 @@ func init() {
2222 appEnv = os.Getenv("APP_ENV")
2323 if appEnv == "" {
2424 appEnv = "prod" // Default to "prod" if APP_ENV is not set
25- }
25+ }
2626 }
2727
2828 type App struct {
@@ -22,7 +22,7 @@ func init() {
22 appEnv = os.Getenv("APP_ENV")22 appEnv = os.Getenv("APP_ENV")
23 if appEnv == "" {23 if appEnv == "" {
24 appEnv = "prod" // Default to "prod" if APP_ENV is not set24 appEnv = "prod" // Default to "prod" if APP_ENV is not set
25- }25+ }
26 }26 }
27 27
28 type App struct {28 type App struct {
M internal/gotemplate/models/html/admin/manager.gohtml +20 -0
@@ -0,0 +1,20 @@
1+<!-- manager.gohtml -->
2+{{template "header.gohtml" .}}
3+<!DOCTYPE html>
4+<html lang="en">
5+
6+<body class="bg-zinc-200 flex flex-col md:flex-row p-4 md:p-8 p-0">
7+ {{template "leftmenu.gohtml" .}}
8+ <!-- Main content here -->
9+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 p-4 md:ml-4">
10+ <div class="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4 flex-grow">
11+ <div class="flex-grow bg-white p-4 rounded-md shadow mb-4">
12+ <h1>hello world</h1>
13+ </div>
14+ </div>
15+
16+ <!-- footer -->
17+ {{template "footer.gohtml" .}}
18+</body>
19+
20+</html>⏎̸
@@ -0,0 +1,20 @@
1+<!-- manager.gohtml -->
2+{{template "header.gohtml" .}}
3+<!DOCTYPE html>
4+<html lang="en">
5+
6+<body class="bg-zinc-200 flex flex-col md:flex-row p-4 md:p-8 p-0">
7+ {{template "leftmenu.gohtml" .}}
8+ <!-- Main content here -->
9+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 p-4 md:ml-4">
10+ <div class="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4 flex-grow">
11+ <div class="flex-grow bg-white p-4 rounded-md shadow mb-4">
12+ <h1>hello world</h1>
13+ </div>
14+ </div>
15+
16+ <!-- footer -->
17+ {{template "footer.gohtml" .}}
18+</body>
19+
20+</html>⏎̸
R internal/gotemplate/models/html/fragments/components.gohtml → internal/gotemplate/models/html/components.gohtml +0 -0 renamed, 100% similar

renamed, 100% similar

A internal/gotemplate/models/html/fragments/manager.gohtml +0 -0

no textual change.

M internal/gotemplate/render/html.go +18 -5
@@ -42,20 +42,33 @@ func (r *Renderer) Render(data interface{}, a *app.App) (string, error) {
4242 return buf.String(), nil
4343 }
4444
45-// GetRenderer function returns a new Renderer instance
46-func GetHTMLRenderer(pathStr string, filename string, fs fs.FS, a *app.App) (*Renderer, error) {
47- // Join path and filename
48- fullPath := path.Join(pathStr, filename)
45+// GetHTMLRenderer function returns a new Renderer instance
46+func GetHTMLRenderer(mainPath string, filename string, fs fs.FS, a *app.App, fragmentsPath ...string) (*Renderer, error) {
47+ // Full path to the main template
48+ fullPath := path.Join(mainPath, filename)
4949 // Check if the file exists in the provided fs.FS using fs.Open
5050 file, err := fs.Open(fullPath)
5151 if err != nil {
5252 return nil, fmt.Errorf("failed to open %s: %w", filename, err)
5353 }
54- file.Close() // Close the file after checking
54+ file.Close()
55+
56+ // Parse the main template
5557 tmpl, err := template.New(filename).ParseFS(fs, fullPath)
5658 if err != nil {
5759 return nil, fmt.Errorf("failed to parse %s: %w", filename, err)
5860 }
61+
62+ // If a fragments path is provided, parse the fragment templates
63+ if len(fragmentsPath) > 0 && fragmentsPath[0] != "" {
64+ fragmentsGlob := path.Join(fragmentsPath[0], "*.gohtml")
65+ _, err = tmpl.ParseFS(fs, fragmentsGlob)
66+ if err != nil {
67+ return nil, fmt.Errorf("failed to parse fragments: %w", err)
68+ }
69+ }
70+
71+ // Return the Renderer instance
5972 return &Renderer{
6073 Template: tmpl,
6174 BuildVersion: a.Config.General.BuildVersion,
@@ -42,20 +42,33 @@ func (r *Renderer) Render(data interface{}, a *app.App) (string, error) {
42 return buf.String(), nil42 return buf.String(), nil
43 }43 }
44 44
45-// GetRenderer function returns a new Renderer instance45+// GetHTMLRenderer function returns a new Renderer instance
46-func GetHTMLRenderer(pathStr string, filename string, fs fs.FS, a *app.App) (*Renderer, error) {46+func GetHTMLRenderer(mainPath string, filename string, fs fs.FS, a *app.App, fragmentsPath ...string) (*Renderer, error) {
47- // Join path and filename47+ // Full path to the main template
48- fullPath := path.Join(pathStr, filename)48+ fullPath := path.Join(mainPath, filename)
49 // Check if the file exists in the provided fs.FS using fs.Open49 // Check if the file exists in the provided fs.FS using fs.Open
50 file, err := fs.Open(fullPath)50 file, err := fs.Open(fullPath)
51 if err != nil {51 if err != nil {
52 return nil, fmt.Errorf("failed to open %s: %w", filename, err)52 return nil, fmt.Errorf("failed to open %s: %w", filename, err)
53 }53 }
54- file.Close() // Close the file after checking54+ file.Close()
55+
56+ // Parse the main template
55 tmpl, err := template.New(filename).ParseFS(fs, fullPath)57 tmpl, err := template.New(filename).ParseFS(fs, fullPath)
56 if err != nil {58 if err != nil {
57 return nil, fmt.Errorf("failed to parse %s: %w", filename, err)59 return nil, fmt.Errorf("failed to parse %s: %w", filename, err)
58 }60 }
61+
62+ // If a fragments path is provided, parse the fragment templates
63+ if len(fragmentsPath) > 0 && fragmentsPath[0] != "" {
64+ fragmentsGlob := path.Join(fragmentsPath[0], "*.gohtml")
65+ _, err = tmpl.ParseFS(fs, fragmentsGlob)
66+ if err != nil {
67+ return nil, fmt.Errorf("failed to parse fragments: %w", err)
68+ }
69+ }
70+
71+ // Return the Renderer instance
59 return &Renderer{72 return &Renderer{
60 Template: tmpl,73 Template: tmpl,
61 BuildVersion: a.Config.General.BuildVersion,74 BuildVersion: a.Config.General.BuildVersion,
M internal/httpserve/handler/adminroutes.go +37 -2
@@ -1,6 +1,9 @@
11 package handler
22
33 import (
4+ "fmt"
5+ "net/http"
6+
47 "github.com/bnema/gordon/internal/app"
58 "github.com/bnema/gordon/internal/gotemplate/render"
69 "github.com/bnema/gordon/internal/httpserve/middleware"
@@ -8,6 +11,11 @@ import (
811 "github.com/labstack/echo/v4"
912 )
1013
14+var (
15+ mainPath = "html/admin"
16+ fragmentsPath = "html/fragments"
17+)
18+
1119 // Handle the admin route to display index.gohtml from the templateFS with the data from strings.yml
1220 func AdminRoute(c echo.Context, a *app.App) error {
1321 lang := c.Get(middleware.LangKey).(string)
@@ -18,8 +26,7 @@ func AdminRoute(c echo.Context, a *app.App) error {
1826 }
1927
2028 // Navigate inside the fs.FS to get the template
21- path := "html/admin"
22- rendererData, err := render.GetHTMLRenderer(path, "index.gohtml", a.TemplateFS, a)
29+ rendererData, err := render.GetHTMLRenderer(mainPath, "index.gohtml", a.TemplateFS, a, fragmentsPath)
2330 if err != nil {
2431 return err
2532 }
@@ -37,3 +44,31 @@ func AdminRoute(c echo.Context, a *app.App) error {
3744
3845 return c.HTML(200, renderedHTML)
3946 }
47+
48+func AdminManagerRoute(c echo.Context, a *app.App) error {
49+ lang := c.Get(middleware.LangKey).(string)
50+ yamlData := webui.StringsYamlData{}
51+ err := webui.ReadStringsDataFromYAML(lang, a.TemplateFS, "strings.yml", &yamlData)
52+ if err != nil {
53+ fmt.Printf("Error reading YAML: %v\n", err)
54+ return echo.NewHTTPError(http.StatusInternalServerError, "Failed to load language data")
55+ }
56+
57+ // Navigate inside the fs.FS to get the template
58+ rendererData, err := render.GetHTMLRenderer(mainPath, "manager.gohtml", a.TemplateFS, a, fragmentsPath)
59+ if err != nil {
60+ return err
61+ }
62+
63+ // Create a data map to pass to the renderer
64+ data := map[string]interface{}{
65+ "CurrentLang": yamlData.CurrentLang,
66+ }
67+
68+ renderedHTML, err := rendererData.Render(data, a)
69+ if err != nil {
70+ return err
71+ }
72+
73+ return c.HTML(200, renderedHTML)
74+}
@@ -1,6 +1,9 @@
1 package handler1 package handler
2 2
3 import (3 import (
4+ "fmt"
5+ "net/http"
6+
4 "github.com/bnema/gordon/internal/app"7 "github.com/bnema/gordon/internal/app"
5 "github.com/bnema/gordon/internal/gotemplate/render"8 "github.com/bnema/gordon/internal/gotemplate/render"
6 "github.com/bnema/gordon/internal/httpserve/middleware"9 "github.com/bnema/gordon/internal/httpserve/middleware"
@@ -8,6 +11,11 @@ import (
8 "github.com/labstack/echo/v4"11 "github.com/labstack/echo/v4"
9 )12 )
10 13
14+var (
15+ mainPath = "html/admin"
16+ fragmentsPath = "html/fragments"
17+)
18+
11 // Handle the admin route to display index.gohtml from the templateFS with the data from strings.yml19 // Handle the admin route to display index.gohtml from the templateFS with the data from strings.yml
12 func AdminRoute(c echo.Context, a *app.App) error {20 func AdminRoute(c echo.Context, a *app.App) error {
13 lang := c.Get(middleware.LangKey).(string)21 lang := c.Get(middleware.LangKey).(string)
@@ -18,8 +26,7 @@ func AdminRoute(c echo.Context, a *app.App) error {
18 }26 }
19 27
20 // Navigate inside the fs.FS to get the template28 // Navigate inside the fs.FS to get the template
21- path := "html/admin"29+ rendererData, err := render.GetHTMLRenderer(mainPath, "index.gohtml", a.TemplateFS, a, fragmentsPath)
22- rendererData, err := render.GetHTMLRenderer(path, "index.gohtml", a.TemplateFS, a)
23 if err != nil {30 if err != nil {
24 return err31 return err
25 }32 }
@@ -37,3 +44,31 @@ func AdminRoute(c echo.Context, a *app.App) error {
37 44
38 return c.HTML(200, renderedHTML)45 return c.HTML(200, renderedHTML)
39 }46 }
47+
48+func AdminManagerRoute(c echo.Context, a *app.App) error {
49+ lang := c.Get(middleware.LangKey).(string)
50+ yamlData := webui.StringsYamlData{}
51+ err := webui.ReadStringsDataFromYAML(lang, a.TemplateFS, "strings.yml", &yamlData)
52+ if err != nil {
53+ fmt.Printf("Error reading YAML: %v\n", err)
54+ return echo.NewHTTPError(http.StatusInternalServerError, "Failed to load language data")
55+ }
56+
57+ // Navigate inside the fs.FS to get the template
58+ rendererData, err := render.GetHTMLRenderer(mainPath, "manager.gohtml", a.TemplateFS, a, fragmentsPath)
59+ if err != nil {
60+ return err
61+ }
62+
63+ // Create a data map to pass to the renderer
64+ data := map[string]interface{}{
65+ "CurrentLang": yamlData.CurrentLang,
66+ }
67+
68+ renderedHTML, err := rendererData.Render(data, a)
69+ if err != nil {
70+ return err
71+ }
72+
73+ return c.HTML(200, renderedHTML)
74+}
M internal/httpserve/router.go +6 -2
@@ -41,10 +41,14 @@ func bindStaticRoute(e *echo.Echo, a *app.App, path string) {
4141 })
4242 }
4343
44-func bindAdminRoute(e *echo.Echo, a *app.App, path string) {
45- e.GET(path, func(c echo.Context) error {
44+func bindAdminRoute(e *echo.Echo, a *app.App, adminPath string) {
45+ e.GET(adminPath, func(c echo.Context) error {
4646 return handler.AdminRoute(c, a)
4747 }, middleware.RequireLogin) // Require login
48+
49+ e.GET(adminPath+"/manager", func(c echo.Context) error {
50+ return handler.AdminManagerRoute(c, a)
51+ })
4852 }
4953
5054 func bindLoginRoute(e *echo.Echo, a *app.App, adminPath string) {
@@ -41,10 +41,14 @@ func bindStaticRoute(e *echo.Echo, a *app.App, path string) {
41 })41 })
42 }42 }
43 43
44-func bindAdminRoute(e *echo.Echo, a *app.App, path string) {44+func bindAdminRoute(e *echo.Echo, a *app.App, adminPath string) {
45- e.GET(path, func(c echo.Context) error {45+ e.GET(adminPath, func(c echo.Context) error {
46 return handler.AdminRoute(c, a)46 return handler.AdminRoute(c, a)
47 }, middleware.RequireLogin) // Require login47 }, middleware.RequireLogin) // Require login
48+
49+ e.GET(adminPath+"/manager", func(c echo.Context) error {
50+ return handler.AdminManagerRoute(c, a)
51+ })
48 }52 }
49 53
50 func bindLoginRoute(e *echo.Echo, a *app.App, adminPath string) {54 func bindLoginRoute(e *echo.Echo, a *app.App, adminPath string) {
M pkg/utils/parser/yaml.go +0 -1
@@ -36,7 +36,6 @@ import (
3636 func OpenYamlFile(fs fs.FS, filename string, out interface{}, dir ...string) error {
3737 // Construct the full path of the YAML file
3838 fullPath := filename
39- fmt.Println("Trying to open file at:", fullPath)
4039 if len(dir) > 0 {
4140 fullPath = filepath.Join(dir[0], filename)
4241 }
@@ -36,7 +36,6 @@ import (
36 func OpenYamlFile(fs fs.FS, filename string, out interface{}, dir ...string) error {36 func OpenYamlFile(fs fs.FS, filename string, out interface{}, dir ...string) error {
37 // Construct the full path of the YAML file37 // Construct the full path of the YAML file
38 fullPath := filename38 fullPath := filename
39- fmt.Println("Trying to open file at:", fullPath)
40 if len(dir) > 0 {39 if len(dir) > 0 {
41 fullPath = filepath.Join(dir[0], filename)40 fullPath = filepath.Join(dir[0], filename)
42 }41 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close