Skip to content

Commit 89a60f6

Browse files
authored
Merge pull request #333 from hjotha/submit/microflow-download-file-statement
feat: support microflow download file statement
2 parents 104ba11 + 1524dc5 commit 89a60f6

35 files changed

Lines changed: 15363 additions & 14669 deletions

.claude/skills/mendix/write-microflows.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,17 @@ rest call delete 'https://api.example.com/items/{1}' with (
824824

825825
**REST CALL supports full error handling** (`on error continue`, `on error rollback`, custom error handlers).
826826

827+
## File Downloads
828+
829+
Use `download file` to stream a `System.FileDocument` from a microflow. Add
830+
`show in browser` when the action should open the file inline instead of forcing
831+
a download.
832+
833+
```mdl
834+
download file $GeneratedReport show in browser;
835+
download file $GeneratedExport;
836+
```
837+
827838
## Error Handling
828839

829840
MDL supports error handling for activities that may fail (microflow calls, commits, external service calls, etc.).

cmd/mxcli/lsp_completions_gen.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/01-project/MDL_QUICK_REFERENCE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ authentication basic, session
225225
| Call nanoflow | `$Result = call nanoflow Module.Name (Param = $value);` | |
226226
| Show page | `show page Module.PageName ($Param = $value);` | Also accepts `(Param: $value)` |
227227
| Close page | `close page;` | |
228+
| Download file | `download file $FileDocument [show in browser];` | Streams a `System.FileDocument` |
228229
| Validation | `validation feedback $entity/attribute message 'message';` | Requires attribute path + MESSAGE |
229230
| Log | `log info\|warning\|error [node 'name'] 'message';` | |
230231
| Position | `@position(x, y)` | Canvas position (before activity) |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Microflow Download File Statement
2+
3+
Status: Draft
4+
5+
## Summary
6+
7+
Add MDL syntax for Mendix `Microflows$DownloadFileAction`:
8+
9+
```mdl
10+
download file $GeneratedReport;
11+
download file $GeneratedReport show in browser;
12+
```
13+
14+
The feature is intentionally small: it exposes an existing Studio Pro microflow
15+
activity without adding new semantics.
16+
17+
## Motivation
18+
19+
Projects that already contain download-file actions should survive
20+
describe/exec/describe without losing the activity or falling back to an
21+
unsupported-action comment. The statement also gives users a straightforward way
22+
to author file downloads when the file document variable already exists.
23+
24+
## Syntax
25+
26+
```antlr
27+
downloadFileStatement
28+
: DOWNLOAD FILE_KW VARIABLE (SHOW IN BROWSER)? onErrorClause? SEMICOLON
29+
;
30+
```
31+
32+
Examples:
33+
34+
```mdl
35+
download file $GeneratedExport;
36+
download file $GeneratedReport show in browser on error rollback;
37+
```
38+
39+
## Semantics
40+
41+
- The operand must be a variable containing a `System.FileDocument`.
42+
- `show in browser` maps to Studio Pro's `ShowInBrowser` flag.
43+
- Error handling follows the normal microflow action `on error ...` forms.
44+
45+
## Tests And Examples
46+
47+
- Parser/visitor coverage for both normal and `show in browser` forms.
48+
- Builder/writer coverage for `DownloadFileAction`.
49+
- Example script: `mdl-examples/doctype-tests/download_file.test.mdl`.

docs/11-proposals/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ BSON schema Registry ◄──── multi-version Support
4343
|----------|--------|---------|------------|
4444
| [MDL Syntax Improvements v1](PROPOSAL_mdl_syntax_improvements.md) | Draft | Go-style assignment, C-style braces, fluent list APIs ||
4545
| [MDL Syntax Improvements v2](PROPOSAL_mdl_syntax_improvements_v2.md) | Proposed | Consolidated v2: unified variable declaration, C-style braces, fluent list ops | Syntax Improvements v1 |
46+
| [Microflow Download File Statement](PROPOSAL_microflow_download_file_statement.md) | Draft | `download file $FileDocument [show in browser]` for `DownloadFileAction` round-trip and authoring ||
4647
| [Page Syntax V2](PROPOSAL_page_syntax_v2.md) | Superseded | Page/widget syntax with `{}` blocks and `->` binding. Superseded by V3 (archived) ||
4748
| [Page Styling Support](page-styling-support.md) | Partial | CSS classes, inline styles, dynamic classes, design properties. Phase 1 (Class/Style) done ||
4849
| [Page Composition](proposal_page_composition.md) | Proposed | Fragment definitions and ALTER PAGE for partial page editing | Page Syntax V2, Page Styling |
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
create microflow SampleFiles.ACT_DownloadReport (
2+
$GeneratedReport: System.FileDocument
3+
)
4+
returns Void
5+
begin
6+
download file $GeneratedReport show in browser;
7+
return;
8+
end;
9+
/
10+
11+
create microflow SampleFiles.ACT_DownloadExport (
12+
$GeneratedExport: System.FileDocument
13+
)
14+
returns Void
15+
begin
16+
download file $GeneratedExport;
17+
return;
18+
end;
19+
/

mdl/ast/ast_microflow.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,16 @@ type ShowMessageStmt struct {
570570

571571
func (s *ShowMessageStmt) isMicroflowStatement() {}
572572

573+
// DownloadFileStmt represents: DOWNLOAD FILE $FileDocument [SHOW IN BROWSER]
574+
type DownloadFileStmt struct {
575+
FileDocument string // File document variable without $ prefix
576+
ShowInBrowser bool // Whether the file opens in the browser
577+
ErrorHandling *ErrorHandlingClause // Optional ON ERROR clause
578+
Annotations *ActivityAnnotations // Optional @position, @caption, @color, @annotation
579+
}
580+
581+
func (s *DownloadFileStmt) isMicroflowStatement() {}
582+
573583
// ValidationFeedbackStmt represents: VALIDATION FEEDBACK $Var/Attr MESSAGE 'message' OBJECTS [$Var1, $Var2];
574584
type ValidationFeedbackStmt struct {
575585
AttributePath *AttributePathExpr // The attribute to associate with the feedback

mdl/executor/cmd_microflows_builder_annotations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func getStatementAnnotations(stmt ast.MicroflowStatement) *ast.ActivityAnnotatio
7171
return s.Annotations
7272
case *ast.ShowMessageStmt:
7373
return s.Annotations
74+
case *ast.DownloadFileStmt:
75+
return s.Annotations
7476
case *ast.ValidationFeedbackStmt:
7577
return s.Annotations
7678
case *ast.RestCallStmt:

mdl/executor/cmd_microflows_builder_calls.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,35 @@ func (fb *flowBuilder) addShowMessageAction(s *ast.ShowMessageStmt) model.ID {
476476
return activity.ID
477477
}
478478

479+
// addDownloadFileAction creates a DOWNLOAD FILE statement.
480+
func (fb *flowBuilder) addDownloadFileAction(s *ast.DownloadFileStmt) model.ID {
481+
action := &microflows.DownloadFileAction{
482+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
483+
FileDocument: s.FileDocument,
484+
ShowInBrowser: s.ShowInBrowser,
485+
ErrorHandlingType: microflows.ErrorHandlingTypeRollback,
486+
}
487+
if s.ErrorHandling != nil {
488+
action.ErrorHandlingType = convertErrorHandlingType(s.ErrorHandling)
489+
}
490+
491+
activity := &microflows.ActionActivity{
492+
BaseActivity: microflows.BaseActivity{
493+
BaseMicroflowObject: microflows.BaseMicroflowObject{
494+
BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
495+
Position: model.Point{X: fb.posX, Y: fb.posY},
496+
Size: model.Size{Width: ActivityWidth, Height: ActivityHeight},
497+
},
498+
AutoGenerateCaption: true,
499+
},
500+
Action: action,
501+
}
502+
503+
fb.objects = append(fb.objects, activity)
504+
fb.posX += fb.spacing
505+
return activity.ID
506+
}
507+
479508
// addClosePageAction creates a CLOSE PAGE statement.
480509
func (fb *flowBuilder) addClosePageAction(s *ast.ClosePageStmt) model.ID {
481510
numPages := s.NumberOfPages
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
package executor
4+
5+
import (
6+
"testing"
7+
8+
"github.com/mendixlabs/mxcli/mdl/ast"
9+
"github.com/mendixlabs/mxcli/sdk/microflows"
10+
)
11+
12+
func TestBuildFlowGraph_DownloadFileCreatesRealAction(t *testing.T) {
13+
fb := &flowBuilder{
14+
posX: 100,
15+
posY: 100,
16+
spacing: HorizontalSpacing,
17+
varTypes: map[string]string{"GeneratedReport": "System.FileDocument"},
18+
declaredVars: map[string]string{"GeneratedReport": "System.FileDocument"},
19+
}
20+
21+
fb.buildFlowGraph([]ast.MicroflowStatement{
22+
&ast.DownloadFileStmt{
23+
FileDocument: "GeneratedReport",
24+
ShowInBrowser: true,
25+
ErrorHandling: &ast.ErrorHandlingClause{Type: ast.ErrorHandlingContinue},
26+
},
27+
}, nil)
28+
29+
var action *microflows.DownloadFileAction
30+
for _, obj := range fb.objects {
31+
activity, ok := obj.(*microflows.ActionActivity)
32+
if !ok {
33+
continue
34+
}
35+
if dl, ok := activity.Action.(*microflows.DownloadFileAction); ok {
36+
action = dl
37+
break
38+
}
39+
}
40+
if action == nil {
41+
t.Fatal("expected DownloadFileAction")
42+
}
43+
if action.FileDocument != "GeneratedReport" {
44+
t.Fatalf("FileDocument = %q, want GeneratedReport", action.FileDocument)
45+
}
46+
if !action.ShowInBrowser {
47+
t.Fatal("ShowInBrowser = false, want true")
48+
}
49+
if action.ErrorHandlingType != microflows.ErrorHandlingTypeContinue {
50+
t.Fatalf("ErrorHandlingType = %q, want Continue", action.ErrorHandlingType)
51+
}
52+
}

0 commit comments

Comments
 (0)