Add "Plan"
101
Plan.md
Normal file
101
Plan.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# План рассылок
|
||||||
|
|
||||||
|
## Yonote интеграция
|
||||||
|
|
||||||
|
План рассылок загружается из базы данных Yonote (аналог Notion, российский).
|
||||||
|
|
||||||
|
### Настройка
|
||||||
|
|
||||||
|
В settings.json → `yonoteConfig`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"databaseId": "abc123", // ID базы в Yonote
|
||||||
|
"statusProperty": "Статус", // название колонки статуса
|
||||||
|
"dateProperty": "Дата", // дата отправки
|
||||||
|
"subjectProperty": "Тема", // тема письма
|
||||||
|
"preheaderProperty": "Прехедер",
|
||||||
|
"idProperty": "ID товаров", // IDs для блоков товаров
|
||||||
|
"extraProperties": ["Проект", "Теги", "Тип"] // доп. колонки
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Токен Yonote — в `config.json` → `yonote_token`.
|
||||||
|
|
||||||
|
### Загрузка данных
|
||||||
|
|
||||||
|
`fetchPlanRows()`:
|
||||||
|
1. GET `/api/yonote/database/:id/rows` — пагинация по 100, макс 500 строк
|
||||||
|
2. Сортировка по `updatedAt` DESC
|
||||||
|
3. Фильтр по дате: -7 дней ... +60 дней
|
||||||
|
4. Извлечение полей из Yonote properties → плоская структура
|
||||||
|
|
||||||
|
### Polling
|
||||||
|
|
||||||
|
`startPlanPolling()` — каждые 3 минуты загружает обновления:
|
||||||
|
- Сравнивает fingerprints (JSON hash каждой строки)
|
||||||
|
- При изменениях → toast уведомление + browser Notification
|
||||||
|
- Кэширует в localStorage (`va-plan-cache`)
|
||||||
|
|
||||||
|
## Календарь
|
||||||
|
|
||||||
|
Мини-календарь в сайдбаре и на странице плана:
|
||||||
|
|
||||||
|
- Точки под датами обозначают запланированные рассылки
|
||||||
|
- Клик на дату → показывает письма этого дня
|
||||||
|
- Навигация по месяцам (← →)
|
||||||
|
- Текущий день подсвечен
|
||||||
|
|
||||||
|
## Группировка на странице плана
|
||||||
|
|
||||||
|
Письма группируются по периодам:
|
||||||
|
- Просрочено (красный)
|
||||||
|
- Сегодня
|
||||||
|
- Завтра
|
||||||
|
- На этой неделе
|
||||||
|
- На следующей неделе
|
||||||
|
- Позже
|
||||||
|
|
||||||
|
## Карточка сборки (Assembly Card)
|
||||||
|
|
||||||
|
Когда письмо привязано к строке из Yonote, в сайдбаре показывается карточка:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ ПЕРЕДАНО В СБОРКУ │ ← статус (цветной бейдж)
|
||||||
|
│ 📮 Тема письма 🧥 │ ← тема из Yonote
|
||||||
|
│ Подзаголовок │ ← preheader
|
||||||
|
│ [Тег1] [Тег2] │ ← теги/тип
|
||||||
|
│ ⎕ Figma │ ← ссылки из extra
|
||||||
|
│ │
|
||||||
|
│ [Mindbox] [Отправлено]│ ← кнопки действий
|
||||||
|
└─────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-matching
|
||||||
|
|
||||||
|
При открытии письма `assemblyInfo` автоматически матчится со строкой в плане:
|
||||||
|
- По `rowId` (если сохранён в письме)
|
||||||
|
- Или по совпадению title + date
|
||||||
|
|
||||||
|
### Статусы
|
||||||
|
|
||||||
|
`setPlanRowStatus(row, newStatus)` — обновляет статус в Yonote.
|
||||||
|
|
||||||
|
Кнопка "Отправлено" → статус "Отправлено" + останавливает трекинг времени.
|
||||||
|
|
||||||
|
## Начало сборки
|
||||||
|
|
||||||
|
`startAssemble(row)`:
|
||||||
|
1. Создаёт новое письмо с заполненным title, date, preheader из Yonote
|
||||||
|
2. Или открывает существующее (если уже привязано к rowId)
|
||||||
|
3. Автозаполняет ID pool из свойства "ID товаров"
|
||||||
|
4. Устанавливает assemblyInfo
|
||||||
|
|
||||||
|
## Трекинг времени
|
||||||
|
|
||||||
|
- `statsStart(letterId, ...)` — запускает 1-секундный интервал
|
||||||
|
- Считает активные секунды (паузится когда вкладка скрыта — `document.hidden`)
|
||||||
|
- `statsMarkHtmlCopied()` — отмечает что HTML скопирован
|
||||||
|
- `statsStop(finalStatus)` — сохраняет если >= 1 минуты
|
||||||
|
- Данные: `{letterId, letterName, userId, userName, project, tag, startedAt, finishedAt, activeSeconds, htmlCopied}`
|
||||||
Reference in New Issue
Block a user