Add DB management in settings and re-enable TPDB server path
This commit is contained in:
parent
4ff7708f76
commit
4067f9b793
|
|
@ -480,7 +480,7 @@ var webCmd = &cobra.Command{
|
|||
}
|
||||
defer database.Close()
|
||||
|
||||
server, err := web.NewServer(database, addr)
|
||||
server, err := web.NewServer(database, addr, dbPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create web server: %w", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -33,9 +34,10 @@ type Server struct {
|
|||
db *db.DB
|
||||
templates *template.Template
|
||||
addr string
|
||||
dbPath string
|
||||
}
|
||||
|
||||
func NewServer(database *db.DB, addr string) (*Server, error) {
|
||||
func NewServer(database *db.DB, addr string, dbPath string) (*Server, error) {
|
||||
tmpl, err := template.ParseFS(content, "templates/*.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse templates: %w", err)
|
||||
|
|
@ -45,6 +47,7 @@ func NewServer(database *db.DB, addr string) (*Server, error) {
|
|||
db: database,
|
||||
templates: tmpl,
|
||||
addr: addr,
|
||||
dbPath: dbPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +94,7 @@ func (s *Server) Start() error {
|
|||
|
||||
// Settings endpoints
|
||||
mux.HandleFunc("/api/settings/api-keys", s.handleAPISettingsKeys)
|
||||
mux.HandleFunc("/api/settings/database", s.handleAPIDatabase)
|
||||
|
||||
// API
|
||||
mux.HandleFunc("/api/import/performer", s.handleAPIImportPerformer)
|
||||
|
|
@ -1369,6 +1373,7 @@ func (s *Server) handleSettingsPage(w http.ResponseWriter, r *http.Request) {
|
|||
data := map[string]interface{}{
|
||||
"PageTitle": "Settings",
|
||||
"ActivePage": "settings",
|
||||
"DBPath": s.dbPath,
|
||||
}
|
||||
|
||||
s.render(w, "settings.html", data)
|
||||
|
|
@ -1427,3 +1432,40 @@ func (s *Server) handleAPISettingsKeys(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
// Database management
|
||||
func (s *Server) handleAPIDatabase(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
info := map[string]interface{}{
|
||||
"path": s.dbPath,
|
||||
}
|
||||
if stat, err := os.Stat(s.dbPath); err == nil {
|
||||
info["size_bytes"] = stat.Size()
|
||||
info["size_mb"] = float64(stat.Size()) / (1024 * 1024)
|
||||
}
|
||||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: "OK",
|
||||
Data: info,
|
||||
})
|
||||
case http.MethodDelete:
|
||||
// Close and recreate
|
||||
if s.db != nil {
|
||||
_ = s.db.Close()
|
||||
}
|
||||
_ = os.Remove(s.dbPath)
|
||||
newDB, err := db.Open(s.dbPath)
|
||||
if err != nil {
|
||||
json.NewEncoder(w).Encode(APIResponse{Success: false, Message: fmt.Sprintf("Failed to recreate DB: %v", err)})
|
||||
return
|
||||
}
|
||||
s.db = newDB
|
||||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: "Database deleted and recreated.",
|
||||
})
|
||||
default:
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,16 @@
|
|||
|
||||
<div id="settings-status" class="status-banner" style="margin-top: 1rem;"></div>
|
||||
</div>
|
||||
|
||||
<div class="gx-card" style="margin-top: 1.5rem; padding: 1.5rem; border: 1px solid #ff8a8a;">
|
||||
<h4 style="color: #ff8a8a;">Database Maintenance</h4>
|
||||
<p class="help-text">Current database: <code>{{.DBPath}}</code></p>
|
||||
<div class="action-buttons" style="margin-top: 0.75rem;">
|
||||
<button class="btn-secondary" onclick="loadDbInfo()">Refresh Info<div class="hoverEffect"><div></div></div></button>
|
||||
<button class="btn" style="background: #ff4d4d;" onclick="confirmDeleteDb()">Delete Database<div class="hoverEffect"><div></div></div></button>
|
||||
</div>
|
||||
<div id="db-info" class="status-banner" style="margin-top: 0.75rem;"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{{template "html-scripts" .}}
|
||||
|
|
@ -90,6 +100,48 @@
|
|||
el.style.display = msg ? 'block' : 'none';
|
||||
}
|
||||
|
||||
async function loadDbInfo() {
|
||||
try {
|
||||
const res = await fetch('/api/settings/database');
|
||||
const result = await res.json();
|
||||
if (result.success && result.data) {
|
||||
const d = result.data;
|
||||
const el = document.getElementById('db-info');
|
||||
el.textContent = `Path: ${d.path || ''} | Size: ${ (d.size_mb || 0).toFixed ? (d.size_mb.toFixed(2) + ' MB') : 'n/a'}`;
|
||||
el.classList.remove('error');
|
||||
el.style.display = 'block';
|
||||
}
|
||||
} catch (err) {
|
||||
const el = document.getElementById('db-info');
|
||||
el.textContent = 'Error loading DB info: ' + err.message;
|
||||
el.classList.add('error');
|
||||
el.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
async function confirmDeleteDb() {
|
||||
if (!confirm('This will DELETE the database file and recreate an empty one. Continue?')) return;
|
||||
try {
|
||||
const res = await fetch('/api/settings/database', { method: 'DELETE' });
|
||||
const result = await res.json();
|
||||
const el = document.getElementById('db-info');
|
||||
if (result.success) {
|
||||
el.textContent = result.message;
|
||||
el.classList.remove('error');
|
||||
el.style.display = 'block';
|
||||
} else {
|
||||
el.textContent = result.message || 'Failed to delete DB';
|
||||
el.classList.add('error');
|
||||
el.style.display = 'block';
|
||||
}
|
||||
} catch (err) {
|
||||
const el = document.getElementById('db-info');
|
||||
el.textContent = 'Error deleting DB: ' + err.message;
|
||||
el.classList.add('error');
|
||||
el.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', loadApiKeys);
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user