diff --git a/backend/data/conf.json b/backend/data/conf.json deleted file mode 100644 index 2c87e84..0000000 --- a/backend/data/conf.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "server": { - "host": "0.0.0.0", - "port": 8443, - "tls_cert": "certs/cert.pem", - "tls_key": "certs/key.pem" - }, - "auth": { - "username": "admin", - "password": "admin" - }, - "serial": { - "enabled": false, - "port": "/dev/ttyACM0", - "baudrate": 115200, - "timeout": 1 - }, - "triggers": { - "GPIO3": { - "name": "Test", - "type": "GPIO3", - "music_file": "SONNERIE A.mp3", - "start_seconds": 0.0, - "end_seconds": null, - "volume": 80 - }, - "GPIO4": { - "name": "Test", - "type": "GPIO4", - "music_file": "SONNERIE A.mp3", - "start_seconds": 0.0, - "end_seconds": null, - "volume": 80 - } - } -} diff --git a/frontend/app/__pycache__/routes.cpython-312.pyc b/frontend/app/__pycache__/routes.cpython-312.pyc index 85b04cf..58ce088 100644 Binary files a/frontend/app/__pycache__/routes.cpython-312.pyc and b/frontend/app/__pycache__/routes.cpython-312.pyc differ diff --git a/frontend/app/routes.py b/frontend/app/routes.py index 42ae1e1..9450f04 100644 --- a/frontend/app/routes.py +++ b/frontend/app/routes.py @@ -21,7 +21,7 @@ from werkzeug.utils import secure_filename from .backend_client import BackendApiError, BackendClient, read_default_backend_url -ui = Blueprint("ui", __name__, template_folder="templates", static_folder="static") +ui = Blueprint("ui", __name__, template_folder="templates") GPIO_PATTERN = re.compile(r"^GPIO\d+$") ALLOWED_AUDIO_EXTENSIONS = {".mp3", ".wav", ".ogg", ".flac", ".aac", ".m4a"} diff --git a/frontend/app/static/css/style.css b/frontend/app/static/css/style.css deleted file mode 100644 index 9a08007..0000000 --- a/frontend/app/static/css/style.css +++ /dev/null @@ -1,455 +0,0 @@ -:root { - --bg: #f8f6ef; - --ink: #1f1c1a; - --panel: #fffef9; - --brand: #0f6f63; - --brand-strong: #0b544b; - --accent: #d66d2d; - --danger: #b13a2e; - --line: #d8d2c3; - --muted: #665e57; - --shadow: 0 12px 40px rgba(45, 37, 23, 0.12); -} - -* { - box-sizing: border-box; -} - -html, -body { - margin: 0; - padding: 0; - min-height: 100%; -} - -body { - font-family: "Noto Sans", "DejaVu Sans", "Segoe UI", "Helvetica Neue", Arial, sans-serif; - color: var(--ink); - background: - radial-gradient(circle at 15% -5%, #ffe8cc 0%, transparent 40%), - radial-gradient(circle at 100% 100%, #d5efe6 0%, transparent 40%), - var(--bg); - overflow-x: hidden; -} - -h1, -h2, -h3 { - font-family: "Noto Sans", "DejaVu Sans", "Segoe UI", "Helvetica Neue", Arial, sans-serif; - margin: 0 0 0.4rem; -} - -.muted { - color: var(--muted); -} - -.bg-orb { - position: fixed; - border-radius: 999px; - pointer-events: none; - filter: blur(4px); - z-index: -1; -} - -.bg-orb-one { - width: 260px; - height: 260px; - background: rgba(214, 109, 45, 0.25); - top: -60px; - right: -40px; -} - -.bg-orb-two { - width: 220px; - height: 220px; - background: rgba(15, 111, 99, 0.18); - bottom: -70px; - left: -40px; -} - -.reveal { - animation: reveal-up 0.45s ease both; -} - -.delay-1 { - animation-delay: 0.05s; -} - -.delay-2 { - animation-delay: 0.11s; -} - -.delay-3 { - animation-delay: 0.16s; -} - -@keyframes reveal-up { - from { - opacity: 0; - transform: translateY(8px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.flash-stack { - position: fixed; - top: 1rem; - right: 1rem; - display: grid; - gap: 0.5rem; - z-index: 50; -} - -.flash { - padding: 0.7rem 0.95rem; - border-radius: 12px; - box-shadow: var(--shadow); - font-size: 0.9rem; - max-width: min(82vw, 420px); - opacity: 1; - transform: translateY(0); - transition: opacity 0.35s ease, transform 0.35s ease; -} - -.flash.is-hiding { - opacity: 0; - transform: translateY(-6px); -} - -.flash-success { - background: #e3f7ef; - border: 1px solid #9cdcbc; -} - -.flash-error { - background: #fdeceb; - border: 1px solid #f2b2ad; -} - -.flash-info { - background: #edf4ff; - border: 1px solid #bed4f9; -} - -.auth-wrap { - min-height: 100vh; - display: grid; - place-items: center; - padding: 1rem; -} - -.auth-card { - width: min(560px, 100%); - background: var(--panel); - border: 1px solid var(--line); - box-shadow: var(--shadow); - border-radius: 22px; - padding: 2rem; -} - -.auth-card h1 { - margin-bottom: 2rem; -} - -.auth-inline-error { - margin: -1rem 0 1rem; - padding: 0.65rem 0.75rem; - border-radius: 10px; - border: 1px solid #f2b2ad; - background: #fdeceb; - color: #7a1f16; - font-size: 0.9rem; -} - -.form-grid { - display: grid; - gap: 0.9rem; -} - -.form-grid > * { - min-width: 0; -} - -label { - display: grid; - gap: 0.4rem; - font-size: 0.9rem; -} - -input, -button { - border-radius: 12px; - border: 1px solid var(--line); - font: inherit; - max-width: 100%; -} - -input { - display: block; - width: 100%; - background: #fff; - padding: 0.65rem 0.75rem; -} - -input[type="file"] { - min-width: 0; -} - -button, -.small-button, -.ghost-link { - text-decoration: none; - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: transform 0.08s ease, background-color 0.2s ease; -} - -button { - background: var(--brand); - color: #fff; - padding: 0.65rem 0.85rem; - border: 0; -} - -button:hover, -.small-button:hover, -.ghost-link:hover { - transform: translateY(-1px); -} - -button.danger { - background: var(--danger); -} - -button.small { - padding: 0.45rem 0.6rem; - font-size: 0.82rem; -} - -.topbar { - margin: 1.2rem; - padding: 1rem; - background: var(--panel); - border: 1px solid var(--line); - border-radius: 16px; - display: flex; - justify-content: space-between; - align-items: center; - gap: 1rem; -} - -.topbar-actions { - display: flex; - align-items: center; - gap: 0.65rem; -} - -.ghost-link { - padding: 0.65rem 0.85rem; - border-radius: 12px; - border: 1px solid var(--line); - color: var(--ink); -} - -.dashboard-grid { - display: grid; - gap: 1rem; - grid-template-columns: repeat(12, minmax(0, 1fr)); - padding: 0 1.2rem 1.2rem; -} - -.panel { - background: var(--panel); - border: 1px solid var(--line); - border-radius: 16px; - padding: 1rem; - box-shadow: var(--shadow); -} - -.panel:nth-child(1) { - grid-column: span 4; -} - -.panel:nth-child(2) { - grid-column: span 8; -} - -.panel:nth-child(3) { - grid-column: span 12; -} - -.time-row { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 0.8rem; -} - -.time-row > * { - min-width: 0; -} - -.volume-row { - display: flex; - flex-direction: column; - gap: 0.3rem; -} - -.volume-row input[type="range"] { - width: 100%; - accent-color: var(--brand); -} - -.table-wrap { - overflow-x: auto; -} - -table { - width: 100%; - border-collapse: collapse; -} - -th, -td { - border-bottom: 1px solid var(--line); - text-align: left; - padding: 0.45rem; - font-size: 0.9rem; -} - -.trigger-row { - cursor: pointer; -} - -.trigger-row:hover { - background: #f7f2e6; -} - -.inline-form { - display: inline-block; - margin-right: 0.35rem; -} - -.upload-row { - display: flex; - flex-wrap: wrap; - gap: 0.7rem; - margin-bottom: 0.75rem; -} - -.audio-player-card { - border: 1px solid var(--line); - border-radius: 12px; - padding: 0.75rem; - margin-bottom: 0.8rem; - background: #fff; -} - -#browser-audio-player { - width: 100%; - margin-top: 0.35rem; -} - -.audio-time { - margin: 0.5rem 0 0; - font-size: 0.9rem; - color: var(--muted); -} - -.modal-backdrop { - position: fixed; - inset: 0; - background: rgba(20, 18, 15, 0.45); - display: none; - align-items: center; - justify-content: center; - padding: 1rem; - z-index: 120; -} - -.modal-backdrop.is-open { - display: flex; -} - -.modal-card { - width: min(460px, 100%); - background: var(--panel); - border: 1px solid var(--line); - border-radius: 14px; - box-shadow: var(--shadow); - padding: 1rem; -} - -.modal-actions { - margin-top: 0.9rem; - display: flex; - justify-content: flex-end; - gap: 0.6rem; -} - -.audio-list { - list-style: none; - margin: 0; - padding: 0; - display: grid; - gap: 0.6rem; -} - -.audio-list li { - border: 1px solid var(--line); - border-radius: 12px; - padding: 0.7rem; - display: flex; - justify-content: space-between; - gap: 0.8rem; - align-items: center; - background: #fff; -} - -.audio-actions { - display: flex; - align-items: center; - gap: 0.45rem; -} - -.small-button { - border: 1px solid var(--line); - border-radius: 10px; - padding: 0.45rem 0.6rem; - font-size: 0.82rem; - color: var(--ink); - background: #fff; -} - -@media (max-width: 1080px) { - .panel:nth-child(1), - .panel:nth-child(2), - .panel:nth-child(3) { - grid-column: span 12; - } -} - -@media (max-width: 640px) { - .topbar { - margin: 0.8rem; - flex-direction: column; - align-items: flex-start; - } - - .dashboard-grid { - padding: 0 0.8rem 0.8rem; - } - - .audio-list li { - flex-direction: column; - align-items: flex-start; - } - - .time-row { - grid-template-columns: 1fr; - } -} diff --git a/frontend/app/templates/base.html b/frontend/app/templates/base.html index 1e8da2e..7d4e81f 100644 --- a/frontend/app/templates/base.html +++ b/frontend/app/templates/base.html @@ -4,7 +4,463 @@ pySonnerie - Interface de controle - +