Skip to content

Commit 5f69898

Browse files
nickgatejclaude
andauthored
feat(samples): add document-validation-subcomponents sample app (#606)
* feat(samples): add document-validation-subcomponents sample app Add a React + TypeScript + Vite sample that builds a custom document review workspace by composing the individual subcomponents exported by @uipath/ui-widgets-validation-station (DocumentViewer, CompactDocTypeField, CompactFieldsForm, CompactTableEditor, CompactBusinessRules) rather than the all-in-one ValidationStation component. - OAuth 2.0 authorization code + PKCE login via @uipath/uipath-typescript - Lists Document Validation tasks and hydrates one with its full payload - Shares bucket artifacts across subcomponents via a single instanceId - Supports complete, save-as-draft, and exception-report flows Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(samples): bump @uipath/ui-widgets-validation-station to 1.0.1 Update both document-validation sample apps to use the published 1.0.1 npm release, replacing the local tgz reference in the subcomponents app. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(samples): pin @uipath/ui-widgets-validation-station to 1.0.0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(samples): memoize OrchestratorDuModule in ReviewInbox Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(samples): add demo preview to document-validation-subcomponents README Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(samples): rename example config to uipath.json.example Aligns document-validation-subcomponents-app with the check-samples example-config rule and the convention used by every other sample app. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(samples): narrow Folders scope to read-only and drop uipath.json commit note Scope the subcomponents sample to OR.Tasks OR.Buckets OR.Folders.Read: folder resolution is read-only, so OR.Folders.Read suffices. Also removes the "Never commit uipath.json" note (the file is already gitignored) per review feedback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e4a5eca commit 5f69898

25 files changed

Lines changed: 7048 additions & 0 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
.uipath
14+
*.local
15+
16+
# Editor directories and files
17+
.vscode/*
18+
!.vscode/extensions.json
19+
.idea
20+
.DS_Store
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?
26+
.env
27+
uipath.json
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@uipath:registry=https://registry.npmjs.org
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# UiPath Document Review Workspace (Validation Station subcomponents)
2+
3+
A sample React + TypeScript + Vite application that builds a **custom** human-in-the-loop document review screen by composing the individual **subcomponents** exported by `@uipath/ui-widgets-validation-station` — rather than the all-in-one `ValidationStation` component.
4+
5+
It lists pending Document Validation tasks from UiPath Action Center and, for the selected task, lays out five compact subcomponents in a grid: the document viewer, a document-type field, the extraction fields form, a line-items table editor, and a business-rules panel. All five share a single `instanceId`, so they mirror one store — selecting a field in the form highlights it in the viewer, picking a table field opens the table editor, and clicking a rule focuses the offending field, with no cross-wiring.
6+
7+
> **Monolithic vs. compose-your-own.** The sibling [`document-validation-app`](../document-validation-app) renders the same task with the single `ValidationStation` component — the fastest path when you want the standard layout. **This** sample shows the other path: drop the subcomponents into your own layout when you need to rearrange, hide, or embed individual panels. Both talk to the same tasks and the same bucket artifacts.
8+
9+
## Preview
10+
11+
![Document review workspace walkthrough](./demo/screen-recording.gif)
12+
13+
## What this sample demonstrates
14+
15+
- OAuth 2.0 authorization code + PKCE login against UiPath Cloud using the `@uipath/uipath-typescript` SDK
16+
- Listing Document Validation tasks (`Tasks.getAll` with an OData filter) and hydrating one with its full validation payload (`Tasks.getById` with `TaskType.DocumentValidation`)
17+
- Fetching the document artifacts **once** with the `useBucketArtifacts` hook and sharing them across subcomponents
18+
- Composing `DocumentViewer`, `CompactDocTypeField`, `CompactFieldsForm`, `CompactTableEditor`, and `CompactBusinessRules` into a custom layout linked by a shared `instanceId`
19+
- Using `options` flags (`hideBusinessRules`, `hideDocumentTypeField`, `emitDtoStateChanges`) so the fields form drops the panels that are rendered standalone
20+
- Submitting the completed task (`Task.complete`), saving in-progress edits (save as draft), and reporting a document as an exception via `OrchestratorDuModule.submitExceptionReport`
21+
22+
## Prerequisites
23+
24+
- Node.js 20+ and npm
25+
- A UiPath Cloud organization and tenant with Action Center enabled
26+
- At least one pending Document Validation task in the tenant (produced by a Document Understanding process)
27+
- An OAuth External Application registered in the UiPath Admin Center (see below)
28+
29+
## Configure the OAuth External Application
30+
31+
1. In UiPath Cloud: **Admin → External Applications → Add Application**.
32+
2. Choose **Non Confidential Application** (this is a browser SPA — no client secret is used or stored).
33+
3. Set:
34+
- **Name**: e.g., `Document Review Subcomponents Sample`
35+
- **Redirect URI**: the exact URL the app runs on, including scheme, host, port, and path. For local development this is `http://localhost:5173/`. The redirect URI is matched **exactly** by UiPath — a trailing-slash or port mismatch will fail the callback.
36+
- **Scopes** (least-privilege set used by this sample):
37+
- `OR.Tasks` — list and complete validation tasks
38+
- `OR.Buckets` — read the source document and write the validated/draft result back to the bucket on submit and save-as-draft
39+
- `OR.Folders.Read` — resolve the folder a task belongs to
40+
4. Save and copy the generated **Application ID** — this is the `clientId` value below.
41+
42+
> Add a separate Redirect URI entry for any other environment (e.g., a staging URL). Do not use wildcards.
43+
44+
## Configure `uipath.json`
45+
46+
Copy the template and fill in the values:
47+
48+
```bash
49+
cp uipath.json.example uipath.json
50+
```
51+
52+
| Field | Where to find it | Example |
53+
|-------|------------------|---------|
54+
| `clientId` | Application ID from the External Application you just created | `12345678-aaaa-bbbb-cccc-1234567890ab` |
55+
| `orgName` | The organization slug in your UiPath Cloud URL (`cloud.uipath.com/<org>/<tenant>/...`) | `acme` |
56+
| `tenantName` | The tenant slug, in the same URL | `DefaultTenant` |
57+
| `baseUrl` | UiPath Cloud API host. Leave as the default unless you use a regional endpoint | `https://api.uipath.com` |
58+
| `redirectUri` | Must match the Redirect URI registered on the External Application **exactly** | `http://localhost:5173/` |
59+
| `scope` | Space-separated scopes — must be a subset of the scopes granted to the External Application | `OR.Tasks OR.Buckets OR.Folders.Read` |
60+
61+
The client ID is not a secret, but `uipath.json` is gitignored to keep environment-specific values out of source control. The `@uipath/coded-apps-dev` Vite plugin reads `uipath.json` and injects the values as `<meta>` tags during local dev; in production, the UiPath platform injects them at deploy time.
62+
63+
## Install, run, and build
64+
65+
```bash
66+
npm install # install dependencies
67+
npm run dev # start Vite dev server at http://localhost:5173
68+
npm run build # type-check and produce a production bundle in dist/
69+
npm run preview # serve the built bundle locally for verification
70+
```
71+
72+
On first load the app shows a **Sign in with UiPath** button. After returning from UiPath Cloud, pick a pending task from the left to open the review workspace. Edit fields, select a table field to open the line-items editor, then **Submit**, **Save as draft**, or **Report exception** from the fields form's built-in actions. The status bar at the bottom of the workspace shows the shared store id and the last cross-component interaction.
73+
74+
## Project layout
75+
76+
```
77+
src/
78+
├── components/
79+
│ ├── TaskList.tsx # Left-pane list of pending tasks
80+
│ ├── ReviewInbox.tsx # Owns task fetch/selection + the SDK mutations
81+
│ ├── ReviewWorkspace.tsx # The 5-subcomponent composition (shared instance-id)
82+
│ ├── Panel.tsx # Grid-area panel wrapper
83+
│ └── CenteredMessage.tsx # Empty / loading / error placeholder
84+
├── hooks/
85+
│ └── useAuth.tsx # AuthProvider wrapping the UiPath SDK + OAuth flow
86+
├── App.tsx # Top-level layout, sign-in / sign-out
87+
└── main.tsx # Entry point
88+
```
89+
90+
### Validation station runtime assets
91+
92+
The validation station web component resolves several files at runtime (relative to its own bundle): the `du-assets/` folder (PDF.js worker, cmaps, wasm, i18n) plus `styles.css`, `fonts.css`, and `media/`. `vite.config.ts` handles these in two ways:
93+
94+
- **Build** — a `closeBundle` plugin copies `du-assets/`, `media/`, `styles.css`, and `fonts.css` from `@uipath/du-validation-station-wc` next to the emitted JS chunks so `import.meta.url` resolution finds them.
95+
- **Dev** — Vite rewrites `.css` requests into JS modules, which would break the component's runtime `fetch("styles.css")`. A dev-only middleware detects that raw fetch (`Sec-Fetch-Dest: empty`) and returns the real CSS instead.
96+
97+
The web component bundle is also excluded from Vite's dependency pre-bundling (`optimizeDeps.exclude`), since pre-bundling rewrites `import.meta.url` and breaks the runtime asset resolution. If these steps are missing, the component silently 404s at runtime — PDFs fail to render and icons fall back to empty boxes.
98+
99+
> **Use `persistent: false`.** With `persistent` on, StrictMode's throwaway unmount triggers `forceDestroy()` on the underlying element, so it never re-renders (a blank panel). These panels live in a static grid and are never re-parented, so `false` is safe.
100+
101+
## Troubleshooting
102+
103+
- **Callback fails with `redirect_uri_mismatch`** — the `redirectUri` in `uipath.json` and the URL you opened in the browser must both match the External Application's Redirect URI character-for-character (scheme, host, port, path, trailing slash).
104+
- **`insufficient_scope` when loading tasks** — the External Application is missing one of `OR.Tasks`, `OR.Buckets`, or `OR.Folders.Read`. Update the app, then sign out and sign back in to get a new token.
105+
- **The list is empty** — the signed-in user has no pending / unassigned Document Validation tasks, or no access to the folder the tasks live in. Verify in Action Center first.
106+
- **A panel is blank** — either the asset copy step in `vite.config.ts` did not run (production), the dev raw-CSS middleware is not registered (dev), or `persistent` was left `true` (see the note above).
107+
108+
## Further reading
109+
110+
- [UiPath TypeScript SDK docs](https://uipath.github.io/uipath-typescript/)
111+
- [OAuth scopes reference](https://uipath.github.io/uipath-typescript/oauth-scopes/)
112+
- [Action Center Tasks](https://docs.uipath.com/action-center/)
4.35 MB
Loading
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import js from '@eslint/js'
2+
import globals from 'globals'
3+
import reactHooks from 'eslint-plugin-react-hooks'
4+
import reactRefresh from 'eslint-plugin-react-refresh'
5+
import tseslint from 'typescript-eslint'
6+
import { defineConfig, globalIgnores } from 'eslint/config'
7+
8+
export default defineConfig([
9+
globalIgnores(['dist']),
10+
{
11+
files: ['**/*.{ts,tsx}'],
12+
extends: [
13+
js.configs.recommended,
14+
tseslint.configs.recommended,
15+
reactHooks.configs.flat.recommended,
16+
reactRefresh.configs.vite,
17+
],
18+
languageOptions: {
19+
globals: globals.browser,
20+
},
21+
},
22+
])
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/png" href="/favicon.png" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>document-validation-subcomponents-app</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)