diff --git a/main.go b/main.go index cf3e351..03a2251 100644 --- a/main.go +++ b/main.go @@ -52,6 +52,7 @@ func setupEcho() *echo.Echo { e.GET("/verify", ui.AmWrap(VerifyEmailForm)) e.POST("/verify", ui.AmWrap(VerifyEMail)) e.GET("/passrecovery/:uid/:auth", ui.AmWrap(PasswordRecovery)) + e.GET("/profile", ui.AmWrap(EditProfileForm)) return e } diff --git a/ui/dialog.go b/ui/dialog.go index 4577401..3104df0 100644 --- a/ui/dialog.go +++ b/ui/dialog.go @@ -218,11 +218,12 @@ func (d *Dialog) RenderInfo(ctxt AmContext, infoMessage string) (string, any, er func (d *Dialog) LoadFromForm(ctxt AmContext) { for i, fld := range d.Fields { d.Fields[i].Value = "" - if fld.Type == "header" || fld.Type == "button" { + switch fld.Type { + case "header": continue - } - if fld.Type == "date" { - d.Fields[i].Value = "" + case "button": + continue + case "date": dvals := make([]int, 3) var err error dvals[0], err = ctxt.FormFieldInt(fmt.Sprintf("%s_month", fld.Name)) @@ -256,7 +257,9 @@ func (d *Dialog) LoadFromForm(ctxt AmContext) { } } d.Fields[i].AuxData = dvals - } else { + case "userphoto": + d.Fields[i].Value = ctxt.FormField(fmt.Sprintf("%s_data", fld.Name)) + default: d.Fields[i].Value = ctxt.FormField(fld.Name) } } @@ -419,8 +422,11 @@ var validators = map[string]validatorFunc{ "header": nilValidator, "hidden": nilValidator, "integer": validateIntegerField, + "localelist": nilValidator, // TODO "password": validateTextField, "text": validateTextField, + "tzlist": nilValidator, // TODO + "userphoto": nilValidator, } /* Validate validates the values in the dialog. diff --git a/ui/dialogs/profile.yaml b/ui/dialogs/profile.yaml new file mode 100644 index 0000000..2425ad6 --- /dev/null +++ b/ui/dialogs/profile.yaml @@ -0,0 +1,200 @@ +# +# Amsterdam Web Communities System +# Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +name: "profile" +formName: "profform" +menuSelector: "nochange" +title: "Edit Your Profile" +action: "/profile" +fields: + - type: "hidden" + name: "tgt" + value: "" + - type: "header" + name: "header1" + caption: "Name" + subcaption: "To change your password, enter a new password into the fields below." + - type: "password" + name: "pass1" + caption: "Password" + required: true + size: 32 + maxlength: 128 + - type: "password" + name: "pass2" + caption: "Password" + subcaption: "(retype)" + required: true + size: 32 + maxlength: 128 + - type: "text" + name: "remind" + caption: "Password reminder phrase" + size: 32 + maxlength: 255 + - type: "header" + name: "header2" + caption: "Name" + - type: "text" + name: "prefix" + caption: "Prefix" + subcaption: "(Mr., Ms., etc.)" + size: 8 + maxlength: 8 + - type: "text" + name: "first" + caption: "First Name" + required: true + size: 32 + maxlength: 64 + - type: "text" + name: "mid" + caption: "Middle Initial" + size: 1 + maxlength: 1 + - type: "text" + name: "last" + caption: "Last Name" + required: true + size: 32 + maxlength: 64 + - type: "text" + name: "suffix" + caption: "Suffix" + subcaption: "(Jr., III, etc.)" + size: 8 + maxlength: 8 + - type: "header" + name: "header3" + caption: "Location" + - type: "text" + name: "company" + caption: "Company" + size: 32 + maxlength: 255 + - type: "text" + name: "addr1" + caption: "Address" + size: 32 + maxlength: 255 + - type: "text" + name: "addr2" + caption: "Address" + subcaption: "(line 2)" + size: 32 + maxlength: 255 + - type: "checkbox" + name: "pvt_addr" + caption: "Hide address in profile" + - type: "text" + name: "loc" + caption: "City" + required: true + size: 32 + maxlength: 64 + - type: "text" + name: "reg" + caption: "State/Province" + required: true + size: 32 + maxlength: 64 + - type: "text" + name: "pcode" + caption: "Zip/Postal Code" + required: true + size: 32 + maxlength: 64 + - type: "countrylist" + name: "country" + caption: "Country" + required: true + - type: "header" + name: "header4" + caption: "Phone Numbers" + - type: "text" + name: "phone" + caption: "Telephone" + size: 32 + maxlength: 32 + - type: "text" + name: "mobile" + caption: "Mobile/cellphone" + size: 32 + maxlength: 32 + - type: "checkbox" + name: "pvt_phone" + caption: "Hide phone/mobile numbers in profile" + - type: "text" + name: "fax" + caption: "Fax" + size: 32 + maxlength: 32 + - type: "checkbox" + name: "pvt_fax" + caption: "Hide fax number in profile" + - type: "header" + name: "header5" + caption: "Internet" + - type: "email" + name: "email" + caption: "E-Mail Address" + required: true + size: 32 + maxlength: 255 + - type: "checkbox" + name: "pvt_email" + caption: "Hide E-mail address in profile" + - type: "text" + name: "url" + caption: "Home Page" + subcaption: "(URL)" + size: 32 + maxlength: 255 + - type: "header" + name: "header6" + caption: "Personal" + - type: "date" + name: "dob" + caption: "Date of Birth" + param: "year:-100" + - type: "text" + name: "descr" + caption: "Personal description" + size: 32 + maxlength: 255 + - type: "userphoto" + name: "photo" + caption: "User Photo" + param: "/profile_photo" + - type: "header" + name: "header7" + caption: "User Preferences" + - type: "checkbox" + name: "pic_in_post" + caption: "Display user photos next to conference posts" + subcaption: "(where applicable)" + - type: "checkbox" + name: "no_mass_mail" + caption: "Don't send me mass E-mail from community/conference hosts" + - type: "localelist" + name: "locale" + caption: "Default locale" + subcaption: "(for formatting dates/times)" + required: true + - type: "tzlist" + name: "tz" + caption: "Default time zone" + required: true + - type: "button" + name: "update" + caption: "Update" + param: "blue" + - type: "button" + name: "cancel" + caption: "Cancel" + param: "red" diff --git a/ui/session_mgr.go b/ui/session_mgr.go index 107bf4c..5da2c02 100644 --- a/ui/session_mgr.go +++ b/ui/session_mgr.go @@ -103,8 +103,6 @@ func (st *AmsterdamStore) New(r *http.Request, name string) (*sessions.Session, * Standard Go error status. */ func (st *AmsterdamStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error { - st.mutex.Lock() - defer st.mutex.Unlock() cookie := sessions.NewCookie(session.Name(), session.ID, session.Options) http.SetCookie(w, cookie) return nil diff --git a/ui/static_images/no-user.png b/ui/static_images/no-user.png new file mode 100644 index 0000000..29921c0 Binary files /dev/null and b/ui/static_images/no-user.png differ diff --git a/ui/views/dialog.jet b/ui/views/dialog.jet index 203f1ea..7da4c24 100644 --- a/ui/views/dialog.jet +++ b/ui/views/dialog.jet @@ -100,7 +100,8 @@
+ value="Y" {{ if .Value != "" }}checked{{ end }} + class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500" />
+ {{ else if .Type == "localelist" }} +
+ + +
+ {{ else if .Type == "tzlist" }} +
+ + +
{{ else if .Type == "date" }} {{ dv := .DateValues() }}
@@ -152,6 +175,16 @@
+ {{ else if .Type == "userphoto" }} +
+ + + + Click to upload photo + +
{{ else if .Type == "header" }}

{{ .Caption }}

{{ else if .Type != "hidden" && .Type != "button" }} diff --git a/ui/views/frame.jet b/ui/views/frame.jet index cc0422b..b7cd537 100644 --- a/ui/views/frame.jet +++ b/ui/views/frame.jet @@ -70,7 +70,7 @@ - Log Out | - Profile + Profile {{ end }} {{ end }} diff --git a/userdata.go b/userdata.go new file mode 100644 index 0000000..0a7096e --- /dev/null +++ b/userdata.go @@ -0,0 +1,43 @@ +/* + * Amsterdam Web Communities System + * Copyright (c) 2025 Erbosoft Metaverse Design Solutions, All Rights Reserved + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +// Package main contains the high-level Amsterdam logic. +package main + +import ( + "errors" + + "git.erbosoft.com/amy/amsterdam/ui" +) + +/* EditProfileForm renders the Amsterdam profile editing form. + * Parameters: + * ctxt - The AmContext for the request. + * Returns: + * Command string dictating what to be rendered. + * Data as a parameter for the command string. + * Standard Go error status. + */ +func EditProfileForm(ctxt ui.AmContext) (string, any, error) { + // Get target URI. + target := ctxt.Parameter("tgt") + if target == "" { + target = "/" + } + u := ctxt.CurrentUser() + if u.IsAnon { + return ui.ErrorPage(ctxt, errors.New("you are not logged in")) + } + dlg, err := ui.AmLoadDialog("profile") + if err == nil { + dlg.Field("tgt").Value = target + // TODO: load fields from current user + return dlg.Render(ctxt) + } + return ui.ErrorPage(ctxt, err) +}