updated web interface - v3

This commit is contained in:
2025-08-19 07:09:23 -07:00
parent 07d19cfd7a
commit b77dbdcc23
24 changed files with 2727 additions and 445 deletions

View File

@@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="navigation"></div>
<div class="activities-container">
<div class="card activities-table-card">
<div class="card-header">
<h3>Activities</h3>
</div>
<div class="table-container">
<table class="activities-table" id="activities-table">
<thead>
<tr>
<th>Date</th>
<th>Activity Type</th>
<th>Duration</th>
<th>Distance</th>
<th>Max HR</th>
<th>Power</th>
</tr>
</thead>
<tbody id="activities-tbody">
<!-- Data populated by JavaScript -->
</tbody>
</table>
</div>
<div class="pagination-container">
<div class="pagination" id="pagination">
<!-- Pagination controls -->
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block page_scripts %}
<script src="/static/activities.js"></script>
{% endblock %}

View File

@@ -3,46 +3,17 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GarminSync Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<title>GarminSync</title>
<link href="/static/style.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link href="/static/components.css" rel="stylesheet">
<link href="/static/responsive.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="/">GarminSync</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" href="/">
<i class="fas fa-tachometer-alt me-1"></i> Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/logs">
<i class="fas fa-clipboard-list me-1"></i> Logs
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/config">
<i class="fas fa-cog me-1"></i> Configuration
</a>
</li>
</ul>
</div>
</div>
</nav>
{% block content %}{% endblock %}
<div class="container mt-4">
{% block content %}{% endblock %}
</div>
<script src="/static/navigation.js"></script>
<script src="/static/utils.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="/static/app.js"></script>
{% block page_scripts %}{% endblock %}
</body>
</html>

View File

@@ -2,11 +2,14 @@
{% block content %}
<div class="container">
<h1>GarminSync Configuration</h1>
<div class="navigation"></div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card">
<div class="card-header">
<h3>GarminSync Configuration</h3>
</div>
<div class="card-body">
<div class="card mb-4">
<div class="card-header">Daemon Settings</div>
<div class="card-body">
<form id="daemon-config-form">
@@ -28,20 +31,25 @@
</form>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">Daemon Status</div>
<div class="card-body">
<p>Current Status: <span id="daemon-status-text">{{ config.status|capitalize }}</span></p>
<p>Last Run: <span id="daemon-last-run">{{ config.last_run or 'Never' }}</span></p>
<p>Next Run: <span id="daemon-next-run">{{ config.next_run or 'Not scheduled' }}</span></p>
<div class="stat-item">
<label>Current Status:</label>
<span id="daemon-status-text">{{ config.status|capitalize }}</span>
</div>
<div class="stat-item">
<label>Last Run:</label>
<span id="daemon-last-run">{{ config.last_run or 'Never' }}</span>
</div>
<div class="stat-item">
<label>Next Run:</label>
<span id="daemon-next-run">{{ config.next_run or 'Not scheduled' }}</span>
</div>
<div class="mt-3">
<button id="start-daemon-btn" class="btn btn-success mr-2">
<button id="start-daemon-btn" class="btn btn-success">
Start Daemon
</button>
<button id="stop-daemon-btn" class="btn btn-danger">
@@ -53,7 +61,9 @@
</div>
</div>
</div>
{% endblock %}
{% block page_scripts %}
<script>
document.addEventListener('DOMContentLoaded', function() {
// Form submission handler
@@ -74,14 +84,14 @@ document.addEventListener('DOMContentLoaded', function() {
});
if (response.ok) {
alert('Configuration saved successfully');
Utils.showSuccess('Configuration saved successfully');
updateStatus();
} else {
const error = await response.json();
alert(`Error: ${error.detail}`);
Utils.showError(`Error: ${error.detail}`);
}
} catch (error) {
alert('Failed to save configuration: ' + error.message);
Utils.showError('Failed to save configuration: ' + error.message);
}
});
@@ -90,14 +100,14 @@ document.addEventListener('DOMContentLoaded', function() {
try {
const response = await fetch('/api/daemon/start', { method: 'POST' });
if (response.ok) {
alert('Daemon started successfully');
Utils.showSuccess('Daemon started successfully');
updateStatus();
} else {
const error = await response.json();
alert(`Error: ${error.detail}`);
Utils.showError(`Error: ${error.detail}`);
}
} catch (error) {
alert('Failed to start daemon: ' + error.message);
Utils.showError('Failed to start daemon: ' + error.message);
}
});
@@ -105,14 +115,14 @@ document.addEventListener('DOMContentLoaded', function() {
try {
const response = await fetch('/api/daemon/stop', { method: 'POST' });
if (response.ok) {
alert('Daemon stopped successfully');
Utils.showSuccess('Daemon stopped successfully');
updateStatus();
} else {
const error = await response.json();
alert(`Error: ${error.detail}`);
Utils.showError(`Error: ${error.detail}`);
}
} catch (error) {
alert('Failed to stop daemon: ' + error.message);
Utils.showError('Failed to stop daemon: ' + error.message);
}
});

View File

@@ -2,100 +2,46 @@
{% block content %}
<div class="container">
<h1>GarminSync Dashboard</h1>
<div class="navigation"></div>
<div class="row">
<!-- Real-time Activity Counter -->
<div class="col-md-3">
<div class="card bg-info text-white">
<div class="card-body">
<h4 id="sync-status">Idle</h4>
<p>Current Operation</p>
<div class="layout-grid">
<!-- Left Sidebar -->
<div class="sidebar">
<div class="card sync-card">
<button id="sync-now-btn" class="btn btn-primary btn-large">
<i class="icon-sync"></i>
Sync Now
</button>
<div class="sync-status" id="sync-status">
Ready to sync
</div>
</div>
<div class="card statistics-card">
<h3>Statistics</h3>
<div class="stat-item">
<label>Total Activities:</label>
<span id="total-activities">{{stats.total}}</span>
</div>
<div class="stat-item">
<label>Downloaded:</label>
<span id="downloaded-activities">{{stats.downloaded}}</span>
</div>
<div class="stat-item">
<label>Missing:</label>
<span id="missing-activities">{{stats.missing}}</span>
</div>
</div>
</div>
<!-- Activity Progress Chart -->
<div class="col-md-5">
<div class="card">
<div class="card-header">Activity Progress</div>
<div class="card-body">
<canvas id="activityChart" width="400" height="200"></canvas>
<!-- Right Content Area -->
<div class="main-content">
<div class="card log-display">
<div class="card-header">
<h3>Log Data</h3>
</div>
</div>
</div>
<!-- Daemon Status -->
<div class="col-md-4">
<div class="card">
<div class="card-header">Daemon Status</div>
<div class="card-body" id="daemon-status">
<!-- Populated by JavaScript -->
</div>
</div>
</div>
</div>
<div class="row mt-4">
<!-- Statistics Card -->
<div class="col-md-6">
<div class="card">
<div class="card-header">Statistics</div>
<div class="card-body">
<p>Total Activities: {{ stats.total }}</p>
<p>Downloaded: {{ stats.downloaded }}</p>
<p>Missing: {{ stats.missing }}</p>
<p>Last Sync: {{ stats.last_sync }}</p>
</div>
</div>
</div>
<!-- Quick Actions Card -->
<div class="col-md-6">
<div class="card">
<div class="card-header">Quick Actions</div>
<div class="card-body">
<button class="btn btn-primary" onclick="triggerSync()">
Sync Now
</button>
<button class="btn btn-secondary" onclick="toggleDaemon()">
Toggle Daemon
</button>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">Recent Activity</div>
<div class="card-body" id="recent-logs">
<!-- Populated by JavaScript -->
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">Schedule Configuration</div>
<div class="card-body">
<form id="schedule-form">
<div class="form-group">
<label for="schedule-enabled">Enable Scheduled Sync</label>
<input type="checkbox" id="schedule-enabled">
</div>
<div class="form-group">
<label for="cron-schedule">Cron Schedule</label>
<input type="text" class="form-control" id="cron-schedule"
placeholder="0 */6 * * *" title="Every 6 hours">
</div>
<button type="submit" class="btn btn-primary">
Update Schedule
</button>
</form>
<div class="log-content" id="log-content">
<!-- Real-time log updates will appear here -->
</div>
</div>
</div>
@@ -103,6 +49,6 @@
</div>
{% endblock %}
{% block scripts %}
<script src="/static/charts.js"></script>
{% block page_scripts %}
<script src="/static/home.js"></script>
{% endblock %}

View File

@@ -2,51 +2,51 @@
{% block content %}
<div class="container">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Sync Logs</h1>
<div>
<button class="btn btn-secondary" onclick="refreshLogs()">Refresh</button>
<button class="btn btn-warning" onclick="clearLogs()">Clear Logs</button>
</div>
</div>
<div class="navigation"></div>
<!-- Filters -->
<div class="card mb-4">
<div class="card-header">Filters</div>
<div class="card">
<div class="card-header">
<h3>Sync Logs</h3>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
<select id="status-filter" class="form-control">
<option value="">All Statuses</option>
<option value="success">Success</option>
<option value="error">Error</option>
<option value="partial">Partial</option>
</select>
</div>
<div class="col-md-3">
<select id="operation-filter" class="form-control">
<option value="">All Operations</option>
<option value="sync">Sync</option>
<option value="download">Download</option>
<option value="daemon">Daemon</option>
</select>
</div>
<div class="col-md-3">
<input type="date" id="date-filter" class="form-control">
</div>
<div class="col-md-3">
<button class="btn btn-primary" onclick="applyFilters()">Apply</button>
<!-- Filters -->
<div class="card mb-4">
<div class="card-header">Filters</div>
<div class="card-body">
<div class="form-group">
<label for="status-filter">Status</label>
<select id="status-filter" class="form-control">
<option value="">All Statuses</option>
<option value="success">Success</option>
<option value="error">Error</option>
<option value="partial">Partial</option>
</select>
</div>
<div class="form-group">
<label for="operation-filter">Operation</label>
<select id="operation-filter" class="form-control">
<option value="">All Operations</option>
<option value="sync">Sync</option>
<option value="download">Download</option>
<option value="daemon">Daemon</option>
</select>
</div>
<div class="form-group">
<label for="date-filter">Date</label>
<input type="date" id="date-filter" class="form-control">
</div>
<button class="btn btn-primary" onclick="applyFilters()">Apply Filters</button>
<button class="btn btn-secondary" onclick="refreshLogs()">Refresh</button>
<button class="btn btn-warning" onclick="clearLogs()">Clear Logs</button>
</div>
</div>
</div>
</div>
<!-- Logs Table -->
<div class="card">
<div class="card-header">Log Entries</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped" id="logs-table">
<!-- Logs Table -->
<div class="table-container">
<table class="activities-table" id="logs-table">
<thead>
<tr>
<th>Timestamp</th>
@@ -64,16 +64,16 @@
</div>
<!-- Pagination -->
<nav>
<ul class="pagination justify-content-center" id="pagination">
<div class="pagination-container">
<div class="pagination" id="pagination">
<!-- Populated by JavaScript -->
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
{% block page_scripts %}
<script src="/static/logs.js"></script>
{% endblock %}