Repository navigation
fix(admin): align toolbar and media upload layouts - #700
Conversation
The options endpoint matches a category name as well as its code, and the factory generates a random code that can be two characters long, so a generated name could contain the searched code and the assertion saw two rows. Claude-Session: https://claude.ai/code/session_01JfF9ke2aCFppkN9pYbCfKn
…e-baseline The tracker re-snapshots the form 700ms after mount unless it has seen a trusted DOM event, so late-initialising widgets do not leave the bar open. TinyMCE edits happen inside an iframe and reach the tracker only through the custom `unsaved-changes:touch` event, which did not count as interaction; an edit made within that window was absorbed into the baseline and the bar unmounted mid-click. Custom touches now mark the form as interacted with, so the fallback never re-baselines over a real edit. Fixes the Playwright "WYSIWYG edit is reverted by Discard" failure on shard 2. Claude-Session: https://claude.ai/code/session_01PsQH9MtPXHUVZUWNVogstf
There was a problem hiding this comment.
🟡 Changes recommended
One critical gallery rendering issue and four unresolved moderate media-file issues block approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR aligns Admin toolbar/media layouts, updates export filename labels across locales, and adds regression coverage.
Changes:
- Makes toolbar and media grids responsive.
- Adds media preview/download handling and unsaved-change tracking.
- Updates localized export labels and related tests.
File summaries
| File | Summary |
|---|---|
packages/Webkul/DataTransfer/src/Validators/JobInstances/Export/ProductJobValidator.php |
Updates the export validation label. |
packages/Webkul/DataTransfer/src/Resources/lang/zh_TW/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/zh_CN/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/vi_VN/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/uk_UA/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/tr_TR/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/tl_PH/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/sv_SE/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ru_RU/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ro_RO/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/pt_PT/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/pt_BR/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/pl_PL/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/no_NO/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/nl_NL/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/mn_MN/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ko_KR/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ja_JP/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/it_IT/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/id_ID/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/hr_HR/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/hi_IN/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/fr_FR/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/fi_FI/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/es_VE/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/es_ES/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/en_US/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/en_NZ/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/en_GB/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/en_AU/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/de_DE/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/da_DK/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ca_ES/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Resources/lang/ar_AE/app.php |
Adds localized filename labels. |
packages/Webkul/DataTransfer/src/Config/exporters.php |
Uses filename translations for product exports. |
packages/Webkul/Admin/tests/Feature/Fields/FieldConfigTest.php |
Tests localized labels and preserved setting names. |
packages/Webkul/Admin/tests/Feature/DataGridToolbarLayoutTest.php |
Adds toolbar layout regression coverage. |
packages/Webkul/Admin/tests/Feature/Catalog/CategoryFilterOptionsTest.php |
Makes category search data deterministic. |
packages/Webkul/Admin/src/Resources/views/components/media/gallery.blade.php |
Adds responsive gallery layout and MIME validation. Critical finding: undeclared $resolvedMimeTypes can fail rendering (3 votes). |
packages/Webkul/Admin/src/Resources/views/components/media/files.blade.php |
Adds responsive file layout and preview fallback. Four moderate findings remain: missing translation (3 votes), txt preview mismatch (2 votes), invalid extension fallback (1 vote), and download gating bypass (1 vote). |
packages/Webkul/Admin/src/Resources/views/components/form/unsaved-changes.blade.php |
Tracks custom media changes as trusted edits. |
packages/Webkul/Admin/src/Resources/views/components/datagrid/toolbar.blade.php |
Prevents toolbar controls from expanding. |
Review details
Suppressed comments (2)
packages/Webkul/Admin/src/Resources/views/components/media/files.blade.php:320
- Saved product/category file labels can be truncated to a value ending in
...; because this condition treats any dot as a real extension, a long.csv/.docxpath can produce an empty or invalid extension and then fall back topdf. Use the full savedinputFile.valuewhen deriving the extension.
packages/Webkul/Admin/src/Resources/views/components/media/files.blade.php:120 - The fallback download link ignores
allowDownload. This prop defaults to false and the regular card correctly hides its download action, but unsupported files now always expose a download control in this modal. Gate the link withv-if="allowDownload"so callers that disable downloads retain that behavior.
- Files reviewed: 110/110 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Validate MagicAI platform extras through the request rule so only a JSON object survives, and persist them only when the field is submitted. Rework the datagrid toolbar, manage-columns and tags field markup for responsive layouts, add an `overlay-open` body class alongside the scroll lock, and register the `txt` MIME type for media content. Adds the matching Pest coverage, the tags translations across all 33 locales, a responsive product grid Playwright spec and rebuilt assets.
Render the tags editor with the shared vue-multiselect classes so chips, active border and dark mode come from the same theme tokens as every other multi-value control, instead of a bespoke bordered box with a counter row. Replace the non-existent `icon-cross-large` class with `icon-cancel`, which the icon set actually defines — the datagrid clear-selection icon rendered at zero size for the same reason. Drop the now-unused hint and counter translations across all 33 locales and move "clear all" onto a cross button inside the control.
The chip padding, right margin and the absolutely positioned remove icon all come from `.multiselect__tag`; overriding the margin and turning the chip into a flex row collapsed the gaps and pulled the icon against the label. Only the row wrapping is ours now.
Chips filling the row shrank the input to zero width, leaving nowhere to type and no hint that more values can be added. Give it a 12rem minimum so it wraps onto its own line instead of collapsing, keep the placeholder visible once chips exist, and match the field's 14px type.
The field hand-rolled its own chip box, so every state — focus ring, chip metrics, dark mode, disabled — had to be re-implemented with overrides and drifted from the multi-value controls next to it. Drive it through the same `v-multiselect` the select fields use, in taggable mode, and keep only the behaviour that is specific to free-text identifiers: splitting a pasted comma or newline separated list, and a clear-all control in the library's own `clear` slot. Adds the `tag-placeholder` string across all 33 locales.
The toolbar now collapses its labels and first/last page controls once it measures narrow, and the modal closes on escape, so specs that clicked the "Filter" label, asserted every pagination arrow or pressed escape to dismiss a select dropdown broke against the new behaviour. - add a `data-grid-filter` hook and open the drawer through it - derive the expected pagination symbols from the toolbar's measured width - close select dropdowns by blurring instead of pressing escape - teleport the confirm modal so it clears `#app` paint containment and the teleported dropdown panels that otherwise swallow its buttons - wait for the filter drawer's enter transition before measuring it
…y' into fix/category-filter-options-flaky
A teleported dropdown panel is a body child at z-10010, so it covers the confirmation dialog inside `#app` — the dialog's buttons were unclickable while the saved-views menu was open. Teleporting the dialog fixed the stacking but moved it out of `#app`, so dismiss the dropdown instead.
The passport spec opens with a block comment, so the added require landed inside it and `closeDropdown` was never defined. The measurement filter test still clicked the collapsed label, which the icon covers.
waitForURL matched the parent edit URL the page was already on, so it resolved before the child existed and childId read back as parentId.
Every localisable or channel scoped attribute expands into its own mapped field, so a wide attribute set exhausted Elasticsearch's default limit of 1000 and the indexer rejected documents. The limit is now configurable and applied to existing indices as a dynamic setting, so no reindex is needed.
Both stylesheets were imported from the plugin entrypoints and the flatpickr dark theme was fetched from npmcdn at runtime, which breaks on an isolated network. They are now part of the admin bundle and themed through the colour tokens, and darkVariantOf() applies the dark variant per selector so grouped rules are checked the way Tailwind compiles them.
The mailer hook replaced the array transport the test environment forces with the host stored in core_config, so the suite dialled the configured SMTP server and the admin forget-password test failed on a 530.
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved critical and moderate findings remain, and the bundled scope is broad while full validation could not run.
Review details
Suppressed comments (4)
UPGRADE.md:147
- The guide now installs 3.1.1, but the “current” release remains 2.1.6 in the layout and in the copy/
--from/worktree commands below. For a 3.1.0 → 3.1.1 upgrade these commands use a stale release and can copy the wrong environment/storage or compare against the wrong tree; update the previous-release references or state explicitly that 2.1.6 is intentional.
curl -fL -o unopim.zip https://github.com/unopim/unopim/archive/refs/tags/v3.1.1.zip
package.json:3
- This change set is substantially broader than the PR description: besides toolbar/media layout tests, it changes AI defaults, mail resolution, Elasticsearch index settings, upload/security rules, DataTransfer behavior, release docs, and the bundled TinyMCE version. Please split these unrelated changes or update the PR scope before approval so each behavior can be reviewed and validated independently.
"version": "3.1.1",
packages/Webkul/Admin/src/Resources/views/components/modal/confirm.blade.php:117
- This event is emitted only by the confirm modal. The regular modal component also locks the body and now closes on Escape, but never emits
overlay:opened, so opening a normal dialog (including media previews) does not deactivate dropdowns through the new listener and can leave a dropdown active behind the overlay. Emit the event from the regular modal open path too.
packages/Webkul/AiAgent/src/Database/Seeders/AgenticPimConfigSeeder.php:14 - The PR description is limited to toolbar/media layout alignment and a regression assertion, but this hunk changes the installation default for Agentic PIM from enabled to disabled, alongside other unrelated release, upload, import, and search changes in the same PR. That is a user-visible behavior change that should be split into a separate change or explicitly documented and validated here.
- Files reviewed: 188/292 changed files
- Comments generated: 5
- Review effort level: Lite
| 'file' => [ | ||
| 'required', | ||
| 'file', | ||
| 'mimes:jpg,jpeg,png,gif,jfif,jif,webp,bmp,tif,tiff,psd,pdf,mp4,webm,mkv,csv,doc,docx,mp3,ppt,pptx,rtf,txt,wav', |
| v-if="isVideo && allowPreview" | ||
| type="button" | ||
| class="pointer-events-auto text-2xl text-white drop-shadow-[0_1px_3px_rgba(0,0,0,0.9)] transition-transform hover:scale-110" | ||
| aria-label="@lang('admin::app.components.media.images.preview-image')" |
| 'pdf' => 'application/pdf', | ||
| 'png' => 'image/png', | ||
| 'svg' => 'image/svg+xml', | ||
| 'txt' => 'text/plain; charset=UTF-8', |
| $view->with('resolvedMimeTypes', (object) array_replace( | ||
| app(MediaMimeTypes::class)->forExtensions($extensions), | ||
| $mimeTypes, | ||
| )); |
Skipping the hook for every test run broke RequestOverheadTest, which resolves a mailer to prove the settings are read lazily. Only the array transport is now left alone, so that deferral is still exercised.
Eight merged pull requests since v3.1.0 carried no changelog entry: the role-escalation and MagicAI SSRF fixes (#689, #690, #691), the export column selection and category keyword matching fixes (#697, #698), the media replacement fix (#709), the Gemini endpoint (#699), the channel deletion fix (#688), the purifier cache race (#675), and the admin UI and configuration work squashed into #700. 3.1.1 is a patch release, so everything is filed under bug fixes and improvements; no feature section. The heading is stamped 3.1.1 to match Core::VERSION, which the branch already carries.
Eight merged pull requests since v3.1.0 carried no changelog entry: the role-escalation and MagicAI SSRF fixes (#689, #690, #691), the export column selection and category keyword matching fixes (#697, #698), the media replacement fix (#709), the Gemini endpoint (#699), the channel deletion fix (#688), the purifier cache race (#675), and the admin UI and configuration work squashed into #700. 3.1.1 is a patch release, so everything is filed under bug fixes and improvements; no feature section. The heading is stamped 3.1.1 to match Core::VERSION, which the branch already carries.
* fix: validate empty files during product import instead of throwing code error (unopim#696) * fix: hide broken logo image in profile dropdown when remote fetch fails (unopim#700) * fix: disable @ attribute suggestions in profile image AI generation (unopim#701) * fix: set HTMLPurifier cache path to storage directory to prevent vendor write error during import (unopim#350) * fix: hide webhook logs tab and enforce ACL for unauthorized roles (unopim#545) * fix: EditImage tool now fetches product image by SKU instead of requiring upload (unopim#683) * fix: add XLSX export support to AI Agent ExportProducts tool (unopim#684) * fix: add SKU validation to AI Agent bulk import to reject special characters (unopim#689) * style: apply pint formatting to AiAgent lang file * fix: address copilot review on PR unopim#353
Summary
Validation