auto-sync: 2026-05-16 20:40:01
This commit is contained in:
285
tasks/enduro-trails/DEV_TASK_RESTORE_UI.md
Normal file
285
tasks/enduro-trails/DEV_TASK_RESTORE_UI.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# DEV TASK: Восстановление UI Enduro Trails до состояния фазы 5.4
|
||||
|
||||
**Статус:** Ready for dev
|
||||
**Проект:** enduro-trails
|
||||
**Фаза:** 5.4 (восстановление)
|
||||
**Приоритет:** 🔴 Критический
|
||||
|
||||
---
|
||||
|
||||
## Цель
|
||||
|
||||
Восстановить `index.html` и `app.js` до состояния фазы 5.4 — с тёмной темой, правильным toolbar, кнопкой рельефа, линейкой масштаба, зумом и всеми фичами фаз 5.0–5.4.
|
||||
|
||||
## Контекст
|
||||
|
||||
Актуальная версия UI была только в Docker-контейнере (через `docker cp`) и не была закоммичена в git. Контейнер удалён. Текущий `index.html` на сервере — версия до фазы 5 (28160 байт, без terrain, без правильного toolbar).
|
||||
|
||||
Нужно восстановить UI по документации.
|
||||
|
||||
---
|
||||
|
||||
## Инфраструктура
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Сервер | `slin@82.22.50.71`, sudo: `motoZ@yaz2010` |
|
||||
| SSH | через node ssh2 из `/home/node/.openclaw/workspace/tasks/enduro-trails/prototype/` |
|
||||
| Целевые файлы | `/home/slin/repos/enduro-trails/src/web/index.html` |
|
||||
| | `/home/slin/repos/enduro-trails/src/web/app.js` |
|
||||
| | `/home/slin/repos/enduro-trails/src/web/app.css` |
|
||||
| Контейнер | `enduro-trails-app-1` (volume mount — файлы сразу видны без рестарта) |
|
||||
| URL | `https://openclaw.mva154.duckdns.org/enduro/` |
|
||||
| Деплой | Файлы монтированы через volume `./src/web:/app/src/web` — просто записать файлы на сервер |
|
||||
|
||||
---
|
||||
|
||||
## Текущее состояние файлов
|
||||
|
||||
- `index.html` на сервере: 30386 байт — **старая версия** (toolbar без terrain, нет линейки масштаба)
|
||||
- `app.js` на сервере: 113632 байт — **есть terrain код** (toggleTerrain, applyTerrainLayer)
|
||||
- `app.css` на сервере: 38764 байт
|
||||
|
||||
---
|
||||
|
||||
## Что должно быть в финальном UI
|
||||
|
||||
### index.html — обязательные элементы:
|
||||
|
||||
**1. Map controls (правый верхний угол):**
|
||||
```html
|
||||
<div id="map-controls">
|
||||
<button class="map-btn" id="btn-compass" onclick="toggleCompass()"><!-- compass SVG --></button>
|
||||
<button class="map-btn" onclick="locateMe()"><!-- locate SVG --></button>
|
||||
<button class="map-btn" id="btn-theme" onclick="toggleTheme()"><!-- theme SVG --></button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**2. Zoom controls (правый верхний угол, под map-controls):**
|
||||
```html
|
||||
<div id="zoom-controls">
|
||||
<button class="map-btn" onclick="map.zoomIn()">+</button>
|
||||
<div id="zoom-level">12</div>
|
||||
<button class="map-btn" onclick="map.zoomOut()">−</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
**3. Scale bar (левый нижний угол):**
|
||||
```html
|
||||
<div id="scale-bar">
|
||||
<div id="scale-line"></div>
|
||||
<span id="scale-label">1 км</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
**4. Toolbar (bottom nav, 7 кнопок):**
|
||||
```html
|
||||
<nav id="toolbar">
|
||||
<button class="tb-btn" id="tb-route" onclick="toggleRouteMode()"><!-- route SVG --><span>Маршрут</span></button>
|
||||
<button class="tb-btn" id="tb-link" onclick="toggleLinkMode()"><!-- link SVG --><span>Связка</span></button>
|
||||
<button class="tb-btn" id="tb-scenic" onclick="toggleScenicMode()"><!-- scenic SVG --><span>Красивый</span></button>
|
||||
<button class="tb-btn" id="tb-recon" onclick="toggleReconMode()"><!-- recon SVG --><span>Разведка</span></button>
|
||||
<button class="tb-btn" id="tb-ruler" onclick="toggleRuler()"><!-- ruler SVG --><span>Линейка</span></button>
|
||||
<button class="tb-btn" id="tb-marker" onclick="toggleMarkerMode()"><!-- marker SVG --><span>Метка</span></button>
|
||||
<button class="tb-btn" id="terrain-toggle" onclick="toggleTerrainPopup()"><!-- mountain SVG --><span>Рельеф</span></button>
|
||||
</nav>
|
||||
```
|
||||
|
||||
**5. Terrain popup:**
|
||||
```html
|
||||
<div id="terrain-popup" style="display:none; position:fixed; bottom:80px; right:12px; ...">
|
||||
<div>🏔️ Рельеф</div>
|
||||
<label><input type="checkbox" id="terrain-hypso-cb" onchange="onTerrainCheckbox()"> Гипсометрия</label>
|
||||
<label><input type="checkbox" id="terrain-hillshade-cb" onchange="onTerrainCheckbox()"> <span id="terrain-hillshade-label">Отмывка</span></label>
|
||||
</div>
|
||||
```
|
||||
|
||||
**6. Bottom sheets** (route, recon, scenic, link) — с drag handle, close button, content
|
||||
|
||||
**7. Mini route bar** (`#sheet-route-mini`) — onboarding panel с поиском Nominatim
|
||||
|
||||
**8. Ruler info bar** (`#ruler-info`) — с кнопками завершить/удалить
|
||||
|
||||
**9. Search bar** (`#search-bar`) — Nominatim поиск
|
||||
|
||||
### app.js — обязательные функции:
|
||||
|
||||
- `toggleTerrainPopup()` — открыть/закрыть terrain popup
|
||||
- `onTerrainCheckbox()` — обработка чекбоксов
|
||||
- `applyTerrainLayer(id, url, enabled, opacity, minzoom, maxzoom)` — добавить/убрать слой
|
||||
- `updateHillshadeAvailability()` — disable чекбокс на зуме < 10
|
||||
- `restoreTerrainState()` — восстановить из localStorage
|
||||
- `updateScaleBar()` — обновить линейку масштаба
|
||||
- `updateZoomLevel()` — обновить отображение зума
|
||||
- Все функции роутинга, линейки, меток, разведки, связки, красивого маршрута
|
||||
|
||||
### app.css — обязательные стили:
|
||||
|
||||
- CSS vars для тёмной/светлой темы
|
||||
- `.tb-btn` — стили toolbar кнопок
|
||||
- `.map-btn` — стили map controls
|
||||
- `#scale-bar` — линейка масштаба
|
||||
- `#zoom-controls` — зум контролы
|
||||
- `#terrain-popup` — попап рельефа
|
||||
- `.bottom-sheet` — bottom sheets
|
||||
- Анимации (slide-up, cardFadeIn, markerPopIn)
|
||||
|
||||
---
|
||||
|
||||
## Задачи
|
||||
|
||||
### Task 1: Анализ текущего состояния
|
||||
|
||||
**Шаги:**
|
||||
|
||||
- [ ] **1.1** Прочитать текущий `index.html` на сервере:
|
||||
```bash
|
||||
cat /home/slin/repos/enduro-trails/src/web/index.html
|
||||
```
|
||||
|
||||
- [ ] **1.2** Прочитать текущий `app.js` (первые 200 строк):
|
||||
```bash
|
||||
head -200 /home/slin/repos/enduro-trails/src/web/app.js
|
||||
```
|
||||
|
||||
- [ ] **1.3** Прочитать документацию:
|
||||
- `/home/node/.openclaw/workspace/tasks/enduro-trails/BRD_PHASE5.md`
|
||||
- `/home/node/.openclaw/workspace/tasks/enduro-trails/BRD_TERRAIN.md`
|
||||
- `/home/node/.openclaw/workspace/tasks/enduro-trails/PROJECT.md` (секция фаз 5.x)
|
||||
|
||||
**Критерий готовности:** Понимание что есть и чего не хватает.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Восстановление index.html
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `/home/slin/repos/enduro-trails/src/web/index.html`
|
||||
|
||||
**Шаги:**
|
||||
|
||||
- [ ] **2.1** Написать полный `index.html` с ВСЕМИ элементами из списка выше
|
||||
- Использовать SVG Lucide-иконки (те же что в текущем файле)
|
||||
- Сохранить все существующие bottom sheets (route, recon, scenic, link)
|
||||
- Добавить zoom-controls, scale-bar, terrain-popup
|
||||
- Toolbar: 7 кнопок включая terrain-toggle
|
||||
|
||||
- [ ] **2.2** Загрузить на сервер через SSH/SFTP
|
||||
|
||||
- [ ] **2.3** Проверить:
|
||||
```bash
|
||||
curl -s https://openclaw.mva154.duckdns.org/enduro/ | grep -c "terrain-toggle\|scale-bar\|zoom-controls"
|
||||
# Ожидаемый результат: 3
|
||||
```
|
||||
|
||||
**Критерий готовности:** В HTTP-ответе есть `terrain-toggle`, `scale-bar`, `zoom-controls`.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Восстановление app.js
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `/home/slin/repos/enduro-trails/src/web/app.js`
|
||||
|
||||
**Шаги:**
|
||||
|
||||
- [ ] **3.1** Проверить что в текущем `app.js` уже есть:
|
||||
```bash
|
||||
grep -c "toggleTerrain\|updateScaleBar\|updateZoomLevel" /home/slin/repos/enduro-trails/src/web/app.js
|
||||
```
|
||||
|
||||
- [ ] **3.2** Добавить недостающие функции:
|
||||
- `updateScaleBar()` — вычисляет масштаб по текущему зуму и широте, обновляет `#scale-line` width и `#scale-label` текст
|
||||
- `updateZoomLevel()` — обновляет `#zoom-level` текстом текущего зума
|
||||
- Вызовы в `map.on('zoom', ...)` и `map.on('move', ...)`
|
||||
|
||||
- [ ] **3.3** Загрузить на сервер
|
||||
|
||||
- [ ] **3.4** Проверить:
|
||||
```bash
|
||||
curl -s https://openclaw.mva154.duckdns.org/enduro/app.js | grep -c "updateScaleBar\|updateZoomLevel"
|
||||
# Ожидаемый результат: 2+
|
||||
```
|
||||
|
||||
**Критерий готовности:** Функции `updateScaleBar` и `updateZoomLevel` присутствуют в файле.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Восстановление app.css
|
||||
|
||||
**Файлы:**
|
||||
- Изменить: `/home/slin/repos/enduro-trails/src/web/app.css`
|
||||
|
||||
**Шаги:**
|
||||
|
||||
- [ ] **4.1** Проверить что есть в текущем `app.css`:
|
||||
```bash
|
||||
grep -c "scale-bar\|zoom-controls\|terrain-popup" /home/slin/repos/enduro-trails/src/web/app.css
|
||||
```
|
||||
|
||||
- [ ] **4.2** Добавить недостающие стили для:
|
||||
- `#scale-bar` — позиция левый нижний угол, белая линия + текст
|
||||
- `#zoom-controls` — вертикальный блок с +/число/−
|
||||
- `#zoom-level` — отображение текущего зума
|
||||
- `#terrain-popup` — если нет в CSS (уже есть inline в HTML — ок)
|
||||
|
||||
- [ ] **4.3** Загрузить на сервер
|
||||
|
||||
**Критерий готовности:** Стили для scale-bar и zoom-controls присутствуют.
|
||||
|
||||
---
|
||||
|
||||
## Проверка (Acceptance)
|
||||
|
||||
| # | Проверка | Команда | Ожидаемый результат |
|
||||
|---|----------|---------|---------------------|
|
||||
| 1 | terrain-toggle в HTML | `curl -s https://openclaw.mva154.duckdns.org/enduro/ \| grep terrain-toggle` | Есть кнопка |
|
||||
| 2 | scale-bar в HTML | `curl -s https://openclaw.mva154.duckdns.org/enduro/ \| grep scale-bar` | Есть элемент |
|
||||
| 3 | zoom-controls в HTML | `curl -s https://openclaw.mva154.duckdns.org/enduro/ \| grep zoom-controls` | Есть элемент |
|
||||
| 4 | updateScaleBar в JS | `curl -s https://openclaw.mva154.duckdns.org/enduro/app.js \| grep updateScaleBar` | Есть функция |
|
||||
| 5 | HTTP 200 | `curl -s -o /dev/null -w "%{http_code}" https://openclaw.mva154.duckdns.org/enduro/` | 200 |
|
||||
|
||||
---
|
||||
|
||||
## Ограничения и контекст
|
||||
|
||||
- ⚠️ Файлы монтированы через Docker volume — рестарт контейнера НЕ нужен, файлы сразу видны
|
||||
- ⚠️ SSH через node ssh2 (бинарник SSH не работает в контейнере — glibc несовместимость)
|
||||
- ⚠️ OSRM на порту 5559 — НЕ ТРОГАТЬ
|
||||
- ⚠️ nginx конфиг — НЕ ТРОГАТЬ
|
||||
- 🚫 Не менять `docker-compose.yml` и `Dockerfile`
|
||||
- 🚫 Не трогать `src/api/main.py` — бэкенд работает
|
||||
- ✅ Terrain тайлы отдаются через nginx alias `/enduro/terrain/` → `/home/slin/repos/enduro-trails/data/terrain/`
|
||||
- ✅ TERRAIN_BASE_URL в app.js: `window.location.pathname.replace(/\/[^\/]*$/, '') + '/terrain'`
|
||||
- ✅ `scheme: 'tms'` для terrain sources (тайлы в TMS формате)
|
||||
- ✅ `bounds: [35, 45, 55, 62]` для terrain sources
|
||||
|
||||
## SSH подключение (пример)
|
||||
|
||||
```javascript
|
||||
const { Client } = require('ssh2');
|
||||
const conn = new Client();
|
||||
function exec(conn, cmd, timeout) {
|
||||
return new Promise((resolve) => {
|
||||
const t = setTimeout(() => resolve({ out: 'TIMEOUT', err: '' }), timeout || 20000);
|
||||
conn.exec(cmd, (err, stream) => {
|
||||
if (err) { clearTimeout(t); return resolve({ out: '', err: err.message }); }
|
||||
let out = '', e = '';
|
||||
stream.on('data', d => out += d);
|
||||
stream.stderr.on('data', d => e += d);
|
||||
stream.on('close', () => { clearTimeout(t); resolve({ out: out.trim(), err: e.trim() }); });
|
||||
});
|
||||
});
|
||||
}
|
||||
conn.on('ready', async () => {
|
||||
// команды здесь
|
||||
conn.end();
|
||||
});
|
||||
conn.connect({ host: '82.22.50.71', username: 'slin', password: 'motoZ@yaz2010', readyTimeout: 15000 });
|
||||
```
|
||||
|
||||
Рабочая директория: `/home/node/.openclaw/workspace/tasks/enduro-trails/prototype`
|
||||
|
||||
---
|
||||
|
||||
*Создано: 2026-05-16 | Автор ТЗ: Стрим | Исполнитель: Dev-агент*
|
||||
Reference in New Issue
Block a user