Migrate PDF.js to DevExpress DxPdfViewer
Transitioned PDF rendering in `EnvelopeReceiverPage.razor` from `PDF.js` to `DevExpress DxPdfViewer`. Updated code and documentation to reflect the verified API of `DevExpress.Blazor.PdfViewer` v25.2.3, addressing its limitations (e.g., lack of `GoToPageAsync`, `PageNumberChanged`). Implemented `CustomizeToolbar` for navigation/zoom controls and manual state tracking for `_currentPage` and `_viewerZoomLevel`. Replaced JavaScript interop for page count with the `PageCount` property. Retained the custom thumbnail sidebar due to API constraints. Added temporary debug tools for DOM analysis and navigation testing. Updated `TESTING_CHECKLIST.md` and added `DEVEXPRESS_V25_LIMITATIONS.md` to document the new strategy, API limitations, and testing scenarios. Cross-page signature navigation implemented with state updates, though visible page changes remain manual. Prepared for future improvements while ensuring functional migration to `DxPdfViewer`.
This commit is contained in:
300
DEBUG_NOTES.md
Normal file
300
DEBUG_NOTES.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# Debug Tools for DevExpress DxPdfViewer Integration
|
||||
|
||||
## Purpose
|
||||
This document describes temporary debug tools added to diagnose DevExpress DOM structure and page navigation issues.
|
||||
|
||||
## IMPORTANT: TEMPORARY DEBUG CODE
|
||||
|
||||
**These debug tools are TEMPORARY and should be REMOVED after resolving the page navigation issue.**
|
||||
|
||||
---
|
||||
|
||||
## Debug Tools Added
|
||||
|
||||
### 1. Debug UI Button (Toolbar)
|
||||
|
||||
**Location:** `EnvelopeReceiverPage.razor` - Toolbar Section
|
||||
|
||||
**Visual:** Orange button with "?" icon in the PDF viewer toolbar
|
||||
|
||||
**What it does:**
|
||||
- Opens a floating overlay panel showing DevExpress DOM analysis
|
||||
- Displays all input elements found in DxPdfViewer
|
||||
- Shows which CSS selectors successfully find the page input
|
||||
- Provides a "Test: Go to Page 2" button for live testing
|
||||
|
||||
**Code Location:**
|
||||
```razor
|
||||
@* DEBUG: DevExpress DOM Inspector *@
|
||||
<div class="pdf-toolbar__section">
|
||||
<button class="pdf-toolbar__btn" @onclick="ShowDebugUI" ...>
|
||||
```
|
||||
|
||||
**C# Method:**
|
||||
```csharp
|
||||
async Task ShowDebugUI()
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("dxPdfViewerShowDebugUI");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. JavaScript Debug Functions
|
||||
|
||||
**Location:** `pdf-viewer.js`
|
||||
|
||||
**Functions Added:**
|
||||
|
||||
#### `window.dxPdfViewerDebugDOM()`
|
||||
- Console-based debug function
|
||||
- Logs detailed DOM analysis to browser console
|
||||
- Returns analysis object for programmatic inspection
|
||||
|
||||
#### `window.dxPdfViewerShowDebugUI()`
|
||||
- HTML overlay-based debug function
|
||||
- Creates visual debug panel without console interaction
|
||||
- No security warnings (no need to paste code)
|
||||
|
||||
---
|
||||
|
||||
## How to Use
|
||||
|
||||
### Step 1: Run Application
|
||||
```powershell
|
||||
dotnet run --project EnvelopeGenerator.Server/EnvelopeGenerator.Server
|
||||
```
|
||||
|
||||
### Step 2: Open Receiver Page
|
||||
Navigate to: `https://localhost:8088/envelope/{EnvelopeKey}`
|
||||
|
||||
### Step 3: Click Debug Button
|
||||
- Look for the **orange "?" button** in the PDF toolbar (left side, after thumbnails toggle)
|
||||
- Click it to open the debug overlay
|
||||
|
||||
### Step 4: Review Debug Information
|
||||
|
||||
The overlay shows:
|
||||
- **Total Inputs**: Number of input elements found
|
||||
- **Input Elements**: Details of each input (type, class, ID, value)
|
||||
- **Selector Tests**: Which CSS selectors work (✓) and which don't (✗)
|
||||
- **Toolbar**: Whether toolbar element was found
|
||||
- **DxWidget**: Whether DevExpress widget element was found
|
||||
|
||||
### Step 5: Test Page Navigation
|
||||
Click the **"Test: Go to Page 2"** button in the overlay
|
||||
|
||||
### Step 6: Report Results
|
||||
|
||||
**Copy the following information:**
|
||||
|
||||
1. **Total Inputs**: X
|
||||
2. **Input Details**: (type, className, id for each input)
|
||||
3. **Selector Test Results**: (which selectors show ✓ FOUND)
|
||||
4. **Test Result**: Did PDF actually navigate to page 2? (Yes/No)
|
||||
5. **Console Messages**: Any errors or warnings in F12 console
|
||||
|
||||
---
|
||||
|
||||
## What to Look For
|
||||
|
||||
### ✓ Success Indicators
|
||||
- At least one selector shows **✓ FOUND**
|
||||
- "Test: Go to Page 2" button actually changes PDF page
|
||||
- Console shows: `✓ Found page input with selector: "..."`
|
||||
|
||||
### ✗ Problem Indicators
|
||||
- All selectors show **✗ NOT FOUND**
|
||||
- "Test: Go to Page 2" does nothing
|
||||
- Console shows: `✗ Page input not found`
|
||||
|
||||
---
|
||||
|
||||
## After Diagnosis
|
||||
|
||||
Once the correct selector is identified:
|
||||
|
||||
### 1. Update `window.dxPdfViewerGoToPage()`
|
||||
Update the `selectors` array in `pdf-viewer.js` to prioritize the working selector:
|
||||
|
||||
```javascript
|
||||
const selectors = [
|
||||
'WORKING_SELECTOR_HERE', // ✓ Move this to top
|
||||
'input[type="number"]',
|
||||
// ... rest
|
||||
];
|
||||
```
|
||||
|
||||
### 2. Remove Debug Code
|
||||
|
||||
**Files to clean up:**
|
||||
|
||||
#### `EnvelopeReceiverPage.razor`
|
||||
Remove:
|
||||
```razor
|
||||
@* DEBUG: DevExpress DOM Inspector *@
|
||||
<div class="pdf-toolbar__section">
|
||||
<button class="pdf-toolbar__btn" @onclick="ShowDebugUI" ...>
|
||||
</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
Remove C# method:
|
||||
```csharp
|
||||
async Task ShowDebugUI() { ... }
|
||||
```
|
||||
|
||||
#### `pdf-viewer.js`
|
||||
Remove:
|
||||
```javascript
|
||||
// ⚠ AUTO-DEBUG: Display results in HTML overlay
|
||||
window.dxPdfViewerShowDebugUI = function() { ... }
|
||||
```
|
||||
|
||||
Keep:
|
||||
- `window.dxPdfViewerDebugDOM()` - can be useful for future debugging (optional)
|
||||
- `window.dxPdfViewerGoToPage()` - this is permanent (after fixing selector)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Debug UI doesn't open
|
||||
- Check browser console (F12) for JavaScript errors
|
||||
- Ensure `pdf-viewer.js` is loaded
|
||||
- Verify DxPdfViewer has finished rendering
|
||||
|
||||
### "Page input not found" error
|
||||
- DevExpress may not have rendered toolbar yet
|
||||
- Try waiting 2-3 seconds after page load
|
||||
- Check if DxPdfViewer is visible on screen
|
||||
|
||||
### Selector works but page doesn't change
|
||||
- DevExpress may require different event sequence
|
||||
- Try adding more events (focus, click, etc.)
|
||||
- May need to find DevExpress client API instead
|
||||
|
||||
---
|
||||
|
||||
## SOLUTION: CustomizeToolbar + Manual State Tracking
|
||||
|
||||
**Identified root cause:**
|
||||
- DevExpress v25.2.3 has no event support
|
||||
- `PageNumberChanged` event does not exist
|
||||
- `ZoomLevelChanged` event does not exist
|
||||
- `ToolbarVisible` property does not exist
|
||||
- `GoToPageAsync()` method does not exist
|
||||
- Only `CustomizeToolbar` event is available
|
||||
|
||||
**Verified working API (v25.2.3):**
|
||||
- `DocumentContent` byte[] – for feeding PDF ✓
|
||||
- `ZoomLevel` double – zoom factor (1.5 = 150%) ✓
|
||||
- `IsSinglePagePreview` bool – single page mode ✓
|
||||
- `PageCount` int (GET only) – **replaces JS call** ✓
|
||||
- `ActivePageIndex` int (GET only) – current page index ✓
|
||||
- `CssClass`, `DocumentName`, `SizeMode` ✓
|
||||
|
||||
**Implemented strategy:**
|
||||
- Create custom navigation/zoom buttons via `CustomizeToolbar`
|
||||
- Manual state tracking with `_currentPage`, `_currentZoom`, `_viewerZoomLevel`
|
||||
- Manually trigger overlay refresh after button clicks
|
||||
- Replace JS getTotalPages() call with `_totalPages = _pdfViewer.PageCount`
|
||||
|
||||
**Correct code example:**
|
||||
|
||||
```csharp
|
||||
protected void OnCustomizeToolbar(ToolbarModel toolbarModel)
|
||||
{
|
||||
toolbarModel.AllItems.Clear();
|
||||
|
||||
var prevButton = new ToolbarItem
|
||||
{
|
||||
Text = "Previous",
|
||||
IconCssClass = "dx-icon-chevronprev",
|
||||
Enabled = _currentPage > 1,
|
||||
Click = async (args) =>
|
||||
{
|
||||
if (_currentPage > 1)
|
||||
{
|
||||
_currentPage--;
|
||||
_viewerZoomLevel = _currentZoom / 100d; // 150 -> 1.5
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var nextButton = new ToolbarItem
|
||||
{
|
||||
Text = "Next",
|
||||
IconCssClass = "dx-icon-chevronnext",
|
||||
Enabled = _currentPage < _totalPages,
|
||||
Click = async (args) =>
|
||||
{
|
||||
if (_currentPage < _totalPages)
|
||||
{
|
||||
_currentPage++;
|
||||
_viewerZoomLevel = _currentZoom / 100d; // 150 -> 1.5
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
toolbarModel.AllItems.Add(prevButton);
|
||||
toolbarModel.AllItems.Add(nextButton);
|
||||
}
|
||||
```
|
||||
|
||||
**PageCount usage (instead of JS):**
|
||||
|
||||
```csharp
|
||||
// In OnAfterRenderAsync
|
||||
if (_pdfViewer is not null && _pdfViewer.PageCount > 0)
|
||||
{
|
||||
_totalPages = _pdfViewer.PageCount; // JS getTotalPages() no longer needed
|
||||
_pdfLoaded = true;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
```
|
||||
|
||||
**Known limitations:**
|
||||
1. If user scrolls PDF, C# receives no notification, overlays may desync
|
||||
2. Thumbnail navigation only updates state, cannot move viewer
|
||||
3. Cross-page signature navigation limited without programmatic page switching
|
||||
|
||||
**See:** `DEVEXPRESS_V25_LIMITATIONS.md` – complete verified API reference
|
||||
|
||||
---
|
||||
|
||||
## Expected Timeline
|
||||
|
||||
1. ✓ **Day 1**: Add debug tools (DONE)
|
||||
2. ✓ **Day 1**: Collect DOM analysis data (DONE)
|
||||
3. ✓ **Day 1**: Identify root cause (DONE - v25.2.3 has no events)
|
||||
4. ✓ **Day 1**: Define workaround strategy (DONE - Custom toolbar with manual tracking)
|
||||
5. ✓ **Day 1**: Implement workaround (DONE)
|
||||
6. ⚠ **Day 2**: Test and document limitations
|
||||
7. ⚠ **Day 2**: Consider DevExpress upgrade or accept limitations
|
||||
|
||||
---
|
||||
|
||||
## Related Files
|
||||
|
||||
- `EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeReceiverPage.razor`
|
||||
- `EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/js/pdf-viewer.js`
|
||||
- `RECEIVER_PDF_VIEWER_CONTEXT.md` (main context document - **UPDATED with new strategy**)
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Debug UI uses inline styles to avoid CSS conflicts
|
||||
- Overlay is positioned at `z-index: 99999` to appear above everything
|
||||
- Close button removes overlay from DOM completely
|
||||
- All debug output also goes to browser console for advanced inspection
|
||||
- **Debug findings led to complete strategy change - see RECEIVER_PDF_VIEWER_CONTEXT.md section 12-14**
|
||||
|
||||
---
|
||||
|
||||
**Remember: This is TEMPORARY debugging code. Delete after completing the new implementation strategy!**
|
||||
Reference in New Issue
Block a user