15 changed files with 203 additions and 110 deletions
@ -1,19 +1,28 @@ |
|||
package web |
|||
|
|||
import ( |
|||
"html/template" |
|||
"log" |
|||
root "marmic/servicetrade-toolbox" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"net/http" |
|||
) |
|||
|
|||
func AdminHandler(w http.ResponseWriter, r *http.Request) { |
|||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/admin.html")) |
|||
session, ok := r.Context().Value("session").(*api.Session) |
|||
if !ok { |
|||
http.Error(w, "Unauthorized", http.StatusUnauthorized) |
|||
return |
|||
} |
|||
|
|||
tmpl := root.WebTemplates |
|||
data := map[string]interface{}{ |
|||
"Title": "Admin", |
|||
"Title": "Admin Dashboard", |
|||
"Session": session, |
|||
} |
|||
|
|||
if r.Header.Get("HX-Request") == "true" { |
|||
tmpl.ExecuteTemplate(w, "content", data) |
|||
} else { |
|||
tmpl.Execute(w, data) |
|||
if err := tmpl.ExecuteTemplate(w, "admin.html", data); err != nil { |
|||
log.Printf("Template execution error: %v", err) |
|||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|||
return |
|||
} |
|||
} |
|||
|
|||
@ -1,19 +1,28 @@ |
|||
package web |
|||
|
|||
import ( |
|||
"html/template" |
|||
"log" |
|||
root "marmic/servicetrade-toolbox" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"net/http" |
|||
) |
|||
|
|||
func AssetsHandler(w http.ResponseWriter, r *http.Request) { |
|||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/assets.html")) |
|||
session, ok := r.Context().Value("session").(*api.Session) |
|||
if !ok { |
|||
http.Error(w, "Unauthorized", http.StatusUnauthorized) |
|||
return |
|||
} |
|||
|
|||
tmpl := root.WebTemplates |
|||
data := map[string]interface{}{ |
|||
"Title": "Assets", |
|||
"Title": "Admin Dashboard", |
|||
"Session": session, |
|||
} |
|||
|
|||
if r.Header.Get("HX-Request") == "true" { |
|||
tmpl.ExecuteTemplate(w, "content", data) |
|||
} else { |
|||
tmpl.Execute(w, data) |
|||
if err := tmpl.ExecuteTemplate(w, "assets.html", data); err != nil { |
|||
log.Printf("Template execution error: %v", err) |
|||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|||
return |
|||
} |
|||
} |
|||
|
|||
@ -1,19 +1,36 @@ |
|||
package web |
|||
|
|||
import ( |
|||
"html/template" |
|||
"log" |
|||
root "marmic/servicetrade-toolbox" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"net/http" |
|||
) |
|||
|
|||
func CompaniesHandler(w http.ResponseWriter, r *http.Request) { |
|||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/companies.html")) |
|||
session, ok := r.Context().Value("session").(*api.Session) |
|||
if !ok { |
|||
http.Error(w, "Unauthorized", http.StatusUnauthorized) |
|||
return |
|||
} |
|||
|
|||
tmpl := root.WebTemplates |
|||
data := map[string]interface{}{ |
|||
"Title": "Companies", |
|||
"Title": "Companies", |
|||
"Session": session, |
|||
"View": "company_content", |
|||
} |
|||
|
|||
var err error |
|||
if r.Header.Get("HX-Request") == "true" { |
|||
tmpl.ExecuteTemplate(w, "content", data) |
|||
err = tmpl.ExecuteTemplate(w, "companies.html", data) |
|||
} else { |
|||
tmpl.Execute(w, data) |
|||
err = tmpl.Execute(w, data) |
|||
} |
|||
|
|||
if err != nil { |
|||
log.Printf("Template execution error: %v", err) |
|||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|||
return |
|||
} |
|||
} |
|||
|
|||
@ -1,46 +1,49 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>ServiceTrade Tools</title> |
|||
<script src="https://unpkg.com/htmx.org@1.9.6"></script> |
|||
<link rel="stylesheet" href="/static/css/styles.css" /> |
|||
</head> |
|||
<body class="flex h-screen bg-gray-100"> |
|||
<!-- Sidebar --> |
|||
<aside class="sidebar"> |
|||
<h1 class="title">ServiceTrade Tools</h1> |
|||
<nav> |
|||
<ul> |
|||
<li><a href="/" hx-get="/" hx-target="#content">Dashboard</a></li> |
|||
<li><a href="/jobs" hx-get="/jobs" hx-target="#content">Jobs</a></li> |
|||
<li><a href="/assets" hx-get="/assets" hx-target="#content">Assets</a></li> |
|||
<li><a href="/companies" hx-get="/companies" hx-target="#content">Companies</a></li> |
|||
<li><a href="/contacts" hx-get="/contacts" hx-target="#content">Contacts</a></li> |
|||
<li><a href="/contracts" hx-get="/contracts" hx-target="#content">Contracts</a></li> |
|||
<li><a href="/generic" hx-get="/generic" hx-target="#content">Generic Tools</a></li> |
|||
<li><a href="/invoices" hx-get="/invoices" hx-target="#content">Invoices</a></li> |
|||
<li><a href="/locations" hx-get="/locations" hx-target="#content">Locations</a></li> |
|||
<li><a href="/notifications" hx-get="/notifications" hx-target="#content">Notifications</a></li> |
|||
<li><a href="/quotes" hx-get="/quotes" hx-target="#content">Quotes</a></li> |
|||
<li><a href="/services" hx-get="/services" hx-target="#content">Services</a></li> |
|||
<li><a href="/tags" hx-get="/tags" hx-target="#content">Tags</a></li> |
|||
<li><a href="/users" hx-get="/users" hx-target="#content">Users</a></li> |
|||
<li><a href="/admin" hx-get="/admin" hx-target="#content">Admin</a></li> |
|||
</ul> |
|||
</nav> |
|||
</aside> |
|||
|
|||
<!-- Main content area --> |
|||
<main class="main-content"> |
|||
<!-- Header with logout --> |
|||
<header class="header"> |
|||
<button class="logout-btn" hx-post="/logout">Logout</button> |
|||
</header> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>ServiceTrade Tools</title> |
|||
<script src="https://unpkg.com/htmx.org@1.9.6"></script> |
|||
<link rel="stylesheet" href="/static/css/styles.css" /> |
|||
</head> |
|||
|
|||
<!-- Dynamic content area --> |
|||
<div id="content" class="content">{{template "content" .}}</div> |
|||
</main> |
|||
</body> |
|||
</html> |
|||
<body class="flex h-screen bg-gray-100"> |
|||
<!-- Sidebar --> |
|||
<aside class="sidebar"> |
|||
<h1 class="title">ServiceTrade Tools</h1> |
|||
<nav> |
|||
<ul> |
|||
<li><a href="/" hx-get="/" hx-target="#content">Dashboard</a></li> |
|||
<li><a href="/jobs" hx-get="/jobs" hx-target="#content">Jobs</a></li> |
|||
<li><a href="/assets" hx-get="/assets" hx-target="#content">Assets</a></li> |
|||
<li><a href="/companies" hx-get="/companies" hx-target="#content">Companies</a></li> |
|||
<li><a href="/contacts" hx-get="/contacts" hx-target="#content">Contacts</a></li> |
|||
<li><a href="/contracts" hx-get="/contracts" hx-target="#content">Contracts</a></li> |
|||
<li><a href="/generic" hx-get="/generic" hx-target="#content">Generic Tools</a></li> |
|||
<li><a href="/invoices" hx-get="/invoices" hx-target="#content">Invoices</a></li> |
|||
<li><a href="/locations" hx-get="/locations" hx-target="#content">Locations</a></li> |
|||
<li><a href="/notifications" hx-get="/notifications" hx-target="#content">Notifications</a></li> |
|||
<li><a href="/quotes" hx-get="/quotes" hx-target="#content">Quotes</a></li> |
|||
<li><a href="/services" hx-get="/services" hx-target="#content">Services</a></li> |
|||
<li><a href="/tags" hx-get="/tags" hx-target="#content">Tags</a></li> |
|||
<li><a href="/users" hx-get="/users" hx-target="#content">Users</a></li> |
|||
<li><a href="/admin" hx-get="/admin" hx-target="#content">Admin</a></li> |
|||
</ul> |
|||
</nav> |
|||
</aside> |
|||
|
|||
<!-- Main content area --> |
|||
<main class="main-content"> |
|||
<!-- Header with logout --> |
|||
<header class="header"> |
|||
<button class="logout-btn" hx-post="/logout">Logout</button> |
|||
</header> |
|||
|
|||
<!-- Dynamic content area --> |
|||
<div id="content" class="content">{{template "content" .}}</div> |
|||
</main> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -1,5 +1,5 @@ |
|||
{{define "content"}} |
|||
{{define "admin"}} |
|||
<h2>Admin</h2> |
|||
<p>Manage your assets here.</p> |
|||
<!-- Add asset management content --> |
|||
{{end}} |
|||
{{end}} |
|||
@ -1,5 +1,5 @@ |
|||
{{define "content"}} |
|||
{{define "assets"}} |
|||
<h2>Assets</h2> |
|||
<p>Manage your assets here.</p> |
|||
<!-- Add asset management content --> |
|||
{{end}} |
|||
{{end}} |
|||
@ -1,5 +1,5 @@ |
|||
{{define "content"}} |
|||
{{define "companies"}} |
|||
<h2>Companies</h2> |
|||
<p>Manage your companies here.</p> |
|||
<!-- Add company management content --> |
|||
{{end}} |
|||
{{end}} |
|||
@ -0,0 +1,55 @@ |
|||
package root |
|||
|
|||
import ( |
|||
"embed" |
|||
"html/template" |
|||
"io/fs" |
|||
"log" |
|||
"path/filepath" |
|||
) |
|||
|
|||
//go:embed templates
|
|||
var webTemplateFS embed.FS |
|||
|
|||
var WebTemplates *template.Template |
|||
|
|||
// InitializeWebTemplates parses all HTML templates in the embedded filesystem
|
|||
func InitializeWebTemplates() error { |
|||
var err error |
|||
WebTemplates, err = parseWebTemplates() |
|||
return err |
|||
} |
|||
|
|||
func parseWebTemplates() (*template.Template, error) { |
|||
tmpl := template.New("") |
|||
|
|||
err := fs.WalkDir(webTemplateFS, "templates", func(path string, d fs.DirEntry, err error) error { |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
if d.IsDir() { |
|||
return nil |
|||
} |
|||
|
|||
if filepath.Ext(path) != ".html" { |
|||
return nil |
|||
} |
|||
|
|||
log.Printf("Parsing template: %s", path) |
|||
|
|||
content, err := webTemplateFS.ReadFile(path) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
_, err = tmpl.New(filepath.Base(path)).Parse(string(content)) |
|||
return err |
|||
}) |
|||
|
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return tmpl, nil |
|||
} |
|||
Loading…
Reference in new issue