diff --git a/README.md b/README.md index c813f6e..7a0c04a 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,34 @@ # Social Graph Builder -Построитель социального графа: импорт контактов, визуализация связей, CRUD. +Построитель социального графа: импорт контактов, визуализация связей, CRUD, карта сети. + +По умолчанию приложение работает в режиме **local-first**: данные хранятся в браузере (IndexedDB), backend для обычной работы не обязателен. ## Стек | Слой | Технология | |------|-----------| -| Backend API | Django 4.2 + Django REST Framework | -| База данных | SQLite | -| Frontend | Vue.js 3 + Vite | -| Граф | vis-network | -| Состояние | Pinia | -| Запуск | Docker Compose | +| Frontend | Vue 3 + Vite + Pinia | +| Локальное хранилище | IndexedDB (Dexie) | +| Backend API (опционально) | Django 4.2 + DRF | +| БД backend | SQLite | +| Граф / карта | vis-network | +| Dev-запуск | Docker Compose | +| Production | Docker Compose + прокси на хосте | -## Быстрый старт +## Режимы данных + +Переключатель: `VITE_DATA_MODE` (задаётся при **сборке** фронта). + +| Режим | Описание | +|-------|----------| +| `local` (по умолчанию) | IndexedDB в браузере, максимум конфиденциальности | +| `remote` | Django API + SQLite на сервере | +| `hybrid` | зарезервирован для будущей синхронизации | + +Пример для production: см. `deploy/.env.prod.example`. + +## Быстрый старт (разработка) ```bash git clone @@ -21,10 +36,51 @@ cd social-graph docker compose up --build ``` -- Frontend: http://localhost:5173 -- Backend API: http://localhost:8000/api/ +- Frontend (Vite): http://localhost:5173 +- Backend API: http://localhost:8000/api/ (для `remote` или legacy) -## API endpoints +Страницы: `/graph`, `/map`, `/contacts`, `/import`. + +## Архитектура frontend + +```text +views / components + ↓ +Pinia store (orchestration) + ↓ +application/usecases + ↓ +infrastructure/repositories → local (IndexedDB) | remote (REST) + ↓ +changelog + syncAdapter (noop, подготовка к sync) +``` + +## Структура проекта + +```text +social-graph/ +├── backend/ # Django API (опционально) +│ ├── contacts/ +│ ├── config/ +│ ├── Dockerfile # dev +│ └── Dockerfile.prod # gunicorn +├── frontend/ +│ ├── src/ +│ │ ├── application/usecases/ +│ │ ├── infrastructure/ # db, repositories, sync, config +│ │ ├── domain/ +│ │ ├── views/ # Graph, NetworkMap, Contacts, Import +│ │ ├── stores/ +│ │ └── components/ +│ ├── Dockerfile # dev (Vite) +│ ├── Dockerfile.prod # build + nginx +│ └── nginx.conf +├── deploy/ # production: Apache, env, инструкции +├── docker-compose.yml # dev +└── docker-compose.prod.yml # production +``` + +## API endpoints (backend, режим remote) | Метод | URL | Описание | |-------|-----|----------| @@ -32,65 +88,36 @@ docker compose up --build | GET/PATCH/DELETE | `/api/contacts/{id}/` | Контакт по ID | | GET/POST | `/api/relations/` | Список / создание связей | | DELETE | `/api/relations/{id}/` | Удалить связь | -| GET | `/api/graph/` | Граф (nodes + edges для vis.js) | +| GET | `/api/graph/` | Граф для vis.js | +| GET | `/api/network-map-graph/` | Граф карты сети | | GET | `/api/relation-types/` | Типы связей | -| POST | `/api/import/` | Импорт CSV/JSON | +| GET | `/api/network-map-choices/` | Справочники карты | +| POST | `/api/import/` | Импорт CSV/JSON (legacy) | -## Формат CSV для импорта +В режиме `local` импорт и бэкап выполняются в браузере (экран **Импорт**). -```csv -name,email,phone,organization,position,notes -Иван Иванов,ivan@example.com,+7-900-000-0001,ООО Ромашка,Директор, -Мария Петрова,maria@example.com,+7-900-000-0002,Газпром,Аналитик, -``` +## Импорт и бэкап (local-first) -## Формат JSON для импорта +- **CSV / JSON** — экран «Импорт», парсинг на клиенте. +- **Экспорт / импорт бэкапа** — JSON или зашифрованный `.sgpkg` (WebCrypto, пароль опционален). -```json -[ - {"name": "Иван Иванов", "email": "ivan@example.com", "organization": "ООО Ромашка"}, - {"name": "Мария Петрова", "phone": "+7-900-000-0002"} -] -``` +## Production -## Структура проекта - -``` -social-graph/ -├── backend/ -│ ├── config/ # Django settings, urls -│ ├── contacts/ # models, serializers, views, urls -│ ├── manage.py -│ ├── requirements.txt -│ └── Dockerfile -├── frontend/ -│ ├── src/ -│ │ ├── views/ # GraphView, ContactsView, ContactDetailView, ImportView -│ │ ├── components/ # ContactForm -│ │ ├── stores/ # Pinia store (contacts) -│ │ ├── router/ # Vue Router -│ │ ├── api.js # Axios instance -│ │ └── App.vue -│ ├── vite.config.js -│ └── Dockerfile -└── docker-compose.yml -``` - -## Production (Docker + прокси на хосте) - -См. [deploy/README.md](deploy/README.md). - -Кратко: +Подробно: [deploy/README.md](deploy/README.md). ```bash +git clone /opt/social-graph && cd /opt/social-graph cp deploy/.env.prod.example deploy/.env.prod -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend -# прокси на хосте → http://127.0.0.1:8080 (см. deploy/apache/social-graph.conf) +docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend +# прокси на хосте → http://127.0.0.1:8080 ``` +Схема: прокси на хосте (Apache/nginx) → контейнер frontend (nginx); backend — только при `VITE_DATA_MODE=remote`. + ## Запуск без Docker **Backend:** + ```bash cd backend pip install -r requirements.txt @@ -99,20 +126,31 @@ python manage.py runserver ``` **Frontend:** + ```bash cd frontend npm install npm run dev ``` -> В `vite.config.js` прокси настроен на `http://backend:8000`. -> При локальном запуске без Docker замените на `http://localhost:8000`. +> В `vite.config.js` прокси `/api` указывает на `http://backend:8000`. +> Без Docker замените на `http://localhost:8000`. -## Планируемые фичи (следующие итерации) +Для local-first backend не нужен. + +## Тесты + +```bash +cd frontend && npm test +# или в контейнере: +docker compose exec frontend npm test -- --run +``` + +## Планируемые фичи - [ ] Авторизация (Django auth + JWT) - [ ] Теги/группы контактов -- [ ] Экспорт в CSV/JSON +- [ ] Синхронизация и shared-workspace - [ ] Поиск по организации и должности - [ ] История изменений контакта - [ ] Импорт из vCard (.vcf) diff --git a/deploy/README.md b/deploy/README.md index af5ab9b..944c386 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,30 +1,40 @@ # Production deploy (контейнеры + прокси на хосте) -Схема: +## Схема ```text [Прокси на хосте :80/:443] - → frontend-контейнер (nginx :8080 на хосте) - → backend-контейнер (gunicorn :8000, только при remote) + → frontend-контейнер (nginx, 127.0.0.1:8080) + → backend-контейнер (gunicorn, 127.0.0.1:8000 — только при remote) ``` -SPA-маршрутизация (`try_files` → `index.html`) выполняется **внутри** frontend-контейнера. +SPA-маршрутизация (`try_files` → `index.html`) — **внутри** frontend-контейнера (`frontend/nginx.conf`). -## 1. Подготовка +## 1. Клонирование и подготовка ```bash +git clone /opt/social-graph cd /opt/social-graph +git checkout main # или нужная ветка + cp deploy/.env.prod.example deploy/.env.prod -# отредактируйте deploy/.env.prod при необходимости +# отредактируйте deploy/.env.prod ``` -## 2. Local-first (только frontend) +`deploy/.env.prod` в git не коммитится (секреты и локальные порты). -Рекомендуется для конфиденциальности — данные в браузере (IndexedDB). +## 2. Local-first (рекомендуется) + +Данные пользователя — в браузере (IndexedDB). Backend на сервере **не поднимать**. + +В `deploy/.env.prod`: + +```env +VITE_DATA_MODE=local +``` ```bash -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod build frontend -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend +docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend ``` Проверка: @@ -41,51 +51,86 @@ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/ ```bash sudo a2enmod proxy proxy_http headers sudo cp deploy/apache/social-graph.conf /etc/apache2/sites-available/social-graph.conf -# ServerName и порты (8080 / 8000) — по вашему .env.prod +``` + +Отредактируйте `ServerName` и при необходимости порты (`FRONTEND_PORT` / `BACKEND_PORT` из `.env.prod`). + +```bash sudo a2ensite social-graph.conf sudo apache2ctl configtest sudo systemctl reload apache2 ``` +HTTPS: + +```bash +sudo certbot --apache -d your-domain.com +``` + ### nginx на хосте См. `deploy/proxy/nginx-host.conf.example`. ## 4. Remote mode (frontend + backend) -В `deploy/.env.prod`: +Общая БД на сервере. В `deploy/.env.prod`: ```env VITE_DATA_MODE=remote -DJANGO_SECRET_KEY=... -ALLOWED_HOSTS=your-domain.com +DJANGO_SECRET_KEY=длинный-случайный-ключ +ALLOWED_HOSTS=your-domain.com,www.your-domain.com ``` Пересоберите frontend (режим зашивается при build) и поднимите оба сервиса: ```bash docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod build -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d backend +docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend +docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend ``` -В `deploy/apache/social-graph.conf` раскомментируйте блок `ProxyPass /api ...` **перед** `ProxyPass /`. +В `deploy/apache/social-graph.conf` раскомментируйте `ProxyPass /api ...` **выше** блока `ProxyPass /`. + +```bash +sudo a2enmod proxy proxy_http headers +sudo systemctl reload apache2 +``` ## 5. Обновление ```bash +cd /opt/social-graph git pull -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod build frontend -docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend -# при remote — также build/up backend -sudo systemctl reload apache2 # или nginx -s reload +docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d --build frontend +# при remote: +# docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend +sudo systemctl reload apache2 # или: sudo nginx -s reload ``` ## Порты по умолчанию -| Сервис | Хост (loopback) | Внутри контейнера | -|----------|-----------------|-------------------| -| frontend | 127.0.0.1:8080 | nginx :80 | -| backend | 127.0.0.1:8000 | gunicorn :8000 | +| Переменная | Значение | Назначение | +|------------|----------|------------| +| `FRONTEND_PORT` | 8080 | nginx в контейнере `sg_frontend` | +| `BACKEND_PORT` | 8000 | gunicorn в контейнере `sg_backend` | +| `FRONTEND_BIND` | 127.0.0.1 | только loopback на хосте | -Наружу открыт только прокси на хосте (80/443). +Наружу открыт только прокси (80/443). + +## Миграция данных + +| Источник | Действие | +|----------|----------| +| CSV/JSON | UI → Импорт | +| Старый Django SQLite | экспорт JSON → Импорт | +| Локальный бэкап `.json` / `.sgpkg` | UI → «Импорт бэкапа» | + +## Устранение неполадок + +```bash +docker compose -f docker-compose.prod.yml ps +docker logs sg_frontend --tail 50 +docker logs sg_backend --tail 50 # если поднят +``` + +Конфликт имени контейнера с dev: остановите `docker compose down` в том же каталоге перед prod-запуском.