Files
Daniel Elliott 8ba7c605f1 Add device settings management and web panel sync API
Features:
- New DeviceSettings admin page at /devicesettings
- Manage device server configurations (URL, mode, deviceId)
- 3 new API endpoints for APK sync functionality
- UserSettings database model with SQLite storage

Implementation:
- ServerSettingsController.cs with getUserSettings, updateUserSettings, getAllUserSettings
- DeviceSettings.cshtml Razor page with add/edit/delete UI
- DeviceSettings.cshtml.cs page model with CRUD operations
- UserSettings model added to ApiModels.cs
- UserSettings DbSet added to RR3DbContext
- EF Core migration: 20260219180936_AddUserSettings
- Link added to Admin dashboard

API Endpoints:
- GET /api/settings/getUserSettings?deviceId={id} - APK sync endpoint
- POST /api/settings/updateUserSettings - Web panel update
- GET /api/settings/getAllUserSettings - Admin list view

Database Schema:
- UserSettings table (Id, DeviceId, ServerUrl, Mode, LastUpdated)
- SQLite storage with EF Core migrations

Integration:
- Works with APK SettingsActivity sync button
- Real-time configuration updates
- Emoji logging for all operations
- Device-specific server URL management

Usage:
1. Admin configures device settings at /devicesettings
2. User opens RR3 APK and taps Sync from Web Panel
3. APK downloads settings via API
4. Settings saved to SharedPreferences
5. Game restart applies configuration

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 10:15:02 -08:00

232 lines
9.7 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@page "/admin"
@model RR3CommunityServer.Pages.AdminModel
@{
Layout = "_Layout";
ViewData["Title"] = "Dashboard";
}
<div class="container-fluid mt-4">
<!-- Header -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center">
<div>
<h1 class="display-4">🏎️ RR3 Community Server</h1>
<p class="text-muted">Administration Dashboard</p>
</div>
<div class="text-end">
<div class="badge bg-success fs-6">🟢 Server Online</div>
<div class="text-muted small mt-1">Uptime: @Model.Uptime</div>
</div>
</div>
</div>
</div>
<!-- Statistics Cards -->
<div class="row g-3 mb-4">
<div class="col-md-3">
<div class="card border-primary">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0">Total Users</h6>
<h2 class="mb-0">@Model.TotalUsers</h2>
</div>
<div class="fs-1 text-primary">👥</div>
</div>
<small class="text-muted">Registered players</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card border-success">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0">Active Sessions</h6>
<h2 class="mb-0">@Model.ActiveSessions</h2>
</div>
<div class="fs-1 text-success">🔄</div>
</div>
<small class="text-muted">Currently online</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card border-info">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0">Total Devices</h6>
<h2 class="mb-0">@Model.TotalDevices</h2>
</div>
<div class="fs-1 text-info">📱</div>
</div>
<small class="text-muted">Registered devices</small>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card border-warning">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-0">Catalog Items</h6>
<h2 class="mb-0">@Model.TotalCatalogItems</h2>
</div>
<div class="fs-1 text-warning">🏪</div>
</div>
<small class="text-muted">Available items</small>
</div>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header bg-dark text-white">
<h5 class="mb-0">⚡ Quick Actions</h5>
</div>
<div class="card-body">
<div class="d-flex gap-2 flex-wrap">
<a href="/admin/users" class="btn btn-primary">
<i class="bi bi-people"></i> Manage Users
</a>
<a href="/admin/catalog" class="btn btn-info">
<i class="bi bi-shop"></i> Manage Catalog
</a>
<a href="/admin/rewards" class="btn btn-warning">
<i class="bi bi-gift"></i> Manage Rewards
</a>
<a href="/admin/sessions" class="btn btn-success">
<i class="bi bi-clock-history"></i> View Sessions
</a>
<a href="/admin/purchases" class="btn btn-warning">
<i class="bi bi-cart"></i> View Purchases
</a>
<a href="/devicesettings" class="btn btn-primary">
<i class="bi bi-phone"></i> Device Settings
</a>
<a href="/admin/settings" class="btn btn-secondary">
<i class="bi bi-gear"></i> Server Settings
</a>
</div>
</div>
</div>
</div>
</div>
<!-- Recent Activity -->
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">📊 Recent Users</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Synergy ID</th>
<th>Joined</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var user in Model.RecentUsers)
{
<tr>
<td><code>@user.SynergyId</code></td>
<td><small>@user.CreatedAt.ToString("g")</small></td>
<td>
<a href="/admin/users?id=@user.Id" class="btn btn-sm btn-outline-primary">View</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<a href="/admin/users" class="btn btn-sm btn-link">View All Users →</a>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header bg-success text-white">
<h5 class="mb-0">🔄 Active Sessions</h5>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Session ID</th>
<th>Expires</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach (var session in Model.RecentSessions)
{
<tr>
<td><code>@session.SessionId.Substring(0, 8)...</code></td>
<td><small>@session.ExpiresAt.ToString("g")</small></td>
<td><span class="badge bg-success">Active</span></td>
</tr>
}
</tbody>
</table>
</div>
<a href="/admin/sessions" class="btn btn-sm btn-link">View All Sessions →</a>
</div>
</div>
</div>
</div>
<!-- Server Info -->
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header bg-dark text-white">
<h5 class="mb-0"> Server Information</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<dl class="row">
<dt class="col-sm-4">Server URL:</dt>
<dd class="col-sm-8"><code>@Model.ServerUrl</code></dd>
<dt class="col-sm-4">Platform:</dt>
<dd class="col-sm-8">@Model.Platform</dd>
<dt class="col-sm-4">.NET Version:</dt>
<dd class="col-sm-8">@Model.DotNetVersion</dd>
</dl>
</div>
<div class="col-md-6">
<dl class="row">
<dt class="col-sm-4">Database:</dt>
<dd class="col-sm-8">SQLite (EF Core)</dd>
<dt class="col-sm-4">API Endpoints:</dt>
<dd class="col-sm-8">12 active</dd>
<dt class="col-sm-4">Swagger:</dt>
<dd class="col-sm-8"><a href="/swagger" target="_blank">View API Docs</a></dd>
</dl>
</div>
</div>
</div>
</div>
</div>
</div>
</div>