6.9 KiB
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
onSubmitfunction to supportkeepOpenoption - 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:
// Before: Simple iframe only
<iframe src={`${fullUrl}#view=FitH`} />
// After: Iframe + fallback buttons
<VStack>
<Box>
<iframe src={`${fullUrl}#view=FitH&toolbar=1`} />
</Box>
<HStack>
<Button href={fullUrl}>Open in new window</Button>
<Button href={pdfjs_url}>View with PDF.js</Button>
<Button href={google_viewer_url}>View via Google</Button>
<Button download>Download PDF</Button>
</HStack>
</VStack>
/frontend/src/pages/admin/ArticlesAdminPage.tsx
Lines changed:
- 852: Modified
onSubmitfunction signature - 994-997: Added conditional modal closing
- 1840-1870: Enhanced Poll tab UI
What changed:
-
Modified
onSubmitfunction:// Before const onSubmit = async () => { ... } // After const onSubmit = async (options: { keepOpen?: boolean } = {}) => { // ... save logic ... if (!options.keepOpen) { closeModal(); } } -
Updated Poll tab:
- Changed from "info" alert to "warning" alert
- Added "Save as draft and add polls" button
- Button calls
onSubmit({ keepOpen: true }) - After save, switches to Poll tab:
setActiveTabIndex(5)
Testing Instructions
Test 1: PDF Preview
-
Upload PDF to article:
- Go to Admin → Články → Edit article
- Go to "Média" tab
- Upload a PDF file in attachments
-
Test preview:
- Click "Náhled" button
- Expected: Modal opens with PDF preview
- If PDF doesn't show: Fallback buttons appear
- Click "Otevřít v novém okně" - PDF opens in new tab
- Click "Zobrazit pomocí PDF.js" - PDF opens in Mozilla viewer
- Click "Zobrazit přes Google" - PDF opens in Google Docs viewer
- Click "Stáhnout PDF" - PDF downloads
Test 2: Poll Creation for New Article
-
Create new article:
- Go to Admin → Články → Nový článek
- Fill in title and category
- Go to "Anketa" tab
-
See warning message:
- Expected: Orange warning box with "Článek ještě není uložen"
- Button: "Uložit jako koncept a přidat ankety"
-
Save as draft:
- Click the button
- Expected:
- Article saves successfully
- Modal stays open
- Tab switches to Poll tab (still showing)
- PollLinker component now visible
- Can create/link polls
-
Create poll:
- Click "Vytvořit novou" tab
- Fill in poll title and options
- Click "Vytvořit anketu"
- Expected: Poll created and linked to article
Test 3: Poll Creation for Existing Article
-
Edit existing article:
- Go to Admin → Články → Edit article
- Go to "Anketa" tab
-
Expected: PollLinker shows immediately (no warning)
-
Create or link polls as normal
Technical Details
PDF Viewing Methods
-
Direct iframe (default):
<iframe src="/uploads/file.pdf#view=FitH&toolbar=1" />- Works if CSP allows
- Fastest method
- Native browser PDF viewer
-
Mozilla PDF.js (fallback 1):
https://mozilla.github.io/pdf.js/web/viewer.html?file=<encoded_url>- Works even with strict CSP
- JavaScript-based PDF renderer
- Requires internet connection
-
Google Docs Viewer (fallback 2):
https://docs.google.com/viewer?url=<encoded_url>&embedded=true- Requires public URL
- May have privacy concerns
- Reliable for most PDFs
-
Direct download (fallback 3):
- Always works
- User opens in their PDF app
Poll Creation Flow
New Article (no ID yet)
↓
User clicks "Save as draft and add polls"
↓
onSubmit({ keepOpen: true })
↓
Article created in database
↓
Modal stays open (closeModal not called)
↓
setActiveTabIndex(5) - Switch to Poll tab
↓
PollLinker now has articleId
↓
User can create/link polls
Known Limitations
PDF Preview
- PDF.js fallback requires internet connection
- Google Viewer requires publicly accessible URLs
- Some browsers may block cross-origin iframes
- Very large PDFs (>10MB) may be slow
Poll Creation
- Article must still be saved before linking polls (can't be fully offline)
- "Keep open" mode doesn't work if there's a network error
- If save fails, modal closes and poll tab doesn't appear
Browser Compatibility
PDF Preview
- ✅ Chrome/Edge: Native PDF viewer works
- ✅ Firefox: Native PDF viewer works
- ✅ Safari: Native PDF viewer works
- ✅ All browsers: Fallback buttons work
Poll Creation
- ✅ All modern browsers (Chrome, Firefox, Safari, Edge)
- ✅ Mobile browsers
Future Improvements
PDF Preview
- Add PDF.js embed directly in application (no external CDN)
- Add thumbnail generation for PDFs
- Add page navigation controls
- Add zoom controls
- Add print button
Poll Creation
- Allow poll creation before article save (store in temp state)
- Add poll preview in article form
- Bulk poll creation/linking
- Poll templates
Related Files
frontend/src/components/common/FilePreview.tsx- PDF preview componentfrontend/src/components/admin/PollLinker.tsx- Poll management componentfrontend/src/pages/admin/ArticlesAdminPage.tsx- Article editorinternal/controllers/base_controller.go- Backend file upload handler
API Endpoints
POST /api/v1/upload- File upload (including PDFs)GET /uploads/**- Serve uploaded filesPOST /api/v1/polls- Create pollPUT /api/v1/polls/:id- Update poll (link to article)GET /api/v1/polls?article_id=X- Get polls for article