Visualize BPF stages for records in grid and subgrid views
Installation • Design Styles • Configuration • Performance • Development • Contributing
Visualize business process flow stages directly in grid and subgrid views
| Feature | v1 (2020) | Current |
|---|---|---|
| Architecture | Standard PCF | Virtual PCF |
| UI Library | Custom CSS | Fluent UI v9 |
| Framework | Vanilla JS | React 16.14 |
| Theming | Custom colors only | Platform theme support |
| Dataverse Calls | 1 per record | Batched + parallel |
| Bundle Size | ~150KB | ~20KB (shared libs) |
| Design Options | 1 | 8 designs |
| Responsive | No | Container-based |
| Style | Description |
|---|---|
chevron |
Classic BPF ribbon arrows (default) |
circles |
Connected circles with labels |
pills |
Rounded badge style |
segmented |
Single segmented progress bar |
stepper |
Numbered boxes with connectors |
gradient |
Gradient progress bar with markers |
line |
Linear progress track with markers |
fraction |
Fraction display (e.g. 2/5) |
Choose your preferred installation method:
Download and import the pre-built managed solution directly into your Dataverse environment.
- Download
BusinessProcessFlowViewer_x.x.x_managed.zipfrom Releases - Go to make.powerapps.com → Select your environment
- Navigate to Solutions → Click Import solution
- Browse and select the downloaded
.zipfile - Click Next → Import
Using PAC CLI:
pac auth create --environment "https://yourorg.crm.dynamics.com"
pac solution import --path BusinessProcessFlowViewer_x.x.x_managed.zipgit clone https://github.com/allandecastro/business-process-flow-viewer.git
cd business-process-flow-viewer
npm install
npm run buildAfter importing the solution:
- Open a Model-Driven App in the app designer
- Select a Grid or Subgrid view
- Click Get more components → search for BusinessProcessFlowViewer
- Configure the BPF JSON parameter (see Configuration)
- Save and Publish
The parametersBPF property accepts a JSON configuration that tells the control which BPF entities to query:
{
"bpfs": [
{
"bpfEntitySchemaName": "opportunitysalesprocess",
"lookupFieldSchemaName": "_opportunityid_value"
}
]
}| Field | Description |
|---|---|
bpfEntitySchemaName |
Schema name of the BPF entity (e.g. opportunitysalesprocess) |
lookupFieldSchemaName |
Lookup field on the BPF entity that references the parent record (e.g. _opportunityid_value) |
Multiple BPF definitions can be configured for entities with more than one business process flow.
| Property | Type | Default | Description |
|---|---|---|---|
parametersBPF |
String | - | JSON configuration for BPFs |
designStyle |
Enum | chevron |
Visual design style |
displayMode |
Enum | stage |
Show stage or category names |
recordNameSize |
Enum | medium |
Record name font size (small/medium/large) |
showEntityName |
Enum | no |
Show entity type badge next to record name |
enableNavigation |
Enum | yes |
Click row to open record in new tab |
showPulseAnimation |
Enum | yes |
Subtle animation on active stage |
usePlatformTheme |
Enum | yes |
Use Dataverse environment theme colors |
completedColor |
String | #107C10 |
Completed stage background color |
completedTextColor |
String | #FFFFFF |
Completed stage text color |
activeColor |
String | #0078D4 |
Active stage background color |
activeTextColor |
String | #FFFFFF |
Active stage text color |
inactiveColor |
String | #E1E1E1 |
Inactive stage background color |
inactiveTextColor |
String | #666666 |
Inactive stage text color |
Custom colors are used when usePlatformTheme is set to no.
| Feature | Description |
|---|---|
| 8 Design Styles | Chevron, Circles, Pills, Segmented, Stepper, Gradient, Line, Fraction |
| Platform Theming | Automatically uses Dataverse environment theme colors via Fluent UI v9 tokens |
| Custom Colors | Override completed, active, and inactive stage colors when platform theme is off |
| Stage Categories | Display stage names or localized category names |
| Conditional BPF | Uses RetrieveActivePath to show only the active branch stages |
| Feature | Description |
|---|---|
| Record Navigation | Click any row to open the record in a new tab |
| Pulse Animation | Subtle animation highlights the currently active stage |
| Responsive Layout | Container-based detection adapts to narrow subgrids and mobile views |
| Error Handling | User-friendly error messages with retry support |
| Feature | Description |
|---|---|
| Batched API Calls | Fetches BPF data for up to 10 records per call using $filter with OR conditions |
| Parallel Requests | Category labels, BPF instances, and active paths fetched concurrently |
| 5-Minute Cache | Stage definitions, workflow IDs, category labels, and active paths are cached |
| Request Cancellation | Stale requests cancelled via AbortController when the dataset changes |
| Column Selection | Only needed columns requested to minimize payload size |
Enable performance metrics in the browser console:
sessionStorage.setItem('BPF_DEBUG', 'true')Each dataset load logs a collapsible timing table. Example output for 5 records (cold cache):
[BPFViewer] processDataset (5 records) completed in 342ms (5 steps)
┌───┬──────────────────────────────────────┬────────────┬───────────────┬────────┐
│ │ Step │ Start (ms) │ Duration (ms) │ Cached │
├───┼──────────────────────────────────────┼────────────┼───────────────┼────────┤
│ 0 │ getEntityDisplayName │ 0 │ 48 │ │
│ 1 │ parallel:instances+categoryLabels │ 0 │ 187 │ │
│ 2 │ retrieveActivePaths │ 188 │ 112 │ │
│ 3 │ fetchBPF:opportunitysalesprocess │ 0 │ 301 │ │
│ 4 │ getBPFDataForRecords │ 0 │ 342 │ │
└───┴──────────────────────────────────────┴────────────┴───────────────┴────────┘
On subsequent loads with warm cache, you'll see Cached: yes and near-zero durations:
[BPFViewer] processDataset (5 records) completed in 3ms (3 steps)
┌───┬──────────────────────────────────────┬────────────┬───────────────┬────────┐
│ │ Step │ Start (ms) │ Duration (ms) │ Cached │
├───┼──────────────────────────────────────┼────────────┼───────────────┼────────┤
│ 0 │ getEntityDisplayName │ 0 │ 0 │ yes │
│ 1 │ parallel:instances+categoryLabels │ 0 │ 2 │ │
│ 2 │ getBPFDataForRecords │ 0 │ 3 │ │
└───┴──────────────────────────────────────┴────────────┴───────────────┴────────┘
Disable with:
sessionStorage.removeItem('BPF_DEBUG')- Node.js 18.x or 20.x
- npm
git clone https://github.com/allandecastro/business-process-flow-viewer.git
cd business-process-flow-viewer
npm installnpm run build # Build the PCF control
npm test # Run tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Generate coverage report
npm run lint # Run ESLintThe project includes comprehensive test coverage:
- 360 tests across 17 test suites
- Unit tests for utilities (config validation, sanitization, theme resolution, error messages, debounce)
- Service tests for BPFService (batching, caching, RetrieveActivePath, fallback behavior)
- Component tests for all 8 design styles, BPFViewer, BPFRow, ErrorBoundary
- Accessibility tests (ARIA attributes, keyboard navigation, screen reader labels)
Pre-commit Hooks:
Husky and lint-staged enforce code quality on every commit:
- ESLint with auto-fix
- Jest tests for modified files
- Commits are blocked if checks fail
business-process-flow-viewer/
├── index.ts # PCF control entry point
├── ControlManifest.Input.xml # PCF manifest
├── components/
│ ├── BPFViewer.tsx # Main wrapper with FluentProvider
│ ├── BPFRow.tsx # Single record row
│ ├── ErrorBoundary.tsx # Error boundary
│ └── designs/ # 8 design style components
│ ├── hooks/ # Shared hooks (useBPFDesignHelpers)
│ └── shared/ # Shared components (StageIcon)
├── services/
│ └── BPFService.ts # Dataverse API (batching, caching, parallel)
├── utils/
│ ├── themeUtils.ts # Color resolution & theme helpers
│ ├── configValidation.ts # BPF config validation
│ ├── sanitize.ts # Input sanitization & validation
│ ├── errorMessages.ts # User-friendly error messages
│ ├── perfTracker.ts # Performance instrumentation
│ └── logger.ts # Centralized logging
├── types/ # TypeScript type definitions
├── __tests__/ # 360 tests across 17 suites
├── Solution/ # Dataverse solution project
└── .github/workflows/ # CI/CD pipelines
Virtual PCF Control
- Built as a Virtual PCF control (React-based
updateViewreturningReact.ReactElement) - Fluent UI v9
FluentProviderwraps the component tree for platform theme support - Container-based responsive detection via
ResizeObserver
Dataverse Integration
- Uses
ComponentFramework.WebApifor OData queries (BPF instances, stages, workflows) - Uses
fetch()for theRetrieveActivePathunbound function (not supported by WebApi) - Automatic same-origin authentication via browser cookies
State Management
- PCF framework manages lifecycle via
init/updateView/destroy notifyOutputChangedtriggers re-renders when async BPF data arrivesAbortControllercancels stale requests when the dataset changes
CI (every push and PR): Linting, tests with coverage, build verification on Node 18.x and 20.x.
CD (on version tag push v*): Builds the managed + unmanaged Dataverse solution and creates a GitHub Release with versioned zip files attached.
node scripts/bump-version.js x.y.z
git add -A && git commit -m "chore: bump version to x.y.z"
git tag vx.y.z
git push && git push --tagsThe CD workflow automatically builds and publishes the solution.
"Invalid BPF configuration JSON"
- Verify the JSON is valid (no trailing commas, correct quotes)
- Check that
bpfEntitySchemaNamematches the BPF entity's schema name in Dataverse - Check that
lookupFieldSchemaNamestarts with_and ends with_value
BPF stages not showing for some records
- The record may not have an active BPF instance
- Check that the BPF is activated in the Dataverse environment
- Enable debug mode (
BPF_DEBUG) to see API call details in the console
Wrong stages showing for conditional BPFs
- The control uses
RetrieveActivePathto fetch only the active branch stages - If this API is unavailable, it falls back to showing all stages
- Check the console for
RetrieveActivePath failedwarnings
Loading spinner stuck
- Check browser console for errors
- Verify the user has read permissions on the BPF entity
- Try the Refresh button to clear cache and refetch
Contributions are welcome! Please read our Contributing Guide for details.
Quick start:
# Fork and clone
git clone https://github.com/YOUR_USERNAME/business-process-flow-viewer.git
# Create feature branch
git checkout -b feature/amazing-feature
# Make changes and test
npm test
npm run lint
# Commit (pre-commit hooks will run automatically)
git commit -m "feat: add amazing feature"
# Push and create PR
git push origin feature/amazing-featureThis project is licensed under the MIT License - see the LICENSE file for details.
Made with ❤️ for the Power Platform Community
