add database backup and restore admin page
Some checks failed
deploy / deploy (push) Has been cancelled
Some checks failed
deploy / deploy (push) Has been cancelled
- SQLCipher-encrypted backup creation via VACUUM INTO - Backup history with auto-pruning (keeps last 5) - Pre-restore automatic backup for safety - Restore from history or uploaded file - Stats display with table breakdown - Download hook for client-side file download - SECRET_KEY_DB config for encryption at rest Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -932,10 +932,25 @@ const EditorKeyboard = {
|
||||
}
|
||||
}
|
||||
|
||||
// Hook to trigger file downloads from LiveView
|
||||
const Download = {
|
||||
mounted() {
|
||||
this.handleEvent("download", ({filename, content, content_type}) => {
|
||||
const blob = new Blob([Uint8Array.from(atob(content), c => c.charCodeAt(0))], {type: content_type})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement("a")
|
||||
a.href = url
|
||||
a.download = filename
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
const liveSocket = new LiveSocket("/live", Socket, {
|
||||
params: {_csrf_token: csrfToken, screen_width: window.innerWidth},
|
||||
hooks: {...colocatedHooks, ColorSync, Lightbox, CartPersist, CartDrawer, ProductImageScroll, SearchModal, MobileNavDrawer, CollectionFilters, AnalyticsInit, AnalyticsExport, ChartTooltip, Clipboard, DirtyGuard, EditorKeyboard, EditorSheet},
|
||||
hooks: {...colocatedHooks, ColorSync, Lightbox, CartPersist, CartDrawer, ProductImageScroll, SearchModal, MobileNavDrawer, CollectionFilters, AnalyticsInit, AnalyticsExport, ChartTooltip, Clipboard, DirtyGuard, EditorKeyboard, EditorSheet, Download},
|
||||
})
|
||||
|
||||
// Show progress bar on live navigation and form submits
|
||||
@@ -956,6 +971,11 @@ window.addEventListener("phx:scroll-top", () => {
|
||||
window.scrollTo({top: 0, behavior: 'instant'})
|
||||
})
|
||||
|
||||
// Scroll element into view (used by flash messages)
|
||||
window.addEventListener("scroll-into-view", (e) => {
|
||||
e.target.scrollIntoView({behavior: 'smooth', block: 'nearest'})
|
||||
})
|
||||
|
||||
// connect if there are any LiveViews on the page
|
||||
liveSocket.connect()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user