refactor: remove inline WebSocket code from templates

collections.templ:
- Removed ~75 lines of inline WebSocket JS
- Added initializeCollectionWebSocket using websocket.ts utility
- Updated template to use x-init for WebSocket init

admin.templ:
- Removed ~55 lines of inline WebSocket JS
- Added initializeScanWebSocket using websocket.ts utility
- Updated template to use x-init for WebSocket init

Both now use the shared websocket.ts createWebSocket function
This commit is contained in:
2026-03-13 12:51:11 -04:00
parent 7068fabbee
commit 41e7445524
6 changed files with 110 additions and 155 deletions
+16 -16
View File
@@ -31,7 +31,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Collections - Bookhoard</title><script src=\"/static/htmx.min.js\"></script><script src=\"/static/main.js\" defer></script><link href=\"/static/style.css\" rel=\"stylesheet\"><script>\n\t\t\t\tlet ws = null;\n\t\t\t\tlet collectionId = null;\n\t\t\t\tlet libraryId = null;\n\n\t\t\t\tfunction connectWebSocket() {\n\t\t\t\t\tconst protocol =\n\t\t\t\t\t\twindow.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n\t\t\t\t\tconst wsUrl = `${protocol}//${window.location.host}/ws/sync?token={ user.Token }`;\n\t\t\t\t\tws = new WebSocket(wsUrl);\n\n\t\t\t\t\tws.onopen = function () {\n\t\t\t\t\t\tconsole.log(\"WebSocket connected\");\n\t\t\t\t\t};\n\n\t\t\t\t\tws.onmessage = function (event) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst message = JSON.parse(event.data);\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tmessage.type === \"collection_updated\" &&\n\t\t\t\t\t\t\t\tmessage.data.collection_id === collectionId\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tconst actionText =\n\t\t\t\t\t\t\t\t\tmessage.data.action === \"books_added\"\n\t\t\t\t\t\t\t\t\t\t? `Added ${message.data.count || 0} book(s)`\n\t\t\t\t\t\t\t\t\t\t: message.data.action === \"book_removed\"\n\t\t\t\t\t\t\t\t\t\t\t? \"Removed a book\"\n\t\t\t\t\t\t\t\t\t\t\t: message.data.action === \"books_bulk_removed\"\n\t\t\t\t\t\t\t\t\t\t\t\t? `Removed ${message.data.count || 0} book(s)`\n\t\t\t\t\t\t\t\t\t\t\t\t: \"Collection updated\";\n\n\t\t\t\t\t\t\t\t// Show toast notification\n\t\t\t\t\t\t\t\tif (window.showToast) {\n\t\t\t\t\t\t\t\t\twindow.showToast(actionText, \"info\");\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Check if user is actively typing\n\t\t\t\t\t\t\t\tconst activeElement = document.activeElement;\n\t\t\t\t\t\t\t\tconst isUserActive =\n\t\t\t\t\t\t\t\t\tactiveElement &&\n\t\t\t\t\t\t\t\t\t(activeElement.tagName === \"INPUT\" ||\n\t\t\t\t\t\t\t\t\t\tactiveElement.tagName === \"TEXTAREA\" ||\n\t\t\t\t\t\t\t\t\t\tactiveElement.tagName === \"SELECT\" ||\n\t\t\t\t\t\t\t\t\t\tactiveElement.getAttribute(\"contenteditable\") === \"true\");\n\n\t\t\t\t\t\t\t\tif (!isUserActive) {\n\t\t\t\t\t\t\t\t\tsetTimeout(function () {\n\t\t\t\t\t\t\t\t\t\tlocation.reload();\n\t\t\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconsole.log(\"User actively typing - skipping auto-reload\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Failed to parse WebSocket message:\", error);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tws.onclose = function () {\n\t\t\t\t\t\tconsole.log(\"WebSocket disconnected, reconnecting in 5s...\");\n\t\t\t\t\t\tsetTimeout(connectWebSocket, 5000);\n\t\t\t\t\t};\n\n\t\t\t\t\tws.onerror = function (error) {\n\t\t\t\t\t\tconsole.error(\"WebSocket error:\", error);\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tdocument.addEventListener(\"DOMContentLoaded\", function () {\n\t\t\t\t\t// Get collection and library IDs from data attributes\n\t\t\t\t\tconst dataEl = document.getElementById(\"collection-data\");\n\t\t\t\t\tif (dataEl) {\n\t\t\t\t\t\tcollectionId = dataEl.dataset.id || \"\";\n\t\t\t\t\t\tlibraryId = dataEl.dataset.libraryId || \"\";\n\t\t\t\t\t\tconnectWebSocket();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t</script></head><body x-data=\"collections\" class=\"theme-{ user.Theme }\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Collections - Bookhoard</title><script src=\"/static/htmx.min.js\"></script><script src=\"/static/main.js\" defer></script><link href=\"/static/style.css\" rel=\"stylesheet\"></head><body x-data=\"collections\" x-init=\"initializeCollectionWebSocket\" class=\"theme-{ user.Theme }\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -57,7 +57,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 141, Col: 82}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 63, Col: 82}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
@@ -70,7 +70,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(col.Color)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 145, Col: 30}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 67, Col: 30}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
@@ -83,7 +83,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 148, Col: 41}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 70, Col: 41}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@@ -96,7 +96,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID + "/edit-modal")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 151, Col: 60}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 73, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -109,7 +109,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/api/collections/" + col.ID + "")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 160, Col: 56}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 82, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -122,7 +122,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 170, Col: 92}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 92, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -135,7 +135,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(col.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 171, Col: 86}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 93, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -190,13 +190,13 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 188, Col: 27}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 110, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " - Bookhoard</title><script src=\"/static/htmx.min.js\"></script><script src=\"/static/main.js\" defer></script><link href=\"/static/style.css\" rel=\"stylesheet\"></head><body x-data=\"collections\" class=\"theme-{ user.Theme }\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " - Bookhoard</title><script src=\"/static/htmx.min.js\"></script><script src=\"/static/main.js\" defer></script><link href=\"/static/style.css\" rel=\"stylesheet\"></head><body x-data=\"collections\" x-init=\"initializeCollectionWebSocket\" class=\"theme-{ user.Theme }\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -211,7 +211,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 201, Col: 81}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 123, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
@@ -224,7 +224,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 203, Col: 90}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 125, Col: 90}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
@@ -237,7 +237,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 204, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 126, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@@ -261,7 +261,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(book.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 261, Col: 22}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 183, Col: 22}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
@@ -279,7 +279,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(book.Author)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 268, Col: 27}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 190, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@@ -302,7 +302,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(book.CoverImagePath)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 276, Col: 36}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 198, Col: 36}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {