@webiny/mcp 6.0.0 → 6.1.0-beta.1
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/agents/claude.d.ts +2 -2
- package/agents/claude.js.map +1 -1
- package/agents/cline.d.ts +2 -2
- package/agents/cline.js.map +1 -1
- package/agents/copilot.d.ts +2 -2
- package/agents/copilot.js +1 -1
- package/agents/copilot.js.map +1 -1
- package/agents/cursor.d.ts +2 -2
- package/agents/cursor.js.map +1 -1
- package/agents/instructions.js +1 -1
- package/agents/instructions.js.map +1 -1
- package/agents/kiro.d.ts +15 -0
- package/agents/kiro.js +33 -0
- package/agents/kiro.js.map +1 -0
- package/agents/opencode.d.ts +22 -0
- package/agents/opencode.js +76 -0
- package/agents/opencode.js.map +1 -0
- package/agents/shared.d.ts +5 -5
- package/agents/shared.js +3 -3
- package/agents/shared.js.map +1 -1
- package/agents/windsurf.d.ts +2 -2
- package/agents/windsurf.js.map +1 -1
- package/bin.d.ts +2 -0
- package/bin.js +4 -0
- package/bin.js.map +1 -0
- package/cli/ConfigureMcp.d.ts +7 -14
- package/cli/ConfigureMcp.js +24 -52
- package/cli/ConfigureMcp.js.map +1 -1
- package/cli/McpServer.d.ts +3 -10
- package/cli/McpServer.js +83 -109
- package/cli/McpServer.js.map +1 -1
- package/cli.d.ts +1 -0
- package/cli.js +60 -0
- package/cli.js.map +1 -0
- package/index.d.ts +6 -1
- package/index.js +7 -1
- package/index.js.map +1 -1
- package/package.json +11 -23
- package/skills/admin/admin-architect/SKILL.md +389 -0
- package/skills/admin/ui-extensions/SKILL.md +268 -0
- package/skills/api/api-architect/SKILL.md +189 -0
- package/skills/api/custom-field-type/SKILL.md +263 -0
- package/skills/api/event-handler-pattern/SKILL.md +131 -0
- package/skills/{custom-graphql-api → api/graphql-api}/SKILL.md +3 -3
- package/skills/api/use-case-pattern/SKILL.md +102 -0
- package/skills/cli-extensions/SKILL.md +45 -47
- package/skills/configure-auth0/SKILL.md +4 -4
- package/skills/configure-okta/SKILL.md +3 -3
- package/skills/content-models/SKILL.md +197 -196
- package/skills/dependency-injection/SKILL.md +9 -219
- package/skills/full-stack-architect/SKILL.md +195 -0
- package/skills/generated/admin/SKILL.md +119 -0
- package/skills/generated/admin/aco/SKILL.md +28 -0
- package/skills/generated/admin/build-params/SKILL.md +33 -0
- package/skills/generated/admin/cms/SKILL.md +342 -0
- package/skills/generated/admin/configs/SKILL.md +23 -0
- package/skills/generated/admin/env-config/SKILL.md +30 -0
- package/skills/generated/admin/form/SKILL.md +88 -0
- package/skills/generated/admin/graphql-client/SKILL.md +23 -0
- package/skills/generated/admin/lexical/SKILL.md +105 -0
- package/skills/generated/admin/local-storage/SKILL.md +42 -0
- package/skills/generated/admin/router/SKILL.md +48 -0
- package/skills/generated/admin/security/SKILL.md +63 -0
- package/skills/generated/admin/tenancy/SKILL.md +64 -0
- package/skills/generated/admin/ui/SKILL.md +468 -0
- package/skills/generated/admin/website-builder/SKILL.md +318 -0
- package/skills/generated/api/SKILL.md +40 -0
- package/skills/generated/api/aco/SKILL.md +202 -0
- package/skills/generated/api/build-params/SKILL.md +31 -0
- package/skills/generated/api/cms/SKILL.md +646 -0
- package/skills/generated/api/event-publisher/SKILL.md +31 -0
- package/skills/generated/api/file-manager/SKILL.md +189 -0
- package/skills/generated/api/graphql/SKILL.md +61 -0
- package/skills/generated/api/key-value-store/SKILL.md +31 -0
- package/skills/generated/api/logger/SKILL.md +25 -0
- package/skills/generated/api/opensearch/SKILL.md +39 -0
- package/skills/generated/api/scheduler/SKILL.md +112 -0
- package/skills/generated/api/security/SKILL.md +317 -0
- package/skills/generated/api/system/SKILL.md +34 -0
- package/skills/generated/api/tasks/SKILL.md +31 -0
- package/skills/generated/api/tenancy/SKILL.md +124 -0
- package/skills/generated/api/tenant-manager/SKILL.md +34 -0
- package/skills/generated/api/website-builder/SKILL.md +356 -0
- package/skills/generated/cli/SKILL.md +28 -0
- package/skills/generated/cli/command/SKILL.md +24 -0
- package/skills/generated/extensions/SKILL.md +43 -0
- package/skills/generated/infra/SKILL.md +190 -0
- package/skills/infrastructure-extensions/SKILL.md +3 -2
- package/skills/local-development/SKILL.md +2 -28
- package/skills/project-structure/SKILL.md +78 -56
- package/skills/webiny-sdk/SKILL.md +77 -76
- package/skills/website-builder/SKILL.md +143 -149
- package/ui.d.ts +24 -0
- package/ui.js +31 -0
- package/ui.js.map +1 -0
- package/Extension.d.ts +0 -2
- package/Extension.js +0 -11
- package/Extension.js.map +0 -1
- package/skills/admin-ui-extensions/SKILL.md +0 -267
- package/skills/api-custom-feature/SKILL.md +0 -195
- package/skills/lifecycle-events/SKILL.md +0 -348
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: webiny-content-models
|
|
2
|
+
name: webiny-api-cms-content-models
|
|
3
3
|
context: webiny-extensions
|
|
4
4
|
description: >
|
|
5
5
|
Creating Headless CMS content models via code using the ModelFactory pattern.
|
|
@@ -7,7 +7,8 @@ description: >
|
|
|
7
7
|
definitions, define fields and validators, set up reference fields between models,
|
|
8
8
|
configure field layouts, or work with the ModelFactory builder API. Also covers field types
|
|
9
9
|
(text, number, boolean, datetime, file, ref, object, richText) and validation (required,
|
|
10
|
-
unique, email, pattern, minLength, maxLength, gte, predefinedValues)
|
|
10
|
+
unique, email, pattern, minLength, maxLength, gte, predefinedValues),
|
|
11
|
+
single-entry (singleton) models via .singleEntry(), and model/field tags via .tags().
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
# Creating Content Models via Code
|
|
@@ -24,25 +25,27 @@ Every code-based content model follows the same structure:
|
|
|
24
25
|
import { ModelFactory } from "webiny/api/cms/model";
|
|
25
26
|
|
|
26
27
|
class MyModelImpl implements ModelFactory.Interface {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
async execute(builder: ModelFactory.Builder) {
|
|
29
|
+
return [
|
|
30
|
+
builder
|
|
31
|
+
.public({ modelId: "myModel", name: "My Model", group: "ungrouped" })
|
|
32
|
+
.description("Description of the model")
|
|
33
|
+
.fields(fields => ({
|
|
34
|
+
// field definitions here
|
|
35
|
+
}))
|
|
36
|
+
.layout([
|
|
37
|
+
/* row definitions */
|
|
38
|
+
])
|
|
39
|
+
.titleFieldId("fieldId")
|
|
40
|
+
.singularApiName("MyModel")
|
|
41
|
+
.pluralApiName("MyModels")
|
|
42
|
+
];
|
|
43
|
+
}
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
export const MyModel = ModelFactory.createImplementation({
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
implementation: MyModelImpl,
|
|
48
|
+
dependencies: []
|
|
46
49
|
});
|
|
47
50
|
```
|
|
48
51
|
|
|
@@ -54,53 +57,56 @@ Register in `webiny.config.tsx`:
|
|
|
54
57
|
|
|
55
58
|
## Model Configuration Methods
|
|
56
59
|
|
|
57
|
-
| Method
|
|
58
|
-
|
|
59
|
-
| `.public({ modelId, name, group })`
|
|
60
|
-
| `.description("...")`
|
|
61
|
-
| `.fields(fields => ({ ... }))`
|
|
62
|
-
| `.layout([["field1", "field2"], ["field3"]])` | Arrange fields in rows in the Admin editor. Each inner array is one row.
|
|
63
|
-
| `.titleFieldId("name")`
|
|
64
|
-
| `.descriptionFieldId("message")`
|
|
65
|
-
| `.singularApiName("Product")`
|
|
66
|
-
| `.pluralApiName("Products")`
|
|
60
|
+
| Method | Purpose |
|
|
61
|
+
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `.public({ modelId, name, group })` | Creates a public model (accessible via Read API). `modelId` is the internal DB identifier. `group` organizes it in the Admin sidebar. |
|
|
63
|
+
| `.description("...")` | Model description shown in Admin UI |
|
|
64
|
+
| `.fields(fields => ({ ... }))` | Define all fields using the fluent field builder |
|
|
65
|
+
| `.layout([["field1", "field2"], ["field3"]])` | Arrange fields in rows in the Admin editor. Each inner array is one row. |
|
|
66
|
+
| `.titleFieldId("name")` | Which field to use as the entry's display title |
|
|
67
|
+
| `.descriptionFieldId("message")` | Which field to use as the entry's description |
|
|
68
|
+
| `.singularApiName("Product")` | Singular name for GraphQL queries (e.g., `getProduct`) |
|
|
69
|
+
| `.pluralApiName("Products")` | Plural name for GraphQL queries (e.g., `listProducts`) |
|
|
70
|
+
| `.singleEntry()` | Makes the model a singleton (only one entry can exist). Automatically adds the `"singleEntry"` tag. |
|
|
71
|
+
| `.tags(["tag1", "tag2"])` | Assign custom tags to the model. The tag `"type:model"` is always added automatically. Duplicates are removed. |
|
|
67
72
|
|
|
68
73
|
## Field Types
|
|
69
74
|
|
|
70
|
-
| Builder Method
|
|
71
|
-
|
|
72
|
-
| `fields.text()`
|
|
73
|
-
| `fields.longText()` | Multi-line text
|
|
74
|
-
| `fields.richText()` | Rich text (Lexical)
|
|
75
|
-
| `fields.number()`
|
|
76
|
-
| `fields.boolean()`
|
|
77
|
-
| `fields.datetime()` | Date/time picker
|
|
78
|
-
| `fields.file()`
|
|
79
|
-
| `fields.ref()`
|
|
80
|
-
| `fields.object()`
|
|
75
|
+
| Builder Method | Description | Common Renderers |
|
|
76
|
+
| ------------------- | ----------------------------- | -------------------------------------------- |
|
|
77
|
+
| `fields.text()` | Single-line text | `"textInput"` |
|
|
78
|
+
| `fields.longText()` | Multi-line text | `"textarea"` |
|
|
79
|
+
| `fields.richText()` | Rich text (Lexical) | `"lexicalTextInput"` |
|
|
80
|
+
| `fields.number()` | Numeric value | `"numberInput"` |
|
|
81
|
+
| `fields.boolean()` | True/false toggle | `"boolean"` |
|
|
82
|
+
| `fields.datetime()` | Date/time picker | `"dateTimeInput"` |
|
|
83
|
+
| `fields.file()` | File/image attachment | `"fileInput"` |
|
|
84
|
+
| `fields.ref()` | Reference to another model | `"refDialogSingle"`, `"refAdvancedMultiple"` |
|
|
85
|
+
| `fields.object()` | Nested object with sub-fields | `"objectInput"` |
|
|
81
86
|
|
|
82
87
|
## Field Validators (Chainable)
|
|
83
88
|
|
|
84
|
-
| Validator
|
|
85
|
-
|
|
86
|
-
| `.required("msg")`
|
|
87
|
-
| `.unique()`
|
|
88
|
-
| `.email()`
|
|
89
|
-
| `.pattern(regex, msg)`
|
|
90
|
-
| `.minLength(n)`
|
|
91
|
-
| `.maxLength(n)`
|
|
92
|
-
| `.gte(n, msg)`
|
|
93
|
-
| `.predefinedValues([...])` | Restrict to predefined options
|
|
89
|
+
| Validator | Description | Example |
|
|
90
|
+
| -------------------------- | ----------------------------------- | -------------------------------------------------------- |
|
|
91
|
+
| `.required("msg")` | Field is required | `.required("Name is required")` |
|
|
92
|
+
| `.unique()` | Value must be unique across entries | `.unique()` |
|
|
93
|
+
| `.email()` | Must be a valid email | `.email()` |
|
|
94
|
+
| `.pattern(regex, msg)` | Must match a regex | `.pattern("^[a-z0-9-]+$", "Lowercase and hyphens only")` |
|
|
95
|
+
| `.minLength(n)` | Minimum string length | `.minLength(2)` |
|
|
96
|
+
| `.maxLength(n)` | Maximum string length | `.maxLength(100)` |
|
|
97
|
+
| `.gte(n, msg)` | Greater than or equal (numbers) | `.gte(0, "Must be non-negative")` |
|
|
98
|
+
| `.predefinedValues([...])` | Restrict to predefined options | `.predefinedValues([{ label: "Work", value: "work" }])` |
|
|
94
99
|
|
|
95
100
|
## Field Configuration (Chainable)
|
|
96
101
|
|
|
97
|
-
| Method
|
|
98
|
-
|
|
99
|
-
| `.renderer("rendererName")`
|
|
100
|
-
| `.label("Display Name")`
|
|
101
|
-
| `.help("Helper text")`
|
|
102
|
-
| `.list()`
|
|
102
|
+
| Method | Description |
|
|
103
|
+
| ------------------------------- | -------------------------------------------------- |
|
|
104
|
+
| `.renderer("rendererName")` | Set the Admin UI renderer |
|
|
105
|
+
| `.label("Display Name")` | Field label in the editor |
|
|
106
|
+
| `.help("Helper text")` | Helper text shown below the field |
|
|
107
|
+
| `.list()` | Make the field accept multiple values (arrays) |
|
|
103
108
|
| `.models([{ modelId: "..." }])` | For `ref()` fields: which models can be referenced |
|
|
109
|
+
| `.tags(["tag1"])` | Assign tags to a field (e.g., `"$bulk-edit"`) |
|
|
104
110
|
|
|
105
111
|
## Full Examples
|
|
106
112
|
|
|
@@ -113,48 +119,44 @@ import { ModelFactory } from "webiny/api/cms/model";
|
|
|
113
119
|
export const PRODUCT_CATEGORY_MODEL_ID = "productCategory";
|
|
114
120
|
|
|
115
121
|
class ProductCategoryModelImpl implements ModelFactory.Interface {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
.singularApiName("ProductCategory")
|
|
150
|
-
.pluralApiName("ProductCategories")
|
|
151
|
-
];
|
|
152
|
-
}
|
|
122
|
+
async execute(builder: ModelFactory.Builder) {
|
|
123
|
+
return [
|
|
124
|
+
builder
|
|
125
|
+
.public({
|
|
126
|
+
modelId: PRODUCT_CATEGORY_MODEL_ID,
|
|
127
|
+
name: "Product Category",
|
|
128
|
+
group: "ungrouped"
|
|
129
|
+
})
|
|
130
|
+
.description("Product categories for organizing products")
|
|
131
|
+
.fields(fields => ({
|
|
132
|
+
name: fields
|
|
133
|
+
.text()
|
|
134
|
+
.renderer("textInput")
|
|
135
|
+
.label("Name")
|
|
136
|
+
.help("Name of the product category")
|
|
137
|
+
.required("Name is required")
|
|
138
|
+
.minLength(2)
|
|
139
|
+
.maxLength(100),
|
|
140
|
+
slug: fields
|
|
141
|
+
.text()
|
|
142
|
+
.renderer("textInput")
|
|
143
|
+
.label("Slug")
|
|
144
|
+
.help("URL-friendly identifier")
|
|
145
|
+
.required("Slug is required")
|
|
146
|
+
.unique(),
|
|
147
|
+
description: fields.longText().renderer("textarea").label("Description").minLength(10)
|
|
148
|
+
}))
|
|
149
|
+
.layout([["name", "slug"], ["description"]])
|
|
150
|
+
.titleFieldId("name")
|
|
151
|
+
.singularApiName("ProductCategory")
|
|
152
|
+
.pluralApiName("ProductCategories")
|
|
153
|
+
];
|
|
154
|
+
}
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
export const ProductCategoryModel = ModelFactory.createImplementation({
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
implementation: ProductCategoryModelImpl,
|
|
159
|
+
dependencies: []
|
|
158
160
|
});
|
|
159
161
|
```
|
|
160
162
|
|
|
@@ -167,57 +169,57 @@ import { ModelFactory } from "webiny/api/cms/model";
|
|
|
167
169
|
export const PRODUCT_MODEL_ID = "product";
|
|
168
170
|
|
|
169
171
|
class ProductModelImpl implements ModelFactory.Interface {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
172
|
+
async execute(builder: ModelFactory.Builder) {
|
|
173
|
+
return [
|
|
174
|
+
builder
|
|
175
|
+
.public({
|
|
176
|
+
modelId: PRODUCT_MODEL_ID,
|
|
177
|
+
name: "Product",
|
|
178
|
+
group: "ungrouped"
|
|
179
|
+
})
|
|
180
|
+
.description("Products for our e-commerce store")
|
|
181
|
+
.fields(fields => ({
|
|
182
|
+
name: fields
|
|
183
|
+
.text()
|
|
184
|
+
.renderer("textInput")
|
|
185
|
+
.label("Name")
|
|
186
|
+
.help("Product name")
|
|
187
|
+
.required("Name is required"),
|
|
188
|
+
sku: fields
|
|
189
|
+
.text()
|
|
190
|
+
.renderer("textInput")
|
|
191
|
+
.label("SKU")
|
|
192
|
+
.help("Stock Keeping Unit - unique product identifier")
|
|
193
|
+
.required("SKU is required")
|
|
194
|
+
.unique(),
|
|
195
|
+
description: fields
|
|
196
|
+
.longText()
|
|
197
|
+
.renderer("textarea")
|
|
198
|
+
.label("Description")
|
|
199
|
+
.help("Detailed product description"),
|
|
200
|
+
price: fields
|
|
201
|
+
.number()
|
|
202
|
+
.renderer("numberInput")
|
|
203
|
+
.label("Price")
|
|
204
|
+
.required("Price is required")
|
|
205
|
+
.gte(0, "Price must be greater than or equal to 0"),
|
|
206
|
+
category: fields
|
|
207
|
+
.ref()
|
|
208
|
+
.renderer("refDialogSingle")
|
|
209
|
+
.label("Category")
|
|
210
|
+
.models([{ modelId: "productCategory" }])
|
|
211
|
+
}))
|
|
212
|
+
.layout([["name"], ["sku"], ["category"], ["description"], ["price"]])
|
|
213
|
+
.titleFieldId("name")
|
|
214
|
+
.singularApiName("Product")
|
|
215
|
+
.pluralApiName("Products")
|
|
216
|
+
];
|
|
217
|
+
}
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
export const ProductModel = ModelFactory.createImplementation({
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
implementation: ProductModelImpl,
|
|
222
|
+
dependencies: []
|
|
221
223
|
});
|
|
222
224
|
```
|
|
223
225
|
|
|
@@ -230,61 +232,61 @@ import { ModelFactory } from "webiny/api/cms/model";
|
|
|
230
232
|
export const CONTACT_SUBMISSION_MODEL_ID = "contactSubmission";
|
|
231
233
|
|
|
232
234
|
class ContactSubmissionModelImpl implements ModelFactory.Interface {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
235
|
+
async execute(builder: ModelFactory.Builder) {
|
|
236
|
+
return [
|
|
237
|
+
builder
|
|
238
|
+
.public({
|
|
239
|
+
modelId: CONTACT_SUBMISSION_MODEL_ID,
|
|
240
|
+
name: "Contact Submission",
|
|
241
|
+
group: "ungrouped"
|
|
242
|
+
})
|
|
243
|
+
.description("Stores contact form submissions from the website")
|
|
244
|
+
.fields(fields => ({
|
|
245
|
+
name: fields
|
|
246
|
+
.text()
|
|
247
|
+
.renderer("textInput")
|
|
248
|
+
.label("Name")
|
|
249
|
+
.help("Enter your full name")
|
|
250
|
+
.required("Name is required")
|
|
251
|
+
.minLength(2)
|
|
252
|
+
.maxLength(100),
|
|
253
|
+
email: fields
|
|
254
|
+
.text()
|
|
255
|
+
.renderer("textInput")
|
|
256
|
+
.label("Email")
|
|
257
|
+
.help("Enter a valid email address")
|
|
258
|
+
.required("Email is required")
|
|
259
|
+
.email(),
|
|
260
|
+
message: fields
|
|
261
|
+
.longText()
|
|
262
|
+
.renderer("textarea")
|
|
263
|
+
.label("Message")
|
|
264
|
+
.help("Enter your message...")
|
|
265
|
+
.required("Message is required")
|
|
266
|
+
.minLength(10)
|
|
267
|
+
.maxLength(1000),
|
|
268
|
+
emailType: fields
|
|
269
|
+
.text()
|
|
270
|
+
.renderer("radioButtons")
|
|
271
|
+
.label("Email Type")
|
|
272
|
+
.help("Automatically classified as Work or Personal")
|
|
273
|
+
.predefinedValues([
|
|
274
|
+
{ label: "Work", value: "work" },
|
|
275
|
+
{ label: "Personal", value: "personal" }
|
|
276
|
+
])
|
|
277
|
+
}))
|
|
278
|
+
.layout([["name", "email"], ["message"], ["emailType"]])
|
|
279
|
+
.titleFieldId("name")
|
|
280
|
+
.descriptionFieldId("message")
|
|
281
|
+
.singularApiName("ContactSubmission")
|
|
282
|
+
.pluralApiName("ContactSubmissions")
|
|
283
|
+
];
|
|
284
|
+
}
|
|
283
285
|
}
|
|
284
286
|
|
|
285
287
|
export const ContactSubmissionModel = ModelFactory.createImplementation({
|
|
286
|
-
|
|
287
|
-
|
|
288
|
+
implementation: ContactSubmissionModelImpl,
|
|
289
|
+
dependencies: []
|
|
288
290
|
});
|
|
289
291
|
```
|
|
290
292
|
|
|
@@ -301,6 +303,5 @@ Deploy: yarn webiny deploy api (or use watch mode)
|
|
|
301
303
|
|
|
302
304
|
## Related Skills
|
|
303
305
|
|
|
304
|
-
- `dependency-injection` -- The `createImplementation` pattern used here
|
|
305
|
-
- `lifecycle-events` -- Hook into create/update/delete events on your models
|
|
306
|
+
- `webiny-dependency-injection` -- The `createImplementation` pattern used here
|
|
306
307
|
- `webiny-sdk` -- Query and write data to your models from external apps
|