perf(templates): add defer attribute to main.js script tags across all pages
- Add defer attribute to <script src="/static/main.js"> in 21 template files - Improves page load performance by allowing HTML parsing to continue without blocking - Maintains script execution order while enabling parallel resource loading - Remove duplicate defer attribute from header.templ line 264 - Add websocket.ts import to main.ts for module registration This optimization reduces page render blocking and improves perceived load times by allowing the browser to continue parsing HTML while the main.js bundle loads. The defer attribute ensures scripts execute in order after HTML parsing completes. Affected templates include: - Admin pages: admin, admin_library, admin_settings, admin_users - Content pages: analytics, bookshelf, collections, conflicts, custom_section - User pages: dashboard, devices, docs, index, login, profile, progress, queue, register - System pages: header, unlinked_books
This commit is contained in:
@@ -3,7 +3,7 @@ package templates
|
||||
templ APIExplorer(explorer APIExplorerData) {
|
||||
if !explorer.IsLoggedIn {
|
||||
// Show mode toggle and mock data
|
||||
<div class="border border-border rounded-lg p-6 mt-8 bg-background-secondary">
|
||||
<div x-data="devices" class="border border-border rounded-lg p-6 mt-8 bg-background-secondary">
|
||||
<div class="flex gap-2 mb-4">
|
||||
<button class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary cursor-pointer bg-accent text-white">Mock Data</button>
|
||||
<button class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary opacity-50 cursor-not-allowed" disabled>Login to Try Real</button>
|
||||
@@ -25,16 +25,16 @@ templ APIExplorer(explorer APIExplorerData) {
|
||||
<pre class="bg-background-primary p-4 rounded-lg overflow-x-auto"><code class="text-text-primary text-sm">{ explorer.Endpoint.Response }</code></pre>
|
||||
</div>
|
||||
<div class="flex gap-2 mt-4">
|
||||
<button @click="$store.devices.copyToClipboard(JSON.stringify({ explorer.Endpoint.RequestBody }, null, 2))" class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary hover:bg-background-secondary cursor-pointer text-sm">Copy Request</button>
|
||||
<button @click="$store.devices.copyToClipboard(JSON.stringify({ explorer.Endpoint.Response }, null, 2))" class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary hover:bg-background-secondary cursor-pointer text-sm">Copy Response</button>
|
||||
<button @click="copyToClipboard(JSON.stringify({ explorer.Endpoint.RequestBody }, null, 2))" class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary hover:bg-background-secondary cursor-pointer text-sm">Copy Request</button>
|
||||
<button @click="copyToClipboard(JSON.stringify({ explorer.Endpoint.Response }, null, 2))" class="px-4 py-2 border border-border rounded bg-background-primary text-text-primary hover:bg-background-secondary cursor-pointer text-sm">Copy Response</button>
|
||||
</div>
|
||||
</div>
|
||||
} else {
|
||||
// Show interactive explorer with real execution
|
||||
<div class="border border-border rounded-lg p-6 mt-8 bg-background-secondary" x-data="apiExplorerDoc" x-init="initAPIExplorerDoc('{ explorer.Endpoint.Path }', '{ explorer.Endpoint.RequestBody }', '{ explorer.Endpoint.Response }')">
|
||||
<div class="flex gap-2 mb-4">
|
||||
<button class="mode-btn px-4 py-2 border border-border rounded bg-background-primary text-text-primary cursor-pointer hover:bg-background-secondary text-sm" id="mock-btn" @click="$store.apiExplorerDoc.showDocMode('mock')">Mock Data</button>
|
||||
<button class="mode-btn px-4 py-2 bg-accent text-white rounded cursor-pointer text-sm" id="real-btn" @click="$store.apiExplorerDoc.showDocMode('real')">Try It Out</button>
|
||||
<button class="mode-btn px-4 py-2 border border-border rounded bg-background-primary text-text-primary cursor-pointer hover:bg-background-secondary text-sm" id="mock-btn" @click="showDocMode('mock')">Mock Data</button>
|
||||
<button class="mode-btn px-4 py-2 bg-accent text-white rounded cursor-pointer text-sm" id="real-btn" @click="showDocMode('real')">Try It Out</button>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="mb-4">
|
||||
|
||||
@@ -19,7 +19,7 @@ templ BookShelf(user User, libraries []LibraryData) {
|
||||
<div class="flex flex-col sm:flex-row gap-4 items-center justify-between">
|
||||
<div class="flex-1 w-full">
|
||||
<label class="block text-sm font-medium mb-2" style="color: var(--text-secondary)">Select Library</label>
|
||||
<select id="library-select" @change="$store.bookshelf.selectLibrary" class="w-full px-4 py-3 border rounded-lg text-lg" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border);">
|
||||
<select id="library-select" @change="selectLibrary" class="w-full px-4 py-3 border rounded-lg text-lg" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border);">
|
||||
if len(libraries) == 0 {
|
||||
<option value="">No libraries available</option>
|
||||
} else {
|
||||
@@ -30,7 +30,7 @@ templ BookShelf(user User, libraries []LibraryData) {
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<button @click="$store.bookshelf.loadBookshelf" class="btn-primary px-6 py-3 rounded-lg font-medium">
|
||||
<button @click="loadBookshelf" class="btn-primary px-6 py-3 rounded-lg font-medium">
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -112,7 +112,7 @@ templ Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []P
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border);"
|
||||
/>
|
||||
<button
|
||||
@click="$store.devices.copyToClipboard(document.getElementById('sync-url-{ device.ID }').value, 'Kobo sync URL')"
|
||||
@click="copyToClipboard(document.getElementById('sync-url-{ device.ID }').value, 'Kobo sync URL')"
|
||||
class="px-3 py-2 text-xs rounded hover:opacity-80"
|
||||
style="background-color: var(--accent); color: white;"
|
||||
>
|
||||
@@ -136,7 +136,7 @@ templ Devices(user User, devices []handlers.DeviceInfo, pendingRegistrations []P
|
||||
style="background-color: var(--bg-primary); color: var(--text-primary); border-color: var(--border); font-family: monospace;"
|
||||
/>
|
||||
<button
|
||||
@click="$store.devices.copyToClipboard(document.getElementById('auth-token-{ device.ID }').value, 'Auth token')"
|
||||
@click="copyToClipboard(document.getElementById('auth-token-{ device.ID }').value, 'Auth token')"
|
||||
class="px-3 py-2 text-xs rounded hover:opacity-80"
|
||||
style="background-color: var(--accent); color: white;"
|
||||
>
|
||||
|
||||
+14
-14
@@ -1,7 +1,7 @@
|
||||
package templates
|
||||
|
||||
templ Header(user User, currentPath string) {
|
||||
<nav class="border-b header-nav" style="border-color: var(--border); background-color: var(--bg-secondary);">
|
||||
<nav x-data="theme" class="border-b header-nav" style="border-color: var(--border); background-color: var(--bg-secondary);">
|
||||
<div x-data="{}" x-init="console.log('Alpine is working!', $el)"></div>
|
||||
<div class="w-full px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center h-16">
|
||||
@@ -70,7 +70,7 @@ templ Header(user User, currentPath string) {
|
||||
<h3 class="text-sm font-semibold mb-3" style="color: var(--text-primary)">Select Theme</h3>
|
||||
<div class="space-y-2">
|
||||
<button
|
||||
@click="$store.theme.changeTheme('tokyo-night'); themeDropdownOpen = false"
|
||||
@click="changeTheme('tokyo-night'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -78,7 +78,7 @@ templ Header(user User, currentPath string) {
|
||||
Tokyo Night
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('dracula'); themeDropdownOpen = false"
|
||||
@click="changeTheme('dracula'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -86,7 +86,7 @@ templ Header(user User, currentPath string) {
|
||||
Dracula
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('nord'); themeDropdownOpen = false"
|
||||
@click="changeTheme('nord'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -94,7 +94,7 @@ templ Header(user User, currentPath string) {
|
||||
Nord
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('solarized-dark'); themeDropdownOpen = false"
|
||||
@click="changeTheme('solarized-dark'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -102,7 +102,7 @@ templ Header(user User, currentPath string) {
|
||||
Solarized Dark
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('monokai'); themeDropdownOpen = false"
|
||||
@click="changeTheme('monokai'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -110,7 +110,7 @@ templ Header(user User, currentPath string) {
|
||||
Monokai
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('one-dark-pro'); themeDropdownOpen = false"
|
||||
@click="changeTheme('one-dark-pro'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -118,7 +118,7 @@ templ Header(user User, currentPath string) {
|
||||
One Dark Pro
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeTheme('material-dark'); themeDropdownOpen = false"
|
||||
@click="changeTheme('material-dark'); themeDropdownOpen = false"
|
||||
class="w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary); background-color: var(--bg-primary);"
|
||||
>
|
||||
@@ -128,7 +128,7 @@ templ Header(user User, currentPath string) {
|
||||
<div class="border-t pt-2 mt-2" style="border-color: var(--border);">
|
||||
<p class="text-xs mb-2" style="color: var(--text-secondary)">Bookshelf Background</p>
|
||||
<button
|
||||
@click="$store.theme.changeWoodPaneling('none'); themeDropdownOpen = false"
|
||||
@click="changeWoodPaneling('none'); themeDropdownOpen = false"
|
||||
class="wood-paneling-btn w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary);"
|
||||
data-wood="none"
|
||||
@@ -136,7 +136,7 @@ templ Header(user User, currentPath string) {
|
||||
None
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeWoodPaneling('wood-light'); themeDropdownOpen = false"
|
||||
@click="changeWoodPaneling('wood-light'); themeDropdownOpen = false"
|
||||
class="wood-paneling-btn w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary);"
|
||||
data-wood="wood-light"
|
||||
@@ -148,7 +148,7 @@ templ Header(user User, currentPath string) {
|
||||
Wood Light
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeWoodPaneling('wood-dark'); themeDropdownOpen = false"
|
||||
@click="changeWoodPaneling('wood-dark'); themeDropdownOpen = false"
|
||||
class="wood-paneling-btn w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary);"
|
||||
data-wood="wood-dark"
|
||||
@@ -160,7 +160,7 @@ templ Header(user User, currentPath string) {
|
||||
Wood Dark
|
||||
</button>
|
||||
<button
|
||||
@click="$store.theme.changeWoodPaneling('wood-mahogany'); themeDropdownOpen = false"
|
||||
@click="changeWoodPaneling('wood-mahogany'); themeDropdownOpen = false"
|
||||
class="wood-paneling-btn w-full text-left px-3 py-2 rounded hover:opacity-80 transition-opacity"
|
||||
style="color: var(--text-primary);"
|
||||
data-wood="wood-mahogany"
|
||||
@@ -208,7 +208,7 @@ templ Header(user User, currentPath string) {
|
||||
}
|
||||
<div class="border-t my-1" style="border-color: var(--border);"></div>
|
||||
<button
|
||||
@click="$store.header.logout(); userMenuOpen = false"
|
||||
@click="logout(); userMenuOpen = false"
|
||||
class="block w-full text-left px-4 py-2 text-sm hover:opacity-80"
|
||||
style="color: var(--text-primary); background-color: var(--bg-secondary);"
|
||||
>
|
||||
@@ -261,5 +261,5 @@ templ Header(user User, currentPath string) {
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<script src="/static/main.js" defer defer></script>
|
||||
<script src="/static/main.js" defer></script>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ templ Index(loggedIn bool) {
|
||||
<div class="relative max-w-7xl mx-auto px-4 py-16 sm:px-6 sm:py-24 lg:py-32 lg:px-8">
|
||||
<div class="flex justify-between items-start mb-8">
|
||||
<div></div>
|
||||
<select id="theme-select" @change="$store.theme.changeTheme" class="px-3 py-2 border rounded text-sm" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)">
|
||||
<select id="theme-select" @change="changeTheme" class="px-3 py-2 border rounded text-sm" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)">
|
||||
<option value="tokyo-night">Tokyo Night</option>
|
||||
<option value="dracula">Dracula</option>
|
||||
<option value="nord">Nord</option>
|
||||
|
||||
@@ -15,7 +15,7 @@ templ Login(sessionExpired bool, deleted bool) {
|
||||
<div class="container mx-auto px-4 py-8 max-w-md">
|
||||
<div class="flex justify-between items-center mb-8">
|
||||
<h1 class="text-3xl font-bold">Login to Bookhoard</h1>
|
||||
<select id="theme-select" @change="$store.login.changeTheme()" class="px-3 py-2 border rounded" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)">
|
||||
<select id="theme-select" @change="changeTheme()" class="px-3 py-2 border rounded" style="background-color: var(--bg-secondary); color: var(--text-primary); border-color: var(--border)">
|
||||
<option value="tokyo-night">Tokyo Night</option>
|
||||
<option value="dracula">Dracula</option>
|
||||
<option value="nord">Nord</option>
|
||||
|
||||
Reference in New Issue
Block a user