Beskrivelse
Manage and bulk edit WooCommerce products, orders, coupons, posts, users, subscriptions; any WordPress post type and taxonomies (including custom) and custom fields using an Excel-like sheet editor.
Add products, update prices, edit SKUs, change order statuses, manage coupons, edit blog posts - perform hundreds of store operations from one place, instantly.
WebAlive-specific features
This build is the WebAlive fork of Smart Manager, with a large set of stock-management, UX and integration features layered on top of the upstream grid. All additions are scoped to #woo-wa-stock-manager-premium-app so nothing bleeds outside the plugin, and every DOM injection uses the safe appendChild-only overlay pattern so React re-renders never crash the grid.
Stock Manager grid — WebAlive columns & controls
- Placering column (Row / Rack / Shelf) — per-product warehouse location shown as a compact badge between Product name and Price. Click a badge to open the inline edit modal (Row / Rack / Shelf + optional Stock qty). Values are stored in three plain post meta keys (
_wwsmp_loc_row,_wwsmp_loc_rack,_wwsmp_loc_shelf) and are also editable from the WooCommerce product edit screen's Beholdning tab and from a dedicated sub-page (?page=stock-manager-locations) with search + pagination + AJAX save. - Stock qty in the Placering modal — entering a quantity here auto-enables Manage stock, persists the quantity, updates the stock status (
instock/outofstock) and paints an overlay on the row's „Stockstatus & antal“ cells so the new value is visible immediately, even before React re-renders. - Auto-enable "Allow backorders, notify customer" — when Manage stock is turned on (via the grid checkbox or the Placering modal), the product's Backorders setting is automatically flipped from "Do not allow" to "Allow, but notify customer". Only fires on the transition, so an explicit backorders=no choice is never overridden retroactively.
- Statusmærke badge column (WWSS integration) — when Woo Webalive Stock Status Premium is active, a badge column shows at-a-glance state: red UDGÅET for discontinued products, blue Tilbage DD-MM-YYYY when a restock date is set, purple Egen tekst when per-product WWSS text-overrides exist, or a subtle — for defaults. Clicking the badge opens a full editor modal for all WWSS fields (7 text overrides, Discontinued flag, hide-stock-status, expected restock date, alternative products picker) — no navigation to the product edit page required. Auto-detected: column only appears when
WWSS_Pluginclass exists. - Compact stock-status picker — the upstream Stock Status
<select>has options with very long labels (fx Product has been discontinued by producer, Remote stock — 4-5 days) that ballooned the column width. WWSMP layers a small overlay showing only the current label + a chevron; clicking opens a compact modal picker that writes the choice back to the React-managed<select>via the native prototype value setter + bubblingchangeevent (React-compatible pattern). - + Add product button — inline in the „Lager Administration“ heading row (pastel-purple ghost button style). Opens a modal with SKU / Title / Price / Manage stock / Stock qty / Row / Rack / Shelf and creates the product as a draft via a dedicated AJAX endpoint (
wwsmp_sm_create_product). Location fields are written to the same meta keys as the Placering column so the new row shows its location immediately. - Ghost-draft filter — drafts left over from failed WooCommerce imports, discarded new-product wizards or plugins that spawn hidden drafts are hidden from the grid. Only drafts that WWSMP itself created via + Add product are shown (marked via
_wwsmp_sm_draft = yes). Implemented as aposts_whereclause onwoocommerce_rest_product_object_query. - Orange draft IDs — draft products that WWSMP created (and are therefore still visible in the grid) render their ID cell in bold orange (
#c2410c) so it is obvious the row is not yet live on the storefront. - Partial SKU-match — typing
531in the SKU filter now finds510-0531,531-2000,2015-0531-Aand so on. Implemented onrest_request_before_callbacks: WWSMP intercepts the SKU parameter, runs a directLIKElookup againstpostmeta(unioned with parent IDs so variation matches surface the parent), and rewrites the parameter to a comma-separated list of exact SKUs that matched. WC's own strictIN-filter then runs unchanged, bulletproof against downstream sanitisation. - Wider SKU column — inputs in
.stock-manager-field-skuwidened tomin-width: 25chso SKUs like510-50201081andRD201-31032are visible without truncation. - Compact number inputs & row spacing — Price / Sale price / Stock qty inputs constrained to 4.5 rem, cell padding tightened to 4 px, Placering + Statusmærke columns squeezed to 80/90 px minimum. Keeps the widened SKU column from pushing the table off-screen.
imagespayload hardening — the upstream WSM React bundle readsproduct.images.lengthwithout a nullish guard, so a single product without animagesarray crashes the entire Redux-driven grid. WWSMP adds awoocommerce_rest_prepare_product_objectfilter that guarantees$response->data['images']is always an array.
Silent auto-save + toast feedback
- Auto-save every edit — the WSM React "Save all changes" fixed-bottom bar is hidden by default (walked up from the Save button to the first
position:fixedancestor, then marked with a stable class — works despite webpack CSS Modules' hashed class names). A short debounce (~1.5 s) auto-clicks the invisible Save button after any edit. - Toast notifications — a small slide-in toast in the bottom-right corner confirms every save cycle: green Gemt on success, red Kunne ikke gemme with response detail on failure. Auto-dismisses after 3 s (6 s for errors). Implemented via a
window.fetchinterceptor scoped to actual save actions only (wwsmp_sm_save_location,wwsmp_sm_wwss_save,wwsmp_sm_create_product,POST /wp-json/wc/v3/products/batch,POST /wp-json/wc/v3/products/{id}/variations/batch) — batch-read endpoints, WP heartbeat and unrelated admin-ajax traffic are silently ignored. - Live status sync — after every successful save the
wwsmp-sm-savedcustom event fires, the WWSS labels cache is invalidated in place, every visible row is re-batched, and both the Statusmærke badge and the upstream Stock Status cell are repainted with fresh data.
Warehouse Locations sub-page (?page=stock-manager-locations)
- PHP-rendered table with search + pagination.
- Inline-edit Row / Rack / Shelf per product row, AJAX save on blur (no page reload).
- Helper
WWSMP_SM_Locations::get_for_product( $product_id )returns the combined"A / 01 / 3"string — useful for packing slips, PoS displays and custom order views.
Access, branding & UX polish
- Shop Manager role fixed — the
webshop-managerrole now sees the full set of Smart Manager dashboards by default (emptywwsmp_access_privilege_shop_manageroption no longer resolves to "one dashboard whose key is the empty string"). Admins can still lock down individual roles via Settings → Access Privileges. - Auto-collapsed admin sidebar — Stock Manager sub-pages (
?page=stock-manager,?page=stock-manager-import-export,?page=stock-manager-log) automatically collapse the WordPress admin sidebar to icons on load (matches the main WWSMP grid). Respects the existingwp_force_collapse_admin_menusetting; users can still un-collapse via WP's own toggle. - Modernised look — 12 px rounded cards with subtle shadow, WWSMP-purple primary buttons (
#5850ec), striped tables with hover-highlight, WordPress-native underline tabs on.stock-manager-navigation, system-ui typography, warmer neutral palette (#f9fafbbackground,#e5e7ebborders). - Compact filter layout — Category / Type / Stock status dropdowns share a row with SKU / Search and are pushed to the right edge via
:has()— no React bundle patch needed. - "Manage with Smart Manager" list-table button — the button injected next to WP list-tables' Add new title-action uses the WebAlive blueduck logo (18 px), reads simply "Smart Manager", and matches the WWSMP purple / border-radius: 6 px look.
- Brand cleanup — upstream StoreApps testimonials and third-party brand assets (Acrom, Bryan Batcher, Jeff Smith,
storeapps-logo.svg, etc.) removed from the pricing page and image folders. - Renamed to "Webalive Smart Manager Premium" — plugin header, admin menu title, header helper, all
__()/_x()strings and readme content updated. Folder slug, text-domain, PHP constants, hook / option / transient prefixes and the update-server URI are unchanged so existing installs are not broken. - Danish translations wired up correctly —
wp_set_script_translationsnow uses the'woo-wa-stock-manager-premium'domain and the rootlanguages/folder, and apre_load_script_translationsfilter merges every per-source Poedit JSON (Product.js,ProductFilter.js, …) into the single JSON WordPress serves for the compiled React bundle. Poedit's normal Save workflow "just works" — nowp i18n make-jsonstep required.
Cron / scheduler stability
- Action Scheduler PHP 8+ fix — string-keyed action args are normalised to positional args before hook dispatch, preventing fatal errors like
Unknown named parameter $tasks_meta_idduring cron queue execution.
Ændringslog
1.5.26 (2026-07-16)
- Fix: Placering modal's stock-qty save no longer paints a WWSMP-owned green overlay on top of the WSM „Stockstatus & antal“ cells. That approach from 1.5.24 was wrong — it made the row look different from every other row in the grid and hid the real React-managed input beneath a custom badge. Removed
paintStockCells, the.wwsmp-qty-overlay/.wwsmp-status-overlay--managedCSS, and the extrastock_status/stock_status_labelfields on the save-response payload. Now the modal save simply writes to WSM's existing.stock-manager-field-stock-quantity inputand.stock-manager-field-manage-stock input[type="checkbox"]via the same native-prototype_valueTrackertrick already used for the stock-status<select>picker (reactSetInputValue,reactSetCheckboxValue) — React sees a real change event, its Redux store updates, and the row is re-rendered by the WSM app itself with its own styling. Nothing custom, nothing overwritten. - Fix: Placering modal now pre-populates the Stock qty field with the actual persisted WooCommerce value (from
WC_Product::get_stock_quantity()), not by inspecting the row's DOM for a number input — the previous approach found the FIRST number input (regular-price) instead of the qty input, and returned empty on non-managed rows where the qty input doesn't render at all. Extendedwwsmp_sm_get_locations_batchto return{ combined, stock_qty, manage_stock }per product ID (was"combined"string only); the JS cache mirrors this shape, so opening the modal shows the true DB qty and correct manage_stock state without an extra round-trip.
1.5.25 (2026-07-16)
- Docs: Expanded the Description section with a full WebAlive-feature index (Placering, Statusmærke, compact stock-status picker, + Add product, ghost-draft filter, orange draft IDs, partial SKU-match, wider SKU column, compact number inputs,
imagespayload hardening, silent auto-save + toast, WWSS live status sync, Warehouse Locations sub-page, Shop Manager role fix, auto-collapsed sidebar, modernised look, brand cleanup, Danish translations, Action Scheduler PHP 8+ fix). Added a recommended installation path via WA Quick Installer at the top of the Installation section, with the manual/wp-content/plugins/upload kept as a fallback. Readme-only release — no functional code changes over 1.5.24.
1.5.24 (2026-07-16)
- Fix: Setting a stock quantity in the Placering modal did not visibly update the „Stockstatus & antal“ column afterwards. The AJAX save persisted the value correctly, but the JS then poked
tr.querySelector('input[type="number"]')— which matches the FIRST number input in the row (the regular-price cell), not.stock-manager-field-stock-quantity. Even with the correct selector the input often didn't exist yet becausemanage_stockhad just been flipped on and React had not re-rendered the row into number-input mode. Fixed on two ends: (1)wwsmp_sm_save_locationnow always returnsstock_status,stock_status_labelandmanage_stockin the response so the client has authoritative post-save state; (2)wwsmp-sm-locations-grid.jsnow paints WWSMP-owned overlays on.stock-manager-field-stock-quantity(showing the qty as text) and.stock-manager-field-stock-status(showing the status label) using the sameappendChild-only overlay pattern used for the stock-status picker, so the persisted values become visible immediately regardless of React's internal state. Overlays are kept in sync by an extension topaintStatusOverlaysthat reads back from the row's own inputs when React does eventually re-render.
1.5.23 (2026-07-16)
- Fix: Infinite AJAX loop.
wwsmp-sm-autosave.js's fetch interceptor treated EVERY POST toadmin-ajax.phpas a save („relevant=true“), which included the internalwwsmp_sm_wwss_batch,wwsmp_sm_get_locations_batchandwwsmp_sm_get_statuses_batchfetches. Those triggered thewwsmp-sm-savedevent, which in turn calledrefetchAllVisible(), which fired another batch fetch, ad infinitum — hundreds of "Gemt" toasts stacking up on every page load. Narrowed the interceptor to only recognise actual save actions:wwsmp_sm_save_location,wwsmp_sm_wwss_save,wwsmp_sm_create_product, plus WC REST product/variation batch endpoints. Batch-read actions and unrelated admin-ajax traffic (klawoo subscribe, heartbeat, etc.) are silently ignored.
1.5.22 (2026-07-16)
- Change: The upstream Stock Status
<select>(visible on non-managed-stock products) contains options with very long labels (e.g.Product has been discontinued by producer,Remote stock - 4-5 days) that ballooned the column width and pushed the table off-screen. Constrained the cell to 140px via CSS and layered a WWSMP-owned overlay (<div>) on top that displays only the currently-selected label. Clicking the overlay opens a compact modal listing all available statuses; picking one writes the new value back to the underlying React-managed<select>via the nativeHTMLSelectElement.prototypevalue setter + a bubblingchangeevent, which is the standard React-compatible pattern for driving controlled inputs from external JS. No<td>content is overwritten — the overlay isappendChilded once, and React continues managing its<select>child untouched.
1.5.21 (2026-07-16)
- Fix: Ticking "Mark as discontinued" in the Stock Status modal appeared to wipe every text-override on the product. Root cause: the JS submitted every label field (including empty ones because most rows have no per-product custom text), and the PHP save handler treated an empty submitted value as
delete_post_meta(...). The Discontinued flag saved correctly, but the seven label meta keys were nuked in the same request. Rewrote the save flow to only send labels the user actually changed (viadata-originalattributes on each<input>), and dropped thedelete_post_metacall on the PHP side. Fields still get cleared by explicitly wiping them (they will now be recognised as "changed to empty" and sent as such). - New: When the WSM React grid's "Manage stock" checkbox is ticked (or Manage stock is enabled via the Placering modal's Stock qty input), the product's Backorders setting is automatically flipped from "Do not allow" to "Allow, but notify customer". Only fires on the transition, so a user's explicit backorders=no choice is never overridden retroactively. Hooked on
woocommerce_before_product_object_save.
1.5.20 (2026-07-16)
- Change: Compacted the Stock Manager grid so the wider SKU column from 1.5.17 does not push the table off-screen. Reduced number-input max-width for Price / Sale price / Stock qty (
.numberControl input) from 6rem to 4.5rem, tightened cell horizontal padding to 4px, and squeezed the Placering + Statusmærke badge columns (padding-inline: 6px, min-width 80/90px). All rules scoped to#woo-wa-stock-manager-premium-appso nothing bleeds outside the WSM grid.
1.5.19 (2026-07-16)
- New: Restock date is now surfaced in the WWSMP-owned "Statusmærke" badge column (rolled back from the React-managed "Stock status" cell in 1.5.18 for safety). When a product has
_wwss_restock_dateset and is not marked as discontinued, the blue "Restock / alt." badge is replaced with a formatted date badge („Tilbage 17-07-2026“ using the site'sdate_formatwhen available, otherwiseDD-MM-YYYY). Falls back to the plain "Restock / alt." label if only alternative products are set (no date). Zero DOM mutation of React-owned cells — date lives inside our own<td>that WWSMP fully owns.
1.5.18 (2026-07-16)
- Fix: Grid rendered as empty after clicking the Manage-stock checkbox on any row, with
DOMException: Node.removeChild: The node to be removed is not a child of this nodein the console. Root cause was 1.5.6 / 1.5.7'srewriteStockStatusCell()which overwrote the WSM React app's<td>content directly withtextContent = .... React's virtual DOM still expected its<Control>component in that cell; when the row re-rendered after the checkbox click, React tried to unmount the Control it thought was there and threw when the DOM node no longer existed. Rolled back the cell-rewrite entirely: the upstreamStock statuscolumn now shows whatever the WSM React bundle wants to show (typically WWSS's own re-labelled text viawoocommerce_get_availability), and the WWSS Restock date / Discontinued state is surfaced exclusively through the WWSMP-owned "Statusmærke" badge column + modal.
1.5.17 (2026-07-16)
- Change: Widened the SKU (varenummer) column input in the Stock Manager grid by ~5 characters (from the browser default ~20ch to
min-width: 25ch). SKUs like510-50201081andRD201-31032are now fully visible without horizontal truncation. Implemented as CSS injected bywwsmp-sm-locations-grid.jstargeting the existing.stock-manager-field-sku inputclass WSM already sets, so no React bundle rebuild is needed.
1.5.16 (2026-07-16)
- Fix: The Stock Manager grid table showed as empty (
TypeError: can't access property "length", e.images is undefinedatProducts.js:196) on sites where a WooCommerce product had noimagesarray on its REST payload. The upstream WSM React bundle readsproduct.images.lengthinProducts.jsline 20 without any nullish guard, so a single malformed product crashes the entire Redux-driven grid render. Added a defensivewoocommerce_rest_prepare_product_objectfilter that ensures$response->data['images']is always an array before the payload leaves the server — fixes the crash for all products, past and future, without needing to rebuild the React bundle.
1.5.15 (2026-07-16)
- New: Stock quantity input added to the Placering modal. When the product's Manage stock flag is not already enabled, saving via this modal automatically enables it (
set_manage_stock( true )) so the entered quantity actually takes effect. Modal now pre-populates the field with the current WC stock quantity, and any change is persisted alongside Row / Rack / Shelf in the same AJAX round-trip. - Change: Removed the auto-save-when-all-three-location-fields-are-filled debounce. The modal now only saves on explicit action — Enter key (from any input) OR click on Gem. Rationale: users typing a partial location + Tab-ing between fields sometimes triggered a premature save.
1.5.14 (2026-07-16)
- New: The Stock Manager grid now filters out "ghost" draft products — drafts left over from failed WooCommerce imports, discarded new-product wizards, or plugins that spawn hidden drafts. Only drafts that WWSMP itself created via the "+ Add product" modal are shown; every other draft is invisible in the grid until it is published. Implemented via a marker post meta
_wwsmp_sm_draft = yesset byWWSMP_SM_Locations::ajax_create()on creation, plus aposts_whereclause hooked ontowoocommerce_rest_product_object_querythat requires either non-draft status or presence of the marker. - New: Draft products that DO appear (i.e. WWSMP-created drafts still awaiting publication) now render their ID cell in bold orange (
#c2410c), making it obvious at a glance that the row is not yet live on the storefront. Batch-fetched via a new lightweight endpointwwsmp_sm_get_statuses_batchand applied bywwsmp-sm-locations-grid.json every column paint pass.
1.5.13 (2026-07-16)
- Fix: The "Mark as discontinued" checkbox in the Stock Status modal was persisted server-side but appeared to "lose" its state on reopen. Root cause was 1.5.12's
refetchAllVisible()reassigningcache = Object.create( null )whilesaveModal()'s own success handler was still executing — both hold a lexical reference to the samecachevariable, so the modal'scache[ pid ] = json.datasometimes landed on the freshly-emptied object before the batch refetch populated it, and the next modal open readdata.discontinued === undefined(falsy → unchecked). Rewrote the invalidation to CLEAR entries in place (for ( var k in cache ) { delete cache[ k ]; }) so all writers see the same shared object identity throughout the save cycle. - Debug: Added
console.debug( 'WWSMP save payload: {...}' )andconsole.debug( 'WWSMP save response: {...}' )insidesaveModal()so it is trivial to confirm what value is being sent + received for every field.
1.5.12 (2026-07-16)
- Fix: The "Stock status" grid column stayed on its old value (e.g.
Ikke på lager) after the user changed the stock quantity and the auto-save persisted it. The WWSS labels grid cached each product'seffective_labeland re-used it forever; there was no invalidation path when a save happened. Added a decoupledwwsmp-sm-savedcustom event:wwsmp-sm-autosave.jsdispatches it after every successful save-fetch, andwwsmp-sm-wwss-labels-grid.jslistens for it, clears its per-product cache, re-batches every visible row, and repaints both the Statusmærke badge and the upstream "Stock status" cell. 500 ms delay before the refetch so WooCommerce has time to persist meta changes before we ask for the resolved label.
1.5.11 (2026-07-16)
- Fix: Save toast rendered to the DOM in 1.5.10 but was never visible on the user's site. The
opacity: 0 → opacity: 1fade-in relied on asetTimeout( ..., 10 )adding a.visibleclass, and a race with browser paint frames occasionally landed the toast in the removed state before the.visibleclass was applied. Replaced the two-step fade-in with immediate visibility (opacity 1 by default) — the toast now appears the frame it is appended. Also added aconsole.debug( 'WWSMP toast: ...' )log at every render so it is trivial to verify the DOM insertion in DevTools.
1.5.10 (2026-07-16)
- Change: Removed the immediate "Saving…" toast on the debounced auto-save button click. All feedback now comes strictly from the
window.fetchinterceptor — green "Saved" on 2xx, red "Save failed" on non-2xx or network error. Rationale: the click-based fallback fired even when the underlying WC REST batch call was already in flight from a previous edit, causing double-toasts and false-positive feedback. - Debug: The fetch interceptor now emits
console.debugon every intercepted call (WWSMP fetch: <method> <url> → relevant=<bool>) so it is trivial to diagnose why a save is not surfacing a toast. Filter the DevTools Console byWWSMPto see the full trace.
1.5.9 (2026-07-16)
- Fix: 1.5.8's "hide the Save all changes bar" CSS never matched anything because the WSM React app uses webpack CSS Modules (
SaveChanges.scss) that emit hashed runtime class names (SaveChanges_wrapper__<hash>). Replaced the static selector list with a JS walk:wwsmp-sm-autosave.jsnow locates the Save button (which we already find for auto-save), walks up until it hits an element withposition: fixedin its computed style, and adds a stable marker classwwsmp-sm-save-bar-hiddenon that wrapper. A MutationObserver re-runs the walk on every React re-render so the bar cannot come back. The invisible Save button remains in the DOM so the debounced auto-save can still click it. - New: Immediate "Saving…" toast on every debounced auto-save so the user sees feedback even before the WooCommerce REST batch call resolves. Final "Saved" / "Save failed" toast still fires from the
window.fetchinterceptor when the response returns. Added aconsole.info( 'WWSMP autosave: fetch interceptor active' )log so it is trivial to verify the interceptor is installed via DevTools.
1.5.8 (2026-07-16)
- Fix:
stock_status was called incorrectly_doing_it_wrongnotice spammed the debug log every time the WWSS labels batch endpoint fired. Root cause wasWC_Product::get_availability()running thewoocommerce_get_availabilityfilter chain, which on this site includes a third-party function (woocommerce_get_custom_availability) that still uses direct property access$product->stock_status. RewroteWWSMP_SM_WWSS_Labels::get_for_product()to bypassget_availability()entirely and callWoo_Stock_Base::woo_rename_stock_status()directly — same result (per-product override → category meta → global setting → default) but without invoking unrelated third-party filters. - Fix:
include_once ... class-wwsmp-manager-pro-base.phpwarning on every admin page load. The upstream WWSMP layout had apro/common-pro/folder that our fork never shipped, but theWWSMP_Controllerbootstrap tried to include one specific file inside it during the scheduled-tasks setup. Wrapped the include infile_exists(), matching the existingfile_exists()guards on the sibling includes in the same block. - Change: The upstream React "Save all changes" fixed-bottom bar is now hidden by default (
display:none !important). Edits are auto-saved silently by the existingwwsmp-sm-autosave.jsdebouncer (unchanged behaviour, just no visible bar). Instead, a small slide-in toast appears in the bottom-right corner after each save cycle: green with a checkmark on success, red with an X and the response message on failure. The toast auto-dismisses after 3 s; failures stay visible for 6 s. Implemented via awindow.fetchinterceptor scoped to the WSM REST endpoints (/wp-json/wc/v3/products*andwp-admin/admin-ajax.php?action=wwsmp*) so it does not touch unrelated network activity.
1.5.8 (2026-07-15)
- Fix: Action Scheduler compatibility on PHP 8+ — normalized string-keyed action args to positional args before hook dispatch to prevent fatal errors like
Unknown named parameter $tasks_meta_idduring cron queue execution.
1.5.7 (2026-07-14)
- Fix: The Stock Status grid column now appends the WWSS restock date when set, e.g.
Ikke på lager (tilbage 17. juli 2026). Server-side format uses WordPress'sdate_i18n()with the site'sdate_formatoption, so the date honours the current locale automatically. - Fix: Modal layout — the two flag rows Marker som udgået and Skjul lagerstatus were moved to the BOTTOM of the modal (just above the Save/Cancel bar). The modal now flows top-to-bottom in order of increasing rarity: restock date + alternatives (most-edited) → text overrides → flags (edge cases).
- Fix: WSM React grid headers ("SKU", "Product name", "Stock status", filter labels, etc.) stayed in English despite Poedit having translated them. Root cause: Poedit generates one script-translations JSON per source file (
Product.js,ProductFilter.js, …), but WordPress'swp_set_script_translationsonly serves the ONE JSON whose filename ismd5(enqueued_script_src).json— which for the compiled React bundle only contained 12 internal property strings, not the UI text. Registered apre_load_script_translationsfilter that, on the WSM React handle, discovers all per-source JSONs inlanguages/and merges theirlocale_data.messagesinto a single response. Poedit's normal Save workflow now "just works" — nowp i18n make-jsonstep required.
1.5.6 (2026-07-14)
- Change: Text-overrides section in the Stock Status modal is now laid out in two columns instead of a single stacked list, roughly halving the modal's vertical footprint. The two flag rows (Discontinued / Hide status) and the restock date + alternatives row are unaffected.
- New: "Udfyld fra standard" button in the text-overrides section. Fills every EMPTY override input with the current WWSS global setting (
wc_slr_<status>). Non-empty inputs are left alone so an existing per-product customisation is never overwritten by accident. Global values are shown as greyed-out placeholders even before the button is pressed, so it is always clear what each empty field will fall back to on the frontend. - New: The grid's built-in "Stock status" column (rendered by the upstream WSM React bundle) is now rewritten to show the effective WWSS availability label — i.e. the same text a shopper would see on the product page after WWSS resolves per-product override → category meta → global setting → hardcoded default. Implemented via a batch fetch that calls
WC_Product::get_availability()server-side (fires WWSS's ownwoocommerce_get_availabilityfilter chain), then overwrites the cell content in the same MutationObserver pass that paints the Status label badge. Falls back silently to whatever WSM originally rendered if WWSS is not active orget_availability()returns empty (e.g. variable-parent with mixed variation states).
1.5.5 (2026-07-13)
- New: Full WWSS Stock Status modal editor in the Stock Manager grid — clicking the "Status label" badge now opens an in-grid modal that reads and writes every relevant WWSS post meta directly (no edit-page navigation, no data duplication). Editable fields:
- Marker som udgået (checkbox,
_wwss_discontinued) — forces Discontinued display, blocks add-to-cart, reports schema.org/Discontinued. - Skjul lagerstatus (checkbox,
hide_stock_status) — suppresses the stock status message entirely. - Forventet genopfyldnings-dato (date,
_wwss_restock_date) — drives the restock notice module (auto-hides after date passes). - Alternativer (WC product multi-picker,
_wwss_alternative_products) — uses the samewc-product-searchSelect2 the WWSS product page does; suggested replacements always show alongside the restock notice / discontinued badge on frontend. - 7 tekst-overrides (
in_stock,only_s_left_in_stock,can_be_backordered,s_in_stock,available_on_backorder,out_of_stock,discontinued) — per-product custom labels, blank = fall through to the WWSS global setting.
- Marker som udgået (checkbox,
- New:
wwsmp_sm_wwss_saveAJAX endpoint (edit_productscap, dedicated nonce) validates all inputs (date must matchYYYY-MM-DD, alternatives must be existingproductpost IDs) and writes them viaupdate_post_meta/delete_post_metaso an empty value cleans up the DB row rather than storing''. - Change: The badge column's batch endpoint (
wwsmp_sm_wwss_batch) now returns the full state so the modal can pre-populate without a second round-trip, and so the badge can distinguish "has custom text" from "has restock date / alternatives".
1.5.4 (2026-07-11)
- Change: Replaced 1.5.3's custom in-grid modal for editing WWSS stock-status labels with a plain hyperlink on the badge that opens the product's WooCommerce edit screen scoped to the existing WWSS "Custom Stock Status" tab (
post.php?post=<pid>&action=edit#custom_stock_status_data). Rationale: WWSS already owns the fully-fledged editing UI on the product page (all 7 label fields, colors, per-variation overrides, Discontinued checkbox, hide-status option), so a second parallel modal in the grid duplicated logic and diverged in features. The badge column still gives the at-a-glance status (red UDGÅET / purple Egen tekst / gray dash), fetched via the existingwwsmp_sm_wwss_batchendpoint, and clicking it now takes you straight to the canonical editor. - Cleanup: Removed the
wwsmp_sm_wwss_saveAJAX endpoint, the client-side save/cancel/keyboard-modal logic, and 8 modal-only localized strings that were never rendered again — shrinks the JS bundle from ~14 KB to ~5 KB and removes 8 English fallback strings that were dependent on translation timing.
1.5.3 (2026-07-11)
- New: WWSS (Woo Webalive Stock Status Premium) custom stock-status labels are now surfaced and editable directly from the Stock Manager grid (
?page=stock-manager). A new "Status label" column is injected next to Placering; each row shows an at-a-glance badge — red UDGÅET if the product is flagged Discontinued (via WWSS 1.0.6's_wwss_discontinuedmeta), purple Egen tekst if any of the 6 built-in per-product WWSS text overrides is set, or a subtle — if the product uses the WWSS global defaults. Clicking the badge opens a modal with all 7 text override fields (in_stock,only_s_left_in_stock,can_be_backordered,s_in_stock,available_on_backorder,out_of_stock,discontinued) plus a Mark as discontinued checkbox. Saves via a new AJAX endpoint (wwsmp_sm_wwss_save,edit_productscapability, dedicated nonce) that writes directly to WWSS's existing post meta keys — no data duplication, no sync layer, so WWSS and WWSMP stay in perfect agreement. - Auto-detection: the column + modal only enqueue when WWSS is active (
class_exists( 'WWSS_Plugin' )at admin_enqueue_scripts time). Sites without WWSS see no change.
1.5.2 (2026-07-11)
- Fix: "+ Add product" button in 1.5.1 landed above the React grid instead of next to the "Lager Administration" heading. Root cause: the assistant had assumed the
<h2>lived INSIDE#woo-wa-stock-manager-premium-app, soensureAddButton()searched the app container forh1, h2, found none, and fell back to pinning the button at the top of the React app. In reality the heading is rendered server-side bystock-manager/admin/views/admin.phpas a sibling of the app container (<div class="wrap"> → <h2>Lager Administration</h2> → <div id="woo-wa-stock-manager-premium-app">). Moved the button injection out of JS entirely: the PHP template now wraps the heading in a flex row (.wwsmp-sm-page-heading) with the button rendered inline as a sibling of the<h2>. The button is server-rendered, so it survives React re-renders without a MutationObserver. Same pastel ghost-button styling from 1.5.1 preserved.
1.5.1 (2026-07-09)
- UI: "+ Add product" button restyled to match the pastel-purple ghost-button look used on
?page=wwsmp("+ Ny Min Max Rule") — light lavender background (#eeecff), dark purple text (#4b44d9), 6 px radius, subtle 1 px border, no drop-shadow. Repositioned to sit on the same visual line as the<h2>"Lager Administration" heading (auto-detects the firsth1/h2inside#woo-wa-stock-manager-premium-app, wraps its parent in a positioned container, and pins the button top-right of that container). Previously the button was pinned to the app container's top-right corner and landed on top of the filter row instead of the heading row.
1.5.0 (2026-07-09)
- Fix: "+ Add product" button from 1.4.9 never appeared because the grid JS bundle was truncated mid-
boot()(missingMutationObserver, missing IIFE close), and the AJAX action name insubmitAddModalwas hard-coded to a non-existent handler (wwsmp_sm_add_product) instead of the registeredcfg.createAction(wwsmp_sm_create_product). Rewrote the tail ofwwsmp-sm-locations-grid.js:boot()now waits for the app root, injects the button, callsschedule(), and starts aMutationObserverthat re-injects both the Placering column and the Add-product button on every React re-render. Also switched the button from aposition:fixedfloating action button (which floated over the WordPress admin bar) toposition:absolute; top:12px; right:20px;inside the app container, so it sits in the top-right corner of the Stock Manager card as requested. Verified withnode --check.
1.4.9 (2026-07-09)
- New: “+ Add product” floating action button injected top-right on the Stock Manager grid (
?page=stock-manager). Clicking opens a modal with the essential fields — SKU, Title, Price, Manage stock, Stock qty, Row / Rack / Shelf — and creates the product as a draft via a newwwsmp_sm_create_productAJAX endpoint (reuses the existingwwsmp_sm_locationsnonce andedit_productscapability). Location fields are written to the same_wwsmp_loc_row / _wwsmp_loc_rack / _wwsmp_loc_shelfmeta keys as the Placering column so the new row shows the location immediately after save. WooCommerce’s RESTproductsendpoint returns draft products withcontext=edit, so the newly created draft appears in the grid after the automatic page-reload following save.
1.4.8 (2026-07-09)
- UX: Placering inline modal auto-saves when all three fields (Row / Rack / Shelf) have non-empty trimmed content. A 500 ms debounce absorbs mid-typing pauses, and the existing Save button + Enter-to-save + Cancel/Esc all remain functional. Added a double-save guard (
saveBtn.disabled) so the debounce firing near-simultaneously with a manual click cannot dispatch two POSTs.
1.4.7 (2026-07-09)
- Fix: Shop Manager (webshop-manager) role saw an empty Stock Manager dashboard instead of the full set of Smart Manager panels. Root cause:
WWSMP_Pro_Access_Privilege::get_current_user_access_privilege_settings()runsexplode( ",", get_option( 'wwsmp_access_privilege_shop_manager', '' ) )when the option is not configured —explodeof an empty string returnsarray('')(a truthy 1-element array), which the downstream unset-loop then treats as "the user is only allowed one dashboard whose key is the empty string", removing every real dashboard. Rewrote the resolver so an empty option is coerced to an empty array, i.e. "no restriction configured → keep every dashboard". Admins can still lock down individual roles via the existing Settings → Access Privileges UI; only the default (unconfigured) behavior changed. Menu registration inWWSMP::add_menu()was already usingmanage_woocommerce(which shop_manager has) so no menu change was needed.
1.4.6 (2026-07-09)
- Fix: Partial SKU-match — rewritten from scratch on a different hook that cannot be undone by WooCommerce's REST controller. Uses
rest_request_before_callbackson the/wc/v3/productsendpoint: the SKU parameter is intercepted BEFORE WC builds its query, we run our own LIKE-lookup againstpostmeta, and rewrite the parameter to a comma-separated list of the exact SKUs that matched (or a sentinel value if nothing matched). WC then runs its normalIN-based SKU filter with a pre-computed match set, so we don't fight the WC sanitisation pipeline at all.
1.4.5 (2026-07-09)
- Fix: 1.4.3 / 1.4.4's partial SKU-match still didn't work in practice. Root cause:
WC_REST_Products_Controller::prepare_objects_query()adds SKU asmeta_querywithcompare = 'IN'(an array of SKUs, exploded on comma), not a single-value exact match. Simply flipping the compare toLIKEbreaks becauseLIKEdoesn't accept an array value, and the strict WC sanitizer runs after our filter and can re-normalise. Switched to a pre-computedpost__inapproach: our filter runs a directSELECT post_id FROM postmeta WHERE meta_key='_sku' AND meta_value LIKE '%xxx%', unions with parent-IDs so variation matches surface the parent product too, strips WC's own_skumeta_query, and setspost__inon the query. Bulletproof against any downstream sanitisation.
1.4.4 (2026-07-09)
- Fix: 1.4.3's partial SKU-match filter never fired in practice because the
wwsmp_sm_filtergate parameter is not reliably present as the string"true"in$request->get_query_params()— the React app passes a JavaScript boolean, WooCommerce's REST controller strips it during sanitisation, and the strict'true' !== ...check always short-circuited. Removed the gate; partial SKU-match now runs on any WooCommerce REST product query that includes askuparameter. This makes?page=stock-managerfinally find510-0531when typing531,0531,510, or510-05. External integrations that rely on exact-SKU lookup can opt-out via thewwsmp_sm_sku_likefilter (return false to disable).
1.4.3 (2026-07-09)
- Change: The SKU field in the Stock Manager grid filter (
#woocommerce-product-manager-filter-sku) now performs a partial (substring) match instead of exact-match only. Typing15will now find15-1600,15-2000,2015-1600, and so on. Implemented via awoocommerce_rest_product_object_queryfilter at priority 100 that rewrites the_skumeta_query clause added byWC_REST_Products_Controllerfromcompare = '='tocompare = 'LIKE'. Only affects REST requests that come from the Stock Manager grid (identified by thewwsmp_sm_filter=trueparameter that the React app already sends).
1.4.2 (2026-07-08)
- New: Placering badge in the Stock Manager grid now opens an inline edit modal instead of navigating to the product-edit page. Clicking any location cell shows a lightweight modal with Row / Rack / Shelf inputs (same three fields as the Locations sub-page). Saving uses the existing
wwsmp_sm_save_locationAJAX endpoint and updates the badge in place without a page reload.
1.4.1 (2026-07-08)
- New: Warehouse Location fields (Row / Rack / Shelf) are now surfaced in two more places:
- WooCommerce product edit → Varedata → Beholdning tab. Three inline inputs shown right after the existing stock/inventory fields, saved via the standard
woocommerce_process_product_metahook. This is the natural place to enter location while editing a product's stock data, so the previously-added side metabox has been removed to avoid duplication. - Stock Manager grid (
?page=stock-manager). A read-only "Placering" badge column is injected between "Product name" and "Price" via a DOM helper (MutationObserver-based, so it survives grid re-renders on filter/pagination). Product IDs are extracted from the existing#XXXcell, then a single batched AJAX call fetches all locations for the visible rows and paints the values. Editing is done via the Beholdning tab or the dedicated Locations sub-page — keeps the grid injection minimal and robust to upstream React changes. - New batched AJAX endpoint
wwsmp_sm_get_locations_batchthat returns location strings for an array of product IDs in one round-trip.
- WooCommerce product edit → Varedata → Beholdning tab. Three inline inputs shown right after the existing stock/inventory fields, saved via the standard
1.4.0 (2026-07-07)
- New: Warehouse Locations — track physical storage location (row / rack / shelf) per WooCommerce product. Adds:
- A new sub-page under the Stock Manager menu: Lokationer (
?page=stock-manager-locations). PHP-rendered table with search + pagination, inline-edit Row / Rack / Shelf per product row, AJAX save on blur (no page reload). - A Warehouse Location panel on the single WooCommerce product edit screen (
edit.php?post=X) with three inputs and combined display "A / 01 / 3". - Three new product meta keys:
_wwsmp_loc_row,_wwsmp_loc_rack,_wwsmp_loc_shelf(string values — free text for now, can be constrained to enumerated values in a future release). - A helper
WWSMP_SM_Locations::get_for_product( $product_id )that returns the combined location string; useful for packing slips, PoS displays, or custom order views.
- A new sub-page under the Stock Manager menu: Lokationer (
1.3.10 (2026-07-07)
- Change: The "Manage with ..." button that WWSMP injects next to the "Add new" title action on WooCommerce/WP list-tables (Products, Orders, Coupons, Users, custom post types) has been redesigned:
- Icon: replaced the tiny 16px WSM icon with the
webalive_blueduck.svglogo at 18px. - Text: shortened from "Manage with Webalive Smart Manager Premium" to just "Smart Manager".
- Colours: switched from the arbitrary green accent (
#0e9f6e) to the WWSMP purple (#5850ec), consistent with the rest of the plugin. - Padding + rounded corners aligned with the modernised WWSMP look (
border-radius: 6px).
- Icon: replaced the tiny 16px WSM icon with the
1.3.9 (2026-07-07)
- Change: Renamed the plugin display-name from "Webalive Smart Manager Premium" to "Webalive Smart Manager Premium" across the codebase (plugin header, admin menu title, header helper, all
__()/_x()strings, readme title & description). The renaming removes the naming clash between the parent plugin and its folded-instock-manager/sub-module: the parent is now "Smart Manager" (the spreadsheet grid that edits ALL post types, orders, coupons, users, custom fields), and the sub-menu entry "Stock Manager" is the focused stock/log/import view. - Not changed (intentional, would break existing installs): folder slug
woo-wa-stock-manager-premium, text-domainwoo-wa-stock-manager-premium, allWWSMP_*PHP constants, all hook / action / filter / option / transient prefixes, the update-server URI. Only user-visible strings are affected.
1.3.8 (2026-07-07)
- Fix: The React app on the Stock Manager sub-pages was calling
wp_set_script_translations( ..., 'stock-manager', WWSMP_SM_DIR . 'languages' ), so it looked for awoo-wa-stock-manager-premium-admin-script-react-stock-manager-<locale>.jsonfile in the wrong directory. Wave A already renamed the PHP text-domain fromwoocommerce-stock-managertowoo-wa-stock-manager-premium, so all the__()/_x()calls resolve against the main WWSMP.mofile — the JS was the last piece not wired up. Now uses'woo-wa-stock-manager-premium'domain and the rootWWSMP_PATH . 'languages/'folder so React strings resolve against the same translation files as the rest of WWSMP.
1.3.7 (2026-07-07)
- Change: Stock Manager sub-pages (
?page=stock-manager,?page=stock-manager-import-export,?page=stock-manager-log) now automatically collapse the WordPress admin sidebar to icons on load, matching the behaviour of the main WWSMP grid. Implemented server-side viaadmin_body_class(adds the WP-nativefoldedclass) so it takes effect before render, no flash of expanded menu. Respects the samewp_force_collapse_admin_menusetting used by the grid; users can still un-collapse via WP's own#collapse-menutoggle.
1.3.6 (2026-07-07)
- Change: Stock Manager grid page (
?page=stock-manager) filter layout — Category / Type / Stock status dropdowns are now on the same row as SKU / Search, pushed to the right edge (viamargin-left: autoon the second.row). Uses:has()to target the React-rendered filter without patching the bundled JS. - Change: All input, select and textarea fields inside the Stock Manager pages get 6px rounded corners, 1px
#d1d5dbborder and consistent padding to match the modernised WWSMP look. - New: Auto-save on the Stock Manager grid. Instead of waiting for the upstream React "Save all changes" bar (which is a
position: fixedbottom-bar with low z-index that often ends up hidden behind WooCommerce/theme footers), a small helper script now listens for edits inside#woo-wa-stock-manager-premium-appand clicks the primary save button automatically after a short debounce (1500 ms). Also raises the z-index of the fallback save-bar to 999999 so it stays visible if it ever renders.
1.3.5 (2026-07-07)
- Change: Modernised the visual look of the Stock Manager sub-pages (
?page=stock-manager,?page=stock-manager-import-export,?page=stock-manager-log) so they align with the main WWSMP dashboard aesthetic. Added an overlay stylesheet (stock-manager/admin/assets/css/wwsmp-sm-modern.css) enqueued after the upstreamadmin.css:- Rounded corners (12px) and subtle shadow on
.toret-boxcards. - Modern flat buttons with WWSMP purple (
#5850ec) for primary actions and consistent hover states. - Cleaner tables: no heavy
#dddborders, striped rows, hover-highlight. - System-ui typography, warmer neutral palette (
#f9fafbbackground,#e5e7ebborders). - WordPress-native
.stock-manager-navigationtabs (underline style) instead of the boxed classic look. - Filter blocks and pagination redesigned as inline cards.
- Rounded corners (12px) and subtle shadow on
1.3.4 (2026-07-07)
- Change: Removed upstream Smart Manager brand assets and testimonials that referred to third-party customers of the original StoreApps product:
- Deleted image assets:
acrom.png,bryan-batcher.jpeg,jeff-smith.png,sm-in-app-promo.png,dirty.gif,logo-32x32.png,storeapps-logo.svg,sa-onboarding-connect-account.png,sa-onboarding-success.png. - Removed the three testimonial blocks on the Pricing page (Jeff Smith, Acrom, Brian Batcher).
- Replaced the StoreApps privacy-policy link in the Stock Manager subscribe form with the Webalive equivalent.
- Removed dead-code
class-wwsmp-in-app-offer.php(BFCM 2025 promo banner) and its bootstrapping inclass-wwsmp.php.
- Deleted image assets:
- New: Added a shared admin header (
WWSMP::render_admin_header()) with thewebalive_blueduck.svglogo + "Webalive Smart Manager Premium" title. Rendered on: Pricing (?page=wwsmp-pricing), Welcome/FAQs (?page=wwsmp&landing-page=wwsmp-faqs), Settings (?page=wwsmp-settings), and the three Stock Manager sub-pages (stock-manager,stock-manager-import-export,stock-manager-log). The main grid dashboard is intentionally unchanged — it has its own navbar.
1.3.3 (2026-07-07)
- Fix: WP admin plugins list showed "Auto-updates are not available for this plugin" instead of the normal "Enable auto-updates" link. Upstream Smart Manager registered a
plugin_auto_update_setting_htmlfilter that unconditionally overrode the auto-update column text when Pro was installed (originally meant to steer Smart Manager Pro users toward StoreApps' own update flow). WWSMP has its own PUC-based auto-update endpoint atupdates.webalive.dk, so the filter is no longer needed. Removed both theadd_filterhook and theauto_update_setting_html()callback; WordPress' default auto-update UI is now visible again.
1.3.2 (2026-07-07)
- Change: Removed the "Docs & Support" submenu (
page=wwsmp&landing-page=wwsmp-about) and the "WebAlive Plugins" submenu (page=wwsmp-webalive-plugins). Both were legacy landing pages that added noise to the admin menu without providing plugin functionality. The activation redirect that used to land users on the Docs & Support page has been changed to the main dashboard. All page-slug checks (in_arrayfilters for footer text, admin notices, feature notices, footer CSS enqueue, in-app offer plugin-page detection) have been updated so these two slugs are no longer accepted. TheWebAlive_Marketplace::init()call — which was the entire body of the WebAlive Plugins page — is no longer wired up. Theabout_screen()renderer inWWSMP_Admin_Welcomeis retained (unused) but its switch-case entry is removed; the nav-tab that pointed to it has also been removed.
1.3.1 (2026-07-07)
- Fix:
stock-manager/loader.phpnow checks withis_file()that each sub-module class file exists before callingrequire_once. Prevents a fatal error on partial deploys where the newstock-manager/directory has not been fully uploaded yet.
1.3.0 (2026-07-07)
- New: Stock Manager for WooCommerce (StoreApps 3.7.0) folded into WWSMP as a
stock-manager/sub-module. Provides a dedicated stock/price editor dashboard, quick filters, stock log history, and CSV import/export as a sub-page under the WWSMP admin menu. The standalonewoocommerce-stock-managerplugin is no longer required and can be deactivated — its features are now built-in.- Renamed the entire WSM namespace to avoid collision if the standalone plugin is still installed:
- PHP classes:
Stock_Manager→WWSMP_SM_Manager,Stock_Manager_Admin→WWSMP_SM_Admin,WSM_Save→WWSMP_SM_Save,WSM_Stock→WWSMP_SM_Stock. - Constants:
STOCKDIR→WWSMP_SM_DIR,WSM_PLUGIN_URL→WWSMP_SM_URL,WSM_PLUGIN_FILE→WWSMP_SM_FILE,WSM_PLUGIN_VERSION→WWSMP_SM_VERSION. - Hook/CSS prefixes:
wsm_→wwsmp_sm_,wsm-→wwsmp-sm-,sa_→wwsmp_sm_,sa-→wwsmp-sm-,SA_→WWSMP_SM_. - Text domain:
woocommerce-stock-manager→woo-wa-stock-manager-premium(translations merged into the existing WWSMP domain). - The DB table name
{$wpdb->prefix}stock_logis kept unchanged to preserve any existing stock log data from prior WSM installs. - WSM's standalone
add_menu_page( 'Stock' )replaced byadd_submenu_pageunder WWSMP's own menu slug. - Removed upstream StoreApps in-app pricing/promo dead code (
class-wsm-in-app-pricing.php), matching the same policy applied to WWSMP itself. - Removed
register_activation_hook/register_deactivation_hook; the stock-log DB table is now created on demand via WWSMP's install flow.
1.2.7 (2026-07-07)
- Fix (fatal error
Class "WWSMP_Manager_Base" not found):WWSMP_Manager_Controller::request_handler()used a whitelist regex/^class-wa-manager(-pro)?(-[a-z0-9_]+)?\.php$/ito decide which files were safe toinclude_once. When Wave E renamed the physical files fromclass-wa-manager-*.phptoclass-wwsmp-manager-*.phpthis regex stopped matching — so the base class was never loaded, and thewwsmp_manager_handlerfilter callback (WWSMP_Controller::req_handler→include_once class-wwsmp-base.php) hitclass WWSMP_Base extends WWSMP_Manager_BasebeforeWWSMP_Manager_Basewas defined. Updated the whitelist regex to match the newclass-wwsmp-manager-*.phpnaming.
1.2.6 (2026-07-06)
- Fix (systematic audit — the whole reason nothing worked after Wave E). All rename-induced problems fixed in one pass:
- Double-prefix in filter/action/option/transient names. After Wave E,
WWSMP_SKU = 'wwsmp'was concatenated with a'wwsmp_'prefix in ~30 places producing hooks likewwsmp_wwsmp_dashboard_model,wwsmp_wwsmp_data_model,wwsmp_wwsmp_manager_handler,wwsmp_wwsmp_validate_current_page,wwsmp_wwsmp_check_dashboard_access,wwsmp_wwsmp_manager_common_core_path,wwsmp_wwsmp_manager_func_handler,wwsmp_wwsmp_manager_request_handler_allowed_dir_path, plus option/transient/user-meta keyswwsmp_wwsmp_<dashboard_key>,wwsmp_wwsmp_feedback_done,wwsmp_wwsmp_feedback_start_date,wwsmp_wwsmp_feedback_close_date,wwsmp_wwsmp_feedback_action_counts,wwsmp_wwsmp_dashboard_load_count. Meanwhile the pro layer registeredadd_filter('wwsmp_dashboard_model', ...),add_filter('wwsmp_data_model', ...)etc. — the two sides never met, so every pro column, data-model transform, and dashboard access check was silently dead. All'wwsmp_' . $plugin_sku . '_...'collapsed to'wwsmp_...'. - Double-prefix in AJAX action URLs. The background-updater JS was building
?action=wwsmp_wwsmp_manager_include_file, again never matching any handler. Collapsed to?action=wwsmp_manager_include_file. - Dead JS action
wwsmp_beta_include_fileinpro/class-wwsmp-pro-background-updater.php— no PHP handler ever registered under that name (this was a legacysm_beta_include_filefrom upstream that was renamed but never wired up). Routed to the actual handlerwwsmp_manager_include_file. - *`add_filter('wwsmpbeta_include_file', ...)
**-style hooks inclass-wwsmp-pro-user.phpverified consistent withapply_filters('wwsmpbeta*', ...)sites inclass-wwsmp-pro-base.php`.
- Double-prefix in filter/action/option/transient names. After Wave E,
- This release is the result of a top-down audit (AJAX action registrations vs JS action calls,
wp_create_noncevscheck_ajax_referer, filter callers vs listeners, script handle registrations, dashboard-property bridge between base and pro) rather than reacting to one browser console error at a time.
1.2.5 (2026-07-06)
- Fix (root cause of the empty dashboard / empty AJAX response in 1.2.4): two rename escapees from Wave E broke the entire AJAX layer.
wp_ajax_sa_prefix survived the regex rename (word-boundary did not match after_). PHP was still registering the handler aswp_ajax_sa_wwsmp_manager_include_filewhile JS was callingwwsmp_manager_include_file— WordPress never routed the request to any callback so the response was empty. Same issue forwp_ajax_sa_stop_background_processandwp_ajax_sa_wwsmp_stop_background_process. All threesa_prefixes removed fromadd_actioncalls.- Nonce mismatch.
wp_create_nonce()produced'wwsmp-manager-security'(one prefix) butcheck_ajax_referer()verified'wwsmp-' . $plugin_sku . '-manager-security'='wwsmp-wwsmp-manager-security'(double prefix). Every AJAX call failed the nonce check. Aligned both sides to'wwsmp-manager-security'.
1.2.4 (2026-07-06)
- Fix (root cause of the empty dashboard / JSON parse error): the pro JS layer read
window.wwsmp.wwsmp_nonceandwindow.wwsmp.wwsmp_ajax_url, but the base only setthis.saCommonNonce/this.commonManagerAjaxUrl. Every pro-side AJAX request went out withsecurity=undefinedand the WordPress ajax handler exited silently oncheck_ajax_referer— producing an empty response and a JSON parse error in the browser. RenamedsaCommonNonce→wwsmp_nonceandcommonManagerAjaxUrl→wwsmp_ajax_urlin both base and pro so the two sides finally agree. - Breaking: Continued the decoupling from the upstream StoreApps identity. All remaining
sa_/sa-/SA_prefixes (StoreApps namespace) andwa_manager_/WA_Manager_library-wrapper prefixes have been renamed towwsmp_/wwsmp-/WWSMP_/WWSMP_Manager_.- AJAX action
sa_wwsmp_manager_include_file→wwsmp_manager_include_file. - Nonce key
sa-wwsmp-manager-security→wwsmp-manager-security. - Class names
SA_WWSMP_In_App_Offer→WWSMP_In_App_Offer,SA_WWSMP_Deactivation→WWSMP_Deactivation,WA_Manager_Controller/WA_Manager_Base/WA_Manager_Product/WA_Manager_Feedback/WA_Manager_Background_Updater→WWSMP_Manager_*. - Folder
sa-includes/→includes/(bothclasses/andpro/). Filesclass-sa-wwsmp-*.php→class-wwsmp-*.php. - Fixed
pluginSlug = 'sm'in the JS constructor →'wwsmp'(previously produced dead CSS classes likesm-select2after the sm-→wwsmp- CSS rename in 1.2.1). - Removed dead-code
SA_In_App_Offerbase class (defined twice, referenced nowhere) andpro/sa-includes/class-storeapps-cache.php(unused StoreApps cache wrapper).
- AJAX action
- Note: This continues the breaking-change behaviour from 1.2.0-1.2.3. Options, transients and user-metas keyed on the old prefixes will be re-initialised on first load. No functional change beyond identity renaming.
1.2.3 (2026-07-06)
- Fix: Dashboard crashed on load with
You declared cell type "wwsmp.image" as a string that is not mapped to a known objectfrom Handsontable. Root cause of the mismatch introduced in 1.2.1:common-core/class-wa-manager-product.phpbuilds column type strings dynamically as$this->plugin_sku . '.image'— after the SKU rename in 1.2.0 that produceswwsmp.image— whileassets/js/wwsmp.jswas still callingHandsontable.cellTypes.registerCellType('sm.image', ...)and severalpro/classes/*.phpfiles still hardcoded'sm.datetime','sm.date','sm.time','sm.multilist','sm.multipleImage','sm.longstring','sm.serialized','sm.action'as column types. All Handsontable cell-type registrations (9 inwwsmp.js) and all hardcoded'sm.<celltype>'type strings in the pro PHP layer have been aligned to thewwsmp.<celltype>namespace produced byplugin_sku.
1.2.2 (2026-07-06)
- Fix: Dashboard rendered as an empty grid (no columns, no rows) with
TypeError: window.wwsmp.column_names_batch_update is undefinedthrown frompro/wwsmp-product.js:122duringsetDashboardModel. Root cause: the upstream refactor renamed the state property fromcolumn_names_batch_update(snake_case) tocolumnNamesBatchUpdate(camelCase) incore-base.js(assignment site), but left the legacy snake_case reads in the pro layer (pro/wwsmp.jsandpro/wwsmp-product.js). The very first read threw before the grid could paint. All ~20 snake_case reads in the pro JS layer have been aligned with the actual camelCase property.
1.2.1 (2026-06-14)
- Breaking: Continuation of the Smart Manager decoupling started in 1.2.0. All remaining
sm_/sm-prefixes have been renamed towwsmp_/wwsmp-.- CSS class names (
sm-header,sm-base-*,sm-loader,.sm-marketplace,.sm_button, etc.) and CSS custom properties (--color-sm-base-*) renamed towwsmp-*/--color-wwsmp-base-*. - DOM IDs (
#sm_editor_grid,#sm_simple_search_box,#sm_nav_bar, etc.) renamed to#wwsmp_*. - Script/style handles (
sm_custom_*,sm_pro_*,sm_beta_*) renamed towwsmp_*. - PHP variables and properties starting with
$sm_/->sm_renamed to$wwsmp_/->wwsmp_. - JS bridge properties (
window.wwsmp.sm_beta_pro,.sm_views,.sm_dashboards,.sm_nonce, etc.) renamed to.wwsmp_*on both the PHP localize side and the JS reader side. - Database keys (transient names, option names, custom SQL table suffixes like
sm_advanced_search_temp) renamed towwsmp_*. Existing rows keyed on the old prefix will be re-initialised on first load.
- CSS class names (
- Note: This release continues the breaking-change behaviour from 1.2.0. After upgrading, all saved per-user state, transient caches, and the
wp_sm_advanced_search_temptable contents will be re-built on first dashboard load.
1.2.0 (2026-06-14)
- Breaking: Complete decoupling from the upstream Smart Manager identity. All runtime relations to WWSMP have been removed.
- JS globals:
window.wwsmp→window.wwsmp. - JS classes:
WWSMP→WWSMP,WWSMPPro→WWSMPPro. - PHP localize variable:
wwsmp_params→wwsmp_params. - Library classes:
SaCommonManager→WWSMPCommonManager,SaErrorHandler→WWSMPErrorHandler. - Plugin SKU:
WWSMP_SKU = 'sm'→'wwsmp'. Plugin object key:'wwsmp'→'wwsmp'. - Hook/filter/action prefix:
sa_sm_→sa_wwsmp_. Hardcoded AJAX actionswp_ajax_sm_*andwp_ajax_wwsmp_*renamed accordingly.
- JS globals:
- Note: This is a breaking change. Saved per-user dashboard views, column states, transients and any other data keyed on the old
sm/wwsmpprefixes will be re-initialised on first load after upgrade. CSS class names (sm-,sm_) and internal script handles (sm_custom_*) are intentionally left unchanged in this release.
1.1.6 (2026-06-11)
- Fix: Removed two dead
wp_register_scriptcalls forpro/assets/js/wwsmp-nl-converter.jsandpro/assets/js/wwsmp-url-parser.js. Those files do not exist in the package (and never existed in the upstream Smart Manager 8.87.0 source either) - the registrations only produced 404s in the browser console. - Fix: Auto-CSS loader was including
pro/assets/css/wwsmp.cssvia the/pro/assets/css/*.cssglob and then mangling the URL intopro/assets/css/css/wwsmp.css(the folder-path logic only handles CSS files in subfolders). Removed the top-level glob entry;wwsmp.csswas already enqueued explicitly assm_pro_main_styleimmediately afterwards.
1.1.5 (2026-06-11)
- Fix:
pro/assets/js/wwsmp.jsreferenced a non-existent global classWWSMP(left over from the initial Smart Manager → WWSMP rename pass). The actual lite base class isWWSMP, so the pro file threwReferenceError: WWSMP is not definedat parse time and aborted before installing any Pro overrides. Renamed all references:WWSMP_Pro→WWSMPProandWWSMP→WWSMP. This restoreswindow.wwsmpas a properWWSMPProinstance and fixes the cascade errorssetSaveButtonState is not a functionandshowVariationsHtml is not a functionon the products dashboard.
1.1.4 (2026-06-11)
- Compat (PHP 8.x): Fixed
Optional parameter $update_flag declared before required parameter $args is implicitly treated as a required parameterdeprecation inWWSMP_Pro_Product::products_post_batch_update_db_updates(). Removed the default value on$update_flag(the method is only used as asm_post_batch_update_db_updatesfilter callback, which always passes both arguments).
1.1.3 (2026-06-11)
- Updates: Removed the manual update-checker bootstrap from the main plugin file. The proper fix lives in
public/build-packages.php(findMainPluginFile()now scans only the plugin root, so it can no longer accidentally inject into bundled libraries that also carry aPlugin Name:header, such aspro/libraries/action-scheduler/action-scheduler.php). The standard auto-injection now lands in the correct file again.
1.1.2 (2026-06-11)
- Updates: Explicitly bootstrap the WebAlive update checker (yahnis-elsts PUC +
includes/UpdateChecker.php) from the main plugin file so the standard "Undersøg for opdateringer" link shows up on the Plugins screen and updates are pulled fromhttps://updates.webalive.dk. The build pipeline's auto-injection picked the wrong header file (pro/libraries/action-scheduler/action-scheduler.phpalso contains aPlugin Name:header), which is why the link was missing in 1.1.1. - UI: Removed the legacy "Boost us with ⭐⭐⭐⭐⭐" wordpress.org review link and the obsolete "Go Pro" entry from the plugin row meta on the Plugins screen. This plugin is not listed on wordpress.org and ships as Premium (= Pro), so neither entry was meaningful.
1.1.1 (2026-06-11)
- Compat (PHP 8.x): Silenced deprecation notices from the bundled Action Scheduler library:
- Added
#[\ReturnTypeWillChange]toActionScheduler_DateTime::getTimestamp(),getOffset()andsetTimezone()so they no longer trigger PHP 8.1+ "Return type ... should either be compatible" warnings. - Removed the redundant
$this->scheduled_date = null;assignments inActionScheduler_NullSchedule::__construct()/__wakeup()that triggered "Creation of dynamic property" deprecations on PHP 8.2+ (parent's private$scheduled_datealready defaults to NULL). as_get_datetime_object()now coalesces anulldate string to'now'before callingnew DateTime(), fixing the "Passing null to parameter #1 ($datetime) of type string is deprecated" notice on PHP 8.1+.
- Added
- Compat (PHP 8.2): Declared
public $req_params = array();onWWSMP_Pro_Viewsto remove the "Creation of dynamic property WWSMP_Pro_Views::$req_params is deprecated" notice.
1.1.0 (2026-06-10)
- Fix: Fatal error
Declaration of WWSMP_Pro_Base::get_export_csv() must be compatible with WWSMP_Base::get_export_csv($params = [])that crashed all admin-ajax responses for the dashboard. The Pro override now matches the base signature. This was the root cause of the dashboard hanging on the rotating loading messages ("Almost there...", "Warming things up...", "Putting everything in its right place..."): the AJAX call tosa_sm_manager_include_filereturned a fatal-error 500, the JSsetDashboardModelshort-circuited on the empty response, andhideDashboardLoadingMessage()was never called. - Note: Version aligned to 1.1.0 to resolve a previous header/readme mismatch (header was 1.0.7, readme was 1.0.9).
1.0.9 (2026-05-23)
- Compatibility: Declare support for WooCommerce High-Performance Order Storage (HPOS) and Cart/Checkout Blocks in the main bootstrap file to remove the "incompatible plugin" notice in WooCommerce 10.7+.
1.0.8 (2026-05-22)
- Compatibility: Tested with WordPress 7.0 and WooCommerce 10.7.
1.0.7
- Compat: Tested with WordPress 7.0 and WooCommerce 10.7.
1.0.6
- Cleanup: Removed dead-code file
pro/sa-includes/class-storeapps-upgrade-3-9.php(legacy StoreApps OAuth connector /WebAlive_Upgrade_3_9). The class was never loaded by the current bootstrap and contained an unused OAuth flow POSTing towebalive.dk/oauth/token. No functional change.
1.0.5
- Privacy/Offline: Removed the outbound deactivation-survey HTTP call to webalive.dk in
sa_submit_deactivation_reason_action(). The deactivation modal still shows and the AJAX handler still validates nonce +manage_options, but no data (domain, activation dates, reason, etc.) is sent anywhere. The handler now returns success immediately.
1.0.4
- Updates: Plugin updates are now delivered through the WebAlive update server at
https://updates.webalive.dkvia the standard WebAlive update checker (yahnis-elsts PUC, auto-injected by the build pipeline). AddedUpdate URI:header pointing at the metadata endpoint. - Privacy/Offline: Removed the legacy one-time
wp_remote_gettowebalive.dk/wp-admin/admin-ajax.php?action=check_updateinpro_activated()(that endpoint was unrelated to the actual update server). The optionWWSMP_PREFIX._check_updateis still written/read so the call stays disabled across upgrades.
1.0.3
- Privacy/Offline: Removed the outbound license-validation HTTP call to webalive.dk in
show_upgrade_to_pro(). Since the plugin only ships as Premium (= Pro), the call served no purpose and leaked the license key + site URL on every WWSMP admin pageload. The Pro install marker is now alwaystrueand no network request is made. The behavior can be re-enabled via thewwsmp_enable_remote_license_checkfilter if license management is added later.
1.0.2
- Fix: Fatal error "Class 'WebAlive_Upgrade_4_0' not found" on
wp_loadedwhen the ported StoreApps upgrader class file is not shipped.on_wp_loaded()now verifies that the resolved upgrade class actually exists before instantiating it.
1.0.1
- Security: AJAX request handler in WA_Manager_Controller now enforces a
current_user_can('manage_woocommerce')capability check (filterwa_manager_required_capability) in addition to the existing nonce and admin-page checks. - Security: Top-level admin menu (
add_menu_page) capability raised fromreadtomanage_woocommerce(filterwwsmp_menu_capability). - Change: Pro Access Privilege option prefix renamed from legacy
sm_beta_towwsmp_(option name pattern is nowwwsmp_{role}_accessible_dashboards). Existing per-role dashboard assignments will need to be re-saved once after upgrade.
1.0.0
- Initial WebAlive release. Ported Smart Manager 8.87.0 codebase into a Webalive-branded plugin with PSR-4 bootstrap (
WebAlive\WWSMP), webalive text domainwoo-wa-stock-manager-premium, and renamed constants/classes (WWSMP_*,WWSMP). All Lite + Pro feature modules included.