mirror of
https://github.com/migatu/astrololo.git
synced 2026-07-14 13:34:38 +00:00
16d35c16dc
Trzy niezależne usługi FastAPI komunikujące się przez HTTP/JSON, każda zna tylko adres warstwy bezpośrednio pod nią: - presentation (:8000) — strona WWW + formularz - logic (:8001) — reguły biznesowe, pośrednik - data (:8002) — wyszukiwanie danych za interfejsem DataProvider Warstwa danych: czytanie setek plików .xlsx z wykrywaniem nagłówka i mapowaniem układu kolumn na schemat kanoniczny, z 4-poziomowym cache (schemat L1, Parquet L2, wyniki zapytań L3, odwrócony indeks L4) i unieważnianiem po odcisku pliku. Gotowa ścieżka migracji do SQL (ingest/to_sql.py + SqlDataProvider, przełączane przez DATA_PROVIDER). Zawiera docker-compose, Makefile, generator danych przykładowych. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
1.9 KiB
HTML
63 lines
1.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="pl">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>astrololo</title>
|
|
<link rel="stylesheet" href="/static/styles.css">
|
|
</head>
|
|
<body>
|
|
<main>
|
|
<h1>astrololo</h1>
|
|
<p class="sub">Warstwa prezentacji → logiczna → bazodanowa</p>
|
|
|
|
<form method="post" action="/">
|
|
<div class="row">
|
|
<input type="text" name="query" placeholder="Szukana fraza…"
|
|
value="{{ form.query or '' }}" autofocus required>
|
|
<select name="field">
|
|
{% for f in ["name", "id", "symbol", "category", "value"] %}
|
|
<option value="{{ f }}" {{ 'selected' if form.field == f else '' }}>{{ f }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<button type="submit">Szukaj</button>
|
|
</div>
|
|
<div class="opts">
|
|
<label><input type="checkbox" name="exact" value="true"
|
|
{{ 'checked' if form.exact else '' }}> dokładne</label>
|
|
<label>limit
|
|
<input type="number" name="limit" min="1" max="200" value="{{ form.limit or 25 }}">
|
|
</label>
|
|
</div>
|
|
</form>
|
|
|
|
{% if error %}
|
|
<div class="error">{{ error }}</div>
|
|
{% endif %}
|
|
|
|
{% if result %}
|
|
<div class="meta">
|
|
Znaleziono <strong>{{ result.count }}</strong> ·
|
|
provider: {{ result.meta.data_provider }} ·
|
|
cache: {{ result.meta.data_cache }} ·
|
|
{{ result.meta.data_elapsed_ms }} ms
|
|
</div>
|
|
{% if result.results %}
|
|
<table>
|
|
<thead>
|
|
<tr>{% for col in result.results[0].keys() %}<th>{{ col }}</th>{% endfor %}</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for row in result.results %}
|
|
<tr>{% for v in row.values() %}<td>{{ v }}</td>{% endfor %}</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p class="empty">Brak wyników.</p>
|
|
{% endif %}
|
|
{% endif %}
|
|
</main>
|
|
</body>
|
|
</html>
|