saasufy-components 1.10.2 → 1.12.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/input-provider.js CHANGED
@@ -1,4 +1,4 @@
1
- import { debouncer } from './utils.js';
1
+ import { debouncer, updateConsumerElements } from './utils.js';
2
2
 
3
3
  const DEFAULT_DEBOUNCE_DELAY = 800;
4
4
 
@@ -113,52 +113,6 @@ class InputProvider extends HTMLElement {
113
113
  };
114
114
  }
115
115
 
116
- updateConsumerElements(consumers, value) {
117
- let parentElement = this.parentElement;
118
- if (parentElement) {
119
- let consumerParts = consumers.split(',')
120
- .filter(part => part)
121
- .map(part => {
122
- part = part.trim();
123
- return part.split(':').map(subPart => subPart.trim());
124
- })
125
- .filter(([ selector, attributeName ]) => selector);
126
-
127
- for (let [ selector, attributeName ] of consumerParts) {
128
- let matchingElements = parentElement.querySelectorAll(selector);
129
- if (attributeName) {
130
- for (let element of matchingElements) {
131
- if (typeof value === 'boolean') {
132
- if (value) {
133
- element.setAttribute(attributeName, '');
134
- } else {
135
- element.removeAttribute(attributeName);
136
- }
137
- } else {
138
- element.setAttribute(attributeName, value);
139
- }
140
- }
141
- } else {
142
- for (let element of matchingElements) {
143
- if (element.nodeName === 'INPUT') {
144
- if (element.type === 'checkbox') {
145
- if (value) {
146
- element.setAttribute('checked', '');
147
- } else {
148
- element.removeAttribute('checked');
149
- }
150
- } else {
151
- element.value = value;
152
- }
153
- } else {
154
- element.innerHTML = value;
155
- }
156
- }
157
- }
158
- }
159
- }
160
- }
161
-
162
116
  updateConsumerElementsOnEdit() {
163
117
  let consumers = this.getAttribute('consumers');
164
118
  if (!consumers) return;
@@ -175,16 +129,16 @@ class InputProvider extends HTMLElement {
175
129
  if (inputElement.type === 'checkbox') {
176
130
  let checked = !!inputElement.checked;
177
131
  this.lastValue = checked;
178
- this.updateConsumerElements(consumers, checked);
132
+ updateConsumerElements(this.parentElement, consumers, checked);
179
133
  return;
180
134
  }
181
135
  this.lastValue = event.target.value;
182
136
  if (event.target.value === '') {
183
- this.updateConsumerElements(consumers, '');
137
+ updateConsumerElements(this.parentElement, consumers, '');
184
138
  } else {
185
139
  let targetValue = inputElement.type === 'number' ?
186
140
  Number(event.target.value) : event.target.value;
187
- this.updateConsumerElements(consumers, targetValue);
141
+ updateConsumerElements(this.parentElement, consumers, targetValue);
188
142
  }
189
143
  }, debounceDelay);
190
144
  };
@@ -197,11 +151,11 @@ class InputProvider extends HTMLElement {
197
151
  if (event.target.value === this.lastValue) return;
198
152
  this.lastValue = event.target.value;
199
153
  if (event.target.value === '') {
200
- this.updateConsumerElements(consumers, '');
154
+ updateConsumerElements(this.parentElement, consumers, '');
201
155
  } else {
202
156
  let targetValue = inputElement.type === 'number' ?
203
157
  Number(event.target.value) : event.target.value;
204
- this.updateConsumerElements(consumers, targetValue);
158
+ updateConsumerElements(this.parentElement, consumers, targetValue);
205
159
  }
206
160
  }, debounceDelay);
207
161
  };
package/log-in-form.js CHANGED
@@ -70,7 +70,11 @@ class LogInForm extends SocketConsumer {
70
70
  capitaliskLogIn.removeAttribute('error');
71
71
  capitaliskLogIn.setAttribute('submit-button-text', 'Loading...');
72
72
  try {
73
- let logInResponse = await this.socket.invoke('log-in', event.detail);
73
+ let credentials = {
74
+ ...event.detail,
75
+ networkSymbol
76
+ };
77
+ let logInResponse = await this.socket.invoke('log-in', credentials);
74
78
  } catch (error) {
75
79
  capitaliskLogIn.setAttribute('error', `${error.message}.`);
76
80
  capitaliskLogIn.removeAttribute('disabled');
package/model-input.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { SocketConsumer } from './socket.js';
2
- import { debouncer } from './utils.js';
2
+ import { debouncer, updateConsumerElements } from './utils.js';
3
3
  import AGModel from '/node_modules/ag-model/ag-model.js';
4
4
 
5
5
  class ModelInput extends SocketConsumer {
@@ -25,6 +25,7 @@ class ModelInput extends SocketConsumer {
25
25
  'model-instance-property',
26
26
  'type',
27
27
  'placeholder',
28
+ 'consumers',
28
29
  'show-error-message',
29
30
  'model-type',
30
31
  'model-id',
@@ -80,10 +81,19 @@ class ModelInput extends SocketConsumer {
80
81
  if (modelInstanceProperty) {
81
82
  while (currentNode) {
82
83
  model = currentNode[modelInstanceProperty];
84
+ if (model && modelType && (model.type !== modelType || !(model.fields || []).includes(modelField))) {
85
+ model = null;
86
+ }
83
87
  if (model) break;
84
88
  currentNode = currentNode.getRootNode().host || currentNode.parentNode;
85
89
  }
86
- if (!model) return;
90
+ if (!model) {
91
+ throw new Error(
92
+ `The ${
93
+ this.nodeName.toLowerCase()
94
+ } element failed to obtain a model via the specified model-instance-property - Ensure that the element is nested inside a parent element which exposes a model instance of the same type which has the relevant field`
95
+ );
96
+ };
87
97
  } else {
88
98
  this.socket = this.getSocket();
89
99
  model = new AGModel({
@@ -167,25 +177,34 @@ class ModelInput extends SocketConsumer {
167
177
 
168
178
  syncInputElementWithModel(inputElement, model, fieldName, messageContainerElement) {
169
179
  if (model.isLoaded) {
180
+ let consumers = this.getAttribute('consumers');
170
181
  let fieldValue = model.value[fieldName];
171
182
  if (inputElement.type === 'checkbox') {
172
- inputElement.checked = !!fieldValue;
183
+ let checked = !!fieldValue;
184
+ inputElement.checked = checked;
185
+ updateConsumerElements(this.parentElement, consumers, checked);
173
186
  } else {
174
187
  let defaultValue = this.getAttribute('default-value') || '';
175
188
  inputElement.value = fieldValue == null ? defaultValue : fieldValue;
189
+ updateConsumerElements(this.parentElement, consumers, inputElement.value);
176
190
  }
177
191
  }
178
192
  let stopSaving = this.saveInputElementOnEdit(inputElement, model, fieldName, messageContainerElement);
179
193
  let changeConsumer = model.listener('change').createConsumer();
180
194
  (async () => {
181
195
  for await (let event of changeConsumer) {
182
- if (event.resourceField !== fieldName || !event.isRemote) continue;
196
+ let hasFocus = document.activeElement === this.inputElement;
197
+ if (event.resourceField !== fieldName || (hasFocus && !event.isRemote)) continue;
198
+ let consumers = this.getAttribute('consumers');
183
199
  let fieldValue = model.value[fieldName];
184
200
  if (inputElement.type === 'checkbox') {
185
- inputElement.checked = !!fieldValue;
201
+ let checked = !!fieldValue;
202
+ inputElement.checked = checked;
203
+ updateConsumerElements(this.parentElement, consumers, checked);
186
204
  } else {
187
205
  let defaultValue = this.getAttribute('default-value') || '';
188
206
  inputElement.value = fieldValue == null ? defaultValue : fieldValue;
207
+ updateConsumerElements(this.parentElement, consumers, inputElement.value);
189
208
  }
190
209
  }
191
210
  })();
@@ -212,6 +231,7 @@ class ModelInput extends SocketConsumer {
212
231
  messageContainerElement.classList.add('hidden');
213
232
  };
214
233
 
234
+ let consumers = this.getAttribute('consumers');
215
235
  let debounceDelay = this.getAttribute('debounce-delay');
216
236
  debounceDelay = debounceDelay ? Number(debounceDelay) : null;
217
237
  let debounce = debouncer();
@@ -221,17 +241,21 @@ class ModelInput extends SocketConsumer {
221
241
  debounce(async () => {
222
242
  try {
223
243
  if (inputElement.type === 'checkbox') {
224
- await model.update(fieldName, !!inputElement.checked);
244
+ let checked = !!inputElement.checked;
245
+ updateConsumerElements(this.parentElement, consumers, checked);
246
+ await model.update(fieldName, checked);
225
247
  inputElement.classList.remove(errorStyleClass);
226
248
  inputElement.classList.add(successStyleClass);
227
249
  hideErrorMessage(fieldName);
228
250
  return;
229
251
  }
230
252
  if (event.target.value === '') {
253
+ updateConsumerElements(this.parentElement, consumers, '');
231
254
  await model.delete(fieldName);
232
255
  } else {
233
256
  let targetValue = inputElement.type === 'number' ?
234
257
  Number(event.target.value) : event.target.value;
258
+ updateConsumerElements(this.parentElement, consumers, targetValue);
235
259
  await model.update(fieldName, targetValue);
236
260
  }
237
261
  inputElement.classList.remove(errorStyleClass);
@@ -253,9 +277,11 @@ class ModelInput extends SocketConsumer {
253
277
  try {
254
278
  if (event.target.value === '') {
255
279
  await model.delete(fieldName);
280
+ updateConsumerElements(this.parentElement, consumers, '');
256
281
  } else {
257
282
  let targetValue = inputElement.type === 'number' ?
258
- Number(event.target.value) : event.target.value;
283
+ Number(event.target.value) : event.target.value;
284
+ updateConsumerElements(this.parentElement, consumers, targetValue);
259
285
  await model.update(fieldName, targetValue);
260
286
  }
261
287
  inputElement.classList.remove(errorStyleClass);
package/model-text.js CHANGED
@@ -42,10 +42,19 @@ class ModelText extends SocketConsumer {
42
42
  if (modelInstanceProperty) {
43
43
  while (currentNode) {
44
44
  model = currentNode[modelInstanceProperty];
45
+ if (model && modelType && (model.type !== modelType || !(model.fields || []).includes(modelField))) {
46
+ model = null;
47
+ }
45
48
  if (model) break;
46
49
  currentNode = currentNode.getRootNode().host || currentNode.parentNode;
47
50
  }
48
- if (!model) return;
51
+ if (!model) {
52
+ throw new Error(
53
+ `The ${
54
+ this.nodeName.toLowerCase()
55
+ } element failed to obtain a model via the specified model-instance-property - Ensure that the element is nested inside a parent element which exposes a model instance of the same type which has the relevant field`
56
+ );
57
+ };
49
58
  } else {
50
59
  this.socket = this.getSocket();
51
60
  model = new AGModel({
@@ -79,7 +88,7 @@ class ModelText extends SocketConsumer {
79
88
  let changeConsumer = model.listener('change').createConsumer();
80
89
  (async () => {
81
90
  for await (let event of changeConsumer) {
82
- if (event.resourceField !== modelField || !event.isRemote) continue;
91
+ if (event.resourceField !== modelField) continue;
83
92
  let fieldValue = toSafeHTML(model.value[modelField]);
84
93
  this.innerHTML = fieldValue;
85
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saasufy-components",
3
- "version": "1.10.2",
3
+ "version": "1.12.0",
4
4
  "description": "Components for Saasufy.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/socket.js CHANGED
@@ -123,7 +123,7 @@ export class SocketConsumer extends HTMLElement {
123
123
  throw new Error(
124
124
  `The ${
125
125
  this.nodeName.toLowerCase()
126
- } element failed to obtain a socket - Make sure it is nested inside a socket-provider element`
126
+ } element failed to obtain a socket - Ensure that it is nested inside a socket-provider element`
127
127
  );
128
128
  }
129
129
  return socket;
package/utils.js CHANGED
@@ -223,6 +223,51 @@ export function renderTemplate(templateString, data, socket) {
223
223
  });
224
224
  }
225
225
 
226
+ export function updateConsumerElements(parentElement, consumers, value) {
227
+ if (parentElement && consumers) {
228
+ let consumerParts = consumers.split(',')
229
+ .filter(part => part)
230
+ .map(part => {
231
+ part = part.trim();
232
+ return part.split(':').map(subPart => subPart.trim());
233
+ })
234
+ .filter(([ selector, attributeName ]) => selector);
235
+
236
+ for (let [ selector, attributeName ] of consumerParts) {
237
+ let matchingElements = parentElement.querySelectorAll(selector);
238
+ if (attributeName) {
239
+ for (let element of matchingElements) {
240
+ if (typeof value === 'boolean') {
241
+ if (value) {
242
+ element.setAttribute(attributeName, '');
243
+ } else {
244
+ element.removeAttribute(attributeName);
245
+ }
246
+ } else {
247
+ element.setAttribute(attributeName, value);
248
+ }
249
+ }
250
+ } else {
251
+ for (let element of matchingElements) {
252
+ if (element.nodeName === 'INPUT') {
253
+ if (element.type === 'checkbox') {
254
+ if (value) {
255
+ element.setAttribute('checked', '');
256
+ } else {
257
+ element.removeAttribute('checked');
258
+ }
259
+ } else {
260
+ element.value = value;
261
+ }
262
+ } else {
263
+ element.innerHTML = value;
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+
226
271
  export function wait(duration) {
227
272
  return new Promise((resolve) => setTimeout(resolve, duration));
228
273
  }