feat(gallery): Vue refactor and unified modal styles#121
feat(gallery): Vue refactor and unified modal styles#121Ibochkarev wants to merge 2 commits intobetafrom
Conversation
- Replace legacy gallery JS (panel, toolbar, view, window) with Vue components - Add ProductGallery, ProductGalleryGrid, ProductGalleryToolbar, ProductGalleryEditDialog - Add useGalleryApi composable, integrate GalleryUploader - Unify modal width via --ms3-modal-width, fix ConfirmDialog width (90vw max) - Fix Edit Dialog close button: use closeButtonProps for circular focus ring - Add lexicon entries (ru/en), update Upload processor and product controller
biz87
left a comment
There was a problem hiding this comment.
Ревью PR #121: feat(gallery): Vue refactor and unified modal styles
Большой и качественный PR — полная замена ExtJS-галереи на Vue. Архитектура хорошая: отдельные компоненты, composable useGalleryApi с withLoading, provide/inject для thumb, design-token для модалей. Лексиконы на двух языках, Uppy полностью локализован.
1. Безопасность: getMediaSourcesList() без проверки прав
public function getMediaSourcesList()
{
$sources = $this->modx->getCollection('sources.modMediaSource', ['id:>' => 0]);
...
}Загружает все медиа-источники без проверки access policies. MODX поддерживает ACL на медиа-источники — пользователь может не иметь доступа к некоторым из них.
Старый ms3-combo-source (ExtJS) загружал список через коннектор с проверкой прав. Новый код отдаёт все источники в JSON-конфиг страницы.
Нужно фильтровать через $source->checkPolicy('view') или использовать стандартный механизм MODX для получения доступных источников.
2. updateProductSource — частичное обновление через Product\Update
export async function updateProductSource(productId, sourceId) {
await connectorRequest(PRODUCT_UPDATE, {
id: productId,
source_id: sourceId,
})
location.reload()
}Старый ExtJS код отправлял всю форму через MODx.activePage.submitForm(). Новый код отправляет только id + source_id в Product\Update. Если процессор ожидает обязательные поля (pagetitle и т.д.) или обнуляет пустые — это может привести к потере данных товара. Нужно проверить поведение процессора при частичном вводе.
3. Мёртвый watcher в ProductGalleryGrid.vue
watch(
() => props.first,
(v) => {
if (searchQuery.value !== undefined) return
}
)searchQuery — всегда строка (инициализирован как ''), !== undefined всегда true. Watcher ничего не делает — мёртвый код, удалить.
4. Глобальные стили ConfirmDialog
В ProductGallery.vue (unscoped <style>):
.p-confirm-dialog {
width: var(--ms3-modal-width, 28rem);
max-width: 90vw;
...
}Затронет все ConfirmDialog на странице, не только галерейные. Может сломать другие диалоги (ProductData, будущие компоненты). Стоит ограничить scope или использовать отдельный CSS-класс.
5. CSS галереи загружается безусловно
Старый код загружал CSS/JS аплоадера только при $show_gallery === true. Новый код загружает GalleryUploader.min.css всегда, без проверки настройки ms3_product_tab_gallery.
6. Двойной emit при закрытии EditDialog
<Dialog
@update:visible="(v) => $emit('update:visible', v)"
@hide="close"
>close() вызывает emit('update:visible', false). При закрытии Dialog сначала вызовет @update:visible(false), потом @hide → close() → ещё один emit. Не вредит, но стоит убрать одно из двух.
7. Имя CSS-файла
gallery-uploader.min.css → GalleryUploader.min.css (PascalCase). Проверить, что Vite генерирует файл именно с таким именем.
Что сделано хорошо
- Composable
useGalleryApiсwithLoading— элегантный паттерн provide/injectдля обновления thumb- vuedraggable для drag&drop, context menu на правый клик
- Robust JSON parsing с fallback для PHP notices в
getResponseData - Debounced search
- Полная локализация Uppy
- Design-token
--ms3-modal-width
Итог
Пункты 1-2 — блокирующие (безопасность + потенциальная потеря данных). Остальное — улучшения.
…yles - Update product gallery components to enhance styling and functionality - Refactor ConfirmDialog and ProductGalleryEditDialog for consistent class usage - Adjust CSS class names for better specificity - Modify product update API endpoint for clarity - Remove unused watch functionality in ProductGalleryGrid
biz87
left a comment
There was a problem hiding this comment.
Ревью
PR отличный по архитектуре — composable с withLoading, provide/inject для thumb, отдельный UpdateSource процессор. Замечания biz87 учтены (checkPolicy, dedicated processor, переписанный watcher). Два момента:
1. Блокирующее: watch не импортирован в ProductGalleryGrid.vue
// строка 10
import { computed, ref } from 'vue'// строка 57 — вызов watch(), которого нет в импорте
watch(
() => props.items,
(val) => { orderedItems.value = val?.length ? [...val] : [] },
{ immediate: true }
)Компонент упадёт с ReferenceError: watch is not defined при рендере. Без этого watcher'а сетка галереи не будет обновляться при загрузке данных.
Фикс: import { computed, ref, watch } from 'vue'
2. Не блокирующее: connectorRequest фильтрует пустые строки — нельзя очистить description
В useGalleryApi.js:
Object.entries(allParams).filter(([_, v]) => v !== undefined && v !== null && v !== '')updateFile передаёт description: payload.description ?? ''. Если пользователь очистит description → пустая строка отфильтруется → процессор не получит параметр → значение останется прежним.
Старый ExtJS-код отправлял форму как есть, пустые поля доходили до процессора.
Варианты:
- Убрать
v !== ''из общего фильтра - Или не фильтровать пустые строки только для
updateFile(передавать params напрямую)
Описание
Рефакторинг галереи товара: замена старого JS (gallery.panel, toolbar, view, window) на Vue-компоненты и унификация стилей модальных окон.
Галерея:
ProductGallery,ProductGalleryGrid,ProductGalleryToolbar,ProductGalleryEditDialoguseGalleryApiдля работы с API галереиGalleryUploaderв новую структуруМодальные окна:
--ms3-modal-width(design tokens), ширина ConfirmDialog и Dialog приведена к единому виду (без растягивания на 90vw по умолчанию)closeButtonPropsдля применения класса к корневому элементу кнопки; круглая обводка при фокусе черезbox-shadowвместоoutlineТип изменений
Связанные Issues
(номер issue при наличии)
Как это было протестировано?
Конфигурация тестирования:
Скриншоты (если применимо)
Чеклист
Дополнительные заметки
gallery.panel.js,gallery.toolbar.js,gallery.view.js,gallery.window.js; стили галереи убраны изmain.cssoverflow-x: hidden) вынесены вprimevue.scss