Fix clipboard copy on HTTP (non-secure) contexts, update docs
navigator.clipboard is undefined on non-HTTPS origins — add execCommand fallback. Also sync CLAUDE.md with actual project structure (Dockerfiles, nginx, CI, correct API/button descriptions). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
10
CLAUDE.md
10
CLAUDE.md
@@ -20,13 +20,17 @@ blood-brain-barrier/
|
|||||||
│ │ ├── App.tsx # Основной компонент: textarea + список записей
|
│ │ ├── App.tsx # Основной компонент: textarea + список записей
|
||||||
│ │ ├── api.ts # Функции для запросов к API
|
│ │ ├── api.ts # Функции для запросов к API
|
||||||
│ │ └── main.tsx
|
│ │ └── main.tsx
|
||||||
|
│ ├── Dockerfile # Сборка фронтенда + nginx
|
||||||
|
│ ├── nginx.conf # Конфиг nginx для раздачи SPA и проксирования API
|
||||||
│ └── package.json
|
│ └── package.json
|
||||||
├── backend/ # Rust API (Axum)
|
├── backend/ # Rust API (Axum)
|
||||||
│ ├── src/
|
│ ├── src/
|
||||||
│ │ ├── main.rs # Точка входа, подключение к БД, CORS, запуск сервера
|
│ │ ├── main.rs # Точка входа, подключение к БД, CORS, запуск сервера
|
||||||
│ │ ├── db.rs # Подключение к PostgreSQL, init_db
|
│ │ ├── db.rs # Подключение к PostgreSQL, init_db
|
||||||
│ │ └── routes.rs # Хендлеры API
|
│ │ └── routes.rs # Хендлеры API
|
||||||
|
│ ├── Dockerfile # Сборка бэкенда
|
||||||
│ └── Cargo.toml
|
│ └── Cargo.toml
|
||||||
|
├── .woodpecker.yml # CI pipeline
|
||||||
├── docker-compose.yml # PostgreSQL
|
├── docker-compose.yml # PostgreSQL
|
||||||
└── CLAUDE.md
|
└── CLAUDE.md
|
||||||
```
|
```
|
||||||
@@ -47,15 +51,15 @@ CREATE TABLE entries (
|
|||||||
|
|
||||||
| Метод | Путь | Описание |
|
| Метод | Путь | Описание |
|
||||||
|--------|------------------|-------------------------|
|
|--------|------------------|-------------------------|
|
||||||
| GET | /api/entries | Получить все записи |
|
| GET | /api/entries | Список записей (id, created_at — без content) |
|
||||||
| POST | /api/entries | Создать запись |
|
| POST | /api/entries | Создать запись |
|
||||||
| DELETE | /api/entries/:id | Удалить запись по id |
|
| DELETE | /api/entries/:id | Удалить запись по id |
|
||||||
| GET | /api/entries/:id/content | Получить контент записи (plain text) |
|
| GET | /api/entries/:id/content | Получить контент записи (plain text) |
|
||||||
|
|
||||||
## Frontend
|
## Frontend
|
||||||
|
|
||||||
- Сверху: большая `<textarea>` + кнопка "Создать"
|
- Сверху: большая `<textarea>` + кнопка "Create"
|
||||||
- Ниже: список всех записей (новые сверху), у каждой кнопки "Удалить" и "Копировать"
|
- Ниже: список всех записей (новые сверху), у каждой кнопки "Delete" и "Copy"
|
||||||
- Копирование — через `navigator.clipboard.writeText()`
|
- Копирование — через `navigator.clipboard.writeText()`
|
||||||
|
|
||||||
## Команды
|
## Команды
|
||||||
|
|||||||
@@ -29,7 +29,18 @@ function App() {
|
|||||||
|
|
||||||
const handleCopy = async (id: number) => {
|
const handleCopy = async (id: number) => {
|
||||||
const text = await getEntryContent(id);
|
const text = await getEntryContent(id);
|
||||||
navigator.clipboard.writeText(text);
|
if (navigator.clipboard) {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
} else {
|
||||||
|
const textarea = document.createElement("textarea");
|
||||||
|
textarea.value = text;
|
||||||
|
textarea.style.position = "fixed";
|
||||||
|
textarea.style.opacity = "0";
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user