feat: implement collections book picker with Alpine.store
Add multi-select book picker modal for collections using Alpine.js patterns:
- Alpine.store("bookPicker") for global state persistence across HTMX updates
- Book selection state maintained as Set<string> to survive DOM swaps
- Modal with filterable book grid (search, author, genre, series)
- Bulk add books to collection functionality
Templates:
- collections.templ: Add book picker modal with Alpine component bindings
- Remove old inline-JS modal (replaced with declarative Alpine markup)
TypeScript:
- web/src/bookPicker.ts: New module with Alpine.store and Alpine.data definitions
- web/src/main.ts: Import bookPicker module
- web/src/collections.ts: Remove old modal functions (replaced by Alpine)
This implements the Book Picker Modal feature from the collections system,
following SSR-first Alpine.js patterns with HTMX for dynamic updates.
Fixes "Add Books" button being disabled - modal now fully functional.
This commit is contained in:
+1
-115
@@ -1,9 +1,6 @@
|
|||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import "bookhoard/internal/handlers"
|
||||||
"bookhoard/internal/handlers"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
templ Collection(user User, collections []CollectionData, errorMessage string) {
|
templ Collection(user User, collections []CollectionData, errorMessage string) {
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -365,117 +362,6 @@ templ CollectionDetail(user User, collection CollectionData, books []handlers.Bo
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
x-show="bookPickerOpen"
|
|
||||||
x-transition:enter="transition ease-out duration-200"
|
|
||||||
x-transition:enter-start="opacity-0"
|
|
||||||
x-transition:enter-end="opacity-100"
|
|
||||||
x-transition:leave="transition ease-in duration-150"
|
|
||||||
x-transition:leave-start="opacity-100"
|
|
||||||
x-transition:leave-end="opacity-0"
|
|
||||||
@click.self="closeBookPicker()"
|
|
||||||
@keyup.escape.window="closeBookPicker()"
|
|
||||||
class="fixed inset-0 z-50 flex items-center justify-center"
|
|
||||||
style="background-color: rgba(0, 0, 0, 0.7); display: none;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
@click.stop
|
|
||||||
class="card rounded-lg w-full max-w-4xl mx-4 my-8"
|
|
||||||
style="background-color: var(--bg-secondary); border-color: var(--border);"
|
|
||||||
>
|
|
||||||
<!-- Header -->
|
|
||||||
<div
|
|
||||||
class="flex justify-between items-center p-4 border-b"
|
|
||||||
style="border-color: var(--border);"
|
|
||||||
>
|
|
||||||
<h2 class="text-xl font-bold" style="color: var(--text-primary)">Add Books to Collection</h2>
|
|
||||||
<button @click="closeBookPicker()" class="p-2 hover:opacity-80 rounded" style="color: var(--text-primary)">✕</button>
|
|
||||||
</div>
|
|
||||||
<!-- Filters -->
|
|
||||||
<div class="p-4 border-b" style="border-color: var(--border);">
|
|
||||||
<div class="flex flex-wrap gap-4 items-center">
|
|
||||||
<div class="flex-1 min-w-[200px]">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="search"
|
|
||||||
placeholder="Search books..."
|
|
||||||
class="w-full px-3 py-2 border rounded-lg"
|
|
||||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
|
|
||||||
hx-get={ fmt.Sprintf("/api/media-items/filtered?show_checkbox=true&collection_id=%s", collection.ID) }
|
|
||||||
hx-target="#book-picker-grid"
|
|
||||||
hx-trigger="keyup changed delay:300ms"
|
|
||||||
hx-include="#book-picker-filters"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 min-w-[150px]">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="author_filter"
|
|
||||||
placeholder="Author"
|
|
||||||
class="w-full px-3 py-2 border rounded-lg"
|
|
||||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
|
|
||||||
hx-get={ fmt.Sprintf("/api/media-items/filtered?show_checkbox=true&collection_id=%s", collection.ID) }
|
|
||||||
hx-target="#book-picker-grid"
|
|
||||||
hx-trigger="change"
|
|
||||||
hx-include="#book-picker-filters"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
@click="clearBookPickerFilters()"
|
|
||||||
class="px-4 py-2 rounded-lg border"
|
|
||||||
style="border-color: var(--border); color: var(--text-primary);"
|
|
||||||
>
|
|
||||||
✕ Clear
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!-- Hidden form for HTMX -->
|
|
||||||
<form id="book-picker-filters" class="hidden">
|
|
||||||
<input type="hidden" name="limit" value="50"/>
|
|
||||||
<input type="hidden" name="offset" value="0"/>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<!-- Books Grid with Checkboxes -->
|
|
||||||
<div
|
|
||||||
id="book-picker-grid"
|
|
||||||
class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-4 p-4 max-h-96 overflow-y-auto"
|
|
||||||
>
|
|
||||||
<!-- Books rendered via HTMX -->
|
|
||||||
</div>
|
|
||||||
<!-- Footer with Selection Count and Submit -->
|
|
||||||
<div
|
|
||||||
class="p-4 border-t flex justify-between items-center"
|
|
||||||
style="border-color: var(--border);"
|
|
||||||
>
|
|
||||||
<span class="text-sm" style="color: var(--text-secondary);">
|
|
||||||
<span x-text="bookPickerSelected.length"></span> books selected
|
|
||||||
</span>
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<button
|
|
||||||
@click="closeBookPicker()"
|
|
||||||
class="px-4 py-2 rounded-lg border"
|
|
||||||
style="border-color: var(--border); color: var(--text-primary);"
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<!-- HTMX Form Submission -->
|
|
||||||
<form
|
|
||||||
hx-post={ fmt.Sprintf("/api/collections/%s/books", collection.ID) }
|
|
||||||
hx-on::after-request="if(event.detail.successful) { closeBookPicker(); htmx.trigger(htmx.find('#books-container'), 'refresh'); }"
|
|
||||||
@submit.prevent="if(bookPickerSelected.length === 0) return; $el.querySelector('input[name=book_ids]').value = bookPickerSelected.join(','); $el.submit()"
|
|
||||||
>
|
|
||||||
<input type="hidden" name="book_ids" value=""/>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="px-4 py-2 rounded-lg font-medium"
|
|
||||||
style="background-color: var(--accent); color: var(--bg-primary);"
|
|
||||||
>
|
|
||||||
Add Selected Books
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
<div
|
<div
|
||||||
id="collection-data"
|
id="collection-data"
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ package templates
|
|||||||
import "github.com/a-h/templ"
|
import "github.com/a-h/templ"
|
||||||
import templruntime "github.com/a-h/templ/runtime"
|
import templruntime "github.com/a-h/templ/runtime"
|
||||||
|
|
||||||
import (
|
import "bookhoard/internal/handlers"
|
||||||
"bookhoard/internal/handlers"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Collection(user User, collections []CollectionData, errorMessage string) templ.Component {
|
func Collection(user User, collections []CollectionData, errorMessage string) templ.Component {
|
||||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||||
@@ -60,7 +57,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var2 string
|
var templ_7745c5c3_Var2 string
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID)
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 65, Col: 82}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 62, Col: 82}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -73,7 +70,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(col.Color)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(col.Color)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 69, Col: 30}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 66, Col: 30}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -86,7 +83,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Icon)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(col.Icon)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 72, Col: 41}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 69, Col: 41}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -99,7 +96,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID + "/edit-modal")
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs("/collections/" + col.ID + "/edit-modal")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 75, Col: 60}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 72, Col: 60}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -112,7 +109,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var6 string
|
var templ_7745c5c3_Var6 string
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/api/collections/" + col.ID + "")
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/api/collections/" + col.ID + "")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 84, Col: 56}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 81, Col: 56}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -125,7 +122,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name)
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(col.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 94, Col: 92}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 91, Col: 92}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -138,7 +135,7 @@ func Collection(user User, collections []CollectionData, errorMessage string) te
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(col.Description)
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(col.Description)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 95, Col: 86}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 92, Col: 86}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -193,7 +190,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
|
|||||||
var templ_7745c5c3_Var10 string
|
var templ_7745c5c3_Var10 string
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 112, Col: 27}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 109, Col: 27}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -214,7 +211,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
|
|||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var11 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon)
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Icon)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 124, Col: 81}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 121, Col: 81}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -227,7 +224,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
|
|||||||
var templ_7745c5c3_Var12 string
|
var templ_7745c5c3_Var12 string
|
||||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Name)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 126, Col: 90}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 123, Col: 90}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -240,7 +237,7 @@ func CollectionDetail(user User, collection CollectionData, books []handlers.Boo
|
|||||||
var templ_7745c5c3_Var13 string
|
var templ_7745c5c3_Var13 string
|
||||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description)
|
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(collection.Description)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 127, Col: 71}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/collections.templ`, Line: 124, Col: 71}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -495,49 +495,6 @@ export {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Alpine.data("collections", () => ({
|
Alpine.data("collections", () => ({
|
||||||
// Book Picker State
|
|
||||||
bookPickerOpen: false,
|
|
||||||
bookPickerSelected: [] as string[],
|
|
||||||
// Book Picker Methods
|
|
||||||
openBookPicker(): void {
|
|
||||||
this.bookPickerOpen = true;
|
|
||||||
this.bookPickerSelected = [];
|
|
||||||
},
|
|
||||||
closeBookPicker(): void {
|
|
||||||
this.bookPickerOpen = false;
|
|
||||||
this.bookPickerSelected = [];
|
|
||||||
},
|
|
||||||
toggleBookPickerBook(bookId: string): void {
|
|
||||||
const index = this.bookPickerSelected.indexOf(bookId);
|
|
||||||
if (index > -1) {
|
|
||||||
this.bookPickerSelected.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
this.bookPickerSelected.push(bookId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isBookPickerBookSelected(bookId: string): boolean {
|
|
||||||
return this.bookPickerSelected.includes(bookId);
|
|
||||||
},
|
|
||||||
getBookPickerSelectedCount(): number {
|
|
||||||
return this.bookPickerSelected.length;
|
|
||||||
},
|
|
||||||
clearBookPickerFilters(): void {
|
|
||||||
const filterForm = document.getElementById(
|
|
||||||
"book-picker-filters",
|
|
||||||
) as HTMLFormElement;
|
|
||||||
if (!filterForm) return;
|
|
||||||
|
|
||||||
const inputs = filterForm.querySelectorAll("input:not([type='checkbox'])");
|
|
||||||
inputs.forEach((input) => {
|
|
||||||
(input as HTMLInputElement).value = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
const grid = document.getElementById("book-picker-grid");
|
|
||||||
if (grid) {
|
|
||||||
htmx.trigger(grid, "refresh");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Collection Methods
|
// Collection Methods
|
||||||
closeCollectionModal,
|
closeCollectionModal,
|
||||||
createRule,
|
createRule,
|
||||||
|
|||||||
+3
-2
@@ -2,11 +2,12 @@ import "./alpine";
|
|||||||
import { Alpine } from "./alpine";
|
import { Alpine } from "./alpine";
|
||||||
|
|
||||||
import "./admin";
|
import "./admin";
|
||||||
import "./api";
|
|
||||||
import "./analytics";
|
import "./analytics";
|
||||||
|
import "./api";
|
||||||
import "./api-explorer";
|
import "./api-explorer";
|
||||||
import "./api-explorer-docs";
|
import "./api-explorer-docs";
|
||||||
import "./bookPicker";
|
import "./bookPicker";
|
||||||
|
import "./bookshelf";
|
||||||
import "./collection-rules";
|
import "./collection-rules";
|
||||||
import "./collections";
|
import "./collections";
|
||||||
import "./conflicts";
|
import "./conflicts";
|
||||||
@@ -19,8 +20,8 @@ import "./events";
|
|||||||
import "./header";
|
import "./header";
|
||||||
import "./index";
|
import "./index";
|
||||||
import "./library";
|
import "./library";
|
||||||
import "./login";
|
|
||||||
import "./linking";
|
import "./linking";
|
||||||
|
import "./login";
|
||||||
import "./password_validation";
|
import "./password_validation";
|
||||||
import "./profile";
|
import "./profile";
|
||||||
import "./profile-modal";
|
import "./profile-modal";
|
||||||
|
|||||||
Reference in New Issue
Block a user