got most of the login functionality together
This commit is contained in:
@@ -32,7 +32,9 @@ type AmContext interface {
|
||||
RC() int
|
||||
OutputType() string
|
||||
Parameter(string) string
|
||||
RemoteIP() string
|
||||
Render(string) error
|
||||
ReplaceUser(*database.User)
|
||||
SubRender(string) ([]byte, error)
|
||||
Session() *sessions.Session
|
||||
SetOutputType(string)
|
||||
@@ -121,6 +123,11 @@ func (c *amContext) Parameter(name string) string {
|
||||
return rc
|
||||
}
|
||||
|
||||
// RemoteIP returns the remote IP address.
|
||||
func (c *amContext) RemoteIP() string {
|
||||
return c.echoContext.RealIP()
|
||||
}
|
||||
|
||||
/* Render renders a template to the output. Called at the top level only.
|
||||
* Parameters:
|
||||
* name = The name of the tempate to be rendered.
|
||||
@@ -131,6 +138,14 @@ func (c *amContext) Render(name string) error {
|
||||
return c.echoContext.Render(c.httprc, name, c)
|
||||
}
|
||||
|
||||
/* ReplaceUser replaces the current user in the context.
|
||||
* Parameters:
|
||||
* u - New user to associate with the context.
|
||||
*/
|
||||
func (c *amContext) ReplaceUser(u *database.User) {
|
||||
c.session.Values["user_id"] = u.Uid
|
||||
}
|
||||
|
||||
// Scratchpad returns the per-request scratchpad for values.
|
||||
func (c *amContext) Scratchpad() map[string]any {
|
||||
if c.scratchpad == nil {
|
||||
|
||||
@@ -124,6 +124,20 @@ func (d *Dialog) Render(ctxt AmContext) (string, any, error) {
|
||||
return "framed_template", "dialog.jet", nil
|
||||
}
|
||||
|
||||
/* RenderError sets up the rendering parameters to send this dialog to the output with an error message.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for this request.
|
||||
* errormessage - The error message to be displayed.
|
||||
* Returns:
|
||||
* Command string dictating what to be rendered.
|
||||
* Data as a parameter for the command string.
|
||||
* Standard Go error status.
|
||||
*/
|
||||
func (d *Dialog) RenderError(ctxt AmContext, errormessage string) (string, any, error) {
|
||||
ctxt.VarMap().Set("amsterdam_errorMessage", errormessage)
|
||||
return d.Render(ctxt)
|
||||
}
|
||||
|
||||
/* LoadFromForm loads the values in a dialog from the form fields in the request.
|
||||
* Parameters:
|
||||
* ctxt - The AmContext for this request.
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"git.erbosoft.com/amy/amsterdam/config"
|
||||
"github.com/CloudyKit/jet/v6"
|
||||
@@ -36,10 +37,13 @@ var static_views embed.FS
|
||||
// views is the main Jet template repository.
|
||||
var views *jet.Set
|
||||
|
||||
// cachedCountryList is the cached country list after sorting.
|
||||
var cachedCountryList []countries.CountryCode = nil
|
||||
|
||||
// countryListMutex control access to internalGetCountryList.
|
||||
var countryListMutex sync.Mutex
|
||||
|
||||
// internalGetCountryList is a wrapper around countries.All() that sorts it by country name.
|
||||
func internalGetCountryList() []countries.CountryCode {
|
||||
countryListMutex.Lock()
|
||||
defer countryListMutex.Unlock()
|
||||
@@ -126,6 +130,21 @@ func makeYearRange(a jet.Arguments) reflect.Value {
|
||||
}
|
||||
}
|
||||
|
||||
/* CapitalizeString changes the first character of trhe string to a capital.
|
||||
* Parameters:
|
||||
* s - The string to be capitalized.
|
||||
* Returns:
|
||||
* The capitalized string.
|
||||
*/
|
||||
func CapitalizeString(s string) string {
|
||||
runes := []rune(s)
|
||||
if len(runes) > 0 {
|
||||
runes[0] = unicode.ToUpper(runes[0])
|
||||
return string(runes)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SetupTemplates is called to set up the template renderer after the configuration is loaded.
|
||||
func SetupTemplates() {
|
||||
views = jet.NewSet(
|
||||
@@ -143,6 +162,11 @@ func SetupTemplates() {
|
||||
views.AddGlobalFunc("MakeIntRange", makeIntRange)
|
||||
views.AddGlobalFunc("MakeYearRange", makeYearRange)
|
||||
|
||||
views.AddGlobalFunc("CapitalizeString", func(a jet.Arguments) reflect.Value {
|
||||
s := a.Get(0).Convert(reflect.TypeFor[string]()).String()
|
||||
return reflect.ValueOf(CapitalizeString(s))
|
||||
})
|
||||
|
||||
// preload the country list in the background
|
||||
go internalGetCountryList()
|
||||
}
|
||||
|
||||
@@ -25,6 +25,20 @@
|
||||
<p class="text-black text-sm mb-6">Required fields are marked with a <span class="text-red-600">*</span>.</p>
|
||||
{{ end }}
|
||||
|
||||
{{ if isset(amsterdam_errorMessage) }}
|
||||
<!-- Error Message Banner -->
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-6 hidden" id="error-banner">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<span class="text-red-500 text-xl">⚠️</span>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="text-sm font-medium" id="error-message">{{ CapitalizeString(amsterdam_errorMessage) }}.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="bg-gray-50 p-6 rounded-lg">
|
||||
<div class="space-y-4">
|
||||
{{ range amsterdam_dialog.Fields }}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
<h1 class="text-blue-800 text-4xl font-bold mb-2">Amsterdam Internal Server Error</h1>
|
||||
<hr class="border-2 border-gray-400 w-4/5 mb-4">
|
||||
<p class="text-black text-sm mb-4">
|
||||
The Amsterdam server encountered an error: {{ error }}
|
||||
The Amsterdam server encountered an error: {{ CapitalizeString(error) }}.
|
||||
</p>
|
||||
<p class="text-black text-sm mb-4">
|
||||
<a href="/">Click here</a> to return to the home page.
|
||||
|
||||
Reference in New Issue
Block a user