feat: lightroom-style workspace UI with album covers
Backend: - expose cover thumbnail URL on album responses (LEFT JOIN + presign) - auto-assign cover only when empty; FK cover_photo_id -> photos ON DELETE SET NULL - add photos_count / members_count to album responses; cover repo test Frontend: - split layouts into (app) shell (resizable rail + contextual panel) and (public) - album rail + create-album dialog; album panel with cover picker / make-cover - photo viewer route with filmstrip, replacing lightbox; share reuses it - grid density slider, toolbar + drag-and-drop upload, dark graphite default OpenSpec: add lightroom-workspace-ui change (proposal, design, specs, tasks)
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Spec Delta
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Отображение обложки альбома
|
||||
Данные альбома SHALL включать URL миниатюры обложки, когда обложка задана, чтобы клиенты
|
||||
могли показать её в списке, рейле и карточке.
|
||||
|
||||
#### Scenario: Обложка задана
|
||||
- **WHEN** клиент запрашивает список альбомов или альбом по id, и у альбома есть обложка
|
||||
- **THEN** ответ содержит URL миниатюры обложки
|
||||
|
||||
#### Scenario: Обложка отсутствует
|
||||
- **WHEN** у альбома нет обложки или фото обложки удалено
|
||||
- **THEN** ответ не содержит URL обложки, и клиент показывает плейсхолдер
|
||||
|
||||
### Requirement: Выбор обложки
|
||||
Владелец и админ SHALL иметь возможность назначить обложкой любое фото альбома или сбросить
|
||||
обложку; после сброса обложка определяется заново по умолчанию.
|
||||
|
||||
#### Scenario: Назначение обложки
|
||||
- **WHEN** владелец выбирает фото альбома как обложку
|
||||
- **THEN** система сохраняет выбор и отражает его в списке и карточках
|
||||
|
||||
#### Scenario: Сброс обложки
|
||||
- **WHEN** админ сбрасывает обложку
|
||||
- **THEN** система удаляет явный выбор, и обложка возвращается к значению по умолчанию
|
||||
|
||||
#### Scenario: Нет прав на смену обложки
|
||||
- **WHEN** участник без права редактирования пытается сменить обложку
|
||||
- **THEN** система отклоняет запрос
|
||||
@@ -0,0 +1,15 @@
|
||||
# Spec Delta
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Обложка по умолчанию
|
||||
При обработке загруженного фото система SHALL назначать его обложкой альбома только если
|
||||
обложка ещё не задана.
|
||||
|
||||
#### Scenario: Первое фото
|
||||
- **WHEN** фото обработано, и у альбома нет обложки
|
||||
- **THEN** система назначает это фото обложкой
|
||||
|
||||
#### Scenario: Обложка уже задана
|
||||
- **WHEN** фото обработано, а обложка уже задана
|
||||
- **THEN** система не меняет обложку
|
||||
@@ -0,0 +1,121 @@
|
||||
# Spec Delta
|
||||
|
||||
## Purpose
|
||||
|
||||
Рабочий стол веб-приложения: постоянный каркас с рейлом альбомов, контекстной панелью,
|
||||
режимом просмотра фото и адаптивным поведением, обеспечивающий цельный «lightroom»-вид.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Рабочий стол приложения
|
||||
Аутентифицированные экраны SHALL отображаться внутри постоянного каркаса с топбаром, левым
|
||||
рейлом альбомов и контекстной правой панелью. Публичные экраны (вход, инвайт, share-ссылка)
|
||||
SHALL отображаться вне каркаса, но в общей теме оформления.
|
||||
|
||||
#### Scenario: Внутренний экран
|
||||
- **WHEN** аутентифицированный пользователь открывает список альбомов или альбом
|
||||
- **THEN** экран отрисован внутри каркаса с рейлом и панелью, рейл не перезагружается при переходе
|
||||
|
||||
#### Scenario: Публичный экран
|
||||
- **WHEN** пользователь открывает публичную share-ссылку без входа
|
||||
- **THEN** экран отрисован без рейла и контекстной панели, но в тех же цветовых токенах
|
||||
|
||||
### Requirement: Рейл альбомов
|
||||
Рейл SHALL постоянно показывать список доступных альбомов с их обложками и отмечать
|
||||
активный альбом.
|
||||
|
||||
#### Scenario: Активный альбом
|
||||
- **WHEN** пользователь находится в альбоме
|
||||
- **THEN** соответствующий элемент рейла выделен, остальные показывают обложки или плейсхолдер
|
||||
|
||||
### Requirement: Создание альбома
|
||||
Создание альбома SHALL выполняться через иконочную кнопку с подсказкой, открывающую
|
||||
модальное окно ввода названия, вместо инлайн-формы.
|
||||
|
||||
#### Scenario: Создание через модалку
|
||||
- **WHEN** пользователь нажимает кнопку создания, вводит название и подтверждает
|
||||
- **THEN** система создаёт альбом и делает его активным
|
||||
|
||||
#### Scenario: Пустое название
|
||||
- **WHEN** пользователь подтверждает пустое название
|
||||
- **THEN** создание не выполняется
|
||||
|
||||
### Requirement: Контекстная панель альбома
|
||||
Правая панель SHALL показывать превью обложки, название, счётчики фото и участников,
|
||||
управление обложкой и переходы к участникам, настройкам и ссылкам. Элементы управления
|
||||
обложкой SHALL быть доступны только owner и admin.
|
||||
|
||||
#### Scenario: Владелец альбома
|
||||
- **WHEN** owner открывает альбом
|
||||
- **THEN** панель показывает управление обложкой и переходы к участникам и настройкам
|
||||
|
||||
#### Scenario: Наблюдатель
|
||||
- **WHEN** viewer открывает альбом
|
||||
- **THEN** панель не показывает управление обложкой
|
||||
|
||||
### Requirement: Режим просмотра фотографии
|
||||
Просмотр фото SHALL быть отдельным маршрутом внутри каркаса с крупным изображением,
|
||||
лентой миниатюр снизу и панелью метаданных и комментариев. Тот же режим SHALL
|
||||
использоваться на публичных share-страницах.
|
||||
|
||||
#### Scenario: Открытие фото
|
||||
- **WHEN** пользователь выбирает фото в сетке
|
||||
- **THEN** открывается маршрут фото в каркасе, рейл и панель остаются доступны, адрес отражает фото
|
||||
|
||||
#### Scenario: Навигация в просмотре
|
||||
- **WHEN** пользователь использует стрелки влево/вправо или ленту миниатюр
|
||||
- **THEN** показывается соседнее фото, адрес обновляется
|
||||
|
||||
#### Scenario: Публичный просмотр
|
||||
- **WHEN** посетитель share-ссылки открывает фото
|
||||
- **THEN** используется тот же режим просмотра без рейла и панели
|
||||
|
||||
### Requirement: Плотность сетки
|
||||
Сетка SHALL давать пользователю управлять размером миниатюр, и выбранный размер SHALL
|
||||
сохраняться между сессиями.
|
||||
|
||||
#### Scenario: Изменение размера
|
||||
- **WHEN** пользователь двигает регулятор плотности
|
||||
- **THEN** размер миниатюр меняется, значение сохраняется и восстанавливается при следующем открытии
|
||||
|
||||
### Requirement: Загрузка фотографий из рабочего стола
|
||||
Загрузка SHALL запускаться действием в тулбаре; перетаскивание файлов над альбомом SHALL
|
||||
показывать оверлей и загружать их; пустой альбом SHALL показывать подсказку-зону загрузки.
|
||||
Загрузка SHALL быть доступна только ролям с правом загрузки.
|
||||
|
||||
#### Scenario: Перетаскивание
|
||||
- **WHEN** пользователь с правом загрузки перетаскивает файлы над альбомом
|
||||
- **THEN** показывается оверлей загрузки, и файлы загружаются
|
||||
|
||||
#### Scenario: Пустой альбом
|
||||
- **WHEN** пользователь открывает альбом без фото и имеет право загрузки
|
||||
- **THEN** в центре показана зона-подсказка загрузки
|
||||
|
||||
### Requirement: Тёмная графитовая тема
|
||||
Тёмная тема SHALL использовать графитовый хром Lightroom и SHALL применяться по умолчанию;
|
||||
остальные темы SHALL оставаться доступными.
|
||||
|
||||
#### Scenario: Первый вход
|
||||
- **WHEN** пользователь впервые открывает приложение без сохранённой темы
|
||||
- **THEN** применяется тёмная графитовая тема
|
||||
|
||||
#### Scenario: Смена темы
|
||||
- **WHEN** пользователь выбирает другую тему
|
||||
- **THEN** интерфейс и иконки переключаются согласованно и выбор сохраняется
|
||||
|
||||
### Requirement: Адаптивность рабочего стола
|
||||
На узких экранах рейл SHALL становиться выдвижной панелью, контекстная панель —
|
||||
сворачиваемой секцией, а лента миниатюр — горизонтально прокручиваемой.
|
||||
|
||||
#### Scenario: Узкий экран
|
||||
- **WHEN** ширина окна меньше порога рабочего стола
|
||||
- **THEN** рейл скрыт за кнопкой открытия, панель сворачиваема, лента прокручивается горизонтально
|
||||
|
||||
### Requirement: Доступность рабочего стола
|
||||
Иконочные органы управления каркаса SHALL иметь доступные имена, панели SHALL быть
|
||||
достижимы с клавиатуры с видимым фокусом, анимации SHALL учитывать
|
||||
предпочтение уменьшенного движения.
|
||||
|
||||
#### Scenario: Клавиатурная навигация
|
||||
- **WHEN** пользователь работает только с клавиатуры
|
||||
- **THEN** органы управления каркаса достижимы, доступные имена присутствуют, фокус виден
|
||||
Reference in New Issue
Block a user