summaryrefslogtreecommitdiffci
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
-rw-r--r--internal/mailer/mailer.go76
-rw-r--r--internal/router/api-v1-general-page-body.go83
-rw-r--r--internal/router/api-v1-subs.go67
-rw-r--r--locale/localization.en.yaml10
-rw-r--r--locale/localization.go10
-rw-r--r--locale/localization.ru.yaml10
-rw-r--r--main.go1
-rw-r--r--static/input.css4
-rw-r--r--views/pages/user-page.html117
9 files changed, 34 insertions, 344 deletions
diff --git a/internal/mailer/mailer.go b/internal/mailer/mailer.go
index cd5eda8..450b818 100644
--- a/internal/mailer/mailer.go
+++ b/internal/mailer/mailer.go
@@ -43,14 +43,6 @@ type Mailer struct {
l map[string]*locale.LocaleConfig
}
-type SubscriptionType int
-
-const (
- All SubscriptionType = iota
- None
- Specific
-)
-
func NewMailer(db *sql.DB, clientHost string, mailHost string, publicName string, mailAddress string, username string, password string, salt []byte, localization map[string]*locale.LocaleConfig) (*Mailer, error) {
verificationCodes, err := ristretto.NewCache(&ristretto.Config[uint64, string]{
NumCounters: 10000,
@@ -287,71 +279,3 @@ func (m *Mailer) Verify(verificationCodeEncoded string, lang string) error {
delete(m.lostMailMap, verificationSegments[0])
return nil
}
-
-func (m *Mailer) GetSubscriptions(userId string) (subscriptionType SubscriptionType, tags []string, err error) {
- tx, err := m.db.Begin()
- if err != nil {
- return None, nil, fmt.Errorf("failed to initialize transaction with db: %s", err)
- }
-
- hash := m.GetHash(userId)
-
- var rows *sql.Rows
- if rows, err = tx.Query(`SELECT tags FROM subscription_user_to_tags_table WHERE user_id=? LIMIT 1;`, hash); err != nil {
- tx.Rollback()
- return None, nil, fmt.Errorf("failed to query user-to-tags table in db for the user: %s", err)
- }
- defer tx.Commit()
- defer rows.Close()
-
- if !rows.Next() {
- return None, nil, nil
- }
-
- tagsString := ""
- if err = rows.Scan(&tagsString); err != nil {
- return None, nil, fmt.Errorf("failed to scan the result from user-to-tags query: %s", err)
- }
-
- switch tagsString {
- case "":
- return None, nil, nil
- case "_all":
- return All, nil, nil
- default:
- return Specific, strings.Split(tagsString, ","), nil
- }
-}
-
-func (m *Mailer) Subscribe(userId string, subscriptionType SubscriptionType, tags ...string) error {
- tx, err := m.db.Begin()
- if err != nil {
- return fmt.Errorf("failed to initialize transaction with db: %s", err)
- }
-
- tagsOutput := ""
- switch subscriptionType {
- case All:
- tagsOutput = "_all"
- case None:
- tagsOutput = ""
- case Specific:
- tagsOutput = strings.Join(tags, ",")
- }
-
- hash := m.GetHash(userId)
-
- if _, err = tx.Exec(`INSERT INTO subscription_user_to_tags_table(user_id, tags) VALUES(?, ?)
- ON CONFLICT(user_id) DO UPDATE SET
- tags=excluded.tags;`, hash, tagsOutput); err != nil {
- tx.Rollback()
- return fmt.Errorf("failed to configure user-to-tags table in db for the user: %s", err)
- }
-
- if err = tx.Commit(); err != nil {
- tx.Rollback()
- return fmt.Errorf("failed to commit transaction to db: %s", err)
- }
-
- return nil
-}
diff --git a/internal/router/api-v1-general-page-body.go b/internal/router/api-v1-general-page-body.go
index 66f1234..6f856d3 100644
--- a/internal/router/api-v1-general-page-body.go
+++ b/internal/router/api-v1-general-page-body.go
@@ -95,12 +95,33 @@ func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []config.A
queryTags = append(queryTags, string(match[1]))
}
- tagsArray, err := getTags(b2Client, lang)
+ pages, err := b2Client.Scan(lang + "/")
if err != nil {
- slog.Warn("failed to get the available tags", slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to gather available tags")
+ slog.Warn("failed to scan pages via b2", slog.String("error", err.Error()))
+ return c.Status(fiber.ErrInternalServerError.Code).SendString(fmt.Sprintf("failed to scan pages via b2: %s", slog.String("error", err.Error())))
}
+ tagsMap := make(map[string]int)
+ for _, page := range pages {
+ for _, tag := range page.Metadata.Tags {
+ tagsMap[tag]++
+ }
+ }
+ slog.Debug("enlist pages for catalogue", slog.Int("tag_count", len(tagsMap)), slog.Int("page_count", len(pages)), slog.String("path", c.Path()))
+
+ type Tag struct {
+ Name string `json:"Name" yaml:"name"`
+ Count int `json:"Count" yaml:"count"`
+ }
+
+ tagsArray := make([]Tag, 0, len(tagsMap))
+ for tag, count := range tagsMap {
+ tagsArray = append(tagsArray, Tag{tag, count})
+ }
+ slices.SortFunc(tagsArray, func(a Tag, b Tag) int {
+ return strings.Compare(a.Name, b.Name)
+ })
+
values["Tags"] = tagsArray
values["QuerySort"] = querySort
values["QueryTags"] = strings.Join(queryTags, ",")
@@ -114,33 +135,8 @@ func Api_V1_GeneralPage_Body(l map[string]*locale.LocaleConfig, langs []config.A
if err != nil {
slog.Error("get info from mailer about a client", slog.String("error", err.Error()))
}
-
- tagsArray, err := getTags(b2Client, lang)
- if err != nil {
- slog.Warn("failed to get the available tags", slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to gather available tags")
- }
-
- subscriptionType, tags, err := Mailer.GetSubscriptions(c.IP())
- if err != nil {
- slog.Warn("failed to get the user subscriptions", slog.String("error", err.Error()))
- return c.Status(fiber.ErrInternalServerError.Code).SendString("failed to get the user subscriptions")
- }
-
- switch subscriptionType {
- case mailer.None:
- values["TagsPicked"] = "none"
- case mailer.All:
- values["TagsPicked"] = "all"
- case mailer.Specific:
- values["TagsPicked"] = "specific"
- }
-
- values["TagsPickedList"] = tags
-
values["Email"] = email
values["EmailCode"] = c.Query("email_code")
- values["ExistingTags"] = tagsArray
additionalTemplates = append(additionalTemplates, "views/pages/user-page.html")
} else if len(pathParts) == 3 && pathParts[1] == "blog" {
@@ -208,34 +204,3 @@ func readBlogPost(md goldmark.Markdown, b2Client *b2.B2Client, sourceName string
return metadata, buf.String(), nil
}
-
-type Tag struct {
- Name string `json:"Name" yaml:"name"`
- Count int `json:"Count" yaml:"count"`
-}
-
-func getTags(b2Client *b2.B2Client, lang string) (tags []Tag, err error) {
- pages, err := b2Client.Scan(lang + "/")
- if err != nil {
- slog.Warn("failed to scan pages via b2", slog.String("error", err.Error()))
- return nil, fmt.Errorf("failed to scan pages via b2: %w", err)
- }
-
- tagsMap := make(map[string]int)
- for _, page := range pages {
- for _, tag := range page.Metadata.Tags {
- tagsMap[tag]++
- }
- }
- slog.Debug("enlist pages for catalogue", slog.Int("tag_count", len(tagsMap)), slog.Int("page_count", len(pages)), slog.String("lang", lang))
-
- tagsArray := make([]Tag, 0, len(tagsMap))
- for tag, count := range tagsMap {
- tagsArray = append(tagsArray, Tag{tag, count})
- }
- slices.SortFunc(tagsArray, func(a Tag, b Tag) int {
- return strings.Compare(a.Name, b.Name)
- })
-
- return tagsArray, nil
-}
diff --git a/internal/router/api-v1-subs.go b/internal/router/api-v1-subs.go
deleted file mode 100644
index 8995ebe..0000000
--- a/internal/router/api-v1-subs.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package router
-
-import (
- "net/url"
- "strings"
-
- "github.com/SayaAndy/saya-today-web/internal/mailer"
- "github.com/SayaAndy/saya-today-web/locale"
- "github.com/gofiber/fiber/v2"
-)
-
-func init() {
- assert(0, tm.Add("personal-page-status", "views/partials/personal-page-status.html"))
-}
-
-func Api_V1_Subs_Put(l map[string]*locale.LocaleConfig) func(c *fiber.Ctx) error {
- return func(c *fiber.Ctx) error {
- c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
-
- id := c.IP()
- lang := "en"
-
- var referer, path string
- var pathParts []string
- var urlStruct *url.URL
- var err error
-
- referer = c.Get("Referer", "")
- if referer == "" {
- goto skipFetchingLang
- }
-
- urlStruct, err = url.ParseRequestURI(referer)
- if err != nil {
- goto skipFetchingLang
- }
-
- path = urlStruct.EscapedPath()
- pathParts = strings.Split(strings.Trim(path, "/"), "/")
- if len(pathParts) == 0 {
- goto skipFetchingLang
- }
-
- lang = pathParts[0]
-
- skipFetchingLang:
- subscriptionType := c.FormValue("tags")
- var subscriptionTypeEnum mailer.SubscriptionType
- switch subscriptionType {
- case "all":
- subscriptionTypeEnum = mailer.All
- case "none":
- subscriptionTypeEnum = mailer.None
- case "specific":
- subscriptionTypeEnum = mailer.Specific
- default:
- return api_v1_email_sendStatusHtml(c, "subs-message", l, "Failed", fiber.StatusUnprocessableEntity, lang, l[lang].UserProfile.SubscribeInvalidType, map[string]string{})
- }
-
- specificTags := c.FormValue("tags_picked")
- if err = Mailer.Subscribe(id, subscriptionTypeEnum, specificTags); err != nil {
- return api_v1_email_sendStatusHtml(c, "subs-message", l, "Failed", fiber.StatusUnprocessableEntity, lang, l[lang].UserProfile.FailedToSubscribe, map[string]string{})
- }
-
- return api_v1_email_sendStatusHtml(c, "subs-message", l, "OK", fiber.StatusOK, lang, l[lang].UserProfile.SubscribedSuccessfully, map[string]string{})
- }
-}
diff --git a/locale/localization.en.yaml b/locale/localization.en.yaml
index 8816f2e..49d21ee 100644
--- a/locale/localization.en.yaml
+++ b/locale/localization.en.yaml
@@ -52,13 +52,3 @@ UserProfile:
VerificationSuccess: 'Success! You are now able to subscribe with your new e-mail.'
VerificationFailed: 'Verification code is invalid, please ask administrator for a more detailed cause.'
VerificationEmpty: 'Verification code is unset or empty.'
- SubscriptionHeader: 'Subscribe to...'
- TagsNone: 'None'
- TagsAll: 'All'
- TagsSpecific: 'Specific'
- TagDoesNotExist: 'The tag "{}" does not exist on the site.'
- TagAlreadyAdded: 'The tag "{}" is already in your subscribed list.'
- SaveButton: 'Save'
- SubscribeInvalidType: 'Invalid subscription type.'
- FailedToSubscribe: 'Failed to subscribe by new settings, please ask administrator for a more detailed cause.'
- SubscribedSuccessfully: 'Successfully subscribed you by new settings!'
diff --git a/locale/localization.go b/locale/localization.go
index cd83aa1..9022b50 100644
--- a/locale/localization.go
+++ b/locale/localization.go
@@ -86,16 +86,6 @@ type UserProfileConfig struct {
VerificationSuccess string `yaml:"VerificationSuccess" json:"VerificationSuccess"`
VerificationFailed string `yaml:"VerificationFailed" json:"VerificationFailed"`
VerificationEmpty string `yaml:"VerificationEmpty" json:"VerificationEmpty"`
- SubscriptionHeader string `yaml:"SubscriptionHeader" json:"SubscriptionHeader"`
- TagsNone string `yaml:"TagsNone" json:"TagsNone"`
- TagsAll string `yaml:"TagsAll" json:"TagsAll"`
- TagsSpecific string `yaml:"TagsSpecific" json:"TagsSpecific"`
- TagDoesNotExist string `yaml:"TagDoesNotExist" json:"TagDoesNotExist"`
- TagAlreadyAdded string `yaml:"TagAlreadyAdded" json:"TagAlreadyAdded"`
- SaveButton string `yaml:"SaveButton" json:"SaveButton"`
- SubscribeInvalidType string `yaml:"SubscribeInvalidType" json:"SubscribeInvalidType"`
- FailedToSubscribe string `yaml:"FailedToSubscribe" json:"FailedToSubscribe"`
- SubscribedSuccessfully string `yaml:"SubscribedSuccessfully" json:"SubscribedSuccessfully"`
}
func LoadConfig(path string, config *LocaleConfig) error {
diff --git a/locale/localization.ru.yaml b/locale/localization.ru.yaml
index 8a0ec5e..fe6d55f 100644
--- a/locale/localization.ru.yaml
+++ b/locale/localization.ru.yaml
@@ -52,13 +52,3 @@ UserProfile:
VerificationSuccess: 'Поздравляем! Теперь по этой почте можно подписаться на блог.'
VerificationFailed: 'Код для верификации невалиден, при вопросах, пожалуйста, обращайтесь к администратору.'
VerificationEmpty: 'Код для верификации не введён.'
- SubscriptionHeader: 'Подписаться на...'
- TagsNone: 'Ничего'
- TagsAll: 'Всё'
- TagsSpecific: 'Определённое'
- TagDoesNotExist: 'Тэга "{}" нет на сайте.'
- TagAlreadyAdded: 'Тэг "{}" уже у вас добавлен.'
- SaveButton: 'Сохранить'
- SubscribeInvalidType: 'Неизвестный тип подписки.'
- FailedToSubscribe: 'Неудачная попытка записать новую подписку, более подробно спрашивайте у администратора.'
- SubscribedSuccessfully: 'Вы успешно подписались по новым настройкам!'
diff --git a/main.go b/main.go
index 5a14bc6..2d9dafd 100644
--- a/main.go
+++ b/main.go
@@ -171,7 +171,6 @@ func main() {
app.Post("/api/v1/email/send-verification-code", router.Api_V1_Email_SendVerificationCode(localization))
app.Post("/api/v1/email/verify", router.Api_V1_Email_Verify(localization))
app.Get("/api/v1/email/is-in-verification", router.Api_V1_Email_IsInVerification(localization))
- app.Put("/api/v1/subs", router.Api_V1_Subs_Put(localization))
app.Static("/", "./static")
diff --git a/static/input.css b/static/input.css
index c3c10fd..cc88959 100644
--- a/static/input.css
+++ b/static/input.css
@@ -180,8 +180,8 @@ a:hover, .linklike:hover {
text-decoration: underline;
}
-.disabled::before,
-.htmx-request::before {
+form.disabled::before,
+form.htmx-request::before {
content: '';
position: absolute;
top: 0;
diff --git a/views/pages/user-page.html b/views/pages/user-page.html
index 6fab0ad..1632670 100644
--- a/views/pages/user-page.html
+++ b/views/pages/user-page.html
@@ -1,9 +1,9 @@
{{ define "body" }}
-<div class="bg-background-light flex flex-col inset-shadow-[0_0_0.4rem_black] px-8 py-4">
+<div class="bg-background-light flex flex-col inset-shadow-[0_0_0.4rem_black] px-8 py-4 overflow-y-auto">
<form id="email-form" class="w-full mb-2 flex flex-col relative"
hx-get="/api/v1/email/is-in-verification" hx-target="#email-message" hx-swap="outerHTML" hx-trigger="load" hx-indicator="this">
<div class="flex flex-row w-full mb-4 z-21">
- <div class="flex flex-col w-full sm:flex-3/5 grow-0">
+ <div class="flex flex-col flex-3/5 grow-0">
<label class="block text-main-medium font-bold mb-1 z-22">
{{ .L.UserProfile.EmailHeader }}
</label>
@@ -12,78 +12,30 @@
data-validated-email="{{ .Email }}" onchange="checkIfValidated(this);">
</div>
</div>
- <button class="w-max mx-auto bg-(--main-hard-color) hover:bg-(--main-medium-color) active:bg-(--main-soft-color) active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-(--background-light-color) font-bold py-2 px-4 rounded z-22"
+ <button class="w-1/3 mx-auto bg-(--main-hard-color) hover:bg-(--main-medium-color) active:bg-(--main-soft-color) active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-(--background-light-color) font-bold py-2 px-4 rounded z-22"
hx-post="/api/v1/email/send-verification-code" hx-target="#email-message" hx-swap="outerHTML" hx-indicator="#email-form">
{{ .L.UserProfile.SendCodeButton }}
</button>
</form>
- <div id="email-message" class="bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
-
+ <div id="email-message"></div>
<hr class="my-2 border-t-4 border-dotted border-main-hard">
-
<form id="email-verification-form" class="w-full mb-2 flex flex-col relative hidden"
{{ if .EmailCode }}hx-post="/api/v1/email/verify" hx-target="#verification-message" hx-swap="outerHTML" hx-trigger="load" hx-indicator="this"{{ end }}>
<div class="flex flex-row w-full mb-4 z-21">
- <div class="flex flex-col w-full sm:flex-2/5 grow-0">
+ <div class="flex flex-col flex-2/5 grow-0">
<label class="block text-main-medium font-bold ml-1 z-22">
{{ .L.UserProfile.VerificationCodeHeader }}
</label>
<input class="bg-(--background-medium-color) appearance-none border-(--background-medium-color) rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-(--background-light-color) focus:text-main-hard z-22"
- name="email_code" type="text" value="{{ .EmailCode }}" placeholder="0123456789ABCDEF" maxlength="16" autocapitalize="characters">
+ name="email_code" type="text" value="{{ .EmailCode }}" placeholder="0123456789ABCDEF" maxlength="16">
</div>
</div>
- <button class="w-max mx-auto bg-(--main-hard-color) hover:bg-(--main-medium-color) active:bg-(--main-soft-color) active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-(--background-light-color) font-bold py-2 px-4 rounded z-22"
+ <button class="w-1/3 mx-auto bg-(--main-hard-color) hover:bg-(--main-medium-color) active:bg-(--main-soft-color) active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-(--background-light-color) font-bold py-2 px-4 rounded z-22"
hx-post="/api/v1/email/verify" hx-target="#verification-message" hx-swap="outerHTML" hx-indicator="#email-verification-form">
{{ .L.UserProfile.VerifyButton }}
</button>
</form>
- <div id="verification-message" class="bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
-</div>
-
-<hr class="my-4 border-t-4 border-dotted border-main-hard">
-
-<div class="bg-background-light flex flex-col inset-shadow-[0_0_0.4rem_black] px-8 py-4">
- <form id="subs-form" class="w-full mb-2 flex flex-col relative">
- <div class="flex flex-col w-full mb-4 z-21">
- <label class="block text-main-medium font-bold mb-1 z-22">
- {{ .L.UserProfile.SubscriptionHeader }}
- </label>
- <div class="flex flex-col sm:flex-row w-full">
- <div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsNone" name="tags" value="none" {{ if eq .TagsPicked "none" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsNone }}</label>
- </div>
- <div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsAll" name="tags" value="all" {{ if eq .TagsPicked "all" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsAll }}</label>
- </div>
- <div class="m-1 w-1/3">
- <label><input class="mr-1" type="radio" id="tagsSpecific" name="tags" value="specific" {{ if eq .TagsPicked "specific" }}checked{{ end }} onclick="toggleTagsPick(this);">{{ .L.UserProfile.TagsSpecific }}</label>
- </div>
- </div>
- <div id="pick-tags-form" class="flex flex-col w-full relative">
- <input type="text" class="bg-(--background-medium-color) appearance-none border-(--background-medium-color) rounded ml-6 mr-4 py-2 px-4 text-main-medium leading-tight inset-shadow-[0_0_0.4rem_black] focus:outline-none focus:bg-(--background-light-color) focus:text-main-hard z-22"
- list="existing-tags" onchange="addTag(this.value);" onkeydown="if (event.keyCode === 13) {addTag(this.value); this.value=''; return false;}">
- <datalist id="existing-tags">
- {{- range .ExistingTags }}
- <option value="{{ .Name }}">
- {{- end }}
- </datalist>
- <div id="tags-picked-list" class="bg-background-dark flex flex-wrap inset-shadow-[0_0_0.4rem_black] p-2 m-4 w-full">
- {{- range .TagsPickedList }}
- <div id="tagPicked{{ . }}" class="bg-main-hard text-background-light m-2 flex flex-row">
- <p class="py-1 px-2">{{ . }}</p>
- <p class="py-1 px-2 bg-main-soft cursor-pointer" onclick="htmx.remove(htmx.find('#tagPicked{{ . }}'));">✘</p>
- <input type="hidden" name="tags_picked" value="{{ . }}">
- </div>
- {{- end }}
- </div>
- </div>
- <button class="w-max mx-auto bg-(--main-hard-color) hover:bg-(--main-medium-color) active:bg-(--main-soft-color) active:inset-shadow-[0.2em_0.2em_0.2rem_black] transition-colors transition-300 text-(--background-light-color) font-bold py-2 px-4 rounded z-22"
- hx-put="/api/v1/subs" hx-target="#subs-message" hx-swap="outerHTML" hx-indicator="#subs-form">
- {{ .L.UserProfile.SaveButton }}
- </button>
- </div>
- </form>
- <div id="subs-message" class="bg-background-dark text-main-soft z-26 w-full inset-shadow-[0_0_0.4rem_black] py-2 px-4 text-center"></div>
+ <div id="verification-message"></div>
</div>
<script>
@@ -140,58 +92,5 @@ function checkIfValidated(elem) {
}
checkIfValidated(htmx.find("#email-input"));
-
-function toggleTagsPick(elem) {
- const pickTagsForm = htmx.find("#pick-tags-form");
- if (elem.value === "specific" && elem.checked) {
- pickTagsForm.classList.remove("disabled");
- } else {
- pickTagsForm.classList.add("disabled");
- }
-}
-
-toggleTagsPick(htmx.find("#tagsSpecific"));
-
-function addTag(name) {
- name = name.trim();
- const subsMessage = htmx.find("#subs-message");
- const existingTags = htmx.findAll(htmx.find("#existing-tags"), "option");
- found = [...existingTags].find(opt => opt.value===name);
- if (!found) {
- subsMessage.classList.remove("hidden");
- subsMessage.innerHTML = "{{ .L.UserProfile.TagDoesNotExist }}".replace("{}", name);
- return;
- }
-
- const tagsPickedList = htmx.find("#tags-picked-list");
- const subscribedTags = htmx.findAll(tagsPickedList, "div input");
- found = [...subscribedTags].find(opt => opt.value===name);
- if (found) {
- subsMessage.classList.remove("hidden");
- subsMessage.innerHTML = "{{ .L.UserProfile.TagAlreadyAdded }}".replace("{}", name);
- return;
- }
-
- tagsPickedList.innerHTML += `
- <div id="tagPicked${name}" class="bg-main-hard text-background-light m-2 flex flex-row">
- <p class="py-1 px-2">${name}</p>
- <p class="py-1 px-2 bg-main-soft cursor-pointer" onclick="htmx.remove(htmx.find('#tagPicked${name}'));">✘</p>
- <input type="hidden" name="tags_picked" value="${name}">
- </div>
- `;
-}
-
-htmx.on("htmx:configRequest", (e) => {
- const params = e.detail.parameters;
-
- if (Array.isArray(params.tags_picked)) {
- tags_join = params.tags_picked[0] || "";
- for (i = 1; i < params.tags_picked.length; i++) {
- tags_join += ",";
- tags_join += params.tags_picked[i];
- }
- params.tags_picked = tags_join;
- }
-})
</script>
{{ end }} \ No newline at end of file