|
| 1 | +## ADDED Requirements |
| 2 | + |
| 3 | +### Requirement: onBeforeExport action fires before export starts |
| 4 | + |
| 5 | +The widget SHALL expose an optional `onBeforeExport` action property. When configured, the widget MUST call `onBeforeExport.execute(args)` once, fire-and-forget, immediately before the first datasource page fetch of an export operation. |
| 6 | + |
| 7 | +The action MUST receive the following variables: |
| 8 | + |
| 9 | +- `gridName` (String) — the Studio Pro widget name (`props.name`) |
| 10 | +- `columnTitles` (String) — comma-separated header captions of the visible, exported columns in their current display order (e.g. `"First name,Last Name,Date of Birth"`). Columns hidden by the user SHALL NOT be included. |
| 11 | +- `chunkSize` (Integer) — the effective number of rows fetched per datasource request during the export (`Math.max(requestedLimit, 10)`). |
| 12 | +- `fileName` (String) — the target file name for the export (e.g. `"export.xlsx"`), as provided by the export caller. SHALL be an empty string when not provided. |
| 13 | +- `sheetName` (String) — the target sheet/tab name within the export file (e.g. `"Sheet1"`), as provided by the export caller. SHALL be an empty string when not provided. |
| 14 | +- `startTime` (DateTime) — the timestamp captured immediately before `req.send()` is called. |
| 15 | + |
| 16 | +The action execution MUST NOT block or delay the export flow. |
| 17 | + |
| 18 | +#### Scenario: onBeforeExport fires with correct variables on normal export |
| 19 | + |
| 20 | +- **WHEN** a configured `onBeforeExport` action exists and `canExecute` is true |
| 21 | +- **AND** an export is triggered on the grid |
| 22 | +- **THEN** `onBeforeExport.execute` is called once with `gridName`, `columnTitles`, `chunkSize`, `fileName`, `sheetName`, and `startTime` before any datasource page is fetched |
| 23 | + |
| 24 | +#### Scenario: onBeforeExport is skipped when not configured |
| 25 | + |
| 26 | +- **WHEN** `onBeforeExport` is not configured (optional property absent) |
| 27 | +- **AND** an export is triggered |
| 28 | +- **THEN** the export proceeds normally with no errors |
| 29 | + |
| 30 | +#### Scenario: onBeforeExport columnTitles excludes hidden columns |
| 31 | + |
| 32 | +- **WHEN** the user has hidden one or more columns |
| 33 | +- **AND** an export is triggered |
| 34 | +- **THEN** `columnTitles` contains only the headers of the currently visible, exported columns |
| 35 | + |
| 36 | +--- |
| 37 | + |
| 38 | +### Requirement: onAfterExport action fires after export completes |
| 39 | + |
| 40 | +The widget SHALL expose an optional `onAfterExport` action property. When configured, the widget MUST call `onAfterExport.execute(args)` once, fire-and-forget, after the export request resolves — whether it completed successfully or was aborted by the user. |
| 41 | + |
| 42 | +The action MUST receive the following variables: |
| 43 | + |
| 44 | +- `gridName` (String) — same as `onBeforeExport.gridName` |
| 45 | +- `columnTitles` (String) — same as `onBeforeExport.columnTitles` |
| 46 | +- `chunkSize` (Integer) — same as `onBeforeExport.chunkSize` |
| 47 | +- `fileName` (String) — same as `onBeforeExport.fileName` |
| 48 | +- `sheetName` (String) — same as `onBeforeExport.sheetName` |
| 49 | +- `exportedItemCount` (Integer) — total number of rows actually streamed to the export handler before the request ended |
| 50 | +- `status` (String) — `"success"` if all rows were exported; `"aborted"` if the user cancelled mid-export |
| 51 | +- `startTime` (DateTime) — the same timestamp passed to `onBeforeExport` (enables duration calculation in a single microflow) |
| 52 | +- `endTime` (DateTime) — the timestamp captured after the export request's `loadend` event fires |
| 53 | + |
| 54 | +#### Scenario: onAfterExport fires with success status after complete export |
| 55 | + |
| 56 | +- **WHEN** `onAfterExport` is configured and `canExecute` is true |
| 57 | +- **AND** the export completes without interruption |
| 58 | +- **THEN** `onAfterExport.execute` is called once with `status` equal to `"success"` and `exportedItemCount` equal to the total rows streamed |
| 59 | + |
| 60 | +#### Scenario: onAfterExport fires with aborted status when user cancels |
| 61 | + |
| 62 | +- **WHEN** the user clicks cancel on the export progress dialog mid-export |
| 63 | +- **THEN** `onAfterExport.execute` is called once with `status` equal to `"aborted"` and `exportedItemCount` equal to the number of rows streamed before cancellation |
| 64 | + |
| 65 | +#### Scenario: onAfterExport is skipped when not configured |
| 66 | + |
| 67 | +- **WHEN** `onAfterExport` is not configured |
| 68 | +- **AND** an export completes or is aborted |
| 69 | +- **THEN** no error occurs and the export lifecycle completes normally |
| 70 | + |
| 71 | +#### Scenario: onAfterExport startTime matches onBeforeExport startTime |
| 72 | + |
| 73 | +- **WHEN** both `onBeforeExport` and `onAfterExport` are configured |
| 74 | +- **AND** an export runs to completion |
| 75 | +- **THEN** the `startTime` value in `onAfterExport` is identical to the `startTime` value in `onBeforeExport` |
| 76 | + |
| 77 | +#### Scenario: onAfterExport endTime is after startTime |
| 78 | + |
| 79 | +- **WHEN** `onAfterExport` fires after a completed export |
| 80 | +- **THEN** `endTime` is greater than or equal to `startTime` |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +### Requirement: Both export event actions are optional and independent |
| 85 | + |
| 86 | +The widget SHALL allow `onBeforeExport` and `onAfterExport` to be configured independently. Configuring one MUST NOT require configuring the other. |
| 87 | + |
| 88 | +#### Scenario: Only onBeforeExport configured |
| 89 | + |
| 90 | +- **WHEN** `onBeforeExport` is configured and `onAfterExport` is not |
| 91 | +- **AND** an export runs to completion |
| 92 | +- **THEN** `onBeforeExport` fires once and no error occurs for the missing `onAfterExport` |
| 93 | + |
| 94 | +#### Scenario: Only onAfterExport configured |
| 95 | + |
| 96 | +- **WHEN** `onAfterExport` is configured and `onBeforeExport` is not |
| 97 | +- **AND** an export runs to completion |
| 98 | +- **THEN** `onAfterExport` fires once and no error occurs for the missing `onBeforeExport` |
| 99 | + |
| 100 | +#### Scenario: Neither action configured |
| 101 | + |
| 102 | +- **WHEN** neither `onBeforeExport` nor `onAfterExport` is configured |
| 103 | +- **AND** an export runs |
| 104 | +- **THEN** the export behaves identically to before this feature was introduced |
0 commit comments