refactor(ui): promote generic publication fields to their own editor section

Age Rating, Imprint, Scan Information, and Metadata Notes are
format-agnostic columns (the schema marks age rating 'applies to all
formats'; imprint examples span comics and books) — but they rendered
inside the Comic/Manga section, showing a manga dropdown on
audiobooks and hiding useful fields behind comic gating.

Split the editor into:
- Publication Details: Age Rating, Imprint, Scan Information,
  Metadata Notes — always visible for every media type (empty for
  non-comics sources: no standard metadata carries these outside
  ComicInfo.xml; editable and persistent for all).
- Comic/Manga (gated by ShowComicMetadata, unchanged): Manga Type,
  Reading Direction, Story Arc, Black & White.

Pure presentation move — identical form field names, no handler or
schema changes.
This commit is contained in:
John O'Keefe committed 2026-10-25 12:50:37 -04:00
1 parent d41c3e4774
commit a730a62280
2 files changed
+211 -178

No files matched your search

+30 -17
View File
@@ -543,6 +543,36 @@ templ MetadataEditorModal(book handlers.MediaDetail) {
</div>
</div>
}
<div class="rounded-xl border overflow-hidden" style="border-color: var(--border);">
<button type="button" class="w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover"
style="color: var(--text-primary);"
@click="toggleSection('publication')">
<span class="font-semibold">Publication Details</span>
<span class="inline-flex">
<span x-show="openSections.publication">@Icon("chevron-down", "h-4 w-4")</span>
<span x-show="!openSections.publication" x-cloak>@Icon("chevron-right", "h-4 w-4")</span>
</span>
</button>
<div x-show="openSections.publication" x-transition class="p-4 space-y-3 border-t" style="border-color: var(--border);">
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Age Rating</label>
<input type="text" name="age_rating" value={ textToString(book.AgeRating) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Imprint</label>
<input type="text" name="imprint" value={ textToString(book.Imprint) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Scan Information</label>
<input type="text" name="scan_information" value={ textToString(book.ScanInformation) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Metadata Notes</label>
<textarea name="metadata_notes" rows="2" class="input"
>{ textToString(book.MetadataNotes) }</textarea>
</div>
</div>
</div>
if book.ShowComicMetadata() {
<div class="rounded-xl border overflow-hidden" style="border-color: var(--border);">
<button type="button" class="w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover"
@@ -573,27 +603,10 @@ templ MetadataEditorModal(book handlers.MediaDetail) {
<option value="vertical" selected={ textToString(book.ReadingDirection) == "vertical" }>Vertical</option>
</select>
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Age Rating</label>
<input type="text" name="age_rating" value={ textToString(book.AgeRating) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Story Arc</label>
<input type="text" name="story_arc" value={ textToString(book.StoryArc) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Imprint</label>
<input type="text" name="imprint" value={ textToString(book.Imprint) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Scan Information</label>
<input type="text" name="scan_information" value={ textToString(book.ScanInformation) } class="input" />
</div>
<div>
<label class="block text-xs font-semibold uppercase tracking-wide mb-1" style="color: var(--text-secondary);">Metadata Notes</label>
<textarea name="metadata_notes" rows="2" class="input"
>{ textToString(book.MetadataNotes) }</textarea>
</div>
<div class="flex items-center gap-2">
<input type="checkbox" name="is_black_and_white" id="is_black_and_white"
if book.IsBlackAndWhite.Bool { checked }
+181 -161
View File
@@ -1192,8 +1192,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
return templ_7745c5c3_Err
}
}
if book.ShowComicMetadata() {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "<div class=\"rounded-xl border overflow-hidden\" style=\"border-color: var(--border);\"><button type=\"button\" class=\"w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover\" style=\"color: var(--text-primary);\" @click=\"toggleSection('comic')\"><span class=\"font-semibold\">Comic/Manga</span> <span class=\"inline-flex\"><span x-show=\"openSections.comic\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 117, "<div class=\"rounded-xl border overflow-hidden\" style=\"border-color: var(--border);\"><button type=\"button\" class=\"w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover\" style=\"color: var(--text-primary);\" @click=\"toggleSection('publication')\"><span class=\"font-semibold\">Publication Details</span> <span class=\"inline-flex\"><span x-show=\"openSections.publication\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1201,7 +1200,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "</span> <span x-show=\"!openSections.comic\" x-cloak>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 118, "</span> <span x-show=\"!openSections.publication\" x-cloak>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1209,191 +1208,64 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "</span></span></button><div x-show=\"openSections.comic\" x-transition class=\"p-4 space-y-3 border-t\" style=\"border-color: var(--border);\"><div><label for=\"manga_type\" class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Manga Type</label> <select id=\"manga_type\" name=\"manga_type\" class=\"input\"><option value=\"unknown\" selected=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 119, "</span></span></button><div x-show=\"openSections.publication\" x-transition class=\"p-4 space-y-3 border-t\" style=\"border-color: var(--border);\"><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Age Rating</label> <input type=\"text\" name=\"age_rating\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var62 string
templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "unknown")
templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.AgeRating))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 561, Col: 85}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 559, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var62)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "\">Unknown</option> <option value=\"no\" selected=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 120, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Imprint</label> <input type=\"text\" name=\"imprint\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var63 string
templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "no")
templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.Imprint))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 562, Col: 75}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 563, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var63)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "\">No</option> <option value=\"yes\" selected=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Scan Information</label> <input type=\"text\" name=\"scan_information\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var64 string
templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "yes")
templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ScanInformation))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 563, Col: 77}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 567, Col: 93}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var64)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "\">Yes</option> <option value=\"yes_and_right_to_left\" selected=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 122, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Metadata Notes</label> <textarea name=\"metadata_notes\" rows=\"2\" class=\"input\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var65 string
templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "yes_and_right_to_left")
templ_7745c5c3_Var65, templ_7745c5c3_Err = templ.JoinStringErrs(textToString(book.MetadataNotes))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 564, Col: 113}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 572, Col: 43}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var65)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var65))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "\">Yes (Right to Left)</option></select></div><div><label for=\"reading_direction\" class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Reading Direction</label> <select id=\"reading_direction\" name=\"reading_direction\" class=\"input\"><option value=\"auto\" selected=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 123, "</textarea></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var66 string
templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "auto")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 570, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var66)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "\">Auto</option> <option value=\"ltr\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var67 string
templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "ltr")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 571, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var67)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "\">Left to Right</option> <option value=\"rtl\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var68 string
templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "rtl")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 572, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var68)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "\">Right to Left</option> <option value=\"vertical\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var69 string
templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "vertical")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 573, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var69)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "\">Vertical</option></select></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Age Rating</label> <input type=\"text\" name=\"age_rating\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var70 string
templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.AgeRating))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 578, Col: 81}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var70)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Story Arc</label> <input type=\"text\" name=\"story_arc\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var71 string
templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.StoryArc))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 582, Col: 79}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var71)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Imprint</label> <input type=\"text\" name=\"imprint\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var72 string
templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.Imprint))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 586, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var72)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Scan Information</label> <input type=\"text\" name=\"scan_information\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var73 string
templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ScanInformation))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 590, Col: 93}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var73)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Metadata Notes</label> <textarea name=\"metadata_notes\" rows=\"2\" class=\"input\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var74 string
templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.JoinStringErrs(textToString(book.MetadataNotes))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 595, Col: 43}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var74))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "</textarea></div><div class=\"flex items-center gap-2\"><input type=\"checkbox\" name=\"is_black_and_white\" id=\"is_black_and_white\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if book.IsBlackAndWhite.Bool {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, " checked")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, " class=\"rounded\"> <label for=\"is_black_and_white\" class=\"text-sm\" style=\"color: var(--text-secondary);\">Black & White</label></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "<div class=\"rounded-xl border overflow-hidden\" style=\"border-color: var(--border);\"><button type=\"button\" class=\"w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover\" style=\"color: var(--text-primary);\" @click=\"toggleSection('technical')\"><span class=\"font-semibold\">Technical</span> <span class=\"inline-flex\"><span x-show=\"openSections.technical\">")
if book.ShowComicMetadata() {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 124, "<div class=\"rounded-xl border overflow-hidden\" style=\"border-color: var(--border);\"><button type=\"button\" class=\"w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover\" style=\"color: var(--text-primary);\" @click=\"toggleSection('comic')\"><span class=\"font-semibold\">Comic/Manga</span> <span class=\"inline-flex\"><span x-show=\"openSections.comic\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1401,7 +1273,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, "</span> <span x-show=\"!openSections.technical\" x-cloak>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 125, "</span> <span x-show=\"!openSections.comic\" x-cloak>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1409,72 +1281,220 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, "</span></span></button><div x-show=\"openSections.technical\" x-transition class=\"p-4 space-y-3 border-t\" style=\"border-color: var(--border);\"><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Page Count</label> <input type=\"number\" name=\"page_count\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 126, "</span></span></button><div x-show=\"openSections.comic\" x-transition class=\"p-4 space-y-3 border-t\" style=\"border-color: var(--border);\"><div><label for=\"manga_type\" class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Manga Type</label> <select id=\"manga_type\" name=\"manga_type\" class=\"input\"><option value=\"unknown\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var66 string
templ_7745c5c3_Var66, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "unknown")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 591, Col: 85}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var66)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 127, "\">Unknown</option> <option value=\"no\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var67 string
templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "no")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 592, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var67)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 128, "\">No</option> <option value=\"yes\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var68 string
templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "yes")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 593, Col: 77}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var68)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 129, "\">Yes</option> <option value=\"yes_and_right_to_left\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var69 string
templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MangaType) == "yes_and_right_to_left")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 594, Col: 113}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var69)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 130, "\">Yes (Right to Left)</option></select></div><div><label for=\"reading_direction\" class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Reading Direction</label> <select id=\"reading_direction\" name=\"reading_direction\" class=\"input\"><option value=\"auto\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var70 string
templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "auto")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 600, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var70)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 131, "\">Auto</option> <option value=\"ltr\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var71 string
templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "ltr")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 601, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var71)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 132, "\">Left to Right</option> <option value=\"rtl\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var72 string
templ_7745c5c3_Var72, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "rtl")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 602, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var72)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 133, "\">Right to Left</option> <option value=\"vertical\" selected=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var73 string
templ_7745c5c3_Var73, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.ReadingDirection) == "vertical")
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 603, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var73)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 134, "\">Vertical</option></select></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Story Arc</label> <input type=\"text\" name=\"story_arc\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var74 string
templ_7745c5c3_Var74, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.StoryArc))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 608, Col: 79}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var74)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 135, "\" class=\"input\"></div><div class=\"flex items-center gap-2\"><input type=\"checkbox\" name=\"is_black_and_white\" id=\"is_black_and_white\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if book.IsBlackAndWhite.Bool {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 136, " checked")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, " class=\"rounded\"> <label for=\"is_black_and_white\" class=\"text-sm\" style=\"color: var(--text-secondary);\">Black & White</label></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "<div class=\"rounded-xl border overflow-hidden\" style=\"border-color: var(--border);\"><button type=\"button\" class=\"w-full px-4 py-3 flex justify-between items-center hover:bg-surface-hover\" style=\"color: var(--text-primary);\" @click=\"toggleSection('technical')\"><span class=\"font-semibold\">Technical</span> <span class=\"inline-flex\"><span x-show=\"openSections.technical\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = Icon("chevron-down", "h-4 w-4").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "</span> <span x-show=\"!openSections.technical\" x-cloak>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = Icon("chevron-right", "h-4 w-4").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "</span></span></button><div x-show=\"openSections.technical\" x-transition class=\"p-4 space-y-3 border-t\" style=\"border-color: var(--border);\"><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Page Count</label> <input type=\"number\" name=\"page_count\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var75 string
templ_7745c5c3_Var75, templ_7745c5c3_Err = templ.ResolveAttributeValue(fmt.Sprintf("%d", book.PageCount.Int32))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 620, Col: 56}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 633, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var75)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Contributors (comma-separated)</label> <input type=\"text\" name=\"contributors\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "\" class=\"input\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Contributors (comma-separated)</label> <input type=\"text\" name=\"contributors\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var76 string
templ_7745c5c3_Var76, templ_7745c5c3_Err = templ.ResolveAttributeValue(stringSliceToString(book.Contributors))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 625, Col: 93}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 638, Col: 93}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var76)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "\" class=\"input\"></div><div class=\"grid grid-cols-2 gap-3\"><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Format</label> <input type=\"text\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 142, "\" class=\"input\"></div><div class=\"grid grid-cols-2 gap-3\"><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">Format</label> <input type=\"text\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var77 string
templ_7745c5c3_Var77, templ_7745c5c3_Err = templ.ResolveAttributeValue(textToString(book.MimeType))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 630, Col: 62}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 643, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var77)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "\" readonly class=\"input opacity-60\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">File Size</label> <input type=\"text\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "\" readonly class=\"input opacity-60\"></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">File Size</label> <input type=\"text\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var78 string
templ_7745c5c3_Var78, templ_7745c5c3_Err = templ.ResolveAttributeValue(fmt.Sprintf("%.1f MB", float64(book.FileSize.Int64)/1024/1024))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 635, Col: 97}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 648, Col: 97}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var78)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 141, "\" readonly class=\"input opacity-60\"></div></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">File Path</label> <input type=\"text\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 144, "\" readonly class=\"input opacity-60\"></div></div><div><label class=\"block text-xs font-semibold uppercase tracking-wide mb-1\" style=\"color: var(--text-secondary);\">File Path</label> <input type=\"text\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var79 string
templ_7745c5c3_Var79, templ_7745c5c3_Err = templ.ResolveAttributeValue(book.FileLocation)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 641, Col: 51}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/book_detail_modals.templ`, Line: 654, Col: 51}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var79)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 142, "\" readonly class=\"input opacity-60 font-mono text-xs\"></div></div></div></div></div><div class=\"flex items-center justify-between p-6 border-t flex-shrink-0\" style=\"border-color: var(--border);\"><div class=\"flex items-center gap-2\"><button @click=\"rescanBook()\" :disabled=\"rescanning\" class=\"btn btn-secondary\"><span x-show=\"!rescanning\" class=\"inline-flex items-center gap-2\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "\" readonly class=\"input opacity-60 font-mono text-xs\"></div></div></div></div></div><div class=\"flex items-center justify-between p-6 border-t flex-shrink-0\" style=\"border-color: var(--border);\"><div class=\"flex items-center gap-2\"><button @click=\"rescanBook()\" :disabled=\"rescanning\" class=\"btn btn-secondary\"><span x-show=\"!rescanning\" class=\"inline-flex items-center gap-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1482,7 +1502,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 143, "<span>Rescan</span></span> <svg x-show=\"rescanning\" class=\"animate-spin inline-block h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle> <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path></svg></button> <button @click=\"resetMetadata()\" :disabled=\"resetting\" class=\"btn btn-secondary\" title=\"Discard all manual edits and restore scanned metadata\"><span x-show=\"!resetting\" class=\"inline-flex items-center gap-2\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 146, "<span>Rescan</span></span> <svg x-show=\"rescanning\" class=\"animate-spin inline-block h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle> <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path></svg></button> <button @click=\"resetMetadata()\" :disabled=\"resetting\" class=\"btn btn-secondary\" title=\"Discard all manual edits and restore scanned metadata\"><span x-show=\"!resetting\" class=\"inline-flex items-center gap-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1490,7 +1510,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 144, "<span>Reset to Scanned</span></span> <svg x-show=\"resetting\" class=\"animate-spin inline-block h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle> <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path></svg></button></div><div class=\"flex space-x-3\"><button @click=\"hideMetadataEditor()\" class=\"btn btn-secondary\">Cancel</button> <button @click=\"saveMetadata()\" class=\"btn btn-primary\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "<span>Reset to Scanned</span></span> <svg x-show=\"resetting\" class=\"animate-spin inline-block h-5 w-5\" viewBox=\"0 0 24 24\" fill=\"none\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle> <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"></path></svg></button></div><div class=\"flex space-x-3\"><button @click=\"hideMetadataEditor()\" class=\"btn btn-secondary\">Cancel</button> <button @click=\"saveMetadata()\" class=\"btn btn-primary\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -1498,7 +1518,7 @@ func MetadataEditorModal(book handlers.MediaDetail) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 145, "Save</button></div></div></div></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, "Save</button></div></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}