- Add POST /preview/page/{slug} and /preview/template/{cpt} endpoints
- Render full HTML using PageSSR for iframe preview
- Templates use sample post for dynamic placeholder resolution
- PageSettings iframe with debounced section updates (500ms)
- Desktop/Mobile toggle with scaled iframe view
- Show/Hide preview toggle button
- Refresh button for manual preview reload
- Preview indicator banner in iframe
- Add horizontal padding to dialog content (px-1)
- Show real site URL from WNW_CONFIG.siteUrl instead of 'yoursite.com'
- Improve error handling to extract message from response.data.message
- Better slug generation regex (removes special chars properly)
- Reset form when modal closes
- Use theme colors (text-muted-foreground, hover:bg-accent/50)
- Removed all debug logging (backend and frontend)
- Added filter hook 'woonoow_standard_checkout_field_keys' for extensibility
- Added form-row-wide class support to admin OrderForm
- Tax is automatically handled by WC's calculate_totals()
The wpAdminUrl config already includes admin.php?page=woonoow,
so constructing /admin.php?page=wc-settings on top of it was wrong.
Now uses siteUrl + /wp-admin for external WC links.
Removed static method-level fallback. Shipping method selector now:
1. Shows 'Enter shipping address to see available rates' when address incomplete
2. Calls calculate_shipping endpoint to get actual WC_Shipping_Rate objects
3. Displays rate-level options (e.g., JNE REG, JNE YES) not method-level
This ensures third-party shipping plugins like Rajaongkir, UPS, FedEx
display their courier rates correctly.
1. Shipping method selector now shows static shippings list when
address is not complete, instead of 'No shipping methods available'.
Only shows the empty message when address IS complete but no methods
matched.
2. Variation selector in Dialog and Drawer now displays attribute names
(Size, Dispenser) in semibold and values (30ml, pump) in normal
weight for better visual hierarchy.
Instead of mounting to body (which breaks scoped styles), we now
mount the popover portal to #woonoow-admin-app. This ensures
dropdowns inherit the correct CSS variables and styling.
Invoice Page (/orders/:id/invoice):
- A4-ready layout (210mm x 297mm)
- Store header, invoice number, QR code
- Billing/shipping address sections
- Styled items table with alternating rows
- Totals summary with conditional display
- Thank you footer
- Back to Order and Print buttons
Label Page (/orders/:id/label):
- 4x6 inch thermal label layout
- Ship To address with phone
- Items list (physical products only)
- Shipping method
- QR code for scanning
- Back to Order and Print buttons
Order Detail:
- Removed print-mode logic
- Removed print-only layouts
- Invoice/Label buttons now link to dedicated pages
- Label button still hidden for virtual-only orders
- Added license_duration_days field to ProductVariant type
- Added License Duration input to each variation card
- Backend: ProductsController saves/loads variation-level _license_duration_days meta
- Allows different license periods per variation (e.g., 1-year, 2-year, lifetime)
Copy Cart/Checkout Links:
- Added to GeneralTab for simple products (same pattern as variations)
- Link generation with add-to-cart and redirect params
Licensing Settings:
- 'Enable licensing for this product' checkbox in Additional Options
- License settings panel: activation limit, duration (days)
- State management in ProductFormTabbed
- Backend: ProductsController saves/loads licensing meta fields
Backend:
- _licensing_enabled, _license_activation_limit, _license_duration_days post meta
1. Admin Store Link - Add to WP admin bar (Menu.php) with proper option check
2. Activity Log - Fix Loading text to show correct state after data loads
3. Avatar Upload - Use correct option key woonoow_allow_custom_avatar
4. Downloadable Files - Connect to WooCommerce native:
- Add downloads array to format_product_full
- Add downloads/download_limit/download_expiry handling in update_product
- Add downloads handling in create_product
Customer Avatar Upload:
- Add /account/avatar endpoint for upload/delete
- Add /account/avatar-settings endpoint for settings
- Update AccountDetails.tsx with avatar upload UI
- Support base64 image upload with validation
Product Downloadable Files:
- Create DownloadsTab component for file management
- Add downloads state to ProductFormTabbed
- Show Downloads tab when 'downloadable' is checked
- Support file name, URL, download limit, and expiry
- Add Store link to admin header (visible when customer SPA is enabled)
- Add storeUrl and customerSpaEnabled to WNW_CONFIG in Assets.php and StandaloneAdmin.php
- Update window.d.ts with new WNW_CONFIG properties
- Create ActivityLog.tsx component with search, filters, and pagination
- Add /notifications/logs API endpoint to NotificationsController
- Update Notifications.tsx to link to activity log page
- Add ActivityLog route to App.tsx
1. Add allow_custom_avatar toggle to Customer Settings
2. Implement coupon apply/remove in Cart and Checkout pages
3. Update Cart interface with coupons array and discount_total
4. Implement Downloads page to fetch from /account/downloads API
- Created Newsletter/index.tsx as tabs container
- Extracted Newsletter/Subscribers.tsx (from old Newsletter.tsx)
- Moved Campaigns to Newsletter/Campaigns.tsx
- Updated App.tsx routes (campaigns now under newsletter)
- Removed separate Campaigns card from Marketing index
- Follows Customer Notifications tab pattern for consistency
- Sticky not possible when page is inside overflow-auto container
- Using standard flexbox layout where sidebar and content scroll together
- Separate mobile (fixed overlay) and desktop (inline) sidebars
- Clean, simple layout matching typical documentation patterns
- Fixed sidebar to not use inset-y-0 (was overriding top offset)
- Mobile: fixed positioning with sidebarTopClass
- Desktop: lg:sticky for proper sticky behavior
- Added X-WP-Nonce header to docs API fetch calls in Help page
- Fixed build-production.sh to include docs/ folder (changed --exclude='*.md' to --exclude='/*.md')
- This allows root-level docs like README.md to be excluded while keeping docs/ folder
Phase 1: Core Documentation
- Created docs/ folder with 8 markdown documentation files
- Getting Started, Installation, Troubleshooting, FAQ
- Configuration docs (Appearance, SPA Mode)
- Feature docs (Shop, Checkout)
- PHP registry with filter hook for addon extensibility
Phase 2: Documentation Viewer
- DocsController.php with REST API endpoints
- GET /woonoow/v1/docs - List all docs (with addon hook)
- GET /woonoow/v1/docs/{slug} - Get document content
- Admin SPA /help route with sidebar navigation
- Markdown rendering with react-markdown
- Added Help & Docs to More page for mobile access
Filter Hook: woonoow_docs_registry
Addons can register their own documentation sections.
- Created ResetPassword.tsx with:
- Password reset form with strength indicator
- Key validation on load
- Show/hide password toggle
- Success/error states
- Redirect to login on success
- Updated EmailManager.php:
- Changed reset_link from wp-login.php to SPA route
- Format: /wp-admin/admin.php?page=woonoow#/reset-password?key=KEY&login=LOGIN
- Added AuthController API methods:
- validate_reset_key: Validates reset key before showing form
- reset_password: Performs actual password reset
- Registered new REST routes in Routes.php:
- POST /auth/validate-reset-key
- POST /auth/reset-password
Password reset emails now link to the SPA instead of native WordPress.
ROOT CAUSE (from screenshot DevTools):
href="<span style=...>[login_url]</span>" - HTML span inside href attribute!
Flow causing the bug:
1. parseCardsForPreview converts [button url="{login_url}"] to <a href="{login_url}">
2. sampleData replacement runs but login_url NOT in sampleData
3. Variable highlighting injects <span>[login_url]</span> INTO href="..."
4. HTML is completely broken
FIXES APPLIED:
1. Added missing URL variables to sampleData:
- login_url, reset_link, reset_key
- user_login, user_email, user_temp_password
- customer_first_name, customer_last_name
2. Changed variable highlighting from HTML spans to plain text [variable]
- Prevents breaking HTML attributes if variable is inside href, src, etc.
Root cause: parseCardsForPreview was called TWICE in generatePreviewHTML:
1. Line 179 - correctly parses markdown to HTML including buttons
2. Line 283 - redundantly called AGAIN after variable highlighting
After first call, variable highlighting (lines 275-280) replaced unknown
variables like {login_url} with <span>[login_url]</span>. When the second
parseCardsForPreview ran, the [login_url] text was misinterpreted as
shortcode syntax, corrupting button HTML output.
Fix: Remove the redundant second call to parseCardsForPreview at line 283.
The function is already called at line 179 before any variable replacement.
1. API Route Fix (NotificationsController.php):
- Changed PUT to POST for /templates/:eventId/:channelId
- Frontend was using api.post() but backend only accepted PUT
- Templates can now be saved
2. Contextual Variables (EventRegistry.php):
- Added get_variables_for_event() method
- Returns category-based variables (order, customer, product, etc.)
- Merges event-specific variables from event definition
- Sorted alphabetically for easy browsing
3. API Response (NotificationsController.php):
- Template API now returns available_variables for the event
- Frontend can show only relevant variables
4. Frontend (EditTemplate.tsx):
- Removed hardcoded 50+ variable list
- Now uses template.available_variables from API
- Variables update based on selected event type
1. Remove wishlist setting from customer settings (now in module toggle)
- Removed from CustomerSettingsProvider.php
- Removed from Customers.tsx
2. Remove auto-login from REST API (causes cookie issues)
- Auto-login in REST context doesn't properly set browser cookies
- Removed wp_set_current_user/wp_set_auth_cookie calls
3. Fix cart not clearing after order
- Added WC()->cart->empty_cart() after successful order
- Server-side cart was not being cleared, causing re-population
- Frontend clears local store but Cart page syncs with server
- Add Campaigns list page with table, status badges, search, actions
- Add Campaign editor with title, subject, content fields
- Add preview modal, test email dialog, send confirmation
- Update Marketing index to show hub with Newsletter, Campaigns, Coupons cards
- Add routes in App.tsx