Update README files for local-first architecture and production deploy.
Document VITE_DATA_MODE, frontend layers, containerized deploy flow, and refresh deploy guide with git clone, build flags, and troubleshooting. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,19 +1,34 @@
|
|||||||
# Social Graph Builder
|
# Social Graph Builder
|
||||||
|
|
||||||
Построитель социального графа: импорт контактов, визуализация связей, CRUD.
|
Построитель социального графа: импорт контактов, визуализация связей, CRUD, карта сети.
|
||||||
|
|
||||||
|
По умолчанию приложение работает в режиме **local-first**: данные хранятся в браузере (IndexedDB), backend для обычной работы не обязателен.
|
||||||
|
|
||||||
## Стек
|
## Стек
|
||||||
|
|
||||||
| Слой | Технология |
|
| Слой | Технология |
|
||||||
|------|-----------|
|
|------|-----------|
|
||||||
| Backend API | Django 4.2 + Django REST Framework |
|
| Frontend | Vue 3 + Vite + Pinia |
|
||||||
| База данных | SQLite |
|
| Локальное хранилище | IndexedDB (Dexie) |
|
||||||
| Frontend | Vue.js 3 + Vite |
|
| Backend API (опционально) | Django 4.2 + DRF |
|
||||||
| Граф | vis-network |
|
| БД backend | SQLite |
|
||||||
| Состояние | Pinia |
|
| Граф / карта | vis-network |
|
||||||
| Запуск | Docker Compose |
|
| Dev-запуск | Docker Compose |
|
||||||
|
| Production | Docker Compose + прокси на хосте |
|
||||||
|
|
||||||
## Быстрый старт
|
## Режимы данных
|
||||||
|
|
||||||
|
Переключатель: `VITE_DATA_MODE` (задаётся при **сборке** фронта).
|
||||||
|
|
||||||
|
| Режим | Описание |
|
||||||
|
|-------|----------|
|
||||||
|
| `local` (по умолчанию) | IndexedDB в браузере, максимум конфиденциальности |
|
||||||
|
| `remote` | Django API + SQLite на сервере |
|
||||||
|
| `hybrid` | зарезервирован для будущей синхронизации |
|
||||||
|
|
||||||
|
Пример для production: см. `deploy/.env.prod.example`.
|
||||||
|
|
||||||
|
## Быстрый старт (разработка)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone <repo>
|
git clone <repo>
|
||||||
@@ -21,10 +36,51 @@ cd social-graph
|
|||||||
docker compose up --build
|
docker compose up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
- Frontend: http://localhost:5173
|
- Frontend (Vite): http://localhost:5173
|
||||||
- Backend API: http://localhost:8000/api/
|
- 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 | Описание |
|
| Метод | URL | Описание |
|
||||||
|-------|-----|----------|
|
|-------|-----|----------|
|
||||||
@@ -32,65 +88,36 @@ docker compose up --build
|
|||||||
| GET/PATCH/DELETE | `/api/contacts/{id}/` | Контакт по ID |
|
| GET/PATCH/DELETE | `/api/contacts/{id}/` | Контакт по ID |
|
||||||
| GET/POST | `/api/relations/` | Список / создание связей |
|
| GET/POST | `/api/relations/` | Список / создание связей |
|
||||||
| DELETE | `/api/relations/{id}/` | Удалить связь |
|
| 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/` | Типы связей |
|
| GET | `/api/relation-types/` | Типы связей |
|
||||||
| POST | `/api/import/` | Импорт CSV/JSON |
|
| GET | `/api/network-map-choices/` | Справочники карты |
|
||||||
|
| POST | `/api/import/` | Импорт CSV/JSON (legacy) |
|
||||||
|
|
||||||
## Формат CSV для импорта
|
В режиме `local` импорт и бэкап выполняются в браузере (экран **Импорт**).
|
||||||
|
|
||||||
```csv
|
## Импорт и бэкап (local-first)
|
||||||
name,email,phone,organization,position,notes
|
|
||||||
Иван Иванов,ivan@example.com,+7-900-000-0001,ООО Ромашка,Директор,
|
|
||||||
Мария Петрова,maria@example.com,+7-900-000-0002,Газпром,Аналитик,
|
|
||||||
```
|
|
||||||
|
|
||||||
## Формат JSON для импорта
|
- **CSV / JSON** — экран «Импорт», парсинг на клиенте.
|
||||||
|
- **Экспорт / импорт бэкапа** — JSON или зашифрованный `.sgpkg` (WebCrypto, пароль опционален).
|
||||||
|
|
||||||
```json
|
## Production
|
||||||
[
|
|
||||||
{"name": "Иван Иванов", "email": "ivan@example.com", "organization": "ООО Ромашка"},
|
|
||||||
{"name": "Мария Петрова", "phone": "+7-900-000-0002"}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Структура проекта
|
Подробно: [deploy/README.md](deploy/README.md).
|
||||||
|
|
||||||
```
|
|
||||||
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).
|
|
||||||
|
|
||||||
Кратко:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
git clone <repo> /opt/social-graph && cd /opt/social-graph
|
||||||
cp deploy/.env.prod.example deploy/.env.prod
|
cp deploy/.env.prod.example deploy/.env.prod
|
||||||
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
|
||||||
# прокси на хосте → http://127.0.0.1:8080 (см. deploy/apache/social-graph.conf)
|
# прокси на хосте → http://127.0.0.1:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Схема: прокси на хосте (Apache/nginx) → контейнер frontend (nginx); backend — только при `VITE_DATA_MODE=remote`.
|
||||||
|
|
||||||
## Запуск без Docker
|
## Запуск без Docker
|
||||||
|
|
||||||
**Backend:**
|
**Backend:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
@@ -99,20 +126,31 @@ python manage.py runserver
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Frontend:**
|
**Frontend:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
npm install
|
npm install
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
> В `vite.config.js` прокси настроен на `http://backend:8000`.
|
> В `vite.config.js` прокси `/api` указывает на `http://backend:8000`.
|
||||||
> При локальном запуске без Docker замените на `http://localhost:8000`.
|
> Без Docker замените на `http://localhost:8000`.
|
||||||
|
|
||||||
## Планируемые фичи (следующие итерации)
|
Для local-first backend не нужен.
|
||||||
|
|
||||||
|
## Тесты
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend && npm test
|
||||||
|
# или в контейнере:
|
||||||
|
docker compose exec frontend npm test -- --run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Планируемые фичи
|
||||||
|
|
||||||
- [ ] Авторизация (Django auth + JWT)
|
- [ ] Авторизация (Django auth + JWT)
|
||||||
- [ ] Теги/группы контактов
|
- [ ] Теги/группы контактов
|
||||||
- [ ] Экспорт в CSV/JSON
|
- [ ] Синхронизация и shared-workspace
|
||||||
- [ ] Поиск по организации и должности
|
- [ ] Поиск по организации и должности
|
||||||
- [ ] История изменений контакта
|
- [ ] История изменений контакта
|
||||||
- [ ] Импорт из vCard (.vcf)
|
- [ ] Импорт из vCard (.vcf)
|
||||||
|
|||||||
+71
-26
@@ -1,30 +1,40 @@
|
|||||||
# Production deploy (контейнеры + прокси на хосте)
|
# Production deploy (контейнеры + прокси на хосте)
|
||||||
|
|
||||||
Схема:
|
## Схема
|
||||||
|
|
||||||
```text
|
```text
|
||||||
[Прокси на хосте :80/:443]
|
[Прокси на хосте :80/:443]
|
||||||
→ frontend-контейнер (nginx :8080 на хосте)
|
→ frontend-контейнер (nginx, 127.0.0.1:8080)
|
||||||
→ backend-контейнер (gunicorn :8000, только при remote)
|
→ 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
|
```bash
|
||||||
|
git clone <repo-url> /opt/social-graph
|
||||||
cd /opt/social-graph
|
cd /opt/social-graph
|
||||||
|
git checkout main # или нужная ветка
|
||||||
|
|
||||||
cp deploy/.env.prod.example deploy/.env.prod
|
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
|
```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 --build frontend
|
||||||
docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Проверка:
|
Проверка:
|
||||||
@@ -41,51 +51,86 @@ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/
|
|||||||
```bash
|
```bash
|
||||||
sudo a2enmod proxy proxy_http headers
|
sudo a2enmod proxy proxy_http headers
|
||||||
sudo cp deploy/apache/social-graph.conf /etc/apache2/sites-available/social-graph.conf
|
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 a2ensite social-graph.conf
|
||||||
sudo apache2ctl configtest
|
sudo apache2ctl configtest
|
||||||
sudo systemctl reload apache2
|
sudo systemctl reload apache2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
HTTPS:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo certbot --apache -d your-domain.com
|
||||||
|
```
|
||||||
|
|
||||||
### nginx на хосте
|
### nginx на хосте
|
||||||
|
|
||||||
См. `deploy/proxy/nginx-host.conf.example`.
|
См. `deploy/proxy/nginx-host.conf.example`.
|
||||||
|
|
||||||
## 4. Remote mode (frontend + backend)
|
## 4. Remote mode (frontend + backend)
|
||||||
|
|
||||||
В `deploy/.env.prod`:
|
Общая БД на сервере. В `deploy/.env.prod`:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
VITE_DATA_MODE=remote
|
VITE_DATA_MODE=remote
|
||||||
DJANGO_SECRET_KEY=...
|
DJANGO_SECRET_KEY=длинный-случайный-ключ
|
||||||
ALLOWED_HOSTS=your-domain.com
|
ALLOWED_HOSTS=your-domain.com,www.your-domain.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Пересоберите frontend (режим зашивается при build) и поднимите оба сервиса:
|
Пересоберите frontend (режим зашивается при build) и поднимите оба сервиса:
|
||||||
|
|
||||||
```bash
|
```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 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 up -d --build 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 --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. Обновление
|
## 5. Обновление
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
cd /opt/social-graph
|
||||||
git pull
|
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 --build frontend
|
||||||
docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod up -d frontend
|
# при remote:
|
||||||
# при remote — также build/up backend
|
# docker compose -f docker-compose.prod.yml --env-file deploy/.env.prod --profile with-backend up -d --build backend
|
||||||
sudo systemctl reload apache2 # или nginx -s reload
|
sudo systemctl reload apache2 # или: sudo nginx -s reload
|
||||||
```
|
```
|
||||||
|
|
||||||
## Порты по умолчанию
|
## Порты по умолчанию
|
||||||
|
|
||||||
| Сервис | Хост (loopback) | Внутри контейнера |
|
| Переменная | Значение | Назначение |
|
||||||
|----------|-----------------|-------------------|
|
|------------|----------|------------|
|
||||||
| frontend | 127.0.0.1:8080 | nginx :80 |
|
| `FRONTEND_PORT` | 8080 | nginx в контейнере `sg_frontend` |
|
||||||
| backend | 127.0.0.1:8000 | gunicorn :8000 |
|
| `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-запуском.
|
||||||
|
|||||||
Reference in New Issue
Block a user