- add portal API and UI action to delete non-default devices - protect the configured portal default device from deletion - document that trip/history pages still scope to the single DEVICE_NAME Co-authored-by: Copilot <[email protected]>
161 lines
8.3 KiB
HTML
161 lines
8.3 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Device settings – Yaris OBD Remote{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="d-flex flex-column flex-md-row align-items-md-center justify-content-between gap-2 mb-3">
|
||
<div>
|
||
<h3 class="text-dark mb-1 fw-bold">Device settings</h3>
|
||
<p class="text-muted mb-0">
|
||
Manage registered Pi devices, one-time API keys, and synced identity values.
|
||
</p>
|
||
</div>
|
||
<button class="btn btn-primary" id="device-settings-save" type="submit" form="device-settings-form" disabled>
|
||
<i class="fas fa-save me-1"></i>Save device settings
|
||
</button>
|
||
</div>
|
||
|
||
<div id="device-settings-message" class="alert" role="status" hidden></div>
|
||
|
||
<div class="row g-3">
|
||
<div class="col-12 col-xl-4">
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-header py-2 d-flex align-items-center justify-content-between">
|
||
<h6 class="text-primary fw-bold m-0">Registered devices</h6>
|
||
<span class="badge bg-secondary" id="device-count">0</span>
|
||
</div>
|
||
<div class="list-group list-group-flush" id="device-list">
|
||
<div class="list-group-item text-muted small">Loading devices…</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card shadow-sm">
|
||
<div class="card-header py-2">
|
||
<h6 class="text-primary fw-bold m-0">Register new device</h6>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="mb-3">
|
||
<label class="form-label" for="new-device-name">Device name</label>
|
||
<input class="form-control" id="new-device-name" maxlength="100" placeholder="yaris-2013">
|
||
<div class="form-text">This becomes <code>YARIS_DEVICE_NAME</code> on the Pi.</div>
|
||
</div>
|
||
<button class="btn btn-outline-primary" id="create-device-button" type="button">
|
||
<i class="fas fa-plus me-1"></i>Create device + API key
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-12 col-xl-8">
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-header py-2 d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||
<h6 class="text-primary fw-bold m-0">Selected device</h6>
|
||
<div class="d-flex flex-wrap gap-2">
|
||
<button class="btn btn-outline-secondary btn-sm" id="rotate-key-button" type="button" disabled>
|
||
<i class="fas fa-key me-1"></i>Rotate API key
|
||
</button>
|
||
<button class="btn btn-outline-primary btn-sm" id="request-sync-button" type="button" disabled>
|
||
<i class="fas fa-rotate me-1"></i>Request sync
|
||
</button>
|
||
<button class="btn btn-outline-danger btn-sm" id="delete-device-button" type="button" disabled>
|
||
<i class="fas fa-trash-alt me-1"></i>Delete device
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row g-3 mb-3 small">
|
||
<div class="col-md-6">
|
||
<div class="text-muted">Device name</div>
|
||
<div class="fw-semibold" id="selected-device-name">—</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="text-muted">Portal default</div>
|
||
<div class="fw-semibold" id="selected-device-default">—</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="text-muted">Last seen</div>
|
||
<div class="fw-semibold" id="selected-device-last-seen">—</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<div class="text-muted">Last config sync</div>
|
||
<div class="fw-semibold" id="selected-device-last-sync">—</div>
|
||
</div>
|
||
</div>
|
||
|
||
<form id="device-settings-form" novalidate>
|
||
<div class="row g-3">
|
||
<div class="col-12 col-md-6">
|
||
<label class="form-label" for="owner_name">Owner name</label>
|
||
<input class="form-control" id="owner_name" name="owner_name" maxlength="100" required disabled>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<label class="form-label" for="car_model">Car model</label>
|
||
<input class="form-control" id="car_model" name="car_model" maxlength="100" required disabled>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<label class="form-label" for="device_name">Display device name</label>
|
||
<input class="form-control" id="device_name" name="device_name" maxlength="100" disabled>
|
||
<div class="form-text">Friendly label shown in the portal/device UI.</div>
|
||
</div>
|
||
<div class="col-12 col-md-6">
|
||
<label class="form-label" for="avatar_path">Avatar path</label>
|
||
<input class="form-control" id="avatar_path" name="avatar_path" maxlength="255" placeholder="img/yaris.png" disabled>
|
||
<div class="form-text">Relative to the shared <code>static/</code> folder.</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card shadow-sm mb-3">
|
||
<div class="card-header py-2">
|
||
<h6 class="text-primary fw-bold m-0">Pi credential handoff</h6>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="small text-muted mb-3">
|
||
Create or rotate a key, then paste these into the Pi Settings page under Remote server credentials.
|
||
</p>
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="credential-server-url">Server URL</label>
|
||
<input class="form-control" id="credential-server-url" readonly>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="credential-device-name">Device name</label>
|
||
<input class="form-control" id="credential-device-name" readonly>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label" for="credential-api-key">API key</label>
|
||
<input class="form-control" id="credential-api-key" readonly placeholder="Shown only after create / rotate">
|
||
</div>
|
||
</div>
|
||
<div class="d-flex flex-wrap gap-2 mt-3">
|
||
<button class="btn btn-outline-secondary btn-sm" id="copy-credentials-button" type="button" disabled>
|
||
<i class="fas fa-copy me-1"></i>Copy credentials
|
||
</button>
|
||
<span class="small text-muted align-self-center">Raw key is only shown immediately after create/rotate.</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card shadow-sm">
|
||
<div class="card-header py-2">
|
||
<h6 class="text-primary fw-bold m-0">Sync behavior</h6>
|
||
</div>
|
||
<div class="card-body small text-muted">
|
||
<ul class="mb-0 ps-3">
|
||
<li><strong>Request sync</strong> means “fetch this config on the Pi's next online contact”.</li>
|
||
<li>The car can still be offline; the remote server cannot push directly into it.</li>
|
||
<li>Use the Pi's local <strong>Sync now</strong> button for immediate pull attempts.</li>
|
||
<li><strong>Delete device</strong> removes that device row and cascades its trips, tracking logs, and dashcam files from the server.</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script src="{{ url_for('static', filename='js/portal-device-settings.js') }}"></script>
|
||
{% endblock %}
|