alchemy-form 0.2.3 → 0.2.5

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/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.2.5 (2023-04-20)
2
+
3
+ * Add more configuration to `al-code-input`
4
+
5
+ ## 0.2.4 (2023-02-26)
6
+
7
+ * Don't look for a field when the path is not specified
8
+ * Make `al-field-schema` elements use `Field#getSubSchema()` method
9
+ * Add an icon to the translatable-field entry buttons to see if it has a translation or not
10
+
1
11
  ## 0.2.3 (2023-02-11)
2
12
 
3
13
  * Use `Scene#pushToHistory()` instead of directly calling `pushState`
@@ -3,6 +3,46 @@ al-field-translatable {
3
3
  position: relative;
4
4
 
5
5
  .prefix-buttons {
6
-
6
+ button {
7
+ display: flex;
8
+ flex-flow: row;
9
+ }
10
+
11
+ .has-empty-content {
12
+ font-size: 0.7rem;
13
+ }
14
+
15
+ .has-content {
16
+ font-size: 0.9rem;
17
+ }
18
+
19
+ .has-empty-content,
20
+ .has-content {
21
+ margin-left: 0.5rem;
22
+ }
23
+
24
+ [data-has-content="true"] {
25
+ .has-empty-content {
26
+ display: none;
27
+ }
28
+ }
29
+
30
+ [data-has-content="false"] {
31
+ .has-content {
32
+ display: none;
33
+ }
34
+ }
35
+
36
+ [icon-name] {
37
+ color: #333;
38
+ }
39
+
40
+ [icon-name="ban"] {
41
+ color: tomato;
42
+ }
43
+
44
+ .has-content {
45
+ color: green;
46
+ }
7
47
  }
8
48
  }
@@ -16,12 +16,57 @@ const CodeInput = Function.inherits('Alchemy.Element.Form.Base', 'CodeInput');
16
16
  */
17
17
  CodeInput.setTemplateFile('form/elements/code_input');
18
18
 
19
+ /**
20
+ * Line number info
21
+ *
22
+ * @author Jelle De Loecker <jelle@elevenways.be>
23
+ * @since 0.2.5
24
+ * @version 0.2.5
25
+ */
26
+ CodeInput.setAttribute('show-line-numbers', {type: 'boolean', default: true});
27
+
28
+ /**
29
+ * The ace mode to use
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.2.5
33
+ * @version 0.2.5
34
+ */
35
+ CodeInput.setAttribute('language-mode');
36
+
37
+ /**
38
+ * The theme to use
39
+ *
40
+ * @author Jelle De Loecker <jelle@elevenways.be>
41
+ * @since 0.2.5
42
+ * @version 0.2.5
43
+ */
44
+ CodeInput.setAttribute('color-theme');
45
+
46
+ /**
47
+ * The minimum number of lines to show (height)
48
+ *
49
+ * @author Jelle De Loecker <jelle@elevenways.be>
50
+ * @since 0.2.5
51
+ * @version 0.2.5
52
+ */
53
+ CodeInput.setAttribute('min-lines', {type: 'number'});
54
+
55
+ /**
56
+ * The maximum number of lines to show (height)
57
+ *
58
+ * @author Jelle De Loecker <jelle@elevenways.be>
59
+ * @since 0.2.5
60
+ * @version 0.2.5
61
+ */
62
+ CodeInput.setAttribute('max-lines', {type: 'number'});
63
+
19
64
  /**
20
65
  * Get/set the value
21
66
  *
22
67
  * @author Jelle De Loecker <jelle@elevenways.be>
23
68
  * @since 0.1.0
24
- * @version 0.1.0
69
+ * @version 0.2.5
25
70
  */
26
71
  CodeInput.setProperty(function value(value) {
27
72
 
@@ -34,6 +79,11 @@ CodeInput.setProperty(function value(value) {
34
79
  if (editor_el) {
35
80
  return editor_el.textContent;
36
81
  }
82
+
83
+ if (this.assigned_data.value) {
84
+ return this.assigned_data.value;
85
+ }
86
+
37
87
  }, function setValue(value) {
38
88
 
39
89
  if (this._editor) {
@@ -51,6 +101,7 @@ CodeInput.setProperty(function value(value) {
51
101
  return editor_el.textContent = value;
52
102
  }
53
103
 
104
+ this.assigned_data.value = value;
54
105
  });
55
106
 
56
107
  /**
@@ -58,7 +109,7 @@ CodeInput.setProperty(function value(value) {
58
109
  *
59
110
  * @author Jelle De Loecker <jelle@elevenways.be>
60
111
  * @since 0.1.0
61
- * @version 0.1.10
112
+ * @version 0.2.5
62
113
  */
63
114
  CodeInput.setMethod(async function introduced() {
64
115
 
@@ -68,7 +119,20 @@ CodeInput.setMethod(async function introduced() {
68
119
 
69
120
  editor_el.hidden = false;
70
121
 
71
- let editor = ace.edit(editor_el);
122
+ let theme = this.color_theme || 'ace/theme/tomorrow_night_eighties';
123
+
124
+ if (!theme.startsWith('ace/theme')) {
125
+ theme = 'ace/theme/' + theme;
126
+ }
127
+
128
+ let options = {
129
+ showLineNumbers : this.show_line_numbers,
130
+ minLines : this.minLines || 4,
131
+ maxLines : this.maxLines || 50,
132
+ theme : theme,
133
+ };
134
+
135
+ let editor = ace.edit(editor_el, options);
72
136
 
73
137
  editor.session.setUseWrapMode(true);
74
138
  editor.setFontSize(16);
@@ -88,5 +152,17 @@ CodeInput.setMethod(async function introduced() {
88
152
  editor.session.setMode(mode);
89
153
  }
90
154
 
155
+ if (this.assigned_data.value) {
156
+ editor.setValue(this.assigned_data.value, -1);
157
+ }
158
+
159
+ if (this.language_mode) {
160
+ try {
161
+ editor.session.setMode('ace/mode/' + this.language_mode);
162
+ } catch (err) {
163
+ // Ignore
164
+ }
165
+ }
166
+
91
167
  this._editor = editor;
92
168
  });
@@ -21,47 +21,39 @@ FieldSchema.setTemplateFile('form/elements/alchemy_field_schema');
21
21
  *
22
22
  * @author Jelle De Loecker <jelle@elevenways.be>
23
23
  * @since 0.1.0
24
- * @version 0.1.12
24
+ * @version 0.2.4
25
25
  */
26
26
  FieldSchema.setProperty(function schema() {
27
27
 
28
- if (this.alchemy_field && this.alchemy_field.config.options) {
29
- let schema = this.alchemy_field.config.options.schema;
28
+ const field_element = this.alchemy_field;
29
+ const field = field_element?.config;
30
+
31
+ if (field?.options) {
32
+
33
+ let schema = field.options.schema;
30
34
 
31
35
  if (typeof schema == 'string') {
32
- let other_field = this.getSchemaSupplierField();
33
- schema = null;
34
-
35
- if (other_field && other_field.value && other_field.config && other_field.config.options) {
36
- let values = other_field.config.options.values;
37
-
38
- if (values) {
39
- let value;
40
-
41
- if (values instanceof Classes.Alchemy.Map.Backed) {
42
- value = values.get(other_field.value);
43
- } else {
44
- value = values[other_field.value];
45
- }
46
-
47
- if (value) {
48
- if (value.schema) {
49
- schema = value.schema;
50
- } else if (value.value) {
51
- // Enumified values can be wrapped on the server-side
52
- value = value.value;
53
-
54
- if (value.schema) {
55
- schema = value.schema;
56
- }
57
- }
58
- }
59
-
60
- if (!schema) {
61
- schema = value;
62
- }
36
+
37
+ let parent_schema_value;
38
+
39
+ let parent_schema = field_element.queryParents('al-field[field-type="schema"]');
40
+
41
+ if (parent_schema) {
42
+ parent_schema_value = parent_schema.value;
43
+ } else {
44
+
45
+ const form = field_element.alchemy_form;
46
+
47
+ let record_value = form.value;
48
+
49
+ if (form.model) {
50
+ record_value = record_value[form.model];
63
51
  }
52
+
53
+ parent_schema_value = record_value;
64
54
  }
55
+
56
+ return field.getSubschema(parent_schema_value, schema)
65
57
  }
66
58
 
67
59
  return schema;
@@ -75,7 +75,44 @@ FieldTranslatable.setMethod(function showPrefix(prefix) {
75
75
  element.hidden = true;
76
76
  }
77
77
  }
78
+ });
79
+
80
+ /**
81
+ * Check the translation contents
82
+ *
83
+ * @author Jelle De Loecker <jelle@elevenways.be>
84
+ * @since 0.2.4
85
+ * @version 0.2.4
86
+ */
87
+ FieldTranslatable.setMethod(function checkTranslationContents() {
88
+
89
+ let field = this.field_context?.config;
90
+
91
+ let has_content,
92
+ buttons = this.querySelectorAll('button[data-has-content][data-prefix]'),
93
+ button,
94
+ prefix,
95
+ values = this.value,
96
+ value,
97
+ i;
98
+
99
+ for (i = 0; i < buttons.length; i++) {
100
+ button = buttons[i];
101
+ prefix = button.dataset.prefix;
102
+ value = values?.[prefix];
103
+
104
+ if (field) {
105
+ has_content = field.valueHasContent(value);
106
+ } else {
107
+ has_content = value != null && value !== '';
108
+ }
78
109
 
110
+ if (has_content) {
111
+ button.dataset.hasContent = 'true';
112
+ } else {
113
+ button.dataset.hasContent = 'false';
114
+ }
115
+ }
79
116
  });
80
117
 
81
118
  /**
@@ -83,15 +120,37 @@ FieldTranslatable.setMethod(function showPrefix(prefix) {
83
120
  *
84
121
  * @author Jelle De Loecker <jelle@elevenways.be>
85
122
  * @since 0.1.0
86
- * @version 0.1.0
123
+ * @version 0.2.4
87
124
  */
88
125
  FieldTranslatable.setMethod(function introduced() {
89
126
 
90
- const that = this;
127
+ const that = this,
128
+ field = this.field_context;
129
+
130
+ let doTranslationCheck = Function.throttle(() => {
131
+
132
+ if (field?.purpose == 'view') {
133
+ return;
134
+ }
135
+
136
+ that.checkTranslationContents();
137
+ }, 500, true, true);
91
138
 
92
139
  this.onEventSelector('click', '.prefix-buttons button[data-prefix]', function onClick(e) {
140
+
93
141
  e.preventDefault();
94
- that.showPrefix(this.dataset.prefix);
142
+
143
+ let button = this.closest('[data-prefix]');
144
+
145
+ if (!button) {
146
+ return;
147
+ }
148
+
149
+ that.showPrefix(button.dataset.prefix);
150
+ doTranslationCheck();
95
151
  });
96
152
 
153
+ this.addEventListener('change', doTranslationCheck);
154
+ this.addEventListener('keyup', doTranslationCheck);
155
+ this.addEventListener('click', doTranslationCheck);
97
156
  });
@@ -25,6 +25,22 @@ FieldTranslatableEntry.setTemplateFile('form/elements/alchemy_field_translatable
25
25
  */
26
26
  FieldTranslatableEntry.setAttribute('prefix');
27
27
 
28
+ /**
29
+ * Does this translation entry have a valid value?
30
+ *
31
+ * @author Jelle De Loecker <jelle@elevenways.be>
32
+ * @since 0.2.4
33
+ * @version 0.2.4
34
+ */
35
+ FieldTranslatableEntry.setProperty(function has_content() {
36
+
37
+ let field_translatable_el = this.field_context,
38
+ field_el = field_translatable_el.field_context,
39
+ field = field_el.config;
40
+
41
+ field.valueHasContent(this.value);
42
+ });
43
+
28
44
  /**
29
45
  * Get the original value
30
46
  *
@@ -34,7 +50,9 @@ FieldTranslatableEntry.setAttribute('prefix');
34
50
  */
35
51
  FieldTranslatableEntry.setProperty(function original_value() {
36
52
 
37
- let context_value = this.field_context.original_value;
53
+ let field_translatable_el = this.field_context;
54
+
55
+ let context_value = field_translatable_el.original_value;
38
56
 
39
57
  if (context_value) {
40
58
  return context_value[this.prefix];
@@ -289,7 +289,7 @@ Form.setMethod(async function showViolations(err) {
289
289
  *
290
290
  * @author Jelle De Loecker <jelle@elevenways.be>
291
291
  * @since 0.1.0
292
- * @version 0.2.0
292
+ * @version 0.2.4
293
293
  *
294
294
  * @param {String} path
295
295
  *
@@ -297,6 +297,10 @@ Form.setMethod(async function showViolations(err) {
297
297
  */
298
298
  Form.setMethod(function findFieldByPath(path) {
299
299
 
300
+ if (!path) {
301
+ return;
302
+ }
303
+
300
304
  let current = this,
301
305
  result,
302
306
  pieces = path.split('.'),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-form",
3
3
  "description": "Form plugin for Alchemy",
4
- "version": "0.2.3",
4
+ "version": "0.2.5",
5
5
  "repository": {
6
6
  "type" : "git",
7
7
  "url" : "https://github.com/11ways/alchemy-form.git"
@@ -8,9 +8,24 @@
8
8
  <div class="prefix-buttons">
9
9
  <% index = 0 %>
10
10
  <% for (prefix in prefixes) { %>
11
- <button data-prefix=<% prefix %>>
11
+ <% value = null %>
12
+ <% if (values) value = values[prefix] %>
13
+
14
+ <button
15
+ data-prefix={% prefix %}
16
+ data-has-content=<% alchemy_field.config.valueHasContent(value) ? 'true' : 'false' %>
17
+ >
12
18
  <% if (index == 0) $0.classList.add('active') %>
13
- {%= prefix %}
19
+
20
+ <span class="prefix-name">{{ prefix }}</span>
21
+
22
+ <al-icon-stack class="has-empty-content">
23
+ <al-icon icon-name="language"></al-icon>
24
+ <al-icon icon-name="ban" size=2></al-icon>
25
+ </al-icon-stack>
26
+
27
+ <al-icon class="has-content" icon-name="language"></al-icon>
28
+
14
29
  </button>
15
30
 
16
31
  <% index++ %>