feat: save latest summary in session storage to prevent loss of input

This commit is contained in:
wpetit 2025-02-22 15:32:10 +01:00
parent 7f6dd60b89
commit 69df95dabc
4 changed files with 89 additions and 20 deletions

View File

@ -21,7 +21,28 @@ templ FormField(form *form.Form, id string, name string, label string) {
}
}
templ FormTextarea(form *form.Form, id string, name string, label string) {
type FormTextareaOptions struct {
Attrs map[string]any
}
type FormTextareaOptionFunc func(opts *FormTextareaOptions)
func WithTextareaAttrs(kvAttrs ...any) FormTextareaOptionFunc {
return func(opts *FormTextareaOptions) {
opts.Attrs = keyValuesToAttrs(kvAttrs)
}
}
func newFormTextareaOptions(funcs ...FormTextareaOptionFunc) *FormTextareaOptions {
opts := &FormTextareaOptions{}
for _, fn := range funcs {
fn(opts)
}
return opts
}
templ FormTextarea(form *form.Form, id string, name string, label string, funcs ...FormTextareaOptionFunc) {
{{ opts := newFormTextareaOptions(funcs...) }}
{{ field := form.Field(name) }}
if field != nil {
<div class="field">
@ -29,7 +50,7 @@ templ FormTextarea(form *form.Form, id string, name string, label string) {
<div class="control">
{{ err, hasErr := form.Error(name) }}
{{ value, hasValue := field.Get("value") }}
<textarea class={ "textarea", templ.KV("is-danger", hasErr) } id={ id } name={ field.Name() } { field.Attrs()... }>
<textarea class={ "textarea", templ.KV("is-danger", hasErr) } id={ id } name={ field.Name() } { mergeAttrs(field.Attrs(), opts.Attrs)... }>
if hasValue {
{ value.(string) }
}

View File

@ -173,7 +173,27 @@ func FormField(form *form.Form, id string, name string, label string) templ.Comp
})
}
func FormTextarea(form *form.Form, id string, name string, label string) templ.Component {
type FormTextareaOptions struct {
Attrs map[string]any
}
type FormTextareaOptionFunc func(opts *FormTextareaOptions)
func WithTextareaAttrs(kvAttrs ...any) FormTextareaOptionFunc {
return func(opts *FormTextareaOptions) {
opts.Attrs = keyValuesToAttrs(kvAttrs)
}
}
func newFormTextareaOptions(funcs ...FormTextareaOptionFunc) *FormTextareaOptions {
opts := &FormTextareaOptions{}
for _, fn := range funcs {
fn(opts)
}
return opts
}
func FormTextarea(form *form.Form, id string, name string, label string, funcs ...FormTextareaOptionFunc) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -194,6 +214,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
templ_7745c5c3_Var11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
opts := newFormTextareaOptions(funcs...)
field := form.Field(name)
if field != nil {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"field\"><label class=\"label\" for=\"")
@ -203,7 +224,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(id)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 28, Col: 32}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 49, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@ -216,7 +237,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 28, Col: 42}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 49, Col: 42}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@ -253,7 +274,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(id)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 32, Col: 73}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 53, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
@ -266,7 +287,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(field.Name())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 32, Col: 95}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 53, Col: 95}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
@ -276,7 +297,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, field.Attrs())
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, mergeAttrs(field.Attrs(), opts.Attrs))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -288,7 +309,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(value.(string))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 34, Col: 22}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 55, Col: 22}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
@ -307,7 +328,7 @@ func FormTextarea(form *form.Form, id string, name string, label string) templ.C
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(err.Message())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 38, Col: 46}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 59, Col: 46}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
@ -433,7 +454,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(id)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 125, Col: 32}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 146, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
@ -446,7 +467,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 125, Col: 42}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 146, Col: 42}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil {
@ -465,7 +486,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(id)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 130, Col: 20}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 151, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil {
@ -478,7 +499,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(field.Name())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 130, Col: 42}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 151, Col: 42}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
if templ_7745c5c3_Err != nil {
@ -514,7 +535,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(o.Value)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 136, Col: 23}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 157, Col: 23}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
@ -527,7 +548,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(o.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 137, Col: 17}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 158, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {
@ -550,7 +571,7 @@ func FormSelect(form *form.Form, id string, name string, label string, funcs ...
var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(err.Message())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 142, Col: 46}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/common/component/field.templ`, Line: 163, Col: 46}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
if templ_7745c5c3_Err != nil {

View File

@ -80,7 +80,12 @@ templ IssuePage(vmodel IssuePageVModel) {
"hx-push-url", "true",
),
)
@common.FormTextarea(vmodel.SummaryForm, "issue-summary", "summary", "Summary")
@common.FormTextarea(
vmodel.SummaryForm, "issue-summary", "summary", "Summary",
common.WithTextareaAttrs(
"hx-on:change", "onSummaryChange(event)",
),
)
</form>
</div>
<div class="column">
@ -104,6 +109,23 @@ templ IssuePage(vmodel IssuePageVModel) {
</div>
</section>
</div>
<script type="text/javascript">
function onSummaryChange(evt) {
const summary = evt.currentTarget.value;
const projectId = document.getElementById("issue-project").value;
sessionStorage.setItem(`summary-${projectId}`, summary);
}
htmx.onLoad(function(){
const summaryTextarea = document.getElementById("issue-summary");
const summary = summaryTextarea.value;
if (summary !== "") return;
const projectId = document.getElementById("issue-project").value;
if (!projectId) return;
const savedSummary = sessionStorage.getItem(`summary-${projectId}`);
if (!savedSummary) return;
summaryTextarea.value = savedSummary;
})
</script>
}
}

View File

@ -120,7 +120,12 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = common.FormTextarea(vmodel.SummaryForm, "issue-summary", "summary", "Summary").Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = common.FormTextarea(
vmodel.SummaryForm, "issue-summary", "summary", "Summary",
common.WithTextareaAttrs(
"hx-on:change", "onSummaryChange(event)",
),
).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -132,7 +137,7 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></div></section></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></div></section></div><script type=\"text/javascript\">\n\t\tfunction onSummaryChange(evt) {\n\t\t\tconst summary = evt.currentTarget.value;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tsessionStorage.setItem(`summary-${projectId}`, summary);\n\t\t}\n\t\thtmx.onLoad(function(){\n\t\t\tconst summaryTextarea = document.getElementById(\"issue-summary\");\n const summary = summaryTextarea.value;\n\t\t\tif (summary !== \"\") return;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tif (!projectId) return;\n\t\t\tconst savedSummary = sessionStorage.getItem(`summary-${projectId}`);\n\t\t\tif (!savedSummary) return;\n\t\t\tsummaryTextarea.value = savedSummary;\n })\n\t\t</script>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}