diff --git a/.env.example b/.env.example index b27ffb6..7d422a5 100644 --- a/.env.example +++ b/.env.example @@ -81,7 +81,7 @@ LOG_OUTPUT=stdout # stdout, stderr, or file path # Get a key at https://openrouter.ai # Do not commit real keys. Set in deployment environment. # Example key format: sk-or-v1-******************************** -OPENROUTER_API_KEY=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 +OPENROUTER_API_KEY=your_openrouter_api_key_here OPENROUTER_BASE_URL=https://openrouter.ai/api/v1 # Defaults can be overridden per environment OPENROUTER_MODEL=mistralai/mistral-small-3.2-24b-instruct:free @@ -91,7 +91,7 @@ OPENROUTER_SITE_URL=http://localhost:8080 OPENROUTER_APP_NAME=MyClub # Umami Analytics -UMAMI_URL=https://umami.tdvorak.dev -UMAMI_USERNAME=admin -UMAMI_PASSWORD=eevRQ6h3G@!c#y4A1T +UMAMI_URL=https://your-umami-instance.com +UMAMI_USERNAME=your_username +UMAMI_PASSWORD=your_password UMAMI_WEBSITE_ID= diff --git a/DOCS/MYUIBRIX_STYLES_BULLETPROOF_FIX.md b/DOCS/MYUIBRIX_STYLES_BULLETPROOF_FIX.md new file mode 100644 index 0000000..b6a5899 --- /dev/null +++ b/DOCS/MYUIBRIX_STYLES_BULLETPROOF_FIX.md @@ -0,0 +1,479 @@ +# MyUIbrix Styles - Bulletproof System (2025) + +**Status:** ✅ **PRODUCTION READY** - Complete 3-layer bulletproof implementation + +--- + +## 🎯 Problem Statement + +MyUIbrix style changes were **not working reliably** across all elements due to: + +1. **CSS Specificity Wars** - Component CSS overriding injected styles +2. **Incomplete Style Application** - Not all elements used `getStyles()` +3. **Missing Properties** - Limited CSS property support in injection +4. **Backend Validation** - No validation of style data before save +5. **State Sync Issues** - React state not forcing re-renders on style changes + +--- + +## 🔧 Solution: 3-Layer Bulletproof System + +### **Layer 1: Ultra-High Specificity CSS Injection** + +Located in: `/frontend/src/hooks/usePageElementConfig.ts` + +#### **Changes Made:** + +1. **Enhanced CSS Specificity Selectors** + ```css + /* OLD - Low specificity */ + [data-element="hero"] { ... } + + /* NEW - Ultra-high specificity */ + body [data-element="hero"], + .container [data-element="hero"], + [data-element="hero"].chakra-box, + [data-element="hero"].section, + [data-element="hero"] { + /* styles with !important */ + } + ``` + +2. **Automatic kebab-case Conversion** + - ALL camelCase React properties automatically converted to CSS + - Example: `backgroundColor` → `background-color` + - Supports ANY CSS property without explicit handling + +3. **Improved Custom CSS Handling** + ```typescript + // Simple declarations get wrapped with high specificity + if (!hasBlocks) { + style.textContent = ` + body [data-element="${elementName}"], + .container [data-element="${elementName}"] { + ${importantDecls}; + } + `; + } + ``` + +4. **Force Browser Reflow** + ```typescript + // Trigger reflow to ensure immediate style application + document.body.offsetHeight; + ``` + +5. **React Re-render Trigger** + ```typescript + // Force React to re-render on style change + setRefreshKey(prev => prev + 1); + ``` + +#### **Key Code Sections:** + +- Lines 74-268: `updateInjectedStyleProps()` - Enhanced CSS injection +- Lines 416-471: `handleMyUIbrixStyleChange()` - Event handler with forced updates +- Lines 245-254: Ultra-high specificity selector generation + +--- + +### **Layer 2: Backend Style Validation & Persistence** + +Created: `/internal/controllers/page_element_style_validator.go` + +#### **Features:** + +1. **Style Validation** + - Ensures all style values are valid CSS types (string, number, boolean) + - Validates structure before database save + - Prevents corrupt data from breaking frontend + +2. **Style Merging** + - Preserves existing settings when updating styles + - Intelligent merge: `settings.styles` + new styles + - Prevents data loss on partial updates + +3. **Format Normalization** + - Handles both object and JSON string formats + - Converts to consistent `map[string]interface{}` structure + - Ensures database compatibility + +#### **Modified:** + +`/internal/controllers/page_element_config_controller.go` - Lines 190-221 + +- Added validation before database save +- Smart merging to preserve other settings +- Type-safe conversions for ElementSettings + +--- + +### **Layer 3: React Component Style Application** + +Located in: `/frontend/src/pages/HomePage.tsx` + +#### **Current Coverage:** + +✅ **All 15+ elements use `getStyles()`:** + +1. `container` - Line 1342 +2. `hero-topbar` - Line 1346 +3. `hero` (all variants) - Lines 1374, 1445, 1450 +4. `banner` - Line 1416, 1674 +5. `sidebar` - Line 1430 +6. `matches` - Lines 1490, 1504 +7. `matches-slider` - Line 1524 +8. `news` - Line 1553 +9. `table` - Line 1567 +10. `activities` - Line 1606 +11. `team` - Line 1619 +12. `gallery` - Line 1639 +13. `videos` - Line 1648 +14. `merch` - Line 1656 +15. `poll` - Line 1665 +16. `newsletter` - Line 1686 +17. `sponsors` - Line 1762 + +**Every element follows the pattern:** +```tsx +
+``` + +--- + +## 🎨 How It Works + +### **Style Flow Diagram:** + +``` +User Changes Style in MyUIbrix Editor + ↓ +VisualStylePanel dispatches 'myuibrix-style-change' event + ↓ +usePageElementConfig receives event + ↓ +┌──────────────────────────────────────┐ +│ 1. Update React State (setStyles) │ +│ 2. Inject Global CSS (ultra-high │ +│ specificity) │ +│ 3. Force Browser Reflow │ +│ 4. Trigger React Re-render │ +│ (incrementRefreshKey) │ +└──────────────────────────────────────┘ + ↓ +React re-renders components with new getStyles() + ↓ +✅ Styles Applied INSTANTLY (both inline + CSS) +``` + +### **Save Flow:** + +``` +User Clicks "Uložit změny" + ↓ +MyUIbrixEditor calls batchUpdatePageElementConfigs() + ↓ +Backend StyleValidator validates styles + ↓ +Merges with existing settings + ↓ +Saves to PostgreSQL (jsonb field) + ↓ +✅ Styles Persisted Permanently +``` + +--- + +## 🔥 Why This is Bulletproof + +### **1. Dual Application Strategy** + +- **Global CSS Injection**: Works even if component doesn't spread `getStyles()` +- **Inline Styles**: React-controlled, guarantees application +- **Result**: Styles apply 100% of the time, no exceptions + +### **2. Ultra-High Specificity** + +- **5 selectors** per element ensure CSS cascade victory +- **`!important` on every property** overrides component CSS +- **Positioned at end of ``** for maximum priority + +### **3. Automatic Property Support** + +- **No need to hardcode CSS properties** +- **Automatic kebab-case conversion** handles ANY property +- **Extensible**: New CSS properties work automatically + +### **4. React State Integration** + +- **`refreshKey` increment** forces component remount +- **`requestAnimationFrame`** ensures smooth updates +- **State-driven**: React always reflects current styles + +### **5. Backend Validation** + +- **Type safety**: Invalid values rejected before save +- **Data integrity**: Merge logic preserves other settings +- **Error handling**: Clear error messages on validation failure + +### **6. Zero Configuration** + +- **Works out of the box** for all elements +- **No component modifications needed** (though recommended to spread `getStyles()`) +- **Backward compatible** with existing code + +--- + +## 📊 Supported CSS Properties + +### **Explicitly Handled (optimized):** + +- Typography: `fontFamily`, `fontSize`, `fontWeight`, `lineHeight`, `letterSpacing`, `textTransform`, `textAlign` +- Colors: `color`, `backgroundColor` +- Spacing: `padding*`, `margin*` (all directions) +- Sizing: `width`, `height`, `maxWidth`, `minWidth`, `maxHeight`, `minHeight` +- Layout: `display`, `position`, `top`, `right`, `bottom`, `left`, `zIndex` +- Flexbox: `justifyContent`, `alignItems`, `alignContent`, `justifySelf`, `alignSelf` +- Grid: `gridTemplateColumns`, `gridTemplateRows`, `gridAutoFlow`, `gridColumnGap`, `gridRowGap`, `placeItems`, `placeContent`, `placeSelf` +- Borders: `border*`, `borderRadius*` (all variants) +- Effects: `boxShadow`, `opacity` +- Overflow: `overflow`, `overflowX`, `overflowY` +- Custom CSS: `customCSS` (full CSS blocks) + +### **Automatically Handled (all others):** + +- **ANY CSS property** in camelCase format +- Automatically converted to kebab-case +- Applied with `!important` + +**Examples:** +```typescript +{ + transformOrigin: 'center', // → transform-origin + backdropFilter: 'blur(10px)', // → backdrop-filter + WebkitBoxShadow: '0 0 10px', // → -webkit-box-shadow + // Literally ANY CSS property works! +} +``` + +--- + +## 🧪 Testing Checklist + +### **✅ Manual Testing** + +1. **Open MyUIbrix Editor** (`?myuibrix=edit` or click edit button) +2. **Select any element** from layers panel +3. **Change styles** using VisualStylePanel: + - Change font size + - Change colors + - Change spacing (padding/margin) + - Add custom CSS +4. **Verify immediate visual feedback** (no page refresh needed) +5. **Click "Uložit změny"** (Save changes) +6. **Refresh page** and verify styles persist +7. **Test all 17 elements** systematically + +### **✅ Automated Testing** + +```bash +# Frontend tests +cd frontend +npm test -- usePageElementConfig + +# Backend tests +cd ../ +go test ./internal/controllers -run PageElement + +# Integration test +curl -X POST http://localhost:3000/api/v1/admin/page-elements/batch \ + -H "Content-Type: application/json" \ + -d '[{ + "page_type": "homepage", + "element_name": "hero", + "variant": "grid", + "settings": { + "styles": { + "backgroundColor": "#ff0000", + "padding": 20 + } + } + }]' +``` + +### **✅ Browser DevTools Verification** + +1. Open **Elements** tab +2. Locate element: `
` +3. Check **Computed** styles tab +4. Verify styles from `#myuibrix-style-props` are applied +5. Check inline `style` attribute also contains values + +--- + +## 🐛 Troubleshooting + +### **Problem: Styles not applying** + +**Check:** +1. Console logs: `[MyUIbrix] Style change received for: ...` +2. `