Recent Activities
This page shows what are we working on.
-
head
-
1.0.0
-
head
-
Init commit 479fc9
-
-
head
-
fix(filter): handle array value from multiselect getFrontend()->getValue() 9f5ef6
-
fix(filter): use is_visible + input type instead of is_visible_on_front
getIsVisibleOnFront() = 0 for all catalog attributes (name, sku, price
etc) so {{attribute code="*"}} always returned empty string.
New logic: is_visible=1 AND frontend_input NOT IN excluded types
(date, media_image, image, gallery, hidden). Includes text, textarea,
select, multiselect, boolean, price, weight.
Add FilterTest cases for langCodeDirective and attributeDirective. 205910 -
fix(popup): use Magento action-primary button, reduce textarea rows to 4 93c018
-
fix(prompts): add product-name prompt, fix product-meta-keyword typo 4eda0f
-
revert: remove FixPromptFieldIds data patch
No releases yet — fix directly in InstallDefaultPrompts instead. 122ef2 -
fix(prompts): fix product-meta-keyword typo in InstallDefaultPrompts cfb7b6
-
fix(prompts): fix product-meta-keyword typo, add product-name prompt
- prompt #5 field_ids: product-meta-keyword → product-meta-keywords
- add new 'Generate Product Name' prompt for product-name field 6eda92 -
test,docs: update tests and docs for Phase 5 bulk refactoring
- Remove 4 old consumer tests
- Add BulkConsumerTest, GenerateServiceTest
- Update GenerateTest, TranslateTest, SkillGenerateTest
- Update DEVELOPMENT.md, SESSION.md with Phase 5 status
- Add phase-5.md and refactoring-skill-prompt.md plans f000f3 -
feat(css): add BulkAction page styles cc5c33
-
refactor(bulk): remove old per-entity bulk controllers, blocks, consumers
Replaced by universal BulkAction page (Phase 5). Deleted:
- 4 controllers (product/category × generate/translate)
- 9 block classes
- 4 MQ consumers
- 4 layouts, 3 templates
- product_listing.xml mass-actions (swissup_breezeai_generate/translate) b3f6db -
feat(view): add BulkAction layout and edit.phtml template
Single-page form: entity radio, skill radio, store selects,
generate fields (checkbox+prompt), translate fields (checkboxes),
UI grid, sticky Run button. Inline JS handles entity/skill switching
and grid checkbox collection. 8232d2 -
feat(ui): add BulkDataProviders and bulk UI component grids
Product and category grids for the BulkAction page with ID/name
columns, filters, pagination, and mass-select support. d25290 -
feat(bulk): add BulkConsumer, BulkAction controllers, and Edit block
BulkConsumer replaces 4 old consumers — routes by skill/entity_type.
BulkAction/Edit: GET form page.
BulkAction/Save: validates POST, schedules MQ jobs via BulkScheduleTrait. be4b73 -
refactor(acl,menu): consolidate bulk ACL resources and menu item
4 separate ACL resources (bulk_product_generate, bulk_product_translate,
bulk_category_generate, bulk_category_translate) → single bulk_action.
Menu: 'Generate Content for Categories' → 'AI Bulk Action'. 78e03f -
feat(di): register product name field in InputFieldPool d0d391
-
refactor(mq): replace 4 topics/consumers with single swissup.breezeai.bulk
4 separate queues (product-generate, product-translate, category-generate,
category-translate) → one universal queue handled by BulkConsumer. becb6c -
feat(skill): add getSupportedAttributes() to SkillInterface
BulkAction UI needs per-skill attribute lists. Generate uses
InputFieldPool; Translate switches from hardcoded const to
InputFieldPool so both stay in sync with di.xml registrations.
Also moves translateForAllStores + saveAttributeForStore out of
Translate skill into GenerateService (single responsibility). b04e25 -
fix(generate): convert history arrays to MessageInterface objects
JSON deserialization produces plain arrays; OpenAi::chat() closure
requires MessageInterface. Convert in GenerateService before passing
to skill.
Closes #4 60f191 -
fix(openai): handle TypeError from openai-php/client v0.10 string response
v0.10 Response::data() returns array|string; string body passed to
CreateResponse::from(array) causes TypeError. Catch \TypeError with
a clear message. Bump constraint to ^0.10 || ^0.19 to allow upgrade. dda01d -
fix(menu): move Breeze AI below Content Builder b9b95e
-
fix(menu): reduce submenu indent to 28px e01066
-
fix(menu): apply muted color to Breeze AI group title only e4a344
-
feat(menu): add muted color for Breeze AI submenu items 7e2474
-
fix(menu): increase specificity for Breeze AI submenu indent 3d93d8
-
feat(menu): add indent for Breeze AI submenu items 154112
-
fix(menu): shorten menu item titles within Breeze AI group 253b57
-
feat(menu): group Breeze AI items under dedicated submenu 8764fc
-
fix(model): replace parent::_beforeSave() call to fix PHPStan error 1737c7
-
fix(model): remove invalid return type from _beforeSave b96839
-
refactor(consumers+controllers): extract AbstractConsumer and BulkScheduleTrait to eliminate duplication 6093cd
-
fix(cs): fix self-closing path tags and unescaped output d1089b
-
fix(js): skip service fields when attaching AI buttons 708dbb
-
test(integration): add admin HTTP integration tests for generate endpoint
- AbstractAdminApiTest: cURL-based login (form_key, admin cookie, secret key)
- GenerateTest: 7 cases covering generate, translate, validation, no-auth
- bin/test integration: runs via phpfpm container with CURL_CONNECT_TO routing
- AI tests skipped unless TEST_AI_ENABLED=1
Key findings: Magento requires form_key in POST params even with
CsrfAwareActionInterface; admin cookie value = PHP session ID in Redis. 4f1b6f -
docs: add session summary d2d983
-
fix(block): remove typed $_template to fix PHP 8.3 fatal error
Parent Magento\Backend\Block\Widget\Form declares $_template without
a type; redefining it with 'string' type causes a fatal error in PHP 8.3. ede0fa -
refactor(blocks): extract AbstractGenerateAttributes base class
Product and Category generate-tab blocks shared ~100 lines of identical
renderFieldRow/getFieldPromptsHtml/TabInterface code. Extract into
AbstractGenerateAttributes; concrete classes now only define field list
and fieldId prefix. 71ed4a -
docs: move DEVELOPMENT.md to docs/, add integration tests plan 42fb8d
-
refactor(translate): remove store selector, use current scope
Single product translate no longer shows a store picker modal:
- scope=0 (All Store Views): translates & saves to DB for every
non-default store view automatically, shows success alert
- scope=X (specific store): translates and writes result directly
into the form field; admin saves manually
Also fix FormDataProviderTest missing RequestInterface arg. 98ec57 -
fix(prompts): replace invalid directives with correct attribute syntax
{{product_name}} / {{category_name}} are not recognized directives —
filter silently drops them, leaving AI with no product context.
Replace with {{attribute code="name"}}, add {{categories}},
{{attribute code="*"}}, {{langCode}} context matching legacy module.
Also adds Testing Checklist to DEVELOPMENT.md. 10e739 -
fix: cast websiteId to int in bulk product generate save 23ab31
-
fix(model-form): save new record and restore model on edit
- Save.php: unset entity_id/form_key before addData to prevent empty
entity_id string blocking INSERT (Magento treated it as UPDATE id=0)
- FormDataProvider: inject RequestInterface; add getMeta() that passes
savedModel config to JS so edit form shows the correct model option
- model-select.js: read savedModel config on first onProviderChange call
(via imports) to restore the persisted value instead of resetting to
the first option of the newly-loaded provider list 76cf4b -
fix: throw LocalizedException when translate field is empty ffc9e1
-
feat: add menu item for bulk category AI generate fbe18d
-
fix: add TabInterface to Category Content Attributes block 327067
-
feat(phase-4): bulk category AI content generation
- CategoryConsumer: generate+save per category via Generate skill
- Controllers: Edit (render page) + Save (dispatch async bulk)
- Block/Attributes: field/prompt selector for category fields
- Block/Edit: flat category list + store view selector
- Template: checkbox list with Select All, store view dropdown
- Queue: add swissup.breezeai.category.attribute.update topic
- ACL: add bulk_category_generate resource
- Tests: CategoryConsumerTest (11 tests) 09198b -
test: add CategoryTranslateConsumer unit tests e45eaa
-
docs: mark phase-3 done, update phase-4 status
refactor(assistant): wrap buttons in .ai-field-actions container 889ea1 -
refactor: extract translate attributes HTML to shared phtml template, base abstract block 171d07
-
fix: translate button use action-default style + ai-field-actions wrapper, align with generate button d5e9e1
-
feat(phase-3): category bulk translate — controllers, consumer, queue topic, layout, ACL a68cc7
-
feat(phase-3): manual translate UI — inject translate button per field, modal with store selector, apply result to store scope 89596b
-
refactor: extract PromptRepositoryInterface, ModelConfigRepositoryInterface; add setters to ModelConfigInterface; use interfaces in DI 087226
-
refactor: add @api markers, public const, ResultInterface return types to interfaces and controllers fbf28d
-
feat: dynamic model list based on selected provider in model form 4c0d39
-
feat: add Translate skill and bulk product translation (Phase 3) b28da1
-
docs: add bulk product content generation guide to README 4d321f
-
fix: correct product-meta-keyword field_id in default prompts (remove extra 's') 046ea4
-
refactor: render field rows without attribute inputs in bulk form dc7e9f
-
fix: use settings syntax for mass action URL, fix incompatible method signature 1a4321
-
fix: remove incompatible return type from _getAdditionalElementHtml 3004ee
-
test: add extra params and edge case tests for Claude and Gemini providers cccaad
-
chore: ignore .playwright-mcp directory 9551d8
-
feat(phase-2): add Claude and Gemini providers 3f1e47
-
test: add ConsumerTest for bulk product AI generation 5ad94f
-
feat(step-11): bulk product AI content generation via MessageQueue 701783
-
docs: mark step-10, step-12 as done in plan 33d605
-
test: add ModelConfig, ModelConfigRepository, FormDataProvider tests
- ModelConfigTest: getModel custom resolve, encrypt/decrypt api_key,
isEnabled, isDefault, getBaseUrl, getOrganization, getExtra JSON
- ModelConfigRepositoryTest: getById happy/not-found, getDefault with
is_default flag, fallback to first enabled, throws when none exist
- FormDataProviderTest: api_key mask, empty key, id indexing, cache 3ea4df -
feat(step-10): AI Model & Prompt CRUD admin UI
- Model/Prompt controllers (Index, NewAction, Edit, Save, Delete)
- UI listing + form components for both entities
- Form buttons (Back, Delete, Save) for both entities
- DataProviders: listing + form (api_key masked as ****** in form)
- Save controller encrypts api_key via Encryptor; mask ignored on save
- switcherConfig hides custom_model field unless model=custom
- Advanced fieldset (collapsible) for base_url, organization
- Source classes: FieldId, ModelOptions, OpenAiModel (+gpt-4o-mini)
- Menu items under Swissup > Breeze (sortOrder 120/130) 889e2c -
docs: update plan — step-09 done, phase-1 progress 87003f
-
feat(step-09): frontend JS assistant + styles
- assistant.js: MutationObserver inject AI button per field
- auto-select prompt if one, dropdown if multiple
- REST POST to /rest/default/V1/breezeai/generate with X-Requested-With
- TinyMCE + plain textarea support on apply
- _module.less: button + prompt select styles
- Fix apiUrl in Js block to use rest/default/V1 prefix a21c82 -
feat(step-08): admin JS block + layout for product/category edit
- Js block renders JSON config (apiUrl, entityType, entityId, fields+prompts)
- js.phtml initializes Swissup_BreezeAi/js/assistant component
- Layout: catalog_product_edit + catalog_category_edit inject block before.body.end 952053 -
feat(step-08): REST API endpoint POST /V1/breezeai/generate
- GenerateInterface — typed contract with MessageInterface[] history
- GenerateService — load entity by type, dispatch to SkillPool
- webapi.xml — route secured by Swissup_BreezeAi::manage ACL
- acl.xml — add manage resource under assistant
- PromptRepository::getListByFieldId() — filter prompts by field ID
- Tests: GenerateServiceTest, PromptRepositoryTest b555db -
feat(step-07): InputFieldPool via DI — replaces Observer/Event approach
- InputFieldInterface with ENTITY_PRODUCT/CATEGORY constants
- InputField DTO, all config via constructor promoted properties
- InputFieldPool: getAll(), getByEntityType(), getById()
- 9 built-in fields as virtualType in di.xml (product + category)
- Third-party modules extend via di.xml array merge (unique key = add, same key = override) 5b5d59 -
refactor(step-06b): code revision — dead deps, field constants, MessageInterface
- Remove unused constructor in Helper/Config
- Add field constants to ModelConfigInterface, use in ModelConfig/Repository/Collection
- Remove dead deps: CatalogHelper (Product filter), StoreManagerInterface (Category filter)
- Remove dead code: STATUS_DISABLED x2, addProviderFilter()
- Add isEnabled() gate-check in AiRequest::send()
- Add MessageInterface + Message DTO
- SkillInterface::execute() — typed history as separate param MessageInterface[]
- OpenAi::chat() uses getRole()/getContent() instead of array access
- Generate skill builds Message objects, adapts to new execute() signature
- Update AiRequestTest, GenerateTest (new signature + history merge test) cae984 -
feat(step-06): add Filter layer, Generate skill, SkillPool, PromptRepository
- Model/Filter/Filter.php: base template filter with attribute/langCode directives
- Model/Filter/Product.php: adds categories directive (breadcrumb paths)
- Model/Filter/Category.php: adds subcats directive
- Model/Skill/Generate.php: resolves prompt, filters content, calls AiRequest
- Model/SkillPool.php: registry pattern, mirrors ProviderPool
- Model/PromptRepository.php: getById/save/delete
- Prompt::getContent() explicit method (needed for mocks)
- di.xml: register Generate skill in SkillPool
- config.xml: remove provider defaults (moved to DB)
- 34/34 unit tests passing 9525b7 -
feat(step-05): ModelConfig entity+repository, Prompt entity, DB schema, refactor provider interface to use ModelConfigInterface 97f515
-
test: add unit tests for Config, ProviderPool, AiRequest, OpenAi provider 7bd0ad
-
docs: add development plan and per-step task files 424bb2
-
feat(step-04): OpenAI provider, ProviderPool, AiRequest, DI registration b719ec
-
feat(step-03): admin config, menu, ACL, Helper/Config, model sources 8e2498
-
feat(step-02): ProviderInterface and SkillInterface b720d9
-
feat(step-01): module skeleton, composer deps, routes cb7145
-
Update README.md 8c7433
-
Update .gitignore 728872
-
Create LICENSE b5365f
-
Create module.xml c5b252
-
Create registration.php f5ca9f
-
Create composer.json 67ff9d
-
Update .gitignore 92992c
-
Initial commit 94d452
-
-
head
-
head
-
Added missing isEnabled checks 8b8212
-
Update installation instruction e5d6ec
-
Do not allow withdrawal for cancelled orders c80e03
-
Update link to docs 39cf1e
-
Allow using legal notice template in emails 92d113
-
Email style fix c9ca5a
-
days_since_order_creation in email 80955c
-
MCS fix d09f47
-
Footer link ac1571
-
WIP: email notification 8dcb8f
-
WIP a987f6
-
WIP 68a5ce
-
WIP: Withdraw a190c7
-
WIP: Withdraw order 08dc62
-
Fixed access to undefined property 926d4b
-
WIP: Withdraw 692908
-
Unique modal name 710b58
-
Legal notice at checkout page 66c20c
-
WIP: Checkout ac0258
-
Product page containers 5f831b
-
WIP: Legal notice on product page bd8aab
-
acl.xml c8c38b
-
Update composer deps 8883b2
-
Initial commit 2e11c0
-
-
head
-
1.0.8
-
Version 1.0.8 86864b
-
fix(palette): restore header badges on F5 via _bindBadgeUpdates
paletteSection._bind() now calls _bindBadgeUpdates() so
paletteColorChanged triggers _updateHeaderBadges after reload.
_destroy() cleans up via _destroyBadgeUpdates(). 209d5d -
fix(palette): restore swatch colors from draft on F5
syncPaletteSwatchesFromChanges() in CssPreviewManager restores
visual swatch state and triggers paletteColorChanged after
syncFieldsFromChanges() intentionally skips palette swatches. 8893a7 -
fix(jest): support widget method dispatch in $.widget stub
$el.widgetName('destroy') now calls _destroy() and removes $.data,
enabling proper destroy lifecycle testing. 59c8e3 -
test: replace ArrayObject inheritance with IteratorAggregate
EQP rejects extends ArrayObject even with phpcs:ignore.
Stub only needs foreach support — IteratorAggregate + Countable enough. 06b9ce
-
-
1.0.7
-
Version 1.0.7 657b8b
-
fix(auth): show login toast when session expires during CSS load
'Authentication required. Admin access only.' was silently swallowed —
user had no indication they needed to re-login.
- error-presenter: add 'Authentication required' to friendly message
map and isInvalidToken check so panel error + toast both trigger
- css-state-restorer: add Toastify/configManager imports; show auth
error toast in all three switchTo .catch() blocks
- css-manager: add Toastify import; add .catch() with auth toast to
all _applyStoredState() switchTo() calls that previously had none b716ec -
fix(css-preview-manager): update --preview-color var instead of background-color
Preview dot uses ::after with background-color: var(--preview-color).
Setting background-color on the element itself had no visual effect. b57425 -
feat(editor): raw CSS injection for code fields without property
'code' fields with no CSS property now inject their value verbatim into
the live-preview <style> after CSS variable blocks (instant, no reload).
On publish, CssGenerator appends raw CSS blocks after :root {}. Blocks
persist in localStorage and survive iframe reload triggered by PHP-only
field changes. 19 JS + 17 PHP unit tests added. d43ec3 -
feat(preview): PHP-only field changes reload iframe via cookie override
Fields without a CSS property (toggle, select, text, number) now trigger
a debounced iframe reload instead of being silently ignored. A short-lived
session cookie bte_php_preview carries the overridden value so PHP templates
can read it without a publish step. Spinner overlay shown during reload. 404567 -
chore: fix Marketplace EQP errors
- remove .gitignore from repo
- composer.json: tighten constraints (php ^8.1, magento/framework ^2.4,
swissup/module-core ^1.12, magento/module-graph-ql ^2.4)
- move phpcs:ignore inline on ArrayObjectStub extends line 2194e6 -
fix(config): enable module by default b532fe
-
fix(config): guard BP constant for unit test environments 6237d1
-
fix(cache): replace invalidate() with cleanType() after Publish/Rollback
invalidate() only marks FPC as stale in the admin status table without
flushing storage. cleanType() performs a real flush so frontend pages
are evicted immediately after publish or rollback.
Also adds CssPublishIntegrationTest (5 end-to-end tests) and extracts
shared GraphQL test helpers into AbstractThemeEditorGraphQlTest. a004c0 -
fix(graphql): sync JS selection sets with schema
- apply-preset.js: add isModified, updatedAt to values selection
- get-config-from-publication.js: add media, mediaAlias, fontPalette
to BreezeThemeEditorField selection
- get-config-from-publication.js: add modifiedCount to
BreezeThemeEditorMetadata selection 8a586f
-
-
head
-
WIP: implementing Header and Footer management #7 6bc911
-
-
1.0.2
-
3.0.0
-
Fixed version constraint ac9d2d
-
3.0.0 660bdd
-
Remove unused code a4ac19
-
Fixed not working brand colors 06f973
-
Update theme editor:
- Reuse existing css props when possible
- search => minisearch to match element name
- Remove mobile settings to simplify editor b0e44b -
Theme Editor 3e00dd
-
WIP e1d587
-
WIP: Theme Editor 25fd50
-
Update according to breeze-theme prop names c50294
-
WIP 906261
-
WIP 2ae9e8
-
WIP 53cb13
-
Compatibility with `header__dark=deep` 3a6feb
-
Compatibility with `header__dark=deep` e12f36
-
Compatibility with `header__dark=deep` b67dc5
-
-
2.6.1
-
Update composer.json c891ee
-
-
3.0.0
-
Fixed version constraint f3dcdf
-
3.0.0 10e54f
-
Thee editor: remove unused props 8cb548
-
Theme Editor: added listing settings 028b13
-
Theme Editor: added typography and border radius sections 9b5601
-
Theme Editor: added colors section d1b296
-
Theme Editor: added layout config, color and font palettes a65f91
-
WIP a8fec9
-
WIP 53b69b
-
WIP 40767a
-
WIP 4a949e
-
WIP 38312f
-
Remove brand color because it's added in blank theme now c1fff4
-
WIP b17638
-
WIP 321465
-
WIP 17cf73
-