15 changed files with 203 additions and 110 deletions
@ -1,19 +1,28 @@ |
|||||
package web |
package web |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"log" |
||||
|
root "marmic/servicetrade-toolbox" |
||||
|
"marmic/servicetrade-toolbox/internal/api" |
||||
"net/http" |
"net/http" |
||||
) |
) |
||||
|
|
||||
func AdminHandler(w http.ResponseWriter, r *http.Request) { |
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{}{ |
data := map[string]interface{}{ |
||||
"Title": "Admin", |
"Title": "Admin Dashboard", |
||||
|
"Session": session, |
||||
} |
} |
||||
|
|
||||
if r.Header.Get("HX-Request") == "true" { |
if err := tmpl.ExecuteTemplate(w, "admin.html", data); err != nil { |
||||
tmpl.ExecuteTemplate(w, "content", data) |
log.Printf("Template execution error: %v", err) |
||||
} else { |
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
||||
tmpl.Execute(w, data) |
return |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,19 +1,28 @@ |
|||||
package web |
package web |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"log" |
||||
|
root "marmic/servicetrade-toolbox" |
||||
|
"marmic/servicetrade-toolbox/internal/api" |
||||
"net/http" |
"net/http" |
||||
) |
) |
||||
|
|
||||
func AssetsHandler(w http.ResponseWriter, r *http.Request) { |
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{}{ |
data := map[string]interface{}{ |
||||
"Title": "Assets", |
"Title": "Admin Dashboard", |
||||
|
"Session": session, |
||||
} |
} |
||||
|
|
||||
if r.Header.Get("HX-Request") == "true" { |
if err := tmpl.ExecuteTemplate(w, "assets.html", data); err != nil { |
||||
tmpl.ExecuteTemplate(w, "content", data) |
log.Printf("Template execution error: %v", err) |
||||
} else { |
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
||||
tmpl.Execute(w, data) |
return |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,19 +1,36 @@ |
|||||
package web |
package web |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"log" |
||||
|
root "marmic/servicetrade-toolbox" |
||||
|
"marmic/servicetrade-toolbox/internal/api" |
||||
"net/http" |
"net/http" |
||||
) |
) |
||||
|
|
||||
func CompaniesHandler(w http.ResponseWriter, r *http.Request) { |
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{}{ |
data := map[string]interface{}{ |
||||
"Title": "Companies", |
"Title": "Companies", |
||||
|
"Session": session, |
||||
|
"View": "company_content", |
||||
} |
} |
||||
|
|
||||
|
var err error |
||||
if r.Header.Get("HX-Request") == "true" { |
if r.Header.Get("HX-Request") == "true" { |
||||
tmpl.ExecuteTemplate(w, "content", data) |
err = tmpl.ExecuteTemplate(w, "companies.html", data) |
||||
} else { |
} 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> |
<!DOCTYPE html> |
||||
<html lang="en"> |
<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 --> |
<head> |
||||
<main class="main-content"> |
<meta charset="UTF-8" /> |
||||
<!-- Header with logout --> |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||
<header class="header"> |
<title>ServiceTrade Tools</title> |
||||
<button class="logout-btn" hx-post="/logout">Logout</button> |
<script src="https://unpkg.com/htmx.org@1.9.6"></script> |
||||
</header> |
<link rel="stylesheet" href="/static/css/styles.css" /> |
||||
|
</head> |
||||
|
|
||||
<!-- Dynamic content area --> |
<body class="flex h-screen bg-gray-100"> |
||||
<div id="content" class="content">{{template "content" .}}</div> |
<!-- Sidebar --> |
||||
</main> |
<aside class="sidebar"> |
||||
</body> |
<h1 class="title">ServiceTrade Tools</h1> |
||||
</html> |
<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> |
<h2>Admin</h2> |
||||
<p>Manage your assets here.</p> |
<p>Manage your assets here.</p> |
||||
<!-- Add asset management content --> |
<!-- Add asset management content --> |
||||
{{end}} |
{{end}} |
||||
@ -1,5 +1,5 @@ |
|||||
{{define "content"}} |
{{define "assets"}} |
||||
<h2>Assets</h2> |
<h2>Assets</h2> |
||||
<p>Manage your assets here.</p> |
<p>Manage your assets here.</p> |
||||
<!-- Add asset management content --> |
<!-- Add asset management content --> |
||||
{{end}} |
{{end}} |
||||
@ -1,5 +1,5 @@ |
|||||
{{define "content"}} |
{{define "companies"}} |
||||
<h2>Companies</h2> |
<h2>Companies</h2> |
||||
<p>Manage your companies here.</p> |
<p>Manage your companies here.</p> |
||||
<!-- Add company management content --> |
<!-- 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