Features: - Tree view mode for categories with expand/collapse - Product count badges with clickable preview popover - Select parent with all children button - Client-side tree filtering (refine search) - Keyboard shortcuts: Ctrl+A (select all), Ctrl+D (clear) - View mode switching between tree/list/columns - Tree view as default for categories, respects user preference Backend: - Add previewCategoryProducts and previewCategoryPages AJAX handlers - Support pagination and filtering in category previews Styling: - Consistent count-badge styling across tree and other views - Loading and popover-open states for count badges Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
450 lines
14 KiB
Markdown
Executable File
450 lines
14 KiB
Markdown
Executable File
# PrestaShop Entity Selector
|
|
|
|
A reusable entity selection component for PrestaShop admin interfaces. Provides a flexible, searchable UI for targeting entities with multiple selection methods, grouping, include/exclude logic, and preview functionality.
|
|
|
|
## Features
|
|
|
|
- **18 Entity Types** - Products, categories, customers, carriers, and more
|
|
- **130+ Selection Methods** - Filter by properties, patterns, ranges, related entities
|
|
- **Include/Exclude Logic** - Complex targeting with exceptions
|
|
- **Grouping** - Multiple selection groups with AND/OR logic
|
|
- **Live Preview** - See matching items in real-time
|
|
- **Modifiers** - Limit and sort results per group
|
|
|
|
---
|
|
|
|
## Supported Entities
|
|
|
|
| Entity | Icon | Methods | Description |
|
|
|--------|------|---------|-------------|
|
|
| Products | `icon-cube` | 30+ | Full product targeting with attributes, features, conditions |
|
|
| Categories | `icon-folder-open` | 6 | Product categories |
|
|
| Manufacturers | `icon-building` | 5 | Brand/manufacturer targeting |
|
|
| Suppliers | `icon-truck` | 5 | Supplier targeting |
|
|
| CMS Pages | `icon-file-text-o` | 6 | Static content pages |
|
|
| CMS Categories | `icon-folder-o` | 5 | CMS category groupings |
|
|
| Employees | `icon-user-secret` | 5 | Back-office users |
|
|
| Customers | `icon-users` | 12 | Front-office customers |
|
|
| Customer Groups | `icon-group` | 4 | Customer segmentation groups |
|
|
| Carriers | `icon-truck` | 10 | Shipping carriers |
|
|
| Zones | `icon-globe` | 4 | Geographic zones |
|
|
| Countries | `icon-flag` | 9 | Country targeting |
|
|
| Currencies | `icon-money` | 4 | Currency selection |
|
|
| Languages | `icon-language` | 5 | Language targeting |
|
|
| Shops | `icon-shopping-cart` | 4 | Multi-store shop selection |
|
|
| Profiles | `icon-key` | 3 | Employee access profiles |
|
|
| Order States | `icon-tasks` | 6 | Order status targeting |
|
|
| Taxes | `icon-money` | 5 | Tax rule selection |
|
|
|
|
---
|
|
|
|
## Products - Selection Methods
|
|
|
|
### All Products
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All products (no criteria) | none |
|
|
|
|
### By Entity
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `specific` | Specific individual products | entity_search |
|
|
| `by_category` | Products in category(ies) | entity_search |
|
|
| `by_manufacturer` | Products by manufacturer | entity_search |
|
|
| `by_supplier` | Products by supplier | entity_search |
|
|
| `by_tag` | Products by tag | entity_search |
|
|
| `by_attribute` | Products with attribute(s) | entity_search |
|
|
| `by_feature` | Products with feature(s) | entity_search |
|
|
| `by_combination` | Specific combinations | combination_attributes |
|
|
|
|
### By Property
|
|
| Method | Description | Options |
|
|
|--------|-------------|---------|
|
|
| `by_condition` | Product condition | New, Used, Refurbished |
|
|
| `by_visibility` | Visibility setting | Everywhere, Catalog only, Search only, Nowhere |
|
|
| `by_active_status` | Active status | Active, Inactive |
|
|
| `by_stock_status` | Stock status | In stock, Out of stock, Low stock |
|
|
| `by_on_sale` | On sale flag | Yes, No |
|
|
| `by_has_specific_price` | Has discount | Yes, No |
|
|
| `by_is_virtual` | Virtual product | Yes, No |
|
|
| `by_is_pack` | Pack product | Yes, No |
|
|
| `by_has_combinations` | Has combinations | Yes, No |
|
|
| `by_available_for_order` | Available for order | Yes, No |
|
|
| `by_online_only` | Online only | Yes, No |
|
|
| `by_has_related` | Has related products | Yes, No |
|
|
| `by_has_customization` | Has customization | Yes, No |
|
|
| `by_has_attachments` | Has attachments | Yes, No |
|
|
| `by_out_of_stock_behavior` | Out of stock behavior | Deny orders, Allow orders, Use default |
|
|
| `by_delivery_time` | Delivery time setting | None, Default, Specific |
|
|
| `by_has_additional_shipping` | Additional shipping cost | Yes, No |
|
|
| `by_carrier_restriction` | Carrier restriction | Has restriction, All carriers |
|
|
|
|
### By Text Pattern
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `by_name_pattern` | Product name contains | pattern |
|
|
| `by_reference_pattern` | Reference contains | pattern |
|
|
| `by_description_pattern` | Short description contains | pattern |
|
|
| `by_long_description_pattern` | Long description contains | pattern |
|
|
| `by_ean13_pattern` | EAN-13 contains | pattern |
|
|
| `by_upc_pattern` | UPC contains | pattern |
|
|
| `by_isbn_pattern` | ISBN contains | pattern |
|
|
| `by_mpn_pattern` | MPN contains | pattern |
|
|
| `by_meta_title_pattern` | Meta title contains | pattern |
|
|
| `by_meta_description_pattern` | Meta description contains | pattern |
|
|
|
|
### By Range
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `by_id_range` | Product ID range | numeric_range |
|
|
| `by_price_range` | Price range | numeric_range |
|
|
| `by_weight_range` | Weight range | numeric_range |
|
|
| `by_quantity_range` | Stock quantity range | numeric_range |
|
|
| `by_position_range` | Position range | numeric_range |
|
|
| `by_date_added` | Date added range | date_range |
|
|
| `by_date_updated` | Date modified range | date_range |
|
|
|
|
---
|
|
|
|
## Categories - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All categories | none |
|
|
| `specific` | Specific category(ies) | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_product_count` | Product count range | numeric_range |
|
|
| `by_depth_level` | Depth level range | numeric_range |
|
|
| `by_active_status` | Active status | select |
|
|
|
|
---
|
|
|
|
## Manufacturers - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All manufacturers | none |
|
|
| `specific` | Specific manufacturer(s) | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_product_count` | Product count range | numeric_range |
|
|
| `by_active_status` | Active status | select |
|
|
|
|
---
|
|
|
|
## Suppliers - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All suppliers | none |
|
|
| `specific` | Specific supplier(s) | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_product_count` | Product count range | numeric_range |
|
|
| `by_active_status` | Active status | select |
|
|
|
|
---
|
|
|
|
## CMS Pages - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All CMS pages | none |
|
|
| `specific` | Specific page(s) | entity_search |
|
|
| `by_cms_category` | Pages in CMS category | entity_search |
|
|
| `by_name_pattern` | Title contains | pattern |
|
|
| `by_active_status` | Active status | select |
|
|
| `by_indexable` | Indexable status | select |
|
|
|
|
---
|
|
|
|
## Customers - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All customers | none |
|
|
| `specific` | Specific customer(s) | entity_search |
|
|
| `by_group` | By customer group | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_email_pattern` | Email contains | pattern |
|
|
| `by_company` | Has company | select |
|
|
| `by_company_pattern` | Company name contains | pattern |
|
|
| `by_address_count` | Address count range | numeric_range |
|
|
| `by_order_count` | Order count range | numeric_range |
|
|
| `by_turnover` | Total spent range | numeric_range |
|
|
| `by_active_status` | Active status | select |
|
|
| `by_newsletter` | Newsletter subscription | select |
|
|
| `by_guest` | Guest or registered | select |
|
|
|
|
---
|
|
|
|
## Carriers - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All carriers | none |
|
|
| `specific` | Specific carrier(s) | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_active_status` | Active status | select |
|
|
| `by_shipping_handling` | Handling fee | select |
|
|
| `by_free_shipping` | Free shipping | select |
|
|
| `by_zone` | By zone | entity_search |
|
|
| `by_customer_group` | By customer group | entity_search |
|
|
| `by_price_range` | Shipping price range | numeric_range |
|
|
| `by_weight_range` | Max weight range | numeric_range |
|
|
|
|
---
|
|
|
|
## Countries - Selection Methods
|
|
|
|
| Method | Description | Value Type |
|
|
|--------|-------------|------------|
|
|
| `all` | All countries | none |
|
|
| `specific` | Specific country(ies) | entity_search |
|
|
| `by_zone` | By zone | entity_search |
|
|
| `by_name_pattern` | Name contains | pattern |
|
|
| `by_active_status` | Active status | select |
|
|
| `by_contains_states` | Has states | select |
|
|
| `by_need_zip_code` | Requires ZIP | select |
|
|
| `by_zip_format` | ZIP format contains | pattern |
|
|
| `by_need_identification` | Requires ID number | select |
|
|
|
|
---
|
|
|
|
## Other Entities
|
|
|
|
### Customer Groups
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_price_display` | various |
|
|
|
|
### Zones
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_active_status` | various |
|
|
|
|
### Currencies
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_active_status` | various |
|
|
|
|
### Languages
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_active_status`, `by_rtl` | various |
|
|
|
|
### Shops
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_active_status` | various |
|
|
|
|
### Profiles
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern` | various |
|
|
|
|
### Employees
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_profile`, `by_name_pattern`, `by_active_status` | various |
|
|
|
|
### Order States
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_paid`, `by_shipped`, `by_delivery` | various |
|
|
|
|
### Taxes
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_rate_range`, `by_active_status` | various |
|
|
|
|
### CMS Categories
|
|
| Method | Value Type |
|
|
|--------|------------|
|
|
| `all`, `specific`, `by_name_pattern`, `by_active_status`, `by_page_count` | various |
|
|
|
|
---
|
|
|
|
## Value Types
|
|
|
|
| Type | UI Component | Description |
|
|
|------|--------------|-------------|
|
|
| `none` | No input | Used for "All" methods |
|
|
| `entity_search` | Searchable dropdown with chips | Select related entities |
|
|
| `pattern` | Text input | Text/regex pattern matching |
|
|
| `multi_select_tiles` | Toggle buttons | Multiple Yes/No options |
|
|
| `select` | Single dropdown | Single option selection |
|
|
| `numeric_range` | Min/Max inputs | Numeric range filtering |
|
|
| `multi_numeric_range` | Multiple ranges | Multiple numeric ranges |
|
|
| `date_range` | Date pickers | Date range filtering |
|
|
| `combination_attributes` | Attribute selector | Product combination selection |
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
### PHP Integration
|
|
|
|
```php
|
|
use MyPrestaRocks\EntitySelector\EntitySelector;
|
|
|
|
class AdminMyController extends ModuleAdminController
|
|
{
|
|
use EntitySelector;
|
|
|
|
public function setMedia($isNewTheme = false)
|
|
{
|
|
parent::setMedia($isNewTheme);
|
|
$this->initEntitySelector();
|
|
}
|
|
|
|
public function renderForm()
|
|
{
|
|
$html = $this->renderEntitySelectorHtml(
|
|
[
|
|
'id' => 'my-selector',
|
|
'blocks' => ['products', 'categories'],
|
|
'show_modifiers' => true,
|
|
],
|
|
$savedData
|
|
);
|
|
// Add $html to your form
|
|
}
|
|
|
|
public function ajaxProcessEntitySelector()
|
|
{
|
|
$this->handleEntitySelectorAjax();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
```php
|
|
$this->renderEntitySelectorHtml([
|
|
'id' => 'selector-id', // Unique ID
|
|
'blocks' => ['products'], // Which entity tabs to show
|
|
'mode' => 'multi', // 'single' or 'multi' group mode
|
|
'show_modifiers' => true, // Show limit/sort per group
|
|
'show_preview' => true, // Show preview button
|
|
'default_method' => 'all', // Default selection method
|
|
], $savedData);
|
|
```
|
|
|
|
### JavaScript Events
|
|
|
|
```javascript
|
|
// Listen for selection changes
|
|
$(document).on('entitySelector:change', function(e, data) {
|
|
console.log('Selection changed:', data);
|
|
});
|
|
|
|
// Get current selection
|
|
var data = window.EntitySelector.serialize('#my-selector');
|
|
```
|
|
|
|
---
|
|
|
|
## Data Format
|
|
|
|
Selection data is stored as JSON:
|
|
|
|
```json
|
|
{
|
|
"products": {
|
|
"groups": [
|
|
{
|
|
"name": "Group 1",
|
|
"include": {
|
|
"method": "by_category",
|
|
"values": [3, 5, 8]
|
|
},
|
|
"excludes": [
|
|
{
|
|
"method": "specific",
|
|
"values": [42, 99]
|
|
}
|
|
],
|
|
"limit": 10,
|
|
"sort": "bestsellers"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
```
|
|
prestashop-entity-selector/
|
|
├── src/
|
|
│ ├── EntitySelector.php # Main trait (orchestrator)
|
|
│ └── EntitySelector/
|
|
│ ├── ProductConditionResolver.php
|
|
│ ├── EntityQueryHandler.php
|
|
│ ├── EntitySelectorRenderer.php
|
|
│ ├── EntitySearchEngine.php
|
|
│ ├── EntityPreviewHandler.php
|
|
│ └── MethodHelpProvider.php
|
|
├── sources/
|
|
│ ├── scss/
|
|
│ │ ├── main.scss
|
|
│ │ ├── _variables.scss
|
|
│ │ ├── _mixins.scss
|
|
│ │ └── components/
|
|
│ │ ├── _entity-selector.scss
|
|
│ │ ├── _dropdown.scss
|
|
│ │ ├── _chips.scss
|
|
│ │ ├── _groups.scss
|
|
│ │ ├── _modal.scss
|
|
│ │ └── ...
|
|
│ └── js/admin/entity-selector/
|
|
│ ├── _core.js
|
|
│ ├── _events.js
|
|
│ ├── _dropdown.js
|
|
│ ├── _search.js
|
|
│ ├── _groups.js
|
|
│ ├── _chips.js
|
|
│ ├── _methods.js
|
|
│ ├── _preview.js
|
|
│ ├── _filters.js
|
|
│ └── _utils.js
|
|
├── assets/
|
|
│ ├── css/admin/entity-selector.css
|
|
│ └── js/admin/
|
|
│ ├── entity-selector.js
|
|
│ └── entity-selector.min.js
|
|
├── gulpfile.js
|
|
├── package.json
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## Building
|
|
|
|
```bash
|
|
# Install dependencies
|
|
npm install
|
|
|
|
# Build CSS and JS
|
|
npm run build
|
|
|
|
# Watch for changes during development
|
|
npm run watch
|
|
```
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
- PrestaShop 1.7.x or 8.x
|
|
- PHP 7.1+
|
|
- Node.js 16+ (for building)
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
Proprietary - MyPrestaRocks
|