Moved pager to the controller package. Added additional documentation.
This commit is contained in:
parent
1fb4d83e0d
commit
d28f02f8d6
5 changed files with 117 additions and 40 deletions
5
Makefile
5
Makefile
|
|
@ -23,6 +23,11 @@ up:
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|
||||||
|
.PHONY: reset
|
||||||
|
reset:
|
||||||
|
docker-compose down
|
||||||
|
make up
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
clear
|
clear
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// AuthenticatedUserKey is the key value used to store the authenticated user in context
|
||||||
AuthenticatedUserKey = "auth_user"
|
AuthenticatedUserKey = "auth_user"
|
||||||
UserKey = "user"
|
|
||||||
FormKey = "form"
|
// UserKey is the key value used to store a user in context
|
||||||
PasswordTokenKey = "password_token"
|
UserKey = "user"
|
||||||
|
|
||||||
|
// FormKey is the key value used to store a form in context
|
||||||
|
FormKey = "form"
|
||||||
|
|
||||||
|
// PasswordTokenKey is the key value used to store a password token in context
|
||||||
|
PasswordTokenKey = "password_token"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Cache of compiled page templates
|
// templates stores a cache of parsed page templates
|
||||||
templates = sync.Map{}
|
templates = sync.Map{}
|
||||||
|
|
||||||
// Template function map
|
// funcMap stores the Template function map
|
||||||
funcMap = funcmap.GetFuncMap()
|
funcMap = funcmap.GetFuncMap()
|
||||||
|
|
||||||
|
// templatePath stores the complete path to the templates directory
|
||||||
templatePath = getTemplatesDirectoryPath()
|
templatePath = getTemplatesDirectoryPath()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -170,6 +171,7 @@ func (t *Controller) SetValidationErrorMessages(c echo.Context, err error, data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide better error messages depending on the failed validation tag
|
// Provide better error messages depending on the failed validation tag
|
||||||
|
// This should be expanded as you use additional tags in your validation
|
||||||
switch ve.Tag() {
|
switch ve.Tag() {
|
||||||
case "required":
|
case "required":
|
||||||
message = "%s is required."
|
message = "%s is required."
|
||||||
|
|
@ -187,7 +189,7 @@ func (t *Controller) SetValidationErrorMessages(c echo.Context, err error, data
|
||||||
|
|
||||||
// getTemplatesDirectoryPath gets the templates directory path
|
// getTemplatesDirectoryPath gets the templates directory path
|
||||||
// This is needed incase this is called from a package outside of main,
|
// This is needed incase this is called from a package outside of main,
|
||||||
// such as testing
|
// such as within tests
|
||||||
func getTemplatesDirectoryPath() string {
|
func getTemplatesDirectoryPath() string {
|
||||||
_, b, _, _ := runtime.Caller(0)
|
_, b, _, _ := runtime.Caller(0)
|
||||||
d := path.Join(path.Dir(b))
|
d := path.Join(path.Dir(b))
|
||||||
|
|
|
||||||
|
|
@ -7,51 +7,112 @@ import (
|
||||||
|
|
||||||
"goweb/context"
|
"goweb/context"
|
||||||
"goweb/msg"
|
"goweb/msg"
|
||||||
"goweb/pager"
|
|
||||||
|
|
||||||
echomw "github.com/labstack/echo/v4/middleware"
|
echomw "github.com/labstack/echo/v4/middleware"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Page consists of all data that will be used to render a page response for a given controller.
|
||||||
DefaultItemsPerPage = 20
|
// While it's not required for a controller to render a Page on a route, this is the common data
|
||||||
)
|
// object that will be passed to the templates, making it easy for all controllers to share
|
||||||
|
// functionality both on the back and frontend. The Page can be expanded to include anything else
|
||||||
|
// your app wants to support.
|
||||||
|
// Methods on this page also then become available in the templates, which can be more useful than
|
||||||
|
// the funcmap if your methods require data stored in the page, such as the context.
|
||||||
type Page struct {
|
type Page struct {
|
||||||
AppName string
|
// AppName stores the name of the application.
|
||||||
Title string
|
// If omitted, the configuration value will be used.
|
||||||
Context echo.Context
|
AppName string
|
||||||
Reverse func(name string, params ...interface{}) string
|
|
||||||
Path string
|
// Title stores the title of the page
|
||||||
Data interface{}
|
Title string
|
||||||
Layout string
|
|
||||||
Name string
|
// Context stores the request context
|
||||||
IsHome bool
|
Context echo.Context
|
||||||
IsAuth bool
|
|
||||||
|
// ToURL is a function to convert a route name and optional route parameters to a URL
|
||||||
|
ToURL func(name string, params ...interface{}) string
|
||||||
|
|
||||||
|
// Path stores the path of the current request
|
||||||
|
Path string
|
||||||
|
|
||||||
|
// URL stores the URL of the current request
|
||||||
|
URL string
|
||||||
|
|
||||||
|
// Data stores whatever additional data that needs to be passed to the templates.
|
||||||
|
// This is what the controller uses to pass the content of the page.
|
||||||
|
Data interface{}
|
||||||
|
|
||||||
|
// Layout stores the name of the layout base template file which will be used when the page is rendered.
|
||||||
|
// This should match a template file located within the layouts directory inside the templates directory.
|
||||||
|
// The template extension should not be included in this value.
|
||||||
|
Layout string
|
||||||
|
|
||||||
|
// Name stores the name of the page as well as the name of the template file which will be used to render
|
||||||
|
// the content portion of the layout template.
|
||||||
|
// This should match a template file located within the pages directory inside the templates directory.
|
||||||
|
// The template extension should not be included in this value.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// IsHome stores whether the requested page is the home page or not
|
||||||
|
IsHome bool
|
||||||
|
|
||||||
|
// IsAuth stores whether or not the user is authenticated
|
||||||
|
IsAuth bool
|
||||||
|
|
||||||
|
// StatusCode stores the HTTP status code that will be returned
|
||||||
StatusCode int
|
StatusCode int
|
||||||
Metatags struct {
|
|
||||||
|
// Metatags stores metatag values
|
||||||
|
Metatags struct {
|
||||||
|
// Description stores the description metatag value
|
||||||
Description string
|
Description string
|
||||||
Keywords []string
|
|
||||||
|
// Keywords stores the keywords metatag values
|
||||||
|
Keywords []string
|
||||||
}
|
}
|
||||||
Pager pager.Pager
|
|
||||||
CSRF string
|
// Pager stores a pager which can be used to page lists of results
|
||||||
|
Pager Pager
|
||||||
|
|
||||||
|
// CSRF stores the CSRF token for the given request.
|
||||||
|
// This will only be populated if the CSRF middleware is in effect for the given request.
|
||||||
|
// If this is populated, all forms must include this value otherwise the requests will be rejected.
|
||||||
|
CSRF string
|
||||||
|
|
||||||
|
// Headers stores a list of HTTP headers and values to be set on the response
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
Cache struct {
|
|
||||||
Enabled bool
|
// RequestID stores the ID of the given request.
|
||||||
Expiration time.Duration
|
// This will only be populated if the request ID middleware is in effect for the given request.
|
||||||
Tags []string
|
|
||||||
}
|
|
||||||
RequestID string
|
RequestID string
|
||||||
|
|
||||||
|
// Cache stores values for caching the response of this page
|
||||||
|
Cache struct {
|
||||||
|
// Enabled dictates if the response of this page should be cached.
|
||||||
|
// Cached responses are served via middleware.
|
||||||
|
Enabled bool
|
||||||
|
|
||||||
|
// Expiration stores the amount of time that the cache entry should live for before expiring.
|
||||||
|
// If omitted, the configuration value will be used.
|
||||||
|
Expiration time.Duration
|
||||||
|
|
||||||
|
// Tags stores a list of tags to apply to the cache entry.
|
||||||
|
// These are useful when invalidating cache for dynamic events such as entity operations.
|
||||||
|
Tags []string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPage creates and initiatizes a new page for a given request context
|
||||||
func NewPage(c echo.Context) Page {
|
func NewPage(c echo.Context) Page {
|
||||||
p := Page{
|
p := Page{
|
||||||
Context: c,
|
Context: c,
|
||||||
Reverse: c.Echo().Reverse,
|
ToURL: c.Echo().Reverse,
|
||||||
Path: c.Request().URL.Path,
|
Path: c.Request().URL.Path,
|
||||||
|
URL: c.Request().URL.String(),
|
||||||
StatusCode: http.StatusOK,
|
StatusCode: http.StatusOK,
|
||||||
Pager: pager.NewPager(c, DefaultItemsPerPage),
|
Pager: NewPager(c),
|
||||||
Headers: make(map[string]string),
|
Headers: make(map[string]string),
|
||||||
RequestID: c.Response().Header().Get(echo.HeaderXRequestID),
|
RequestID: c.Response().Header().Get(echo.HeaderXRequestID),
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +123,6 @@ func NewPage(c echo.Context) Page {
|
||||||
p.CSRF = csrf.(string)
|
p.CSRF = csrf.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use container?
|
|
||||||
if u := c.Get(context.AuthenticatedUserKey); u != nil {
|
if u := c.Get(context.AuthenticatedUserKey); u != nil {
|
||||||
p.IsAuth = true
|
p.IsAuth = true
|
||||||
}
|
}
|
||||||
|
|
@ -70,10 +130,8 @@ func NewPage(c echo.Context) Page {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Page) SetMessage(typ msg.Type, value string) {
|
// GetMessages gets all flash messages for a given type.
|
||||||
msg.Set(p.Context, typ, value)
|
// This allows for easy access to flash messages from the templates.
|
||||||
}
|
|
||||||
|
|
||||||
func (p Page) GetMessages(typ msg.Type) []template.HTML {
|
func (p Page) GetMessages(typ msg.Type) []template.HTML {
|
||||||
strs := msg.Get(p.Context, typ)
|
strs := msg.Get(p.Context, typ)
|
||||||
ret := make([]template.HTML, len(strs))
|
ret := make([]template.HTML, len(strs))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package pager
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -7,6 +7,11 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultItemsPerPage stores the default amount of items per page
|
||||||
|
DefaultItemsPerPage = 20
|
||||||
|
)
|
||||||
|
|
||||||
type Pager struct {
|
type Pager struct {
|
||||||
Items int
|
Items int
|
||||||
Page int
|
Page int
|
||||||
|
|
@ -14,9 +19,9 @@ type Pager struct {
|
||||||
Pages int
|
Pages int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPager(c echo.Context, itemsPerPage int) Pager {
|
func NewPager(c echo.Context) Pager {
|
||||||
p := Pager{
|
p := Pager{
|
||||||
ItemsPerPage: itemsPerPage,
|
ItemsPerPage: DefaultItemsPerPage,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue