(feature) add Django setup flow for initial pobsync configuration
Add staff-only UI routes for creating/editing the default GlobalConfig and creating the first HostConfig from the dashboard. Improve the empty dashboard state so a fresh database guides the user towards the next useful setup action instead of only showing empty tables. Cover the setup flow with view tests for empty state prompts, global config creation, and host creation.
This commit is contained in:
@@ -8,8 +8,8 @@ from django.views.decorators.http import require_POST
|
||||
|
||||
from pobsync.errors import ConfigError
|
||||
|
||||
from .forms import HostConfigForm, ScheduleConfigForm
|
||||
from .models import BackupRun, HostConfig, ScheduleConfig, SnapshotRecord
|
||||
from .forms import CreateHostConfigForm, GlobalConfigForm, HostConfigForm, ScheduleConfigForm
|
||||
from .models import BackupRun, GlobalConfig, HostConfig, ScheduleConfig, SnapshotRecord
|
||||
from .retention import run_sql_retention_plan
|
||||
from .snapshot_discovery import discover_snapshots
|
||||
|
||||
@@ -22,8 +22,10 @@ def dashboard(request):
|
||||
)
|
||||
context = {
|
||||
"hosts": host_qs,
|
||||
"global_config": GlobalConfig.objects.filter(name="default").first(),
|
||||
"latest_runs": BackupRun.objects.select_related("host", "snapshot").order_by("-created_at")[:10],
|
||||
"counts": {
|
||||
"global_configs": GlobalConfig.objects.count(),
|
||||
"hosts": HostConfig.objects.count(),
|
||||
"enabled_hosts": HostConfig.objects.filter(enabled=True).count(),
|
||||
"schedules": ScheduleConfig.objects.count(),
|
||||
@@ -37,6 +39,49 @@ def dashboard(request):
|
||||
return render(request, "pobsync_backend/dashboard.html", context)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def edit_global_config(request):
|
||||
global_config = GlobalConfig.objects.filter(name="default").first()
|
||||
if request.method == "POST":
|
||||
form = GlobalConfigForm(request.POST, instance=global_config)
|
||||
if form.is_valid():
|
||||
saved_config = form.save()
|
||||
messages.success(request, f"Global config saved for {saved_config.name}.")
|
||||
return redirect("dashboard")
|
||||
else:
|
||||
form = GlobalConfigForm(instance=global_config, initial=_default_global_initial())
|
||||
|
||||
return render(
|
||||
request,
|
||||
"pobsync_backend/global_form.html",
|
||||
{
|
||||
"global_config": global_config,
|
||||
"form": form,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def create_host_config(request):
|
||||
if request.method == "POST":
|
||||
form = CreateHostConfigForm(request.POST)
|
||||
if form.is_valid():
|
||||
host_config = form.save()
|
||||
messages.success(request, f"Host config created for {host_config.host}.")
|
||||
return redirect("host_detail", host=host_config.host)
|
||||
else:
|
||||
form = CreateHostConfigForm(initial=_default_host_initial())
|
||||
|
||||
return render(
|
||||
request,
|
||||
"pobsync_backend/host_form.html",
|
||||
{
|
||||
"host": None,
|
||||
"form": form,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def host_detail(request, host: str):
|
||||
host_config = get_object_or_404(HostConfig, host=host)
|
||||
@@ -158,3 +203,29 @@ def _default_schedule_initial() -> dict[str, object]:
|
||||
"enabled": True,
|
||||
"prune_max_delete": 10,
|
||||
}
|
||||
|
||||
|
||||
def _default_global_initial() -> dict[str, object]:
|
||||
return {
|
||||
"name": "default",
|
||||
"backup_root": "/opt/pobsync/backups",
|
||||
"pobsync_home": "/opt/pobsync",
|
||||
"ssh_user": "root",
|
||||
"ssh_port": 22,
|
||||
"rsync_binary": "rsync",
|
||||
"default_source_root": "/",
|
||||
"retention_daily": 14,
|
||||
"retention_weekly": 8,
|
||||
"retention_monthly": 12,
|
||||
"retention_yearly": 0,
|
||||
}
|
||||
|
||||
|
||||
def _default_host_initial() -> dict[str, object]:
|
||||
return {
|
||||
"enabled": True,
|
||||
"retention_daily": 14,
|
||||
"retention_weekly": 8,
|
||||
"retention_monthly": 12,
|
||||
"retention_yearly": 0,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user