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`.
301 lines
8.4 KiB
Markdown
301 lines
8.4 KiB
Markdown
# 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!**
|