odac 0.9.0 → 1.0.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/.github/workflows/auto-pr-description.yml +0 -2
- package/.github/workflows/codeql.yml +46 -0
- package/.github/workflows/release.yml +13 -6
- package/.github/workflows/test-coverage.yml +10 -9
- package/.releaserc.js +9 -6
- package/CHANGELOG.md +62 -150
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTING.md +8 -8
- package/LICENSE +21 -661
- package/README.md +12 -12
- package/SECURITY.md +4 -4
- package/bin/odac.js +101 -0
- package/{framework/web/candy.js → client/odac.js} +310 -44
- package/docs/backend/01-overview/{01-whats-in-the-candy-box.md → 01-whats-in-the-odac-box.md} +4 -2
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +29 -1
- package/docs/backend/01-overview/03-development-server.md +11 -11
- package/docs/backend/02-structure/01-typical-project-layout.md +4 -4
- package/docs/backend/03-config/00-configuration-overview.md +6 -6
- package/docs/backend/03-config/01-database-connection.md +1 -1
- package/docs/backend/03-config/02-static-route-mapping-optional.md +4 -4
- package/docs/backend/03-config/04-environment-variables.md +20 -20
- package/docs/backend/03-config/05-early-hints.md +4 -4
- package/docs/backend/04-routing/01-basic-page-routes.md +4 -4
- package/docs/backend/04-routing/02-controller-less-view-routes.md +5 -5
- package/docs/backend/04-routing/03-api-and-data-routes.md +3 -3
- package/docs/backend/04-routing/04-authentication-aware-routes.md +5 -5
- package/docs/backend/04-routing/05-advanced-routing.md +3 -3
- package/docs/backend/04-routing/06-error-pages.md +17 -17
- package/docs/backend/04-routing/07-cron-jobs.md +13 -13
- package/docs/backend/04-routing/08-middleware.md +214 -0
- package/docs/backend/04-routing/09-websocket-auth-middleware.md +292 -0
- package/docs/backend/04-routing/09-websocket-examples.md +381 -0
- package/docs/backend/04-routing/09-websocket-quick-reference.md +211 -0
- package/docs/backend/04-routing/09-websocket.md +298 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +3 -3
- package/docs/backend/05-controllers/02-your-trusty-odac-assistant.md +41 -0
- package/docs/backend/05-controllers/03-controller-classes.md +19 -19
- package/docs/backend/05-forms/01-custom-forms.md +114 -114
- package/docs/backend/05-forms/02-automatic-database-insert.md +82 -82
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +26 -26
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +10 -10
- package/docs/backend/07-views/01-the-view-directory.md +1 -1
- package/docs/backend/07-views/02-rendering-a-view.md +22 -22
- package/docs/backend/07-views/03-template-syntax.md +52 -52
- package/docs/backend/07-views/03-variables.md +84 -84
- package/docs/backend/07-views/04-request-data.md +57 -57
- package/docs/backend/07-views/05-conditionals.md +78 -78
- package/docs/backend/07-views/06-loops.md +114 -114
- package/docs/backend/07-views/07-translations.md +66 -66
- package/docs/backend/07-views/08-backend-javascript.md +103 -103
- package/docs/backend/07-views/09-comments.md +71 -71
- package/docs/backend/08-database/01-database-connection.md +8 -8
- package/docs/backend/08-database/02-using-mysql.md +49 -49
- package/docs/backend/09-validation/01-the-validator-service.md +38 -38
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +15 -15
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +10 -10
- package/docs/backend/10-authentication/03-register.md +12 -12
- package/docs/backend/10-authentication/{04-candy-register-forms.md → 04-odac-register-forms.md} +141 -141
- package/docs/backend/10-authentication/05-session-management.md +10 -10
- package/docs/backend/10-authentication/{06-candy-login-forms.md → 06-odac-login-forms.md} +125 -125
- package/docs/backend/11-mail/01-the-mail-service.md +5 -5
- package/docs/backend/12-streaming/01-streaming-overview.md +96 -54
- package/docs/backend/13-utilities/{01-candy-var.md → 01-odac-var.md} +109 -109
- package/docs/frontend/01-overview/01-introduction.md +30 -30
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +45 -45
- package/docs/frontend/02-ajax-navigation/02-configuration.md +14 -14
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +36 -36
- package/docs/frontend/03-forms/01-form-handling.md +32 -32
- package/docs/frontend/04-api-requests/01-get-post.md +33 -33
- package/docs/frontend/05-streaming/01-client-streaming.md +15 -15
- package/docs/frontend/06-websocket/00-overview.md +76 -0
- package/docs/frontend/06-websocket/01-websocket-client.md +139 -0
- package/docs/frontend/06-websocket/02-shared-websocket.md +149 -0
- package/docs/index.json +49 -11
- package/eslint.config.mjs +6 -6
- package/{framework/index.js → index.js} +1 -1
- package/package.json +14 -39
- package/{framework/src → src}/Auth.js +59 -59
- package/{framework/src → src}/Config.js +3 -3
- package/{framework/src → src}/Lang.js +7 -7
- package/{framework/src → src}/Mail.js +5 -5
- package/{framework/src → src}/Mysql.js +42 -42
- package/src/Odac.js +112 -0
- package/{framework/src → src}/Request.js +38 -36
- package/{framework/src → src}/Route/Internal.js +116 -116
- package/src/Route/Middleware.js +75 -0
- package/src/Route.js +621 -0
- package/src/Server.js +22 -0
- package/{framework/src → src}/Stream.js +11 -3
- package/{framework/src → src}/Validator.js +21 -21
- package/{framework/src → src}/Var.js +5 -5
- package/{framework/src → src}/View/EarlyHints.js +1 -1
- package/{framework/src → src}/View/Form.js +69 -69
- package/{framework/src → src}/View.js +78 -81
- package/src/WebSocket.js +403 -0
- package/template/config.json +5 -0
- package/{web → template}/controller/page/about.js +6 -6
- package/{web → template}/controller/page/index.js +9 -9
- package/{web → template}/package.json +4 -5
- package/{web → template}/public/assets/css/style.css +4 -4
- package/{web → template}/public/assets/js/app.js +6 -6
- package/{web → template}/route/www.js +6 -6
- package/{web → template}/skeleton/main.html +1 -1
- package/{web → template}/view/content/about.html +5 -5
- package/{web → template}/view/content/home.html +12 -12
- package/template/view/footer/main.html +11 -0
- package/{web → template}/view/head/main.html +1 -1
- package/{web → template}/view/header/main.html +2 -2
- package/test/core/Candy.test.js +58 -58
- package/test/core/Commands.test.js +7 -7
- package/test/core/Config.test.js +82 -85
- package/test/core/Lang.test.js +2 -2
- package/test/core/Process.test.js +6 -6
- package/test/framework/Route.test.js +56 -37
- package/test/framework/View/EarlyHints.test.js +2 -2
- package/test/framework/WebSocket.test.js +100 -0
- package/test/framework/middleware.test.js +85 -0
- package/test/server/Api.test.js +31 -31
- package/test/server/DNS.test.js +11 -11
- package/test/server/Hub.test.js +497 -0
- package/test/server/Mail.account.test_.js +3 -3
- package/test/server/Mail.init.test_.js +10 -10
- package/test/server/Mail.test_.js +20 -20
- package/test/server/SSL.test_.js +54 -54
- package/test/server/Server.test.js +39 -39
- package/test/server/Service.test_.js +7 -7
- package/test/server/Subdomain.test.js +7 -7
- package/test/server/Web/Firewall.test.js +87 -87
- package/test/server/Web/Proxy.test.js +397 -0
- package/test/server/{Web.test_.js → Web.test.js} +137 -205
- package/test/server/__mocks__/fs.js +2 -2
- package/test/server/__mocks__/{globalCandy.js → globalOdac.js} +5 -5
- package/test/server/__mocks__/index.js +6 -6
- package/test/server/__mocks__/testFactories.js +1 -1
- package/test/server/__mocks__/testHelpers.js +7 -7
- package/.husky/pre-commit +0 -2
- package/.kiro/steering/code-style.md +0 -56
- package/.kiro/steering/product.md +0 -20
- package/.kiro/steering/structure.md +0 -77
- package/.kiro/steering/tech.md +0 -87
- package/AGENTS.md +0 -84
- package/bin/candy +0 -10
- package/bin/candypack +0 -10
- package/cli/index.js +0 -3
- package/cli/src/Cli.js +0 -348
- package/cli/src/Connector.js +0 -93
- package/cli/src/Monitor.js +0 -416
- package/core/Candy.js +0 -87
- package/core/Commands.js +0 -239
- package/core/Config.js +0 -1094
- package/core/Lang.js +0 -52
- package/core/Log.js +0 -43
- package/core/Process.js +0 -26
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +0 -20
- package/docs/server/01-installation/01-quick-install.md +0 -19
- package/docs/server/01-installation/02-manual-installation-via-npm.md +0 -9
- package/docs/server/02-get-started/01-core-concepts.md +0 -7
- package/docs/server/02-get-started/02-basic-commands.md +0 -57
- package/docs/server/02-get-started/03-cli-reference.md +0 -276
- package/docs/server/02-get-started/04-cli-quick-reference.md +0 -102
- package/docs/server/03-service/01-start-a-new-service.md +0 -57
- package/docs/server/03-service/02-delete-a-service.md +0 -48
- package/docs/server/04-web/01-create-a-website.md +0 -36
- package/docs/server/04-web/02-list-websites.md +0 -9
- package/docs/server/04-web/03-delete-a-website.md +0 -29
- package/docs/server/05-subdomain/01-create-a-subdomain.md +0 -32
- package/docs/server/05-subdomain/02-list-subdomains.md +0 -33
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +0 -41
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +0 -34
- package/docs/server/07-mail/01-create-a-mail-account.md +0 -23
- package/docs/server/07-mail/02-delete-a-mail-account.md +0 -20
- package/docs/server/07-mail/03-list-mail-accounts.md +0 -20
- package/docs/server/07-mail/04-change-account-password.md +0 -23
- package/framework/src/Candy.js +0 -81
- package/framework/src/Route.js +0 -455
- package/framework/src/Server.js +0 -15
- package/locale/de-DE.json +0 -80
- package/locale/en-US.json +0 -79
- package/locale/es-ES.json +0 -80
- package/locale/fr-FR.json +0 -80
- package/locale/pt-BR.json +0 -80
- package/locale/ru-RU.json +0 -80
- package/locale/tr-TR.json +0 -85
- package/locale/zh-CN.json +0 -80
- package/server/index.js +0 -5
- package/server/src/Api.js +0 -88
- package/server/src/DNS.js +0 -940
- package/server/src/Hub.js +0 -535
- package/server/src/Mail.js +0 -571
- package/server/src/SSL.js +0 -180
- package/server/src/Server.js +0 -27
- package/server/src/Service.js +0 -248
- package/server/src/Subdomain.js +0 -64
- package/server/src/Web/Firewall.js +0 -170
- package/server/src/Web/Proxy.js +0 -134
- package/server/src/Web.js +0 -451
- package/server/src/mail/imap.js +0 -1091
- package/server/src/mail/server.js +0 -32
- package/server/src/mail/smtp.js +0 -786
- package/test/server/Client.test.js +0 -338
- package/test/server/__mocks__/http-proxy.js +0 -105
- package/watchdog/index.js +0 -3
- package/watchdog/src/Watchdog.js +0 -156
- package/web/config.json +0 -5
- package/web/view/footer/main.html +0 -11
- /package/{framework/src → src}/Env.js +0 -0
- /package/{framework/src → src}/Route/Cron.js +0 -0
- /package/{framework/src → src}/Token.js +0 -0
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
# Custom Forms
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Odac provides an automatic form system with built-in validation, CSRF protection, and seamless client-side integration. The `<odac:form>` tag allows you to create forms with minimal code while maintaining full control.
|
|
4
4
|
|
|
5
5
|
## Basic Usage
|
|
6
6
|
|
|
7
7
|
```html
|
|
8
|
-
<
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
</
|
|
8
|
+
<odac:form action="/contact/submit" method="POST">
|
|
9
|
+
<odac:field name="email" type="email" label="Email">
|
|
10
|
+
<odac:validate rule="required|email" message="Valid email required"/>
|
|
11
|
+
</odac:field>
|
|
12
12
|
|
|
13
|
-
<
|
|
14
|
-
</
|
|
13
|
+
<odac:submit text="Send" loading="Sending..."/>
|
|
14
|
+
</odac:form>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Form Attributes
|
|
18
18
|
|
|
19
|
-
### `<
|
|
19
|
+
### `<odac:form>`
|
|
20
20
|
|
|
21
21
|
- `action` - Form submission URL (optional if using `table`)
|
|
22
22
|
- `method` - HTTP method (default: POST)
|
|
@@ -28,81 +28,81 @@ CandyPack provides an automatic form system with built-in validation, CSRF prote
|
|
|
28
28
|
|
|
29
29
|
```html
|
|
30
30
|
<!-- With custom controller -->
|
|
31
|
-
<
|
|
31
|
+
<odac:form action="/api/save" method="POST" class="my-form" id="contact-form">
|
|
32
32
|
<!-- fields here -->
|
|
33
|
-
</
|
|
33
|
+
</odac:form>
|
|
34
34
|
|
|
35
35
|
<!-- With automatic DB insert -->
|
|
36
|
-
<
|
|
36
|
+
<odac:form table="waitlist" redirect="/" success="Thank you for joining!">
|
|
37
37
|
<!-- fields here -->
|
|
38
|
-
</
|
|
38
|
+
</odac:form>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Field Types
|
|
42
42
|
|
|
43
|
-
### `<
|
|
43
|
+
### `<odac:field>`
|
|
44
44
|
|
|
45
45
|
Supports all standard HTML input types:
|
|
46
46
|
|
|
47
47
|
```html
|
|
48
48
|
<!-- Text input with multiple validations -->
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
</
|
|
49
|
+
<odac:field name="username" type="text" label="Username" placeholder="Enter username">
|
|
50
|
+
<odac:validate rule="required" message="Username is required"/>
|
|
51
|
+
<odac:validate rule="minlen:3" message="Username must be at least 3 characters"/>
|
|
52
|
+
<odac:validate rule="maxlen:20" message="Username cannot exceed 20 characters"/>
|
|
53
|
+
<odac:validate rule="alphanumeric" message="Username can only contain letters and numbers"/>
|
|
54
|
+
</odac:field>
|
|
55
55
|
|
|
56
56
|
<!-- Email input -->
|
|
57
|
-
<
|
|
58
|
-
<
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
</
|
|
57
|
+
<odac:field name="email" type="email" label="Email Address" placeholder="your@email.com">
|
|
58
|
+
<odac:validate rule="required" message="Email address is required"/>
|
|
59
|
+
<odac:validate rule="email" message="Please enter a valid email address"/>
|
|
60
|
+
<odac:validate rule="maxlen:100" message="Email is too long"/>
|
|
61
|
+
</odac:field>
|
|
62
62
|
|
|
63
63
|
<!-- Password input with strong validation -->
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
</
|
|
64
|
+
<odac:field name="password" type="password" label="Password">
|
|
65
|
+
<odac:validate rule="required" message="Password is required"/>
|
|
66
|
+
<odac:validate rule="minlen:8" message="Password must be at least 8 characters long"/>
|
|
67
|
+
<odac:validate rule="maxlen:50" message="Password is too long"/>
|
|
68
|
+
</odac:field>
|
|
69
69
|
|
|
70
70
|
<!-- Textarea with character limits -->
|
|
71
|
-
<
|
|
72
|
-
<
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
</
|
|
71
|
+
<odac:field name="message" type="textarea" label="Your Message" placeholder="Tell us what you think...">
|
|
72
|
+
<odac:validate rule="required" message="Please enter your message"/>
|
|
73
|
+
<odac:validate rule="minlen:10" message="Message must be at least 10 characters"/>
|
|
74
|
+
<odac:validate rule="maxlen:500" message="Message cannot exceed 500 characters"/>
|
|
75
|
+
</odac:field>
|
|
76
76
|
|
|
77
77
|
<!-- Checkbox for terms acceptance -->
|
|
78
|
-
<
|
|
79
|
-
<
|
|
80
|
-
</
|
|
78
|
+
<odac:field name="agree" type="checkbox" label="I agree to the Terms of Service and Privacy Policy">
|
|
79
|
+
<odac:validate rule="accepted" message="You must accept the terms to continue"/>
|
|
80
|
+
</odac:field>
|
|
81
81
|
|
|
82
82
|
<!-- Number input with range -->
|
|
83
|
-
<
|
|
84
|
-
<
|
|
85
|
-
<
|
|
86
|
-
<
|
|
87
|
-
</
|
|
83
|
+
<odac:field name="age" type="number" label="Your Age">
|
|
84
|
+
<odac:validate rule="required" message="Age is required"/>
|
|
85
|
+
<odac:validate rule="min:18" message="You must be at least 18 years old"/>
|
|
86
|
+
<odac:validate rule="max:120" message="Please enter a valid age"/>
|
|
87
|
+
</odac:field>
|
|
88
88
|
|
|
89
89
|
<!-- Phone number -->
|
|
90
|
-
<
|
|
91
|
-
<
|
|
92
|
-
<
|
|
93
|
-
</
|
|
90
|
+
<odac:field name="phone" type="text" label="Phone Number" placeholder="+1 (555) 123-4567">
|
|
91
|
+
<odac:validate rule="required" message="Phone number is required"/>
|
|
92
|
+
<odac:validate rule="minlen:10" message="Phone number must be at least 10 digits"/>
|
|
93
|
+
</odac:field>
|
|
94
94
|
|
|
95
95
|
<!-- URL input -->
|
|
96
|
-
<
|
|
97
|
-
<
|
|
98
|
-
</
|
|
96
|
+
<odac:field name="website" type="url" label="Website" placeholder="https://example.com">
|
|
97
|
+
<odac:validate rule="url" message="Please enter a valid URL"/>
|
|
98
|
+
</odac:field>
|
|
99
99
|
|
|
100
100
|
<!-- Name with alpha validation -->
|
|
101
|
-
<
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
<
|
|
105
|
-
</
|
|
101
|
+
<odac:field name="full_name" type="text" label="Full Name" placeholder="John Doe">
|
|
102
|
+
<odac:validate rule="required" message="Full name is required"/>
|
|
103
|
+
<odac:validate rule="minlen:2" message="Name must be at least 2 characters"/>
|
|
104
|
+
<odac:validate rule="maxlen:50" message="Name is too long"/>
|
|
105
|
+
</odac:field>
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
### Field Attributes
|
|
@@ -116,14 +116,14 @@ Supports all standard HTML input types:
|
|
|
116
116
|
|
|
117
117
|
## Validation Rules
|
|
118
118
|
|
|
119
|
-
### `<
|
|
119
|
+
### `<odac:validate>`
|
|
120
120
|
|
|
121
121
|
Add validation rules to fields:
|
|
122
122
|
|
|
123
123
|
```html
|
|
124
|
-
<
|
|
125
|
-
<
|
|
126
|
-
</
|
|
124
|
+
<odac:field name="username" type="text">
|
|
125
|
+
<odac:validate rule="required|minlen:3|maxlen:20" message="Username must be 3-20 characters"/>
|
|
126
|
+
</odac:field>
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
### Available Rules
|
|
@@ -145,7 +145,7 @@ Add validation rules to fields:
|
|
|
145
145
|
Combine rules with `|`:
|
|
146
146
|
|
|
147
147
|
```html
|
|
148
|
-
<
|
|
148
|
+
<odac:validate rule="required|email|maxlen:100" message="Invalid email"/>
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
### Unique Validation
|
|
@@ -153,20 +153,20 @@ Combine rules with `|`:
|
|
|
153
153
|
For automatic DB insert, use `unique` to check if value already exists:
|
|
154
154
|
|
|
155
155
|
```html
|
|
156
|
-
<
|
|
156
|
+
<odac:validate rule="required|email|unique" message="This email is already registered"/>
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
## Auto-Set Values
|
|
160
160
|
|
|
161
|
-
### `<
|
|
161
|
+
### `<odac:set>`
|
|
162
162
|
|
|
163
163
|
Automatically set field values without user input:
|
|
164
164
|
|
|
165
165
|
```html
|
|
166
|
-
<
|
|
167
|
-
<
|
|
168
|
-
<
|
|
169
|
-
<
|
|
166
|
+
<odac:set name="created_at" compute="now"/>
|
|
167
|
+
<odac:set name="ip" compute="ip"/>
|
|
168
|
+
<odac:set name="user_agent" compute="user_agent"/>
|
|
169
|
+
<odac:set name="status" value="pending"/>
|
|
170
170
|
```
|
|
171
171
|
|
|
172
172
|
### Available Compute Types
|
|
@@ -189,17 +189,17 @@ Automatically set field values without user input:
|
|
|
189
189
|
|
|
190
190
|
## Submit Button
|
|
191
191
|
|
|
192
|
-
### `<
|
|
192
|
+
### `<odac:submit>`
|
|
193
193
|
|
|
194
194
|
```html
|
|
195
195
|
<!-- Simple -->
|
|
196
|
-
<
|
|
196
|
+
<odac:submit text="Submit"/>
|
|
197
197
|
|
|
198
198
|
<!-- With loading state -->
|
|
199
|
-
<
|
|
199
|
+
<odac:submit text="Send Message" loading="Sending..."/>
|
|
200
200
|
|
|
201
201
|
<!-- With styling -->
|
|
202
|
-
<
|
|
202
|
+
<odac:submit text="Save" loading="Saving..." class="btn btn-primary" id="save-btn"/>
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
## Controller Handler
|
|
@@ -208,9 +208,9 @@ Handle form submission in your controller:
|
|
|
208
208
|
|
|
209
209
|
```javascript
|
|
210
210
|
module.exports = {
|
|
211
|
-
submit:
|
|
211
|
+
submit: Odac => {
|
|
212
212
|
// Access validated form data
|
|
213
|
-
const data =
|
|
213
|
+
const data = Odac.formData
|
|
214
214
|
|
|
215
215
|
// data contains all field values
|
|
216
216
|
console.log(data.email, data.message)
|
|
@@ -218,7 +218,7 @@ module.exports = {
|
|
|
218
218
|
// Process the data (save to database, send email, etc.)
|
|
219
219
|
|
|
220
220
|
// Return success response
|
|
221
|
-
return
|
|
221
|
+
return Odac.return({
|
|
222
222
|
result: {
|
|
223
223
|
success: true,
|
|
224
224
|
message: 'Form submitted successfully!',
|
|
@@ -235,12 +235,12 @@ Return validation errors:
|
|
|
235
235
|
|
|
236
236
|
```javascript
|
|
237
237
|
module.exports = {
|
|
238
|
-
submit:
|
|
239
|
-
const data =
|
|
238
|
+
submit: Odac => {
|
|
239
|
+
const data = Odac.formData
|
|
240
240
|
|
|
241
241
|
// Custom validation
|
|
242
242
|
if (data.email.includes('spam')) {
|
|
243
|
-
return
|
|
243
|
+
return Odac.return({
|
|
244
244
|
result: {success: false},
|
|
245
245
|
errors: {
|
|
246
246
|
email: 'This email is not allowed'
|
|
@@ -248,7 +248,7 @@ module.exports = {
|
|
|
248
248
|
})
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
return
|
|
251
|
+
return Odac.return({
|
|
252
252
|
result: {success: true, message: 'Success!'}
|
|
253
253
|
})
|
|
254
254
|
}
|
|
@@ -262,20 +262,20 @@ Forms can automatically insert data into database without writing a controller:
|
|
|
262
262
|
### View (view/content/waitlist.html)
|
|
263
263
|
|
|
264
264
|
```html
|
|
265
|
-
<
|
|
266
|
-
<
|
|
267
|
-
<
|
|
268
|
-
</
|
|
265
|
+
<odac:form table="waitlist" redirect="/" success="Thank you for joining!">
|
|
266
|
+
<odac:field name="email" type="email" label="Email">
|
|
267
|
+
<odac:validate rule="required|email|unique" message="Valid email required"/>
|
|
268
|
+
</odac:field>
|
|
269
269
|
|
|
270
|
-
<
|
|
271
|
-
<
|
|
272
|
-
</
|
|
270
|
+
<odac:field name="name" type="text" label="Name">
|
|
271
|
+
<odac:validate rule="required|minlen:2" message="Name required"/>
|
|
272
|
+
</odac:field>
|
|
273
273
|
|
|
274
|
-
<
|
|
275
|
-
<
|
|
274
|
+
<odac:set name="created_at" compute="now"/>
|
|
275
|
+
<odac:set name="ip" compute="ip"/>
|
|
276
276
|
|
|
277
|
-
<
|
|
278
|
-
</
|
|
277
|
+
<odac:submit text="Join Waitlist" loading="Joining..."/>
|
|
278
|
+
</odac:form>
|
|
279
279
|
```
|
|
280
280
|
|
|
281
281
|
### Database Table
|
|
@@ -294,7 +294,7 @@ CREATE TABLE `waitlist` (
|
|
|
294
294
|
### Route (route/www.js)
|
|
295
295
|
|
|
296
296
|
```javascript
|
|
297
|
-
|
|
297
|
+
Odac.Route.page('/waitlist', 'waitlist')
|
|
298
298
|
```
|
|
299
299
|
|
|
300
300
|
That's it! No controller needed. The form will:
|
|
@@ -312,25 +312,25 @@ That's it! No controller needed. The form will:
|
|
|
312
312
|
<div class="contact-page">
|
|
313
313
|
<h1>Contact Us</h1>
|
|
314
314
|
|
|
315
|
-
<
|
|
316
|
-
<
|
|
317
|
-
<
|
|
318
|
-
</
|
|
315
|
+
<odac:form action="/contact/submit" method="POST" class="contact-form">
|
|
316
|
+
<odac:field name="name" type="text" label="Your Name" placeholder="Enter your name">
|
|
317
|
+
<odac:validate rule="required|minlen:3" message="Name must be at least 3 characters"/>
|
|
318
|
+
</odac:field>
|
|
319
319
|
|
|
320
|
-
<
|
|
321
|
-
<
|
|
322
|
-
</
|
|
320
|
+
<odac:field name="email" type="email" label="Email" placeholder="your@email.com">
|
|
321
|
+
<odac:validate rule="required|email" message="Please enter a valid email"/>
|
|
322
|
+
</odac:field>
|
|
323
323
|
|
|
324
|
-
<
|
|
325
|
-
<
|
|
326
|
-
</
|
|
324
|
+
<odac:field name="subject" type="text" label="Subject" placeholder="What is this about?">
|
|
325
|
+
<odac:validate rule="required|minlen:5" message="Subject must be at least 5 characters"/>
|
|
326
|
+
</odac:field>
|
|
327
327
|
|
|
328
|
-
<
|
|
329
|
-
<
|
|
330
|
-
</
|
|
328
|
+
<odac:field name="message" type="textarea" label="Message" placeholder="Your message...">
|
|
329
|
+
<odac:validate rule="required|minlen:10" message="Message must be at least 10 characters"/>
|
|
330
|
+
</odac:field>
|
|
331
331
|
|
|
332
|
-
<
|
|
333
|
-
</
|
|
332
|
+
<odac:submit text="Send Message" loading="Sending..." class="btn btn-primary"/>
|
|
333
|
+
</odac:form>
|
|
334
334
|
</div>
|
|
335
335
|
```
|
|
336
336
|
|
|
@@ -338,22 +338,22 @@ That's it! No controller needed. The form will:
|
|
|
338
338
|
|
|
339
339
|
```javascript
|
|
340
340
|
module.exports = {
|
|
341
|
-
index:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
341
|
+
index: Odac => {
|
|
342
|
+
Odac.View.skeleton('default')
|
|
343
|
+
Odac.View.set({content: 'contact'})
|
|
344
|
+
Odac.View.print()
|
|
345
345
|
},
|
|
346
346
|
|
|
347
|
-
submit:
|
|
348
|
-
const data =
|
|
347
|
+
submit: Odac => {
|
|
348
|
+
const data = Odac.formData
|
|
349
349
|
|
|
350
350
|
// Save to database
|
|
351
|
-
// await
|
|
351
|
+
// await Odac.Mysql.query('INSERT INTO contacts SET ?', data)
|
|
352
352
|
|
|
353
353
|
// Send email notification
|
|
354
|
-
// await
|
|
354
|
+
// await Odac.Mail().to('admin@example.com').subject('New Contact').send(data.message)
|
|
355
355
|
|
|
356
|
-
return
|
|
356
|
+
return Odac.return({
|
|
357
357
|
result: {
|
|
358
358
|
success: true,
|
|
359
359
|
message: 'Thank you! We will get back to you soon.',
|
|
@@ -367,8 +367,8 @@ module.exports = {
|
|
|
367
367
|
### Route (route/www.js)
|
|
368
368
|
|
|
369
369
|
```javascript
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
Odac.Route.page('/contact', 'contact')
|
|
371
|
+
Odac.Route.post('/contact/submit', 'contact.submit')
|
|
372
372
|
```
|
|
373
373
|
|
|
374
374
|
## Features
|