From 68e69e00cc25e67f6fe07fb47cbcee439e986342 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Mon, 20 Oct 2025 10:40:55 +0200 Subject: [PATCH] dev day #65,5 --- DOCS/BLOG_MATCH_LINK_FIX.md | 94 ++ DOCS/BLOG_MATCH_LINK_VERIFICATION.md | 154 +++ DOCS/PDF_PREVIEW_AND_POLL_FIX.md | 237 ++++ DOCS/RICH_TEXT_EDITOR_IMAGE_FIX.md | 176 +++ cache/blogs/articles.json | 39 - ...d9f0-bfa0-4928-a9b6-936140168f58_info.json | 1 - ...9f0-bfa0-4928-a9b6-936140168f58_table.json | 1 - cache/prefetch/articles.json | 1 - cache/prefetch/articles.json.hdr | 1 - cache/prefetch/competition_aliases.json | 1 - cache/prefetch/competition_aliases.json.hdr | 1 - cache/prefetch/events_upcoming.json | 1 - cache/prefetch/events_upcoming.json.hdr | 1 - cache/prefetch/facr_club_info.json | 1 - cache/prefetch/facr_club_info.json.hdr | 1 - cache/prefetch/facr_tables.json | 1 - cache/prefetch/facr_tables.json.hdr | 1 - cache/prefetch/gallery.json | 1 - cache/prefetch/meta.json | 1 - cache/prefetch/prefetch_status.json | 47 - cache/prefetch/settings.json | 1 - cache/prefetch/settings.json.hdr | 1 - cache/prefetch/sponsors.json | 1 - cache/prefetch/sponsors.json.hdr | 1 - cache/prefetch/team_logo_overrides.json | 1 - cache/prefetch/team_logo_overrides.json.hdr | 1 - cache/prefetch/youtube_channel.json | 1 - cache/prefetch/youtube_channel.json.hdr | 1 - cache/prefetch/zonerama/picks.json | 11 - cache/prefetch/zonerama_albums.json | 102 -- cache/prefetch/zonerama_flat.json | 1 - cache/prefetch/zonerama_flat.json.hdr | 4 - cache/prefetch/zonerama_profile.json | 1071 ----------------- .../components/common/CustomRichEditor.tsx | 50 +- .../src/components/common/FilePreview.tsx | 70 +- .../components/home/CompetitionMatches.tsx | 30 +- .../src/components/home/MatchesSection.tsx | 30 +- frontend/src/pages/CalendarPage.tsx | 25 +- frontend/src/pages/MatchesPage.tsx | 23 +- .../src/pages/admin/ArticlesAdminPage.tsx | 167 ++- .../controllers/poll_controller_refactored.go | 4 +- 41 files changed, 981 insertions(+), 1376 deletions(-) create mode 100644 DOCS/BLOG_MATCH_LINK_FIX.md create mode 100644 DOCS/BLOG_MATCH_LINK_VERIFICATION.md create mode 100644 DOCS/PDF_PREVIEW_AND_POLL_FIX.md create mode 100644 DOCS/RICH_TEXT_EDITOR_IMAGE_FIX.md delete mode 100644 cache/blogs/articles.json delete mode 100644 cache/facr/football_7eacd9f0-bfa0-4928-a9b6-936140168f58_info.json delete mode 100644 cache/facr/football_7eacd9f0-bfa0-4928-a9b6-936140168f58_table.json delete mode 100644 cache/prefetch/articles.json delete mode 100644 cache/prefetch/articles.json.hdr delete mode 100644 cache/prefetch/competition_aliases.json delete mode 100644 cache/prefetch/competition_aliases.json.hdr delete mode 100644 cache/prefetch/events_upcoming.json delete mode 100644 cache/prefetch/events_upcoming.json.hdr delete mode 100644 cache/prefetch/facr_club_info.json delete mode 100644 cache/prefetch/facr_club_info.json.hdr delete mode 100644 cache/prefetch/facr_tables.json delete mode 100644 cache/prefetch/facr_tables.json.hdr delete mode 100644 cache/prefetch/gallery.json delete mode 100644 cache/prefetch/meta.json delete mode 100644 cache/prefetch/prefetch_status.json delete mode 100644 cache/prefetch/settings.json delete mode 100644 cache/prefetch/settings.json.hdr delete mode 100644 cache/prefetch/sponsors.json delete mode 100644 cache/prefetch/sponsors.json.hdr delete mode 100644 cache/prefetch/team_logo_overrides.json delete mode 100644 cache/prefetch/team_logo_overrides.json.hdr delete mode 100644 cache/prefetch/youtube_channel.json delete mode 100644 cache/prefetch/youtube_channel.json.hdr delete mode 100644 cache/prefetch/zonerama/picks.json delete mode 100644 cache/prefetch/zonerama_albums.json delete mode 100644 cache/prefetch/zonerama_flat.json delete mode 100644 cache/prefetch/zonerama_flat.json.hdr delete mode 100644 cache/prefetch/zonerama_profile.json diff --git a/DOCS/BLOG_MATCH_LINK_FIX.md b/DOCS/BLOG_MATCH_LINK_FIX.md new file mode 100644 index 0000000..9303253 --- /dev/null +++ b/DOCS/BLOG_MATCH_LINK_FIX.md @@ -0,0 +1,94 @@ +# Blog Match Link Fix + +## Problem +When creating a new blog article with a match link in the admin panel, the match link was not being saved to the database. The article was created successfully, but the association with the FACR match was lost. + +## Root Cause +The match linking logic was placed in the React Query mutation's `onSuccess` callback. When the page re-rendered after article creation (especially when invalidating queries), a React error #310 was occurring, which interrupted the `onSuccess` callback before the match linking API call could complete. + +## Solution +Moved the match linking logic from the mutation's `onSuccess` callback directly into the `onSubmit` function. This ensures the match linking happens synchronously after article creation, before the modal closes and queries are invalidated. + +### Changes Made + +#### 1. Match Linking in `onSubmit` Function +**File**: `frontend/src/pages/admin/ArticlesAdminPage.tsx` + +- For **new articles**: After `createArticle()` completes, immediately call `putArticleMatchLink()` with the new article ID +- For **existing articles**: After `updateArticle()` completes, call `putArticleMatchLink()` to update or create the link +- All match linking now happens within the same try-catch block as article creation/update +- Modal only closes after all operations complete successfully + +#### 2. Simplified Mutation Callbacks +- `createMut.onSuccess`: Only handles query invalidation and state cleanup +- `updateMut.onSuccess`: Only handles query invalidation +- Removed duplicate match linking code from callbacks +- Success toasts moved to `onSubmit` after all operations complete + +#### 3. Enhanced Error Handling +- Added try-catch blocks around match linking API calls +- Separate error messages for article creation vs. match linking failures +- If article creation succeeds but match linking fails, user gets a warning toast with instructions +- All errors logged to console for debugging + +#### 4. Added Debug Logging +- Log match link state before submission +- Log article creation success +- Log match linking attempts and results +- Helps diagnose issues in production + +#### 5. Fixed `MatchLinkBadge` Loading State +- Added loading state check to prevent React errors when refetching +- Shows "Načítání..." badge while match link data is loading + +## Testing Instructions + +### Test 1: Create New Article with Match Link +1. Go to Admin → Články +2. Click "Nový článek" +3. Fill in required fields (Název, Kategorie) +4. Switch to "Základní" tab +5. Select a match from the picker +6. Click "Uložit" +7. **Expected**: Toast shows "Článek vytvořen a propojen se zápasem" +8. **Verify**: Article list shows match badge with match details + +### Test 2: Create Article Without Match Link +1. Create article without selecting a match +2. **Expected**: Toast shows "Článek byl úspěšně vytvořen" +3. **Verify**: Article list shows "Nepropojeno" badge + +### Test 3: Update Existing Article Match Link +1. Open existing article for editing +2. Select a different match +3. Click "Uložit" +4. **Expected**: Toast shows "Článek aktualizován a propojen se zápasem" +5. **Verify**: Badge updates to show new match + +### Test 4: Match Linking Failure (Backend Error) +1. Simulate backend error (e.g., stop backend) +2. Try to create article with match link +3. **Expected**: Toast shows "Článek vytvořen, ale propojení se zápasem selhalo" +4. **Verify**: Article is created but without match link + +## API Endpoints Used +- `POST /api/v1/articles` - Create article +- `PUT /api/v1/articles/:id` - Update article +- `POST /api/v1/articles/:id/match-link` - Create/update match link +- `GET /api/v1/articles/:id/match-link` - Get match link (for badge display) +- `DELETE /api/v1/articles/:id/match-link` - Delete match link + +## Database Tables +- `articles` - Main article data +- `article_match_links` - Junction table linking articles to FACR match IDs + +## State Management +- `tempMatchLink` - Stores selected match ID for new articles +- `matchIdInput` - Stores selected match ID (UI input) +- `linkedMatchId` - Stores confirmed linked match ID after successful save + +## Future Improvements +- Consider adding optimistic updates to show match link immediately +- Add bulk match linking for multiple articles +- Show match preview in article form before saving +- Add match link history/audit log diff --git a/DOCS/BLOG_MATCH_LINK_VERIFICATION.md b/DOCS/BLOG_MATCH_LINK_VERIFICATION.md new file mode 100644 index 0000000..87e586e --- /dev/null +++ b/DOCS/BLOG_MATCH_LINK_VERIFICATION.md @@ -0,0 +1,154 @@ +# Blog Match Link Fix - Verification Checklist + +## Issue Summary +**Problem**: When creating a blog article and selecting a match from the "Propojit se zápasem" section, the match ID was not being saved to the database. + +**User Evidence**: Console log showed: +```javascript +Saving article with payload: { + "title": "U17: Rýmařov...", + "category_name": "KALMAN TRADE Krajský přebor mladší dorost", + // ... other fields ... + // ❌ NO match_id field in payload +} +``` + +## Fix Applied + +### Technical Changes +1. **Moved match linking from async callback to synchronous flow** + - Previous: Match linking happened in `createMut.onSuccess` callback (after article creation) + - New: Match linking happens in `onSubmit` function (immediately after article creation completes) + - Benefit: Prevents race conditions and React error interruptions + +2. **Added comprehensive error handling** + - Separate try-catch blocks for article save and match linking + - Clear user feedback for each operation + - Logging at each step for debugging + +3. **Fixed React error #310** + - Added loading state to `MatchLinkBadge` component + - Prevents rendering errors during query refetch + +## Verification Steps + +### 1. Check Console Logs +After applying the fix, when creating an article with a match link, you should see: +``` +Match link state before submit: { + tempMatchLink: "12345", + matchIdInput: "12345", + linkedMatchId: "", + isNewArticle: true +} +Linking new article 42 with match 12345 +Match link created for new article +``` + +### 2. Check Toast Messages +- ✅ Success: "Článek vytvořen a propojen se zápasem" (with Match ID) +- ⚠️ Partial Success: "Článek vytvořen, ale propojení se zápasem selhalo" + +### 3. Check Database +Query to verify match link was saved: +```sql +SELECT * FROM article_match_links WHERE article_id = [NEW_ARTICLE_ID]; +``` +Should return: +- `article_id`: The ID of the newly created article +- `external_match_id`: The FACR match ID (e.g., "12345") +- `title`: The article title + +### 4. Check Article List UI +- Badge should show: "Zápas: [Home Team] [Score] [Away Team]" in green (if match has score) or yellow (if no score yet) +- Should NOT show: "Nepropojeno" in gray + +### 5. Check API Response +The article creation response should include match_link: +```json +{ + "id": 42, + "title": "U17: Rýmařov...", + "match_link": { + "article_id": 42, + "external_match_id": "12345", + "title": "U17: Rýmařov..." + } +} +``` + +## Test Scenarios + +### Scenario A: New Article with Match +1. Open Admin → Články → Nový článek +2. Fill in title: "Test článek" +3. Select category: "KALMAN TRADE Krajský přebor mladší dorost" +4. Click on a match in the match picker +5. Click "Uložit" +6. **Expected**: Green toast with match ID +7. **Verify**: List shows match badge with team names + +### Scenario B: New Article without Match +1. Create article without selecting match +2. **Expected**: Standard success toast +3. **Verify**: List shows "Nepropojeno" badge + +### Scenario C: Edit Existing Article, Add Match +1. Open existing article +2. Select a match +3. Click "Uložit" +4. **Expected**: Success toast with match info +5. **Verify**: Badge updates immediately + +### Scenario D: Edit Existing Article, Change Match +1. Open article that already has a match +2. Select different match +3. Click "Uložit" +4. **Expected**: Success toast +5. **Verify**: Badge shows new match + +### Scenario E: Backend Error Handling +1. Stop backend server +2. Try to create article with match +3. **Expected**: Article created locally, warning toast about match linking failure +4. Restart backend +5. **Verify**: Can manually link match by editing article + +## Code Changes Summary + +### Files Modified +1. `/frontend/src/pages/admin/ArticlesAdminPage.tsx` + - Lines 40-43: Added loading state to MatchLinkBadge + - Lines 655-673: Simplified createMut.onSuccess + - Lines 686-702: Simplified updateMut.onSuccess + - Lines 928-987: Refactored onSubmit with inline match linking + +### Files Created +1. `/DOCS/BLOG_MATCH_LINK_FIX.md` - Detailed fix documentation +2. `/DOCS/BLOG_MATCH_LINK_VERIFICATION.md` - This file + +## Rollback Plan +If issues occur, revert the ArticlesAdminPage.tsx changes: +```bash +git checkout HEAD -- frontend/src/pages/admin/ArticlesAdminPage.tsx +``` + +## Performance Impact +- No performance degradation +- Actually improved: One less async operation in mutation callback +- Better user experience: Immediate feedback on match linking status + +## Browser Compatibility +- No new browser APIs used +- Compatible with all modern browsers (Chrome, Firefox, Safari, Edge) +- React Query handles all async state management + +## Known Limitations +- Match linking requires article to be saved first (can't preview match before save) +- If backend is down, match link won't be saved (fails gracefully) +- Maximum 100 matches shown in picker (performance optimization) + +## Related Documentation +- `DOCS/BLOG_CREATION_FIXED.md` - Previous blog creation fixes +- `DOCS/FACR_INTEGRATION.md` - FACR match data integration +- `DOCS/ADMIN_QUICK_REFERENCE.md` - Admin panel overview diff --git a/DOCS/PDF_PREVIEW_AND_POLL_FIX.md b/DOCS/PDF_PREVIEW_AND_POLL_FIX.md new file mode 100644 index 0000000..b0d33ea --- /dev/null +++ b/DOCS/PDF_PREVIEW_AND_POLL_FIX.md @@ -0,0 +1,237 @@ +# PDF Preview and Poll Creation Fix + +## Issues Fixed + +### 1. PDF Preview Not Working (Blank Screen) +**Problem**: When trying to preview PDF files, the screen was blank due to Content Security Policy (CSP) restrictions blocking iframe embedding. + +**Root Cause**: CSP header `frame-ancestors 'self'` prevented PDF files from being embedded in iframes. + +**Solution**: Enhanced `FilePreview.tsx` component with multiple fallback options: +- Primary: Direct iframe embed (works if CSP allows) +- Fallback buttons: + - Open in new window + - View with Mozilla PDF.js + - View via Google Docs Viewer + - Download PDF + +### 2. Poll Creation Requires Saved Article +**Problem**: Users couldn't create or link polls to articles until the article was saved first. The UI showed "Nejprve uložte článek" (Save article first). + +**Root Cause**: `PollLinker` component requires an `articleId` which only exists after the article is saved. + +**Solution**: +- Added "Save as draft and add polls" button +- Modified `onSubmit` function to support `keepOpen` option +- After saving, modal stays open and switches to Poll tab automatically +- Article is saved as draft (published=true by default, but can be unpublished) + +## Files Modified + +### `/frontend/src/components/common/FilePreview.tsx` +**Lines changed**: 124-189 + +**What changed**: +- Wrapped PDF iframe in a VStack with fallback options +- Added 4 alternative viewing methods +- Added helpful message when PDF doesn't display +- Added error handler to iframe + +**Key improvements**: +```tsx +// Before: Simple iframe only +