@cyco77/pptb-flow-documentation-generator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +477 -0
- package/dist/assets/flow-documentation_small-DaHoD29p.png +0 -0
- package/dist/assets/index-WtY2dskx.js +2803 -0
- package/dist/index.html +14 -0
- package/index.html +12 -0
- package/npm-shrinkwrap.json +4864 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# Flow Documentation Generator
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="icon/flow-documentation_small.png" alt="Flow Documentation Generator Logo" width="314" height="150">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
A Power Platform Tool Box (PPTB) tool for viewing and documenting Power Automate Cloud Flows. This tool provides an intuitive interface to explore flow definitions, visualize them as interactive Mermaid diagrams, and export documentation in multiple formats.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
## Screenshots
|
|
12
|
+
|
|
13
|
+
### Dark Theme
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
### Light Theme
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
### Core Capabilities
|
|
24
|
+
|
|
25
|
+
- 📋 **Flow List View** - View all Cloud Flows in your Dynamics 365 environment in a sortable table
|
|
26
|
+
- Sortable columns with visual arrow indicators (ascending/descending)
|
|
27
|
+
- Optimized column widths for better data visibility
|
|
28
|
+
- Click any row to open details in a side drawer
|
|
29
|
+
- 🔍 **Advanced Filtering** - Real-time search by flow name and description
|
|
30
|
+
- 📈 **Interactive Mermaid Diagrams** - Visualize flow logic with auto-generated Mermaid flowcharts
|
|
31
|
+
- 🖼️ **Multiple View Modes**:
|
|
32
|
+
- **Diagram View**: Interactive flowchart visualization with zoom controls
|
|
33
|
+
- **Mermaid Code**: View and copy the raw Mermaid syntax (formatted with line breaks)
|
|
34
|
+
- **JSON View**: Inspect the original flow definition data
|
|
35
|
+
- 🔍 **Advanced Zoom Controls**:
|
|
36
|
+
- Zoom range from 50% to 1000%
|
|
37
|
+
- Interactive slider for precise control
|
|
38
|
+
- +/- buttons for quick adjustments
|
|
39
|
+
- Mouse wheel zoom with Ctrl/Cmd modifier
|
|
40
|
+
- Reset button to return to 100%
|
|
41
|
+
- 📤 **Multiple Export Formats**:
|
|
42
|
+
- Export flow list as CSV file
|
|
43
|
+
- Copy flow list to clipboard as CSV
|
|
44
|
+
- Copy flow list as Markdown table with flow details
|
|
45
|
+
- Export individual flow diagrams as SVG file
|
|
46
|
+
- Copy individual flow diagrams as SVG to clipboard
|
|
47
|
+
- 🎨 **Modern Theme Support**:
|
|
48
|
+
- Automatic light/dark theme switching based on PPTB settings
|
|
49
|
+
- Fresh, modern color palette for light mode diagrams (Material Design)
|
|
50
|
+
- Optimized dark mode styling
|
|
51
|
+
- 📢 **Visual Notifications** - Toast notifications for all operations
|
|
52
|
+
- 📝 **Event Logging** - Track all operations and API calls in real-time
|
|
53
|
+
- 🔄 **Real-time Updates** - Automatic refresh on connection changes
|
|
54
|
+
|
|
55
|
+
### Technical Stack
|
|
56
|
+
|
|
57
|
+
- ✅ React 18 with TypeScript
|
|
58
|
+
- ✅ Fluent UI React Components v9 for consistent Microsoft design
|
|
59
|
+
- ✅ Mermaid.js for diagram rendering
|
|
60
|
+
- ✅ Vite for fast development and optimized builds
|
|
61
|
+
- ✅ Power Platform Toolbox API integration
|
|
62
|
+
- ✅ Dataverse API for querying flow data
|
|
63
|
+
- ✅ Custom hooks for state management
|
|
64
|
+
- ✅ Centralized logging service
|
|
65
|
+
- ✅ Hot Module Replacement (HMR) for development
|
|
66
|
+
|
|
67
|
+
## Structure
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
pptb-flow-documentation-generator/
|
|
71
|
+
├── src/
|
|
72
|
+
│ ├── components/
|
|
73
|
+
│ │ ├── AssemblySteps.tsx # (Legacy component)
|
|
74
|
+
│ │ ├── EventLog.tsx # Real-time event log display
|
|
75
|
+
│ │ ├── Filter.tsx # Text filtering for flow list
|
|
76
|
+
│ │ ├── FlowDetails.tsx # Flow detail view with Mermaid diagram
|
|
77
|
+
│ │ ├── Overview.tsx # Flow list table view
|
|
78
|
+
│ │ └── ToolBar.tsx # Action buttons toolbar
|
|
79
|
+
│ ├── hooks/
|
|
80
|
+
│ │ ├── useConnection.ts # Dataverse connection management
|
|
81
|
+
│ │ ├── useToolboxAPI.ts # PPTB API integration
|
|
82
|
+
│ │ └── useToolboxEvents.ts # PPTB event subscription
|
|
83
|
+
│ ├── mappers/
|
|
84
|
+
│ │ └── flowDefinitionMapper.ts # Map API responses to flow models
|
|
85
|
+
│ ├── services/
|
|
86
|
+
│ │ ├── dataverseService.ts # Dataverse API queries
|
|
87
|
+
│ │ └── loggerService.ts # Centralized logging singleton
|
|
88
|
+
│ ├── types/
|
|
89
|
+
│ │ └── flowDefinition.ts # Flow definition type definitions
|
|
90
|
+
│ ├── utils/
|
|
91
|
+
│ │ ├── exportUtils.ts # Export and clipboard utilities
|
|
92
|
+
│ │ └── Flow2MermaidConverter.ts # Convert flow JSON to Mermaid syntax
|
|
93
|
+
│ ├── App.tsx # Main application component
|
|
94
|
+
│ ├── main.tsx # Entry point
|
|
95
|
+
│ └── index.css # Global styling
|
|
96
|
+
├── dist/ # Build output
|
|
97
|
+
├── index.html
|
|
98
|
+
├── package.json
|
|
99
|
+
├── tsconfig.json
|
|
100
|
+
└── vite.config.ts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Installation
|
|
104
|
+
|
|
105
|
+
### Prerequisites
|
|
106
|
+
|
|
107
|
+
- Node.js >= 18.0.0
|
|
108
|
+
- npm or yarn
|
|
109
|
+
- Power Platform Toolbox installed
|
|
110
|
+
|
|
111
|
+
### Setup
|
|
112
|
+
|
|
113
|
+
1. Clone the repository:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
git clone <repository-url>
|
|
117
|
+
cd pptb-flow-documentation-generator
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
2. Install dependencies:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm install
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Development
|
|
127
|
+
|
|
128
|
+
### Development Server
|
|
129
|
+
|
|
130
|
+
Start development server with HMR:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npm run dev
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The tool will be available at `http://localhost:5173`
|
|
137
|
+
|
|
138
|
+
### Watch Mode
|
|
139
|
+
|
|
140
|
+
Build the tool in watch mode for continuous updates:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npm run watch
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Production Build
|
|
147
|
+
|
|
148
|
+
Build the optimized production version:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
npm run build
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The output will be in the `dist/` directory.
|
|
155
|
+
|
|
156
|
+
### Preview Build
|
|
157
|
+
|
|
158
|
+
Preview the production build locally:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm run preview
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Usage
|
|
165
|
+
|
|
166
|
+
### In Power Platform Toolbox
|
|
167
|
+
|
|
168
|
+
1. Build the tool:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm run build
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
2. Package the tool (creates npm-shrinkwrap.json):
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npm run finalize-package
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
3. Install in Power Platform Toolbox using the PPTB interface
|
|
181
|
+
|
|
182
|
+
4. Connect to a Dataverse environment
|
|
183
|
+
|
|
184
|
+
5. Launch the tool to view and document your Cloud Flows
|
|
185
|
+
|
|
186
|
+
### User Interface
|
|
187
|
+
|
|
188
|
+
#### Flow List View
|
|
189
|
+
|
|
190
|
+
- **Searchable Table**: View all flows with sortable columns (Name, Description, State, Created On, Modified On)
|
|
191
|
+
- Click column headers to sort
|
|
192
|
+
- Visual arrow indicators show sort direction (ascending/descending)
|
|
193
|
+
- Optimized column widths: Name (25%), Description (35%), State (10%), Dates (15% each)
|
|
194
|
+
- **Text Filter**: Real-time search across flow names and descriptions
|
|
195
|
+
- **Action Buttons**:
|
|
196
|
+
- **Copy CSV**: Copy flow list to clipboard in CSV format
|
|
197
|
+
- **Copy Markdown**: Copy flow list as a Markdown table with flow details
|
|
198
|
+
- **Export CSV**: Download flow list as a CSV file
|
|
199
|
+
- **Flow Selection**: Click any row to open the detailed view in a side drawer (80% viewport width, max 1400px)
|
|
200
|
+
|
|
201
|
+
#### Flow Detail View (Drawer)
|
|
202
|
+
|
|
203
|
+
- **Flow Information**:
|
|
204
|
+
- Flow name displayed in drawer header
|
|
205
|
+
- State, Workflow ID, Created On, Modified On in fixed details section
|
|
206
|
+
- **View Mode Tabs** (combined with context-aware controls in single row):
|
|
207
|
+
- **Diagram**: Interactive Mermaid flowchart with modern styling and zoom controls
|
|
208
|
+
- **Mermaid Code**: View and copy the raw Mermaid syntax (formatted with line breaks after semicolons)
|
|
209
|
+
- **JSON**: Inspect the complete flow definition
|
|
210
|
+
- **Context-Aware Controls**:
|
|
211
|
+
- **Diagram View**: Zoom slider (50%-1000%), +/- buttons, reset button, Copy SVG button, Export SVG button
|
|
212
|
+
- **Mermaid View**: Copy to Clipboard button
|
|
213
|
+
- **JSON View**: Copy to Clipboard button
|
|
214
|
+
- **Mouse Wheel Zoom**: Hold Ctrl (Windows/Linux) or Cmd (Mac) and scroll to zoom in/out
|
|
215
|
+
- **Scrollable Content**: Only the diagram/code/JSON area scrolls, header and controls remain fixed
|
|
216
|
+
|
|
217
|
+
#### Event Log
|
|
218
|
+
|
|
219
|
+
- Monitor all operations and API calls
|
|
220
|
+
- Color-coded log levels (info, success, warning, error)
|
|
221
|
+
- Auto-scrolls to show latest entries
|
|
222
|
+
|
|
223
|
+
## API Usage
|
|
224
|
+
|
|
225
|
+
The tool demonstrates various Power Platform Toolbox and Dataverse API features:
|
|
226
|
+
|
|
227
|
+
### Connection Management
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Get current connection
|
|
231
|
+
const connection = await window.toolboxAPI.getConnection();
|
|
232
|
+
console.log(connection.connectionUrl);
|
|
233
|
+
|
|
234
|
+
// Listen for connection changes
|
|
235
|
+
window.toolboxAPI.onToolboxEvent((event, payload) => {
|
|
236
|
+
if (event === "connection:updated") {
|
|
237
|
+
// Refresh data with new connection
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Dataverse Queries
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
// Query Cloud Flows (workflows)
|
|
246
|
+
const flows = await window.dataverseAPI.executeQuery(
|
|
247
|
+
`workflows?$select=workflowid,name,description,createdon,modifiedon,statecode,clientdata&$filter=category eq 5`
|
|
248
|
+
);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Notifications
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
await window.toolboxAPI.utils.showNotification({
|
|
255
|
+
title: "Export Successful",
|
|
256
|
+
body: "Exported 15 plugin assembly steps",
|
|
257
|
+
type: "success",
|
|
258
|
+
duration: 3000,
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### File Operations
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// Save CSV file
|
|
266
|
+
await window.toolboxAPI.utils.saveFile("flow_definitions.csv", csvContent);
|
|
267
|
+
|
|
268
|
+
// Save SVG diagram
|
|
269
|
+
await window.toolboxAPI.utils.saveFile("flow_diagram.svg", svgString);
|
|
270
|
+
|
|
271
|
+
// Copy to clipboard
|
|
272
|
+
await window.toolboxAPI.utils.copyToClipboard(content);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Theme Management
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Get current theme
|
|
279
|
+
const theme = await window.toolboxAPI.utils.getCurrentTheme();
|
|
280
|
+
// Returns 'light' or 'dark'
|
|
281
|
+
|
|
282
|
+
// Listen for theme changes
|
|
283
|
+
window.toolboxAPI.onToolboxEvent((event) => {
|
|
284
|
+
if (event === "settings:updated") {
|
|
285
|
+
updateThemeBasedOnSettings();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Event Subscription
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Subscribe to all PPTB events
|
|
294
|
+
window.toolboxAPI.onToolboxEvent((event, payload) => {
|
|
295
|
+
console.log("Event:", event);
|
|
296
|
+
console.log("Data:", payload.data);
|
|
297
|
+
|
|
298
|
+
// Handle specific events
|
|
299
|
+
switch (event) {
|
|
300
|
+
case "connection:created":
|
|
301
|
+
case "connection:updated":
|
|
302
|
+
refreshConnection();
|
|
303
|
+
break;
|
|
304
|
+
case "connection:deleted":
|
|
305
|
+
clearData();
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Architecture
|
|
312
|
+
|
|
313
|
+
### Custom Hooks
|
|
314
|
+
|
|
315
|
+
- **useConnection**: Manages Dataverse connection state and refresh logic
|
|
316
|
+
- **useToolboxAPI**: Provides PPTB API access with theme management
|
|
317
|
+
- **useToolboxEvents**: Subscribes to PPTB events and handles callbacks
|
|
318
|
+
|
|
319
|
+
### Services
|
|
320
|
+
|
|
321
|
+
- **loggerService**: Singleton service for centralized logging with callback pattern
|
|
322
|
+
|
|
323
|
+
- Methods: `info()`, `success()`, `warning()`, `error()`
|
|
324
|
+
- Eliminates prop drilling for logging across components
|
|
325
|
+
|
|
326
|
+
- **dataverseService**: Handles all Dataverse API queries
|
|
327
|
+
- Queries Cloud Flow definitions (workflows)
|
|
328
|
+
- Maps raw API responses to typed models
|
|
329
|
+
|
|
330
|
+
### Export Utilities
|
|
331
|
+
|
|
332
|
+
- **exportFlowDefinitionsToCSV**: Export flow list to CSV file
|
|
333
|
+
- **copyFlowDefinitionsAsCSV**: Copy flow list as CSV to clipboard
|
|
334
|
+
- **copyFlowDefinitionsAsMarkdown**: Copy flows as Markdown table format
|
|
335
|
+
- **handleExportSVG**: Export individual flow diagram as SVG file
|
|
336
|
+
- **handleCopySVG**: Copy individual flow diagram as SVG to clipboard
|
|
337
|
+
|
|
338
|
+
All export functions support optional notifications for user feedback and use the Power Platform Toolbox API for file operations and clipboard access.
|
|
339
|
+
|
|
340
|
+
### Flow Visualization
|
|
341
|
+
|
|
342
|
+
- **Flow2MermaidConverter**: Converts Power Automate flow JSON definitions to Mermaid flowchart syntax
|
|
343
|
+
- Parses flow actions, triggers, and control structures
|
|
344
|
+
- Generates clean, readable Mermaid diagrams
|
|
345
|
+
- Supports branching, loops, and nested conditions
|
|
346
|
+
|
|
347
|
+
### Type Safety
|
|
348
|
+
|
|
349
|
+
Full TypeScript coverage with:
|
|
350
|
+
|
|
351
|
+
- Interface definitions for all data models
|
|
352
|
+
- Type-safe API responses
|
|
353
|
+
- Strongly typed component props
|
|
354
|
+
- PPTB API types from `@pptb/types` package
|
|
355
|
+
|
|
356
|
+
## Configuration
|
|
357
|
+
|
|
358
|
+
### Vite Build Configuration
|
|
359
|
+
|
|
360
|
+
The tool uses a custom Vite configuration for PPTB compatibility:
|
|
361
|
+
|
|
362
|
+
- **IIFE format**: Bundles as Immediately Invoked Function Expression for iframe compatibility
|
|
363
|
+
- **Single bundle**: Uses `inlineDynamicImports` to avoid module loading issues with file:// URLs
|
|
364
|
+
- **HTML transformation**: Custom plugin removes `type="module"` and moves scripts to end of body
|
|
365
|
+
- **Chunk size limit**: Set to 1000 kB to accommodate Fluent UI bundle size
|
|
366
|
+
|
|
367
|
+
## Data Models
|
|
368
|
+
|
|
369
|
+
### FLowDefinition
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
{
|
|
373
|
+
workflowid: string;
|
|
374
|
+
name: string;
|
|
375
|
+
description: string | null;
|
|
376
|
+
createdon: Date;
|
|
377
|
+
modifiedon: Date;
|
|
378
|
+
statecode: number; // 0=Draft, 1=Active, 2=Inactive
|
|
379
|
+
clientdata: string; // JSON string of flow definition
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Troubleshooting
|
|
384
|
+
|
|
385
|
+
### Build Issues
|
|
386
|
+
|
|
387
|
+
If you encounter chunk size warnings:
|
|
388
|
+
|
|
389
|
+
- The tool uses IIFE format which requires a single bundle
|
|
390
|
+
- Chunk size limit is configured in `vite.config.ts`
|
|
391
|
+
- This is expected for Fluent UI and Mermaid.js components
|
|
392
|
+
|
|
393
|
+
### Connection Issues
|
|
394
|
+
|
|
395
|
+
- Ensure you're connected to a Dataverse environment in PPTB
|
|
396
|
+
- Check the Event Log for connection-related errors
|
|
397
|
+
- Verify permissions to read workflow data
|
|
398
|
+
|
|
399
|
+
### Diagram Rendering Issues
|
|
400
|
+
|
|
401
|
+
- If diagrams don't appear, check browser console for Mermaid errors
|
|
402
|
+
- Try switching to another view mode and back to Diagram
|
|
403
|
+
- Verify the flow has valid `clientdata` in JSON format
|
|
404
|
+
|
|
405
|
+
### Theme Not Updating
|
|
406
|
+
|
|
407
|
+
- The tool automatically syncs with PPTB theme settings
|
|
408
|
+
- Check console for theme update events
|
|
409
|
+
- Verify PPTB version supports theme API
|
|
410
|
+
|
|
411
|
+
## Contributing
|
|
412
|
+
|
|
413
|
+
Contributions are welcome! Please:
|
|
414
|
+
|
|
415
|
+
1. Fork the repository
|
|
416
|
+
2. Create a feature branch
|
|
417
|
+
3. Make your changes with appropriate TypeScript types
|
|
418
|
+
4. Test the build process
|
|
419
|
+
5. Submit a pull request
|
|
420
|
+
|
|
421
|
+
### GitHub Actions
|
|
422
|
+
|
|
423
|
+
The project includes automated CI/CD workflows:
|
|
424
|
+
|
|
425
|
+
#### CI Workflow (`.github/workflows/ci.yml`)
|
|
426
|
+
|
|
427
|
+
Runs on every push and pull request to `main` and `develop` branches:
|
|
428
|
+
|
|
429
|
+
- **Build and Test**:
|
|
430
|
+
|
|
431
|
+
- Tests on Node.js 18.x and 20.x
|
|
432
|
+
- TypeScript type checking
|
|
433
|
+
- Build verification
|
|
434
|
+
- Uploads build artifacts
|
|
435
|
+
|
|
436
|
+
- **Lint Check**:
|
|
437
|
+
|
|
438
|
+
- Runs ESLint if configured
|
|
439
|
+
- Validates code quality
|
|
440
|
+
|
|
441
|
+
- **Security Audit**:
|
|
442
|
+
|
|
443
|
+
- Checks for npm package vulnerabilities
|
|
444
|
+
- Fails on critical vulnerabilities
|
|
445
|
+
- Warns on high-severity issues
|
|
446
|
+
|
|
447
|
+
- **Package Validation**:
|
|
448
|
+
- Validates package.json structure
|
|
449
|
+
- Creates npm-shrinkwrap.json
|
|
450
|
+
- Verifies all required fields
|
|
451
|
+
|
|
452
|
+
#### Release Workflow (`.github/workflows/release.yml`)
|
|
453
|
+
|
|
454
|
+
Triggered when pushing a version tag (e.g., `v1.0.0`):
|
|
455
|
+
|
|
456
|
+
- Builds the project
|
|
457
|
+
- Creates distribution packages (tar.gz and zip)
|
|
458
|
+
- Creates GitHub release with auto-generated notes
|
|
459
|
+
- Attaches build artifacts to release
|
|
460
|
+
|
|
461
|
+
**To create a release:**
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
# Update version in package.json
|
|
465
|
+
npm version patch # or minor, major
|
|
466
|
+
|
|
467
|
+
# Push with tags
|
|
468
|
+
git push origin main --tags
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
## License
|
|
472
|
+
|
|
473
|
+
MIT - See LICENSE file for details
|
|
474
|
+
|
|
475
|
+
## Author
|
|
476
|
+
|
|
477
|
+
Lars Hildebrandt
|
|
Binary file
|