Compare commits

..

No commits in common. "d20573aa99c671aea7b3aa5b728785c0daeaeb9f" and "33277454fa4b0d40a69881f642cbe9bed0a49672" have entirely different histories.

9 changed files with 6 additions and 105 deletions

View File

@ -929,56 +929,3 @@ func handleInvoiceAction(w http.ResponseWriter, r *http.Request, action string,
http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest) http.Error(w, gettext("Invalid action", locale), http.StatusBadRequest)
} }
} }
type tagsForm struct {
Slug string
Tags *TagsField
}
func newTagsForm(slug string, locale *Locale) *tagsForm {
return &tagsForm{
Slug: slug,
Tags: &TagsField{
Name: "tags-" + slug,
Label: pgettext("input", "Tags", locale),
},
}
}
func (form *tagsForm) Parse(r *http.Request) error {
if err := r.ParseForm(); err != nil {
return err
}
form.Tags.FillValue(r)
return nil
}
func ServeEditInvoiceTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
conn := getConn(r)
locale := getLocale(r)
form := newTagsForm(params[0].Value, locale)
if notFoundErrorOrPanic(conn.QueryRow(r.Context(), `select array_to_string(tags, ',') from invoice where slug = $1`, form.Slug).Scan(&form.Tags)) {
http.NotFound(w, r)
return
}
mustRenderStandaloneTemplate(w, r, "tags/edit.gohtml", form)
}
func HandleUpdateInvoiceTags(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
locale := getLocale(r)
conn := getConn(r)
form := newTagsForm(params[0].Value, locale)
if err := form.Parse(r); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := verifyCsrfTokenValid(r); err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
}
slug := conn.MustGetText(r.Context(), "", "update invoice set tags = $1 where slug = $2 returning slug", form.Tags, form.Slug)
if slug == "" {
http.NotFound(w, r)
}
mustRenderStandaloneTemplate(w, r, "tags/view.gohtml", form)
}

View File

@ -31,8 +31,6 @@ func NewRouter(db *Db) http.Handler {
companyRouter.POST("/invoices/:slug", HandleNewInvoiceAction) companyRouter.POST("/invoices/:slug", HandleNewInvoiceAction)
companyRouter.GET("/invoices/:slug/edit", ServeEditInvoice) companyRouter.GET("/invoices/:slug/edit", ServeEditInvoice)
companyRouter.POST("/invoices/:slug/edit", HandleEditInvoiceAction) companyRouter.POST("/invoices/:slug/edit", HandleEditInvoiceAction)
companyRouter.PUT("/invoices/:slug/tags", HandleUpdateInvoiceTags)
companyRouter.GET("/invoices/:slug/tags/edit", ServeEditInvoiceTags)
companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { companyRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
mustRenderMainTemplate(w, r, "dashboard.gohtml", nil) mustRenderMainTemplate(w, r, "dashboard.gohtml", nil)
}) })

View File

@ -57,10 +57,6 @@ func mustRenderTemplate(wr io.Writer, r *http.Request, layout string, filename s
field.Attributes = append(field.Attributes, template.HTMLAttr(attr)) field.Attributes = append(field.Attributes, template.HTMLAttr(attr))
return field return field
}, },
"addTagsAttr": func(attr string, field *TagsField) *TagsField {
field.Attributes = append(field.Attributes, template.HTMLAttr(attr))
return field
},
"boolToInt": func(b bool) int { "boolToInt": func(b bool) int {
if b { if b {
return 1 return 1
@ -119,10 +115,6 @@ func mustRenderMainTemplate(w io.Writer, r *http.Request, filename string, data
} }
} }
func mustRenderStandaloneTemplate(w io.Writer, r *http.Request, filename string, data interface{}) {
mustRenderTemplate(w, r, "standalone.gohtml", filename, data)
}
func mustRenderWebTemplate(w io.Writer, r *http.Request, filename string, data interface{}) { func mustRenderWebTemplate(w io.Writer, r *http.Request, filename string, data interface{}) {
mustRenderTemplate(w, r, "web.gohtml", filename, data) mustRenderTemplate(w, r, "web.gohtml", filename, data)
} }

View File

@ -492,7 +492,7 @@ ul[role="menu"].action-menu li i[class^='ri-'] {
border: none; border: none;
} }
#profile-menu button, td[data-hx-get] { #profile-menu button {
cursor: pointer; cursor: pointer;
} }

View File

@ -73,7 +73,7 @@ class Multiselect extends HTMLDivElement {
} }
window.addEventListener('focusin', this.onFocusOutHandler); window.addEventListener('focusin', this.onFocusOutHandler);
document.addEventListener('click', this.onFocusOutHandler); document.addEventListener('click', this.onFocusOutHandler);
this.rebuild() this.rebuild()
} }
} }
@ -345,10 +345,9 @@ class Tags extends HTMLDivElement {
this.search.addEventListener('keydown', this.onSearchKeydownHandler); this.search.addEventListener('keydown', this.onSearchKeydownHandler);
this.onFocusOutHandler = (e) => { this.onFocusOutHandler = (e) => {
if (this.contains(e.target)) return; if (this.contains(e.target)) return;
if (this.search.value && this.search.value.trim() !== '') { if (e.target.value && e.target.value.trim() !== '') {
this.createTag(); this.createTag();
} }
this.dispatchEvent(new CustomEvent("numerus-tags-out", {bubbles: true}))
}; };
window.addEventListener('focusin', this.onFocusOutHandler); window.addEventListener('focusin', this.onFocusOutHandler);
@ -424,8 +423,7 @@ class Tags extends HTMLDivElement {
button.textContent = '×'; button.textContent = '×';
button.addEventListener('click', (e) => { button.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
this.removeTag(tagText); this.removeTag(tagText)
this.search.focus();
}); });
} }
} }

View File

@ -27,8 +27,7 @@
{{ define "content" }} {{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicesIndexPage*/ -}} {{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.InvoicesIndexPage*/ -}}
<div aria-label="{{( pgettext "Filters" "title" )}}"> <div aria-label="{{( pgettext "Filters" "title" )}}">
<form method="GET" action="{{ companyURI "/invoices"}}" data-hx-target="main" data-hx-boost="true" <form method="GET" action="{{ companyURI "/invoices"}}" data-hx-target="main" data-hx-boost="true" data-hx-trigger="change,search,submit">
data-hx-trigger="change,search,submit">
{{ with .Filters }} {{ with .Filters }}
{{ template "select-field" .Customer }} {{ template "select-field" .Customer }}
{{ template "select-field" .InvoiceStatus }} {{ template "select-field" .InvoiceStatus }}
@ -89,10 +88,7 @@
</form> </form>
</details> </details>
</td> </td>
<td data-hx-get="{{companyURI "/invoices/"}}{{ .Slug }}/tags/edit" <td>
data-hx-target="this"
data-hx-swap="outerHTML"
>
{{- range $index, $tag := .Tags }} {{- range $index, $tag := .Tags }}
{{- if gt $index 0 }}, {{ end -}} {{- if gt $index 0 }}, {{ end -}}
{{ . }} {{ . }}

View File

@ -1 +0,0 @@
{{- template "content" . }}

View File

@ -1,20 +0,0 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.tagsForm*/ -}}
<td data-hx-target="this" data-hx-swap="outerHTML">
<form action="{{companyURI "/invoices/"}}{{ .Slug }}/tags" method="POST"
data-hx-push-url="false" data-hx-boost="true" data-hx-trigger="numerus-tags-out,submit">
{{ csrfToken }}
{{ putMethod }}
{{ template "tags-field" .Tags | addTagsAttr "autofocus" }}
</form>
<script>
(function () {
'use strict';
const edit = document.getElementById('{{.Tags.Name}}-field');
if (edit) {
edit.focus();
}
})();
</script>
</td>
{{- end }}

View File

@ -1,9 +0,0 @@
{{ define "content" }}
{{- /*gotype: dev.tandem.ws/tandem/numerus/pkg.tagsForm*/ -}}
<td data-hx-get="{{companyURI "/invoices/"}}{{ .Slug }}/tags/edit" data-hx-target="this" data-hx-swap="outerHTML">
{{- range $index, $tag := .Tags.Tags }}
{{- if gt $index 0 }}, {{ end -}}
{{ . }}
{{- end }}
</td>
{{- end }}