saasufy-components 7.0.2 → 7.1.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/README.md CHANGED
@@ -321,7 +321,8 @@ In addition to the slots shown above, the `collection-viewer` also supports the
321
321
  - `collection-page-size`: Sets how many items from the collection are displayed at once. This is useful for pagination, allowing users to navigate through large sets of data in chunks.
322
322
  - `collection-page-offset`: Indicates the current page offset in the collection's data. It’s like telling the viewer which page of data you want to display initially.
323
323
  - `collection-get-count`: If this attribute is present, the component will get the record count of the target view. The count can be rendered into the template by prefixing the model name with a dollar sign and accessing the `count` property like this: `{{$MyModelName.count}}`.
324
- - `collection-view-primary-fields`: An optional list of field names to specify which specific `collection-view-params` to watch for real time updates. Fewer primary fields means that the view will be exposed to a broader range of real time updates but at the cost of performance. It is generally recommended to have just one primary field.
324
+ - `collection-view-primary-fields`: An optional list of field names to specify which specific `collection-view-params` to watch for realtime updates. Fewer primary fields means that the view will be exposed to a broader range of realtime updates but at the cost of performance. It is generally recommended to have just one primary field.
325
+ - `collection-disable-realtime`: If this attribute is present, the underlying collection will not listen for changes nor update in realtime. Fields of records that are in view may still update in realtime.
325
326
  - `auto-reset-page-offset`: If this attribute is present, the `collection-page-offset` will be reset to zero whenever the view params change.
326
327
  - `type-alias`: Allows you to provide an alternative name for your `Model` to use when injecting values inside the template. This is useful for situations where you may have multiple `collection-viewer` elements and/or `model-viewer` elements of the same type nested inside each other and want to avoid `Model` name clashes in the nested template definitions. For example, if the `type-alias` in the snippet above was set to `SubChat`, then `{{Chat.message}}` would become `{{SubChat.message}}`.
327
328
  - `hide-error-logs`: A flag which, when present, suppresses error logs from being printed to the console.
@@ -532,7 +533,7 @@ In the example above, the name of the first element can be accessed with `{{Cate
532
533
 
533
534
  ### model-input
534
535
 
535
- Used for displaying and editing a single field of a model instance in real time.
536
+ Used for displaying and editing a single field of a model instance in realtime.
536
537
 
537
538
  **Import**
538
539
 
@@ -583,7 +584,7 @@ Used for displaying and editing a single field of a model instance in real time.
583
584
 
584
585
  ### model-text
585
586
 
586
- Used to displaying a field of a model instance in real time.
587
+ Used to displaying a field of a model instance in realtime.
587
588
 
588
589
  **Import**
589
590
 
@@ -18,10 +18,10 @@ class CollectionViewer extends SocketConsumer {
18
18
  modal.show(event.detail.message, event.detail.callback);
19
19
  };
20
20
 
21
- this.handleCRUDCreateEvent = (event) => {
21
+ this.handleCRUDCreateEvent = async (event) => {
22
22
  event.stopPropagation();
23
23
  if (this.collection) {
24
- this.collection.create(event.detail);
24
+ await this.collection.create(event.detail);
25
25
  this.dispatchEvent(
26
26
  new CustomEvent('collectionCreate', {
27
27
  detail: {
@@ -31,13 +31,16 @@ class CollectionViewer extends SocketConsumer {
31
31
  bubbles: true
32
32
  })
33
33
  );
34
+ if (this.hasAttribute('collection-disable-realtime') && this.collection) {
35
+ this.collection.reloadCurrentPage();
36
+ }
34
37
  }
35
38
  };
36
39
 
37
- this.handleCRUDDeleteEvent = (event) => {
40
+ this.handleCRUDDeleteEvent = async (event) => {
38
41
  event.stopPropagation();
39
42
  if (this.collection) {
40
- this.collection.delete(event.detail);
43
+ await this.collection.delete(event.detail);
41
44
  this.dispatchEvent(
42
45
  new CustomEvent('collectionDelete', {
43
46
  detail: {
@@ -47,6 +50,9 @@ class CollectionViewer extends SocketConsumer {
47
50
  bubbles: true
48
51
  })
49
52
  );
53
+ if (this.hasAttribute('collection-disable-realtime') && this.collection) {
54
+ this.collection.reloadCurrentPage();
55
+ }
50
56
  }
51
57
  };
52
58
 
@@ -123,6 +129,7 @@ class CollectionViewer extends SocketConsumer {
123
129
  'collection-page-size',
124
130
  'collection-page-offset',
125
131
  'collection-get-count',
132
+ 'collection-disable-realtime',
126
133
  'auto-reset-page-offset',
127
134
  'max-show-loader',
128
135
  'type-alias',
@@ -289,6 +296,7 @@ class CollectionViewer extends SocketConsumer {
289
296
  let collectionPageSize = this.getAttribute('collection-page-size');
290
297
  let collectionPageOffset = this.getAttribute('collection-page-offset');
291
298
  let collectionGetCount = this.hasAttribute('collection-get-count');
299
+ let collectionDisableRealtime = this.hasAttribute('collection-disable-realtime');
292
300
  let hideErrorLogs = this.hasAttribute('hide-error-logs');
293
301
  let collectionReloadDelay = Number(
294
302
  this.getAttribute('collection-reload-delay') || DEFAULT_RELOAD_DELAY
@@ -312,7 +320,8 @@ class CollectionViewer extends SocketConsumer {
312
320
  pageSize: Number(collectionPageSize || 10),
313
321
  pageOffset: Number(collectionPageOffset || 0),
314
322
  changeReloadDelay: collectionReloadDelay,
315
- getCount: collectionGetCount
323
+ getCount: collectionGetCount,
324
+ realtimeCollection: !collectionDisableRealtime
316
325
  });
317
326
 
318
327
  this.shadowRoot.innerHTML = `
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saasufy-components",
3
- "version": "7.0.2",
3
+ "version": "7.1.0",
4
4
  "description": "Components for Saasufy.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/utils.js CHANGED
@@ -273,14 +273,17 @@ function* selectExpressions(string) {
273
273
  let isCapturing = false;
274
274
  let isTripleBracket = false;
275
275
  let captureList = [];
276
+ let captureStartIndex = 0;
276
277
  for (let i = 1; i < charList.length; i++) {
277
278
  if (charList[i - 1] === '{' && charList[i] === '{') {
278
279
  captureList = [];
279
280
  captureList.push('{');
280
281
  isCapturing = true;
282
+ captureStartIndex = i - 1;
281
283
  isTripleBracket = charList[i - 2] === '{';
282
284
  if (isTripleBracket) {
283
285
  captureList.push('{');
286
+ captureStartIndex--;
284
287
  }
285
288
  }
286
289
  if (isCapturing) {
@@ -288,10 +291,16 @@ function* selectExpressions(string) {
288
291
  } else if (captureList.length) {
289
292
  captureList.push('}');
290
293
  captureList.push('}');
294
+ let closeBrackets = 2;
291
295
  if (isTripleBracket) {
292
296
  captureList.push('}');
297
+ closeBrackets++;
293
298
  }
294
- yield captureList.join('');
299
+ yield {
300
+ startIndex: captureStartIndex,
301
+ length: (i + closeBrackets) - captureStartIndex,
302
+ value: captureList.join('')
303
+ };
295
304
  captureList = [];
296
305
  }
297
306
  if (
@@ -303,37 +312,44 @@ function* selectExpressions(string) {
303
312
  }
304
313
  }
305
314
 
315
+ function replaceExpressions(string, replaceFn) {
316
+ let charList = string.split('');
317
+ let matches = [ ...selectExpressions(string) ];
318
+ let charSubs = matches.map(item => String(replaceFn(item.value) ?? '').split(''));
319
+ for (let i = matches.length - 1; i >= 0; i--) {
320
+ let match = matches[i];
321
+ charList.splice(match.startIndex, match.length, ...charSubs[i]);
322
+ }
323
+ return charList.join('');
324
+ }
325
+
306
326
  export function renderTemplate(templateString, data, socket) {
307
- let expressionIterator = selectExpressions(templateString);
308
327
  let options = getRenderOptions(data, socket);
309
- for (let expression of expressionIterator) {
310
- let computedValue;
311
- if (expression.match(templateTripleTagsRegExp)) {
312
- let expString = expression.slice(3, -3);
328
+ return replaceExpressions(templateString, (expression) => {
329
+ let expString;
330
+ if (expression.startsWith('{{{') && expression.endsWith('}}}')) {
331
+ expString = expression.slice(3, -3);
313
332
  try {
314
- computedValue = execExpression(
333
+ return execExpression(
315
334
  toExpression(expString),
316
335
  options
317
336
  );
318
337
  } catch (error) {
319
- computedValue = expression;
320
- }
321
- } else {
322
- let expString = expression.slice(2, -2);
323
- try {
324
- computedValue = toSafeHTML(
325
- execExpression(
326
- toExpression(expString),
327
- options
328
- )
329
- );
330
- } catch (error) {
331
- computedValue = expression;
338
+ return expression;
332
339
  }
333
340
  }
334
- templateString = templateString.replace(expression, computedValue);
335
- }
336
- return templateString;
341
+ expString = expression.slice(2, -2);
342
+ try {
343
+ return toSafeHTML(
344
+ execExpression(
345
+ toExpression(expString),
346
+ options
347
+ )
348
+ );
349
+ } catch (error) {
350
+ return expression;
351
+ }
352
+ });
337
353
  }
338
354
 
339
355
  export function updateConsumerElements(consumers, value, template, sourceElementName, outputType) {