From 570e0ca643576491b09999b309425b848b51d112 Mon Sep 17 00:00:00 2001 From: Mikhail Kilin Date: Wed, 18 Mar 2026 13:50:28 +0300 Subject: [PATCH] =?UTF-8?q?Rewrite=20app:=20entries=20=E2=86=92=20projects?= =?UTF-8?q?=20with=20S3=20file=20storage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace flat text entries with project-based structure. Each project has name, local/corp fields, content textarea, and file upload (up to 100MB) stored in MinIO S3. New API: CRUD projects + file download + content copy. Frontend: two views (project list + project page). Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 60 ++- backend/Cargo.lock | 956 ++++++++++++++++++++++++++++++++++++++++-- backend/Cargo.toml | 4 +- backend/src/db.rs | 19 +- backend/src/main.rs | 22 +- backend/src/routes.rs | 244 +++++++++-- backend/src/s3.rs | 35 ++ frontend/nginx.conf | 2 + frontend/src/App.css | 139 ++++-- frontend/src/App.tsx | 235 ++++++++--- frontend/src/api.ts | 71 +++- 11 files changed, 1586 insertions(+), 201 deletions(-) create mode 100644 backend/src/s3.rs diff --git a/CLAUDE.md b/CLAUDE.md index 27d4c3b..7b60437 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,13 +2,14 @@ **Репозиторий:** https://git.mikhailkilin.ru/killingdruid/blood-brain-barrier -Веб-приложение для хранения текстовых записей. Пользователь вводит текст через textarea, сохраняет в PostgreSQL, просматривает список всех записей с возможностью удаления и копирования. +Веб-приложение для управления проектами с текстовыми полями и файлами. Главная страница — список проектов, клик по проекту — страница проекта с полями (local, corp), textarea (content) и загрузкой файлов в MinIO S3. ## Стек - **Frontend:** React + TypeScript + Vite -- **Backend:** Rust (Axum + SQLx) +- **Backend:** Rust (Axum + SQLx + rust-s3) - **БД:** PostgreSQL +- **Файлы:** MinIO S3 - **Async runtime:** Tokio ## Структура проекта @@ -17,17 +18,19 @@ blood-brain-barrier/ ├── frontend/ # React-приложение (Vite) │ ├── src/ -│ │ ├── App.tsx # Основной компонент: textarea + список записей +│ │ ├── App.tsx # Две view: ProjectList + ProjectPage │ │ ├── api.ts # Функции для запросов к API +│ │ ├── App.css # Стили │ │ └── main.tsx │ ├── Dockerfile # Сборка фронтенда + nginx -│ ├── nginx.conf # Конфиг nginx для раздачи SPA и проксирования API +│ ├── nginx.conf # Nginx: SPA + проксирование API (110MB limit) │ └── package.json ├── backend/ # Rust API (Axum) │ ├── src/ -│ │ ├── main.rs # Точка входа, подключение к БД, CORS, запуск сервера +│ │ ├── main.rs # Точка входа, AppState, роуты │ │ ├── db.rs # Подключение к PostgreSQL, init_db -│ │ └── routes.rs # Хендлеры API +│ │ ├── s3.rs # Инициализация MinIO S3 bucket +│ │ └── routes.rs # Хендлеры API (projects + файлы) │ ├── Dockerfile # Сборка бэкенда │ └── Cargo.toml ├── .woodpecker.yml # CI pipeline @@ -37,30 +40,36 @@ blood-brain-barrier/ ## База данных -Одна таблица `entries`: - ```sql -CREATE TABLE entries ( - id SERIAL PRIMARY KEY, - created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), - content TEXT NOT NULL +CREATE TABLE IF NOT EXISTS projects ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + local TEXT NOT NULL DEFAULT '', + corp TEXT NOT NULL DEFAULT '', + content TEXT NOT NULL DEFAULT '', + file_name TEXT, + file_key TEXT, + file_size BIGINT, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); ``` ## API -| Метод | Путь | Описание | -|--------|------------------|-------------------------| -| GET | /api/entries | Список записей (id, created_at — без content) | -| POST | /api/entries | Создать запись | -| DELETE | /api/entries/:id | Удалить запись по id | -| GET | /api/entries/:id/content | Получить контент записи (plain text) | +| Метод | Путь | Описание | +|--------|----------------------------|---------------------------------------| +| GET | /api/projects | Список проектов (id, name, created_at)| +| POST | /api/projects | Создать проект (JSON: {name}) | +| GET | /api/projects/:id | Получить проект целиком | +| PUT | /api/projects/:id | Обновить (multipart: local, corp, content, file?) | +| DELETE | /api/projects/:id | Удалить проект + файл из S3 | +| GET | /api/projects/:id/file | Скачать файл | +| GET | /api/projects/:id/content | Получить content (plain text) | ## Frontend -- Сверху: большая `