alchemy-form 0.2.10 → 0.3.0-alpha.2

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/assets/stylesheets/form/alchemy_form.scss +1 -2
  3. package/assets/stylesheets/form/elements/_badge.scss +41 -0
  4. package/assets/stylesheets/form/elements/_button.scss +4 -31
  5. package/assets/stylesheets/form/elements/_code_input.scss +0 -1
  6. package/assets/stylesheets/form/elements/_feedback_input.scss +2 -0
  7. package/assets/stylesheets/form/elements/_field.scss +29 -23
  8. package/assets/stylesheets/form/elements/_form.scss +7 -2
  9. package/assets/stylesheets/form/elements/_settings_editor.scss +62 -0
  10. package/assets/stylesheets/form/elements/_table.scss +12 -3
  11. package/assets/stylesheets/form/elements/index.scss +19 -17
  12. package/assets/stylesheets/form/general/index.scss +2 -2
  13. package/config/routes.js +3 -3
  14. package/controller/form_api_controller.js +2 -4
  15. package/element/00_form_base.js +21 -0
  16. package/element/10_dataprovider.js +2 -2
  17. package/element/al_code_input.js +51 -13
  18. package/element/al_field.js +89 -24
  19. package/element/al_form.js +9 -2
  20. package/element/al_select.js +2 -1
  21. package/element/al_settings_editor.js +367 -0
  22. package/element/al_table.js +11 -6
  23. package/package.json +4 -3
  24. package/view/form/elements/al_settings_editor.hwk +36 -0
  25. package/view/form/elements/alchemy_field.hwk +1 -12
  26. package/view/form/inputs/edit/object.hwk +9 -0
  27. package/view/form/inputs/edit/settings.hwk +5 -0
  28. package/view/form/inputs/view/string.hwk +14 -1
  29. package/view/form/inputs/view_inline/boolean.hwk +24 -17
  30. package/view/form/inputs/view_inline/datetime.hwk +31 -24
  31. package/view/form/inputs/view_inline/enum.hwk +32 -1
  32. package/view/form/inputs/view_inline/objectid.hwk +9 -1
  33. package/view/form/inputs/view_inline/string.hwk +11 -3
  34. package/view/form/wrappers/default/default.hwk +18 -2
  35. /package/element/{al_string_input.js → 50-al_string_input.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 0.3.0-alpha.2 (2024-02-25)
2
+
3
+ * Added `.alchemy-badge` class
4
+ * Use badges & microcopy for showing in-line empty values
5
+ * Also set the `al-field`'s model attribute inside `al-table` elements
6
+ * Depend on the `alchemy-styleboost` peer dependency
7
+ * Let enum values use automatic styleboost colors in indexes + show correct titles
8
+
9
+ ## 0.3.0-alpha.1 (2024-02-15)
10
+
11
+ * Upgrade to Alchemy v1.4.0
12
+ * Add edit template for the `Object` field type
13
+ * Add settings editor element
14
+ * Make `readonly` attribute work on `al-field` and `al-form` elements
15
+ * Use "alchemy-field-title" and "alchemy-field-description" microcopy in `al-field` labels
16
+
1
17
  ## 0.2.10 (2024-01-15)
2
18
 
3
19
  * Fix `al-table` throwing an error when receiving null data
@@ -1,2 +1 @@
1
- @import "./general/index.scss";
2
- @import "./elements/index.scss";
1
+ @use "elements";
@@ -0,0 +1,41 @@
1
+ @use "styleboost";
2
+
3
+ :root {
4
+ --badge-font-size: 0.9rem;
5
+ --badge-font-weight: 400;
6
+ --badge-line-height: 1;
7
+ --badge-border-radius: 5px;
8
+ --badge-padding: 4px 8px;
9
+ --badge-white-space: nowrap;
10
+ --badge-user-select: none;
11
+ --badge-gap: 5px;
12
+ }
13
+
14
+ .alchemy-badge {
15
+ display: inline-flex;
16
+ text-align: center;
17
+
18
+ gap: var(--badge-gap);
19
+ user-select: var(--badge-user-select);
20
+ padding: var(--badge-padding);
21
+ font-size: var(--badge-font-size);
22
+ font-weight: var(--badge-font-weight);
23
+ line-height: var(--badge-line-height);
24
+ border-radius: var(--badge-border-radius);
25
+ color: var(--badge-color, var(--color-theme-fill-text));
26
+ background-color: var(--badge-bg, var(--color-theme-fill));
27
+ white-space: var(--badge-white-space);
28
+ }
29
+
30
+ $counter: 0;
31
+
32
+ // Iterate over all the available colors and create a badge color set for each
33
+ // We do this without the badge class to lower specificity
34
+ @each $color, $value in styleboost.$colors {
35
+ $counter: $counter + 1;
36
+
37
+ [data-badge-color-set="#{$counter}"] {
38
+ --badge-color: var(--color-shade-#{$counter});
39
+ --badge-bg: var(--color-tint-#{$counter});
40
+ }
41
+ }
@@ -1,33 +1,10 @@
1
- :root {
2
- --al-button-font-size: 1em;
3
- --al-button-font-weight: 400;
4
- --al-button-bg-color: rgb(89, 105, 225);
5
- --al-button-bg-color-hover: rgb(105, 118, 218);
6
- --al-button-text-color: white;
7
- }
1
+ @use "styleboost";
8
2
 
9
3
  al-button {
10
- display: inline-block;
11
- font-size: var(--al-button-font-size);
12
- font-weight: var(--al-button-font-weight);
13
- background-color: var(--al-button-bg-color);
14
- color: var(--al-button-text-color);
15
- cursor: pointer;
16
- user-select: none;
4
+ @extend .default-button;
17
5
 
6
+ display: inline-block;
18
7
  position: relative;
19
- padding: 0.5em 1em;
20
- text-align: center;
21
- text-decoration: none;
22
- vertical-align: bottom;
23
- transition: 0.1s;
24
- overflow: hidden;
25
- line-height: 1.5;
26
-
27
- al-icon,
28
- .icon {
29
- line-height: 1 !important;
30
- }
31
8
 
32
9
  .apb-content {
33
10
  display: flex;
@@ -42,11 +19,7 @@ al-button {
42
19
 
43
20
  &[disabled] {
44
21
  pointer-events: none;
45
- filter: saturate(0.5);
22
+ filter: unquote("saturate(0.5)");
46
23
  cursor: not-allowed;
47
24
  }
48
-
49
- &:hover {
50
- background-color: var(--al-button-bg-color-hover);
51
- }
52
25
  }
@@ -1,6 +1,5 @@
1
1
  al-code-input {
2
2
  display: inline-block;
3
- height: 30rem;
4
3
  width: 100%;
5
4
  position: relative;
6
5
 
@@ -1,3 +1,5 @@
1
+ @use "form/general" as *;
2
+
1
3
  .textareabox,
2
4
  .inputbox {
3
5
  $inputbox: &;
@@ -1,5 +1,8 @@
1
+ @use "styleboost" as *;
2
+
1
3
  al-field {
2
4
  display: block;
5
+ --badge-font-size: 1rem;
3
6
 
4
7
  &[field-type="boolean"] {
5
8
 
@@ -8,29 +11,32 @@ al-field {
8
11
  justify-content: flex-start;
9
12
  }
10
13
 
11
- .boolean-wrapper {
12
- &.boolean-true {
13
- --boolean-color: green;
14
- --text-color: white;
15
- }
16
-
17
- &.boolean-false {
18
- --boolean-color: red;
19
- --text-color: white;
20
- }
21
-
22
- &.boolean-null {
23
- --boolean-color: #f3f3f3;
24
- --text-color: #666;
25
- font-style: italic;
26
- }
27
-
28
- background-color: var(--boolean-color);
29
- border-radius: 5px;
30
- padding: 4px 8px;
31
- min-width: 1rem;
32
- color: var(--text-color, white);
33
- display: inline-flex;
14
+ .boolean-true {
15
+ @extend .use-truthy-theme;
16
+ }
17
+
18
+ .boolean-false {
19
+ @extend .use-falsy-theme;
20
+ }
21
+
22
+ .value-icon {
23
+ margin-right: 0.5rem;
34
24
  }
35
25
  }
26
+
27
+ .alchemy-field-empty-value-placeholder {
28
+ --color-theme-fill: var(--color-inactive-bg);
29
+ --color-theme-fill-text: var(--color-inactive-bg-text);
30
+ font-style: italic;
31
+ }
32
+ }
33
+
34
+ al-form[readonly] al-field,
35
+ al-field[readonly] {
36
+ pointer-events: none;
37
+
38
+ .alchemy-field-value {
39
+ opacity: 0.8;
40
+ filter: brightness(0.95);
41
+ }
36
42
  }
@@ -1,12 +1,17 @@
1
+ @use "styleboost";
2
+
1
3
  al-form {
2
4
  .error-area:empty {
3
5
  display: none;
4
6
  }
5
7
 
6
8
  .error-area:not(:empty) {
7
- border: 1px solid #a80000;
8
- color: #a80000;
9
+ @extend .use-danger-theme;
10
+ border: 1px solid var(--color-theme-accent);
11
+ color: var(--color-theme-bg-text);
12
+ background-color: var(--color-theme-bg);
9
13
  padding: 0.2rem;
14
+ border-radius: 4px;
10
15
  }
11
16
  }
12
17
 
@@ -0,0 +1,62 @@
1
+ al-settings-editor {
2
+ display: grid;
3
+ grid-template-columns: minmax(200px, 1.5fr) minmax(25vw, 9fr);
4
+
5
+ .al-settings-group {
6
+ padding-top: 0.5rem;
7
+ margin-bottom: 0.5rem;
8
+ }
9
+
10
+ .al-settings-setting-header {
11
+ margin-bottom: 0.5rem;
12
+ }
13
+
14
+ .al-settings-group-title {
15
+ font-weight: bold;
16
+ font-size: 1.6rem;
17
+ }
18
+
19
+ .al-settings-group-header {
20
+ padding: 0.2rem 1rem 0.5rem;
21
+ }
22
+
23
+ .al-settings-actions,
24
+ .al-settings-setting {
25
+ padding: 0.2rem 1rem 1.5rem;
26
+ }
27
+
28
+ .al-settings-actions {
29
+ margin-top: 2rem;
30
+ }
31
+
32
+ .al-settings-setting-title {
33
+ font-weight: bold;
34
+ }
35
+
36
+ .al-settings-setting-description micro-copy:not(:empty) {
37
+ display: block;
38
+ margin-top: 0.3rem;
39
+ }
40
+
41
+ .al-settings-sidebar {
42
+ border-right: 1px solid #ebebeb;
43
+ margin-right: 1.5rem;
44
+
45
+ a {
46
+ text-decoration: none;
47
+ color: inherit;
48
+ }
49
+ }
50
+
51
+ al-field {
52
+ .field,
53
+ .field input {
54
+ width: 100%;
55
+ }
56
+ }
57
+
58
+ al-toc {
59
+ position: sticky;
60
+ top: 1rem;
61
+ }
62
+ }
@@ -2,12 +2,9 @@ al-table {
2
2
  display: flex;
3
3
  flex-flow: column;
4
4
  border: 1px solid #dadee0;
5
- font-family: sans-serif;
6
5
  background-color: white;
7
- color: #313131;
8
6
 
9
7
  table {
10
- border-collapse: collapse;
11
8
  width: 100%;
12
9
  color: inherit;
13
10
  }
@@ -34,6 +31,14 @@ al-table {
34
31
  color: inherit;
35
32
  }
36
33
  }
34
+
35
+ th input {
36
+ width: 100%;
37
+ padding: 0px 12px;
38
+ border: 1px solid var(--color-input-border);
39
+ color: var(--text-color);
40
+ height: 2rem;
41
+ }
37
42
  }
38
43
 
39
44
  td, th {
@@ -42,6 +47,10 @@ al-table {
42
47
  cursor: default;
43
48
  }
44
49
 
50
+ td al-field[field-type="fixed_decimal"] {
51
+ text-align: right;
52
+ }
53
+
45
54
  tr:last-of-type {
46
55
  td, th {
47
56
  border-bottom: 0;
@@ -1,17 +1,19 @@
1
- @import "_button.scss";
2
- @import "_code_input.scss";
3
- @import "_feedback_input.scss";
4
- @import "_field.scss";
5
- @import "_field_array.scss";
6
- @import "_field_translatable.scss";
7
- @import "_form.scss";
8
- @import "_pager.scss";
9
- @import "_query_builder.scss";
10
- @import "_select.scss";
11
- @import "_state.scss";
12
- @import "_table.scss";
13
- @import "_toggle.scss";
14
- @import "_tabs.scss";
15
- @import "_pathway.scss";
16
- @import "_apex_charts.scss";
17
- @import "_virtual_scroll.scss";
1
+ @use "_badge.scss";
2
+ @use "_button.scss";
3
+ @use "_code_input.scss";
4
+ @use "_feedback_input.scss";
5
+ @use "_field.scss";
6
+ @use "_field_array.scss";
7
+ @use "_field_translatable.scss";
8
+ @use "_form.scss";
9
+ @use "_pager.scss";
10
+ @use "_query_builder.scss";
11
+ @use "_select.scss";
12
+ @use "_state.scss";
13
+ @use "_table.scss";
14
+ @use "_toggle.scss";
15
+ @use "_tabs.scss";
16
+ @use "_pathway.scss";
17
+ @use "_apex_charts.scss";
18
+ @use "_virtual_scroll.scss";
19
+ @use "_settings_editor.scss";
@@ -1,2 +1,2 @@
1
- @import "_textsizes.scss";
2
- @import "_colors.scss";
1
+ @forward "_textsizes.scss";
2
+ @forward "_colors.scss";
package/config/routes.js CHANGED
@@ -1,4 +1,4 @@
1
- Router.add({
1
+ Plugin.addRoute({
2
2
  name : 'FormApi#related',
3
3
  methods : 'post',
4
4
  paths : '/api/form/data/related',
@@ -7,7 +7,7 @@ Router.add({
7
7
  is_system_route : true,
8
8
  });
9
9
 
10
- Router.add({
10
+ Plugin.addRoute({
11
11
  name : 'FormApi#queryBuilderData',
12
12
  methods : 'post',
13
13
  paths : '/api/form/data/qbdata',
@@ -16,7 +16,7 @@ Router.add({
16
16
  is_system_route : true,
17
17
  });
18
18
 
19
- Router.add({
19
+ Plugin.addRoute({
20
20
  name : 'FormApi#recompute',
21
21
  methods : 'post',
22
22
  paths : '/api/form/data/recompute/{model_name}/{field}',
@@ -17,7 +17,7 @@ const FormApi = Function.inherits('Alchemy.Controller', 'FormApi');
17
17
  *
18
18
  * @author Jelle De Loecker <jelle@elevenways.be>
19
19
  * @since 0.1.0
20
- * @version 0.2.9
20
+ * @version 0.3.0
21
21
  *
22
22
  * @param {Conduit} conduit
23
23
  */
@@ -32,9 +32,7 @@ FormApi.setAction(async function related(conduit) {
32
32
  crit.setOption('scenario', 'related_data');
33
33
 
34
34
  if (body.constraints) {
35
- for (let key in body.constraints) {
36
- crit.where(key).equals(body.constraints[key]);
37
- }
35
+ crit.applyConditions(body.constraints);
38
36
  }
39
37
 
40
38
  if (config.value) {
@@ -102,6 +102,27 @@ Base.setAttribute('purpose', function getPurpose(value) {
102
102
  */
103
103
  Base.setAttribute('mode');
104
104
 
105
+ /**
106
+ * The zone determines where the form/field is being used.
107
+ * For example: admin, frontend, chimera, invoice, ...
108
+ *
109
+ * @author Jelle De Loecker <jelle@elevenways.be>
110
+ * @since 0.3.0
111
+ * @version 0.3.0
112
+ */
113
+ Base.setAttribute('zone', function getZone(value) {
114
+
115
+ if (value) {
116
+ return value;
117
+ }
118
+
119
+ if (!value && this.alchemy_form) {
120
+ value = this.alchemy_form.zone;
121
+ }
122
+
123
+ return value;
124
+ });
125
+
105
126
  /**
106
127
  * The view-type determines which type of wrapper/field to use,
107
128
  * e.g.: view, list, edit, ...
@@ -254,7 +254,7 @@ WithDataprovider.setMethod(function loadRemoteData(fetch_config) {
254
254
  *
255
255
  * @author Jelle De Loecker <jelle@elevenways.be>
256
256
  * @since 0.2.0
257
- * @version 0.2.0
257
+ * @version 0.3.0
258
258
  *
259
259
  * @param {Object} config
260
260
  *
@@ -265,7 +265,7 @@ WithDataprovider.setMethod(function fetchRemoteData(config) {
265
265
  let pledge;
266
266
 
267
267
  if (this.dataprovider) {
268
- pledge = Pledge.cast(this.dataprovider.loadData(config, this));
268
+ pledge = Pledge.Swift.cast(this.dataprovider.loadData(config, this));
269
269
  } else {
270
270
 
271
271
  let method = (this.method || 'get').toLowerCase();
@@ -43,6 +43,15 @@ CodeInput.setAttribute('language-mode');
43
43
  */
44
44
  CodeInput.setAttribute('color-theme');
45
45
 
46
+ /**
47
+ * Is the value an object?
48
+ *
49
+ * @author Jelle De Loecker <jelle@elevenways.be>
50
+ * @since 0.3.0
51
+ * @version 0.3.0
52
+ */
53
+ CodeInput.setAttribute('value-is-object', {type: 'boolean'});
54
+
46
55
  /**
47
56
  * The minimum number of lines to show (height)
48
57
  *
@@ -66,25 +75,43 @@ CodeInput.setAttribute('max-lines', {type: 'number'});
66
75
  *
67
76
  * @author Jelle De Loecker <jelle@elevenways.be>
68
77
  * @since 0.1.0
69
- * @version 0.2.5
78
+ * @version 0.3.0
70
79
  */
71
- CodeInput.setProperty(function value(value) {
80
+ CodeInput.setProperty(function value() {
81
+
82
+ let result;
72
83
 
73
84
  if (this._editor) {
74
- return this._editor.getValue();
85
+ result = this._editor.getValue();
86
+ } else {
87
+ let editor_el = this.querySelector('.code-editor');
88
+
89
+ if (editor_el) {
90
+ result = editor_el.textContent;
91
+ } else {
92
+ if (this.assigned_data.value) {
93
+ return this.assigned_data.value;
94
+ }
95
+
96
+ return;
97
+ }
75
98
  }
76
99
 
77
- let editor_el = this.querySelector('.code-editor');
78
-
79
- if (editor_el) {
80
- return editor_el.textContent;
100
+ if (result && this.value_is_object) {
101
+ result = JSON.safeParse(result);
81
102
  }
82
103
 
83
- if (this.assigned_data.value) {
84
- return this.assigned_data.value;
85
- }
104
+ return result;
105
+
106
+ }, function setValue(original_value) {
86
107
 
87
- }, function setValue(value) {
108
+ let value;
109
+
110
+ if (this.value_is_object) {
111
+ value = JSON.stringify(value, null, '\t');
112
+ } else {
113
+ value = original_value;
114
+ }
88
115
 
89
116
  if (this._editor) {
90
117
  this._editor.setValue(value);
@@ -101,7 +128,9 @@ CodeInput.setProperty(function value(value) {
101
128
  return editor_el.textContent = value;
102
129
  }
103
130
 
104
- this.assigned_data.value = value;
131
+ this.assigned_data.value = original_value;
132
+
133
+ this.hawkejs_renderer.registerElementInstance(this);
105
134
  });
106
135
 
107
136
  /**
@@ -153,7 +182,14 @@ CodeInput.setMethod(async function introduced() {
153
182
  }
154
183
 
155
184
  if (this.assigned_data.value) {
156
- editor.setValue(this.assigned_data.value, -1);
185
+
186
+ let value = this.assigned_data.value;
187
+
188
+ if (this.value_is_object) {
189
+ value = JSON.stringify(value, null, '\t');
190
+ }
191
+
192
+ editor.setValue(value, -1);
157
193
  }
158
194
 
159
195
  if (this.language_mode) {
@@ -164,5 +200,7 @@ CodeInput.setMethod(async function introduced() {
164
200
  }
165
201
  }
166
202
 
203
+ this.style.height = null;
204
+
167
205
  this._editor = editor;
168
206
  });