Skip to content

Commit c6d705d

Browse files
[WTF-2115] Generate types for editable images and files (#159)
## Checklist - Contains unit tests ✅ ❌ - Contains breaking changes ✅ ❌ - Compatible with: MX 7️⃣, 8️⃣, 9️⃣ - Did you update version and changelog? ✅ ❌ - PR title properly formatted (`[XX-000]: description`)? ✅ ❌ ## This PR contains - [ ] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Other (describe) ## What is the purpose of this PR? It will be possible to edit file and image properties. This PR updates the typing accordingly. ## Relevant changes Type generation will now consider allowUpload attribute in the XML to generate the typings for file and image properties. ## What should be covered while testing? _..._ ## Extra comments (optional) _Please add extra comments or delete the section if not required_
2 parents 5e128cb + c104e24 commit c6d705d

File tree

11 files changed

+176
-17
lines changed

11 files changed

+176
-17
lines changed

packages/pluggable-widgets-tools/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
## [11.8.0] - 2026-03-05
10+
11+
### Added
12+
13+
- We added support for editable image and file properties, introduced in Mendix 11.8.
14+
15+
### Changed
16+
17+
- We updated the Mendix package to 11.8.
18+
919
## [11.6.0] - 2026-03-04
1020

1121
### Changed

packages/pluggable-widgets-tools/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mendix/pluggable-widgets-tools",
3-
"version": "11.6.0",
3+
"version": "11.8.0",
44
"description": "Mendix Pluggable Widgets Tools",
55
"engines": {
66
"node": ">=20"
@@ -78,7 +78,7 @@
7878
"jest-jasmine2": "^29.0.3",
7979
"jest-junit": "^13.0.0",
8080
"make-dir": "^3.1.0",
81-
"mendix": "^11.6.0",
81+
"mendix": "^11.8.0",
8282
"mime": "^3.0.0",
8383
"node-fetch": "^2.6.1",
8484
"postcss": "^8.3.11",

packages/pluggable-widgets-tools/src/typings-generator/WidgetXml.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export interface Property {
5151
isDefault?: string;
5252
dataSource?: string;
5353
onChange?: string;
54+
allowUpload?: string;
5455
};
5556
caption?: string[];
5657
category?: string[];

packages/pluggable-widgets-tools/src/typings-generator/__tests__/index.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ import { associationMetaDataNativeInput, associationMetaDataWebInput } from "./i
4545
import { associationMetaDataNativeOutput, associationMetaDataWebOutput } from "./outputs/metadata-association";
4646
import {listActionWithVariablesInput, listActionWithVariablesInputNative} from "./inputs/list-action-with-variables";
4747
import {listActionWithVariablesOutput, listActionWithVariablesOutputNative} from "./outputs/list-action-with-variables";
48+
import {imageWebInput, imageNativeInput} from "./inputs/image";
49+
import {imageWebOutput, imageNativeOutput} from "./outputs/image";
4850

4951
describe("Generating tests", () => {
5052
it("Generates a parsed typing from XML for native", () => {
@@ -236,6 +238,16 @@ describe("Generating tests", () => {
236238
const newContent = generateNativeTypesFor(associationMetaDataNativeInput);
237239
expect(newContent).toBe(associationMetaDataNativeOutput);
238240
});
241+
242+
it("Generates a parsed typing from XML for web using images", () => {
243+
const newContent = generateFullTypesFor(imageWebInput);
244+
expect(newContent).toBe(imageWebOutput);
245+
});
246+
247+
it("Generates a parsed typing from XML for native using images", () => {
248+
const newContent = generateNativeTypesFor(imageNativeInput);
249+
expect(newContent).toBe(imageNativeOutput);
250+
});
239251
});
240252

241253
function generateFullTypesFor(xml: string) {

packages/pluggable-widgets-tools/src/typings-generator/__tests__/inputs/file.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ export const fileInput = `<?xml version="1.0" encoding="utf-8"?>
1212
<caption>File 2</caption>
1313
<description />
1414
</property>
15+
<property key="file3" type="file" allowUpload="true">
16+
<caption>File 3</caption>
17+
<description />
18+
</property>
19+
<property key="file4" type="file" allowUpload="true" required="false">
20+
<caption>File 4</caption>
21+
<description />
22+
</property>
1523
</propertyGroup>
1624
<propertyGroup caption="Actions">
1725
<property key="description" type="attribute">
@@ -49,6 +57,14 @@ export const fileInputNative = `<?xml version="1.0" encoding="utf-8"?>
4957
<caption>File 2</caption>
5058
<description />
5159
</property>
60+
<property key="file3" type="file" allowUpload="true">
61+
<caption>File 3</caption>
62+
<description />
63+
</property>
64+
<property key="file4" type="file" allowUpload="true" required="false">
65+
<caption>File 4</caption>
66+
<description />
67+
</property>
5268
</propertyGroup>
5369
<propertyGroup caption="Actions">
5470
<property key="description" type="attribute">
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
export const imageWebInput = `<?xml version="1.0" encoding="utf-8"?>
2+
<widget id="mendix.mywidget.MyWidget" needsEntityContext="true" offlineCapable="true" pluginWidget="true"
3+
xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../xsd/widget.xsd">
5+
<properties>
6+
<propertyGroup caption="General">
7+
<property key="image" type="image">
8+
<caption>Image</caption>
9+
<description />
10+
</property>
11+
<property key="image2" type="image" required="false">
12+
<caption>Image 2</caption>
13+
<description />
14+
</property>
15+
<property key="image3" type="image" allowUpload="true">
16+
<caption>Image 3</caption>
17+
<description />
18+
</property>
19+
</propertyGroup>
20+
<propertyGroup caption="Actions">
21+
<property key="description" type="attribute">
22+
<caption>Action</caption>
23+
<description />
24+
<attributeTypes>
25+
<attributeType name="String"/>
26+
</attributeTypes>
27+
</property>
28+
<property key="action" type="action">
29+
<caption>Action</caption>
30+
<description />
31+
</property>
32+
</propertyGroup>
33+
<propertyGroup caption="Other">
34+
<propertyGroup caption="System Properties">
35+
<systemProperty key="Label"></systemProperty>
36+
<systemProperty key="TabIndex"></systemProperty>
37+
</propertyGroup>
38+
</propertyGroup>
39+
</properties>
40+
</widget>`;
41+
42+
export const imageNativeInput = `<?xml version="1.0" encoding="utf-8"?>
43+
<widget id="mendix.mywidget.MyWidget" needsEntityContext="true" offlineCapable="true" pluginWidget="true" supportedPlatform="Native"
44+
xmlns="http://www.mendix.com/widget/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
45+
xsi:schemaLocation="http://www.mendix.com/widget/1.0/ ../xsd/widget.xsd">
46+
<properties>
47+
<propertyGroup caption="General">
48+
<property key="image" type="image">
49+
<caption>Image</caption>
50+
<description />
51+
</property>
52+
<property key="image2" type="image" required="false">
53+
<caption>Image 2</caption>
54+
<description />
55+
</property>
56+
<property key="image3" type="image" allowUpload="true">
57+
<caption>Image 3</caption>
58+
<description />
59+
</property>
60+
</propertyGroup>
61+
<propertyGroup caption="Actions">
62+
<property key="description" type="attribute">
63+
<caption>Action</caption>
64+
<description />
65+
<attributeTypes>
66+
<attributeType name="String"/>
67+
</attributeTypes>
68+
</property>
69+
<property key="action" type="action">
70+
<caption>Action</caption>
71+
<description />
72+
</property>
73+
</propertyGroup>
74+
<propertyGroup caption="Other">
75+
<propertyGroup caption="System Properties">
76+
<systemProperty key="Label"></systemProperty>
77+
<systemProperty key="TabIndex"></systemProperty>
78+
</propertyGroup>
79+
</propertyGroup>
80+
</properties>
81+
</widget>`;

packages/pluggable-widgets-tools/src/typings-generator/__tests__/outputs/file.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ export const fileWebOutput = `/**
33
* WARNING: All changes made to this file will be overwritten
44
* @author Mendix Widgets Framework Team
55
*/
6-
import { ActionValue, DynamicValue, EditableValue, FileValue } from "mendix";
6+
import { ActionValue, DynamicValue, EditableValue, EditableFileValue, FileValue } from "mendix";
77
88
export interface MyWidgetContainerProps {
99
name: string;
1010
tabIndex?: number;
1111
id: string;
1212
file: DynamicValue<FileValue>;
1313
file2?: DynamicValue<FileValue>;
14+
file3: EditableFileValue;
15+
file4?: EditableFileValue;
1416
description: EditableValue<string>;
1517
action?: ActionValue;
1618
}
@@ -21,6 +23,8 @@ export interface MyWidgetPreviewProps {
2123
translate: (text: string) => string;
2224
file: string;
2325
file2: string;
26+
file3: string;
27+
file4: string;
2428
description: string;
2529
action: {} | null;
2630
}
@@ -30,6 +34,8 @@ export const fileNativeOutput = `export interface MyWidgetProps<Style> {
3034
style: Style[];
3135
file: DynamicValue<FileValue>;
3236
file2?: DynamicValue<FileValue>;
37+
file3: EditableFileValue;
38+
file4?: EditableFileValue;
3339
description: EditableValue<string>;
3440
action?: ActionValue;
3541
}`;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export const imageWebOutput = `/**
2+
* This file was generated from MyWidget.xml
3+
* WARNING: All changes made to this file will be overwritten
4+
* @author Mendix Widgets Framework Team
5+
*/
6+
import { ActionValue, DynamicValue, EditableValue, EditableImageValue, WebImage } from "mendix";
7+
8+
export interface MyWidgetContainerProps {
9+
name: string;
10+
tabIndex?: number;
11+
id: string;
12+
image: DynamicValue<WebImage>;
13+
image2?: DynamicValue<WebImage>;
14+
image3: EditableImageValue<WebImage>;
15+
description: EditableValue<string>;
16+
action?: ActionValue;
17+
}
18+
19+
export interface MyWidgetPreviewProps {
20+
readOnly: boolean;
21+
renderMode: "design" | "xray" | "structure";
22+
translate: (text: string) => string;
23+
image: { type: "static"; imageUrl: string; } | { type: "dynamic"; entity: string; } | null;
24+
image2: { type: "static"; imageUrl: string; } | { type: "dynamic"; entity: string; } | null;
25+
image3: { type: "static"; imageUrl: string; } | { type: "dynamic"; entity: string; } | null;
26+
description: string;
27+
action: {} | null;
28+
}
29+
`;
30+
export const imageNativeOutput = `export interface MyWidgetProps<Style> {
31+
name: string;
32+
style: Style[];
33+
image: DynamicValue<NativeImage>;
34+
image2?: DynamicValue<NativeImage>;
35+
image3: DynamicValue<NativeImage>;
36+
description: EditableValue<string>;
37+
action?: ActionValue;
38+
}`;

packages/pluggable-widgets-tools/src/typings-generator/generate.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const mxExports = [
1010
"DynamicValue",
1111
"EditableValue",
1212
"EditableListValue",
13+
"EditableFileValue",
14+
"EditableImageValue",
1315
"FileValue",
1416
"ListValue",
1517
"NativeIcon",

packages/pluggable-widgets-tools/src/typings-generator/generateClientTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ function toClientPropType(
131131
case "icon":
132132
return isNative ? "DynamicValue<NativeIcon>" : "DynamicValue<WebIcon>";
133133
case "image":
134-
return isNative ? "DynamicValue<NativeImage>" : "DynamicValue<WebImage>";
134+
return isNative ? "DynamicValue<NativeImage>" : prop.$.allowUpload === "true" ? "EditableImageValue<WebImage>" : "DynamicValue<WebImage>";
135135
case "file":
136-
return "DynamicValue<FileValue>";
136+
return prop.$.allowUpload ? "EditableFileValue" : "DynamicValue<FileValue>";
137137
case "datasource":
138138
return "ListValue";
139139
case "attribute": {

0 commit comments

Comments
 (0)