From dd24746bcde550cffaf698a0c9c727e869e3cfb3 Mon Sep 17 00:00:00 2001 From: Matthew Lemon Date: Thu, 15 Feb 2024 15:43:04 +0000 Subject: Implemented template cache This is not perfect. At the moment, the new render() function, introduced in this commit, expects a templateData{} struct which contains an Operations field. This will need to be made generic, or we have multiple render() functions to accommdate the different types of data struct we want to be able to pass to templates. Also, in this commit I had to get rid of the /pages/operations and /pages/organisation sub directories for now. This does not fit the newTemplateCache() function - also introduced here. This needs to be refactored if we want to have subdirectories of templates - or else we stick to putting them inside pages/ and we name them appropriately, as we have done here with operations_list and organisation_list templates. --- cmd/web/handlers.go | 23 ++---------- cmd/web/helpers.go | 21 +++++++++++ cmd/web/main.go | 10 +++++ cmd/web/templates.go | 41 ++++++++++++++++++++- ui/html/pages/operations/list.tmpl.html | 58 ----------------------------- ui/html/pages/operations_list.tmpl.html | 59 ++++++++++++++++++++++++++++++ ui/html/pages/organisations/list.tmpl.html | 36 ------------------ ui/html/pages/organisations_list.tmpl.html | 36 ++++++++++++++++++ 8 files changed, 168 insertions(+), 116 deletions(-) delete mode 100644 ui/html/pages/operations/list.tmpl.html create mode 100644 ui/html/pages/operations_list.tmpl.html delete mode 100644 ui/html/pages/organisations/list.tmpl.html create mode 100644 ui/html/pages/organisations_list.tmpl.html diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index 6901661..4d90469 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -34,32 +34,15 @@ func (app *application) listOperations(w http.ResponseWriter, r *http.Request) { } } - files := []string{ - "./ui/html/base.tmpl.html", - "./ui/html/pages/operations/list.tmpl.html", - "./ui/html/partials/nav.tmpl.html", - } - - ts, err := template.ParseFiles(files...) - if err != nil { - app.serverError(w, r, err) // Use the serverError() helper - return - } - - data := operationsTemplateData{ + app.render(w, r, http.StatusOK, "operations_list.tmpl.html", templateData{ Operations: newOps, - } - - err = ts.ExecuteTemplate(w, "base", data) - if err != nil { - app.serverError(w, r, err) // Use the serverError() helper - } + }) } func (app *application) listOrganisations(w http.ResponseWriter, r *http.Request) { files := []string{ "./ui/html/base.tmpl.html", - "./ui/html/pages/organisations/list.tmpl.html", + "./ui/html/pages/organisations_list.tmpl.html", "./ui/html/partials/nav.tmpl.html", } diff --git a/cmd/web/helpers.go b/cmd/web/helpers.go index 5f7e4d3..fc9b8f8 100644 --- a/cmd/web/helpers.go +++ b/cmd/web/helpers.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "net/http" "runtime/debug" @@ -29,3 +30,23 @@ func (app *application) clientError(w http.ResponseWriter, status int) { func (app *application) notFound(w http.ResponseWriter) { app.clientError(w, http.StatusNotFound) } + +func (app *application) render(w http.ResponseWriter, r *http.Request, status int, page string, data templateData) { + // retrieve the appropriate template set from the cache based on the page name. + // If no entry exists in the cache with the provided name, create a new error + // and call serverError() helper that we made earlier and return. + ts, ok := app.templateCache[page] + if !ok { + err := fmt.Errorf("the template %s does not exist", page) + app.serverError(w, r, err) + return + } + + // Write out the provided HTTP status code('200 OK', '400 Bad Request', etc). + w.WriteHeader(status) + + err := ts.ExecuteTemplate(w, "base", data) + if err != nil { + app.serverError(w, r, err) + } +} diff --git a/cmd/web/main.go b/cmd/web/main.go index 7e25124..f0632a5 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -3,6 +3,7 @@ package main import ( "database/sql" "flag" + "html/template" "log/slog" "net/http" "os" @@ -16,6 +17,7 @@ type application struct { operations *models.OperationModel organisations *models.OrganisationModel engagement_strategies *models.EngagementStrategyModel + templateCache map[string]*template.Template } func main() { @@ -34,11 +36,19 @@ func main() { defer db.Close() + // initialise the new template cache... + templateCache, err := newTemplateCache() + if err != nil { + logger.Error(err.Error()) + os.Exit(1) + } + app := &application{ logger: logger, operations: &models.OperationModel{DB: db}, organisations: &models.OrganisationModel{DB: db}, engagement_strategies: &models.EngagementStrategyModel{DB: db}, + templateCache: templateCache, } // mux := http.NewServeMux() diff --git a/cmd/web/templates.go b/cmd/web/templates.go index 86e136d..2457053 100644 --- a/cmd/web/templates.go +++ b/cmd/web/templates.go @@ -1,7 +1,44 @@ package main -import "github.com/yulqen/ded-go-core/internal/models" +import ( + "html/template" + "path/filepath" -type operationsTemplateData struct { + "github.com/yulqen/ded-go-core/internal/models" +) + +type templateData struct { Operations []models.Operation } + +func newTemplateCache() (map[string]*template.Template, error) { + cache := map[string]*template.Template{} + + // get a slice of filepaths match the pattern for our page templates + // e.g. [ui/html/pages/home.tmpl.html ui/html/pages/view.tmpl.html] + pages, err := filepath.Glob("./ui/html/pages/*.html") + if err != nil { + return nil, err + } + + // loop through the page filepaths one by one + for _, page := range pages { + // extract "home.tmp.html" from the full filepath. + name := filepath.Base(page) + + files := []string{ + "./ui/html/base.tmpl.html", + "./ui/html/partials/nav.tmpl.html", + page, + } + + ts, err := template.ParseFiles(files...) + if err != nil { + return nil, err + } + + cache[name] = ts + } + + return cache, nil +} diff --git a/ui/html/pages/operations/list.tmpl.html b/ui/html/pages/operations/list.tmpl.html deleted file mode 100644 index eac3325..0000000 --- a/ui/html/pages/operations/list.tmpl.html +++ /dev/null @@ -1,58 +0,0 @@ -{{ define "title" }}Operations{{end}} - - -{{ define "main" }} -

Operations [Admin]

- -

-Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. -

- -{{if .Operations}} - - - - - - - - - - - - - - - {{range .Operations }} - - - - - - - - - - - {{end}} - -
OperationRPLead Inspector[s]DescriptionOrganisationEPsESsSharePoint
{{.Name}}Tim GudgeonTina McKinchey / Barbara Snelland{{.Description}}{{.OrganisationName}}EP 2024 - {{if .EngagementStrategies}} - - {{else}} - NA - {{end}} - Link
-{{else}} -

There are no operations.

-{{end}} - -{{ end }} - diff --git a/ui/html/pages/operations_list.tmpl.html b/ui/html/pages/operations_list.tmpl.html new file mode 100644 index 0000000..2863d19 --- /dev/null +++ b/ui/html/pages/operations_list.tmpl.html @@ -0,0 +1,59 @@ +{{ define "title" }}Operations{{end}} + + +{{ define "main" }} +

Operations [Admin]

+ +

+Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. +

+ + +{{if .Operations}} + + + + + + + + + + + + + + + {{range .Operations }} + + + + + + + + + + + {{end}} + +
OperationRPLead Inspector[s]DescriptionOrganisationEPsESsSharePoint
{{.Name}}Tim GudgeonTina McKinchey / Barbara Snelland{{.Description}}{{.OrganisationName}}EP 2024 + {{if .EngagementStrategies}} + + {{else}} + NA + {{end}} + Link
+{{else}} +

There are no operations.

+{{end}} + +{{ end }} + diff --git a/ui/html/pages/organisations/list.tmpl.html b/ui/html/pages/organisations/list.tmpl.html deleted file mode 100644 index 1b0e3a9..0000000 --- a/ui/html/pages/organisations/list.tmpl.html +++ /dev/null @@ -1,36 +0,0 @@ -{{ define "title" }}Organisations{{end}} - -{{ define "main" }} -

Organisations [Admin]

-

There is nothing to see here yet.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OrganisationRPLead Inspector[s]Another attributeAnother attributeSharePoint
First organisationTim GudgeonTina McKinchey / Barbara SnellandBobbinsBobbinsLink
Second organisationSeth PringBarbara SnellandBobbinsBobbinsLink
-{{ end }} diff --git a/ui/html/pages/organisations_list.tmpl.html b/ui/html/pages/organisations_list.tmpl.html new file mode 100644 index 0000000..1b0e3a9 --- /dev/null +++ b/ui/html/pages/organisations_list.tmpl.html @@ -0,0 +1,36 @@ +{{ define "title" }}Organisations{{end}} + +{{ define "main" }} +

Organisations [Admin]

+

There is nothing to see here yet.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OrganisationRPLead Inspector[s]Another attributeAnother attributeSharePoint
First organisationTim GudgeonTina McKinchey / Barbara SnellandBobbinsBobbinsLink
Second organisationSeth PringBarbara SnellandBobbinsBobbinsLink
+{{ end }} -- cgit v1.2.3