- Architecture overview (Blazor Auto Server+WASM hybrid) - Critical development commands (both API and WebUI must run) - Route structure with render mode requirements - Coordinate system conversions (INCHES in DB) - API architecture quirks and missing endpoints - Status color coding from legacy VB.NET app - Common mistakes to avoid - Configuration locations and migration status
264 lines
8.5 KiB
Markdown
264 lines
8.5 KiB
Markdown
# EnvelopeGenerator - Agent Guide
|
||
|
||
## Must Read First
|
||
- **`COPILOT_CONTEXT.md`** - Architecture, coordinate systems, migration status
|
||
- **`FORM_APPLICATION_CONTEXT.md`** - Legacy VB.NET features to migrate
|
||
|
||
## Active Architecture (Post-Migration)
|
||
|
||
**Frontend:** Blazor Auto (Server+WASM hybrid)
|
||
- **WebUI** (Server): `@rendermode InteractiveServer` - PDF viewers requiring DevExpress backend
|
||
- **WebUI.Client** (WASM): `@rendermode InteractiveWebAssembly` - Login, dashboards, business logic
|
||
|
||
**Backend:** EnvelopeGenerator.API (ASP.NET Core 8.0)
|
||
|
||
**Proxy:** YARP in WebUI routes `/api/*` → `localhost:8088` (API)
|
||
|
||
### Deprecated Projects - DO NOT USE
|
||
- `EnvelopeGenerator.ReceiverUI` - Pure WASM (migrated to WebUI)
|
||
- `EnvelopeGenerator.Web` - Razor Pages (replaced by WebUI)
|
||
- **VB.NET projects** (`Form`, `Service`, `BBTests`) - Legacy, read-only for reference
|
||
|
||
## Development Commands
|
||
|
||
### Run Both Projects (Required)
|
||
```powershell
|
||
# Terminal 1 - API Backend
|
||
cd EnvelopeGenerator.API
|
||
dotnet run
|
||
|
||
# Terminal 2 - Blazor Frontend
|
||
cd EnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI
|
||
dotnet run
|
||
```
|
||
|
||
**Critical:** Both must run simultaneously. WebUI proxy forwards `/api/*` to API.
|
||
|
||
### Build
|
||
```powershell
|
||
dotnet build EnvelopeGenerator.sln
|
||
```
|
||
|
||
## Project Boundaries
|
||
|
||
```
|
||
EnvelopeGenerator.Domain/ # Entities (Envelope, Receiver, Document, etc.)
|
||
EnvelopeGenerator.Application/ # MediatR CQRS (Commands, Queries, Handlers)
|
||
EnvelopeGenerator.Infrastructure/ # EF Core, SQL executors, repositories
|
||
EnvelopeGenerator.API/ # Controllers, endpoints
|
||
EnvelopeGenerator.WebUI/ # Server-side Blazor components
|
||
├─ Components/Pages/ # @rendermode InteractiveServer
|
||
EnvelopeGenerator.WebUI.Client/ # Client-side WASM components
|
||
├─ Pages/ # @rendermode InteractiveWebAssembly
|
||
├─ Services/ # HTTP API clients
|
||
├─ Models/ # DTOs
|
||
```
|
||
|
||
## Route Structure (Critical)
|
||
|
||
| Route | File Location | Render Mode | Purpose |
|
||
|-------|--------------|-------------|---------|
|
||
| `/` | `WebUI.Client/Pages/Index.razor` | WASM | Landing page |
|
||
| `/sender/login` | `WebUI.Client/Pages/LoginSenderPage.razor` | WASM | Sender auth |
|
||
| `/sender` | `WebUI.Client/Pages/EnvelopeSenderPage.razor` | WASM | Sender dashboard |
|
||
| `/envelope/login/{key}` | `WebUI.Client/Pages/LoginReceiverPage.razor` | WASM | Receiver auth |
|
||
| `/envelope/{key}` | `WebUI/Components/Pages/EnvelopeReceiverPage.razor` | **Server** | PDF viewer + signing |
|
||
|
||
**Rule:** PDF viewers MUST use `@rendermode InteractiveServer` (DevExpress backend requirement). Everything else uses WASM.
|
||
|
||
## Coordinate System (CRITICAL)
|
||
|
||
**Database stores INCHES** (GdPicture14 native). Origin: top-left, Y-axis down.
|
||
|
||
### Conversions
|
||
```csharp
|
||
// Database (INCHES) → PDF Points
|
||
float points = inches * 72;
|
||
|
||
// Database (INCHES) → DevExpress DX
|
||
float dx = inches * 100;
|
||
|
||
// PDF.js Pixels → Database (INCHES)
|
||
float inches = (pixelX / canvasWidth) * pageWidthInches;
|
||
```
|
||
|
||
**A4 Page:** 8.27" wide × 11.69" tall = 595pt × 842pt
|
||
|
||
**Signature Field Size:** 1.77" × 1.96" (FIXED, do not change)
|
||
|
||
**Evidence:** See `COPILOT_CONTEXT.md` lines 158-185, `EnvelopeGenerator.Form/frmFieldEditor.vb`
|
||
|
||
## API Architecture Quirks
|
||
|
||
### Monolithic Endpoint (Avoid for UI)
|
||
`POST /api/EnvelopeReceiver` - Creates envelope+document+receivers+fields atomically.
|
||
- **Use case:** External API consumers
|
||
- **Not suitable for:** Step-by-step UI workflow (no draft support, no partial updates)
|
||
|
||
### Missing Granular Endpoints (Need to Create)
|
||
```
|
||
POST /api/Envelope/draft # Create draft envelope
|
||
PUT /api/Envelope/{id} # Update metadata
|
||
DELETE /api/Envelope/{id} # Delete with reason
|
||
POST /api/Envelope/{id}/document # Upload PDF
|
||
POST /api/Envelope/{id}/receivers # Add receiver
|
||
POST /api/Envelope/{id}/signature-fields # Place signature field
|
||
POST /api/Envelope/{id}/send # Send to receivers
|
||
```
|
||
|
||
See `FORM_APPLICATION_CONTEXT.md` for detailed workflow requirements.
|
||
|
||
## Status Color Coding
|
||
|
||
Form app uses DevExpress `CustomDrawCell`. WebUI needs CSS:
|
||
|
||
```css
|
||
.envelope-row.status-partly-signed { background-color: #81C784; } /* GREEN_300 */
|
||
.envelope-row.status-queued,
|
||
.envelope-row.status-sent { background-color: #FFB74D; } /* ORANGE_300 */
|
||
.envelope-row.status-completed { background-color: #81C784; }
|
||
.envelope-row.status-deleted,
|
||
.envelope-row.status-rejected { background-color: #E57373; } /* RED_300 */
|
||
```
|
||
|
||
## Configuration
|
||
|
||
### YARP Proxy (`WebUI/yarp.json`)
|
||
Routes `/api/*`, `/swagger/*`, `/openapi/*`, `/scalar/*` → `https://localhost:8088`
|
||
|
||
### PDF.js Settings (`WebUI/wwwroot/appsettings.json`)
|
||
```json
|
||
{
|
||
"PdfViewerOptions": {
|
||
"ThumbnailBaseScale": 0.75,
|
||
"ThumbnailEnableHiDPI": true,
|
||
"MainCanvasEnableHiDPI": true,
|
||
"ZoomStepPercentage": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
### API Config (`API/appsettings.json`)
|
||
- `ConnectionStrings:Default` - SQL Server DB
|
||
- `AllowedOrigins` - CORS (includes `http://localhost:5131`, `http://localhost:7192`)
|
||
- `Cache:SignatureCacheExpiration` - Signature persistence timeout
|
||
- `PSPDFKitLicenseKey` - **DEPRECATED** (use PDF.js instead)
|
||
|
||
## Migration Status
|
||
|
||
### Complete ✅
|
||
- Receiver login/authentication
|
||
- PDF viewing with PDF.js (HiDPI, zoom, thumbnails)
|
||
- Signature capture (draw/type/image)
|
||
- Signature caching (Redis/SQL)
|
||
- Sender login
|
||
|
||
### Missing (High Priority) ❌
|
||
- Sender dashboard (`/sender`) - Empty stub
|
||
- Envelope editor (`/sender/envelope/{id}`)
|
||
- Signature field placement tool (PDF.js + draggable overlays)
|
||
- Granular API endpoints (draft, receivers, fields)
|
||
- Master-detail grids for receivers/history
|
||
|
||
## Common Mistakes (DO NOT REPEAT)
|
||
|
||
| Mistake | Why Wrong |
|
||
|---------|-----------|
|
||
| Using iText7 in receiver pages | GPL license issue. Use PDF.js overlays. |
|
||
| Using PSPDFKit | Removed from architecture. Use PDF.js + DevExpress. |
|
||
| `@rendermode InteractiveWebAssembly` on PDF viewers | DevExpress DxPdfViewer requires server-side rendering. |
|
||
| Hardcoded quality in PDF.js | Use `appsettings.json` `PdfViewerOptions`. |
|
||
| Coordinates in points/pixels for DB | Database uses INCHES. Convert before save. |
|
||
| `BottomMarginBand` for signatures | Repeats on every page. Use `DetailBand`. |
|
||
|
||
## Testing
|
||
|
||
**No automated tests exist yet.**
|
||
|
||
Manual testing workflow:
|
||
1. Start API (`dotnet run` in `EnvelopeGenerator.API`)
|
||
2. Start WebUI (`dotnet run` in `EnvelopeGenerator.WebUI\EnvelopeGenerator.WebUI`)
|
||
3. Navigate to `https://localhost:5131` (or check console output for port)
|
||
4. Test sender login at `/sender/login`
|
||
5. Test receiver flow at `/envelope/login/{envelopeKey}`
|
||
|
||
## Database
|
||
|
||
**SQL Server** (DD_ECM)
|
||
- Connection string in `API/appsettings.json`
|
||
- EF Core migrations NOT used (manual SQL scripts)
|
||
- Stored procedures: `PRSIG_*` prefix
|
||
|
||
**Key Tables:**
|
||
- `TBSIG_ENVELOPE` - Envelope metadata
|
||
- `TBSIG_ENVELOPE_RECEIVER` - Receiver assignments
|
||
- `TBSIG_DOC_RECEIVER_ELEMENT` - Signature fields (X, Y in INCHES)
|
||
- `TBSIG_RECEIVER` - Receiver registry
|
||
- `TBSIG_DOCUMENT` - PDF binary data
|
||
- `TBSIG_ENVELOPE_HISTORY` - Audit trail
|
||
|
||
## DevExpress
|
||
|
||
**License:** Commercial (v25.2.3)
|
||
**Components Used:**
|
||
- `DxGrid` - Master-detail grids
|
||
- `DxPdfViewer` - Server-side PDF rendering
|
||
- `DxPopup` - Modal dialogs
|
||
- `DxToolbar` - Action bars
|
||
- `DxFormLayout` - Forms
|
||
|
||
**Theme:** Blazing Berry (default)
|
||
|
||
## JavaScript Interop
|
||
|
||
**PDF Viewer:** `wwwroot/js/pdf-viewer.js`
|
||
```javascript
|
||
window.pdfViewer = {
|
||
initialize(canvasId, pdfDataUrl, dotNetRef),
|
||
renderPage(num),
|
||
renderSignatureButtons(signatures, pageNum, dotNetRef),
|
||
applySignature(signatureId, dataUrl, fullName, position, place),
|
||
zoomIn(), zoomOut(), dispose()
|
||
}
|
||
```
|
||
|
||
**Signature Pad:** `wwwroot/js/receiver-signature.js`
|
||
```javascript
|
||
window.receiverSignature = {
|
||
initializeDrawPad(canvasId, dotNetRef),
|
||
getSignatureDataUrl(canvasId),
|
||
clearPad(canvasId)
|
||
}
|
||
```
|
||
|
||
## Multi-Envelope Support
|
||
|
||
Receivers can login to **multiple envelopes simultaneously** via per-envelope cookies:
|
||
```
|
||
AuthTokenSignFLOWReceiver.{envelopeKey}
|
||
```
|
||
|
||
Each envelope maintains independent authentication state.
|
||
|
||
## External Dependencies
|
||
|
||
**CDN:**
|
||
- PDF.js 3.11.174: `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js`
|
||
|
||
**NuGet (WebUI.Client):**
|
||
- `DevExpress.Blazor.*` 25.2.3
|
||
- `SkiaSharp.*` 3.119.1 (WASM rendering)
|
||
|
||
**External Services:**
|
||
- LDAP/AD authentication (optional)
|
||
- GTX Messaging (SMS 2FA)
|
||
- Email dispatcher (signFlow)
|
||
|
||
## Environment Variables
|
||
|
||
None required. All config in `appsettings.json`.
|
||
|
||
**Local dev ports:**
|
||
- API: `https://localhost:8088`
|
||
- WebUI: `https://localhost:5131` or `http://localhost:7192`
|