saasufy-components 2.16.0 → 3.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/README.md +1 -5
- package/model-input.js +39 -76
- package/model-text.js +34 -74
- package/model-viewer.js +20 -30
- package/package.json +3 -3
- package/utils.js +16 -0
package/README.md
CHANGED
|
@@ -348,11 +348,8 @@ Used for displaying and editing a single field of a model instance in real time.
|
|
|
348
348
|
- `model-id` (required): The id of the model instance/record to bind to.
|
|
349
349
|
- `model-field` (required): The field of the model instance/record to bind to for reading and updating.
|
|
350
350
|
- `debounce-delay`: The delay in milliseconds to wait before sending an update to the server. This is useful to batch multiple updates together (as is common when user is typing). Default is 300ms.
|
|
351
|
-
- `enable-rebound`: By default, real-time updates performed via `model-input` components are not sent back to the publishing client as it is assumed that state changes are either localized to a single `model-input` component or shared with other components on the same page via the use of `consumers`, `bind-to-collection` or `bind-to-model` attributes. There may be situations where you have a specific value displayed in multiple places on the same page/screen and want them to be updated in real-time to reflect the latest value of the model field. For convenience, you can add the `enable-rebound` attribute to the `model-input` component to force real-time updates to rebound back to the publisher and this will ensure that all components on the page will receive real-time updates (will sync with each other) without having to explicitly bind them together via the front end. Note that enabling rebound comes with additional performance overheads.
|
|
352
351
|
- `input-id`: Can be used to set an `id` attribute on the inner `input` element.
|
|
353
352
|
- `list`: If specified, this sets the list attribute of the inner `input` element to provide input suggestions (only works with standard input elements).
|
|
354
|
-
- `bind-to-model`: If this attribute exists, the `model-input` component will attempt to host its model data within the nearest compatible `model-viewer` parent component instead of creating its own model internally. This can improve efficiency/reuse of model data and provide a better user experience. For example, if the `model-input` element is re-rendered, it will not have to re-fetch its data as it will be kept inside its parent `model-viewer` component.
|
|
355
|
-
- `bind-to-collection`: If this attribute exists, the `model-input` component will attempt to host its model data within the nearest compatible `collection-browser` or `collection-reducer` parent component instead of creating its own model internally. This can improve efficiency/reuse of model data and provide a better user experience. For example, if the `model-input` element is re-rendered, it will not have to re-fetch its data as it will be kept inside its parent `collection-browser` or `collection-reducer` component. Note that the parent component will take over the responsibility for cleaning up the model; this includes scenarios where the user loads a different page of the collection/view where the specified model instance is no longer present.
|
|
356
353
|
- `type`: The type of the input component; can be `text`, `number`, `select`, `textarea` or `checkbox`.
|
|
357
354
|
- `placeholder`: Can be used to set the placeholder text on the inner input element.
|
|
358
355
|
- `consumers`: This allows you to connect this `model-input` to other elements on your page which share the same parent element. It takes a list of selectors with optional attributes to target. For example `.my-input:value` will find all elements with a `my-input` class and update their `value` attributes with the value of the `model-input` component in real-time. You can specify multiple selectors separated by commas such as `.my-input,my-div` - In this case, because attribute names are not specified, values will be injected into the `value` attribute (for input elements) or into the `innerHTML` property (for other kinds of elements). The default attribute/property depends on the element type.
|
|
@@ -365,6 +362,7 @@ Used for displaying and editing a single field of a model instance in real time.
|
|
|
365
362
|
- `hide-error-logs`: By default, this component will log errors to the console. If set, this attribute will suppress such errors from showing up on the console.
|
|
366
363
|
- `autocapitalize`: Can be `on` or `off` - It will set the auto-capitalize attribute on the inner input element. This is useful for mobile devices to enable or disable auto-capitalization of the first character which is typed into the input element.
|
|
367
364
|
- `autocorrect`: Can be `on` or `off` - It will set the auto-correct attribute on the inner input element. This is useful for mobile devices to enable or disable auto-correct.
|
|
365
|
+
- `enable-rebound`: By default, for efficiency reasons, real-time updates performed via `model-input` components are not sent back to the publishing client; it is usually unnecessary because state changes are shared locally between all components which are bound to the same `socket-provider`. You can add the `enable-rebound` attribute to the `model-input` component to force real-time updates to rebound back to the publisher to support more advanced scenarios. Note that enabling rebound comes with additional performance overheads.
|
|
368
366
|
|
|
369
367
|
### model-text
|
|
370
368
|
|
|
@@ -386,8 +384,6 @@ Used to displaying a field of a model instance in real time.
|
|
|
386
384
|
- `model-type` (required): Specifies the type of model to bind to. This should match a `Model` available in your Saasufy service.
|
|
387
385
|
- `model-id` (required): The id of the model instance/record to bind to.
|
|
388
386
|
- `model-field` (required): The field of the model instance/record to bind to for reading.
|
|
389
|
-
- `bind-to-model`: If this attribute exists, the `model-text` component will attempt to fetch its model data from the nearest compatible `model-viewer` parent component instead of creating its own model internally. This can improve efficiency/reuse of model data and provide a better user experience. For example, if the `model-text` element is re-rendered, it will not have to re-fetch its data as it will be kept inside its parent `model-viewer` component.
|
|
390
|
-
- `bind-to-collection`: If this attribute exists, the `model-text` component will attempt to fetch its model data from the nearest compatible `collection-browser` or `collection-reducer` parent component instead of creating its own model internally. This can improve efficiency/reuse of model data and provide a better user experience. For example, if the `model-text` element is re-rendered, it will not have to re-fetch its data as it will be kept inside its parent `collection-browser` or `collection-reducer` component. Note that the parent component will take over the responsibility for cleaning up the model; this includes scenarios where the user loads a different page of the collection/view where the specified model instance is no longer present.
|
|
391
387
|
- `hide-error-logs`: By default, this component will log errors to the console. If set, this attribute will suppress such errors from showing up on the console.
|
|
392
388
|
|
|
393
389
|
### model-viewer
|
package/model-input.js
CHANGED
|
@@ -8,6 +8,7 @@ class ModelInput extends SocketConsumer {
|
|
|
8
8
|
this.isReady = false;
|
|
9
9
|
this.inputElement = null;
|
|
10
10
|
}
|
|
11
|
+
|
|
11
12
|
connectedCallback() {
|
|
12
13
|
this.isReady = true;
|
|
13
14
|
this.destroy = () => {};
|
|
@@ -22,10 +23,7 @@ class ModelInput extends SocketConsumer {
|
|
|
22
23
|
return [
|
|
23
24
|
'input-id',
|
|
24
25
|
'list',
|
|
25
|
-
'
|
|
26
|
-
'collection-instance-property',
|
|
27
|
-
'bind-to-model',
|
|
28
|
-
'bind-to-collection',
|
|
26
|
+
'socket-instance-property',
|
|
29
27
|
'type',
|
|
30
28
|
'placeholder',
|
|
31
29
|
'consumers',
|
|
@@ -89,10 +87,7 @@ class ModelInput extends SocketConsumer {
|
|
|
89
87
|
|
|
90
88
|
render() {
|
|
91
89
|
this.innerHTML = '';
|
|
92
|
-
let
|
|
93
|
-
let modelInstanceProperty = this.getAttribute('model-instance-property');
|
|
94
|
-
let bindToCollection = this.hasAttribute('bind-to-collection');
|
|
95
|
-
let collectionInstanceProperty = this.getAttribute('collection-instance-property');
|
|
90
|
+
let socketInstanceProperty = this.getAttribute('socket-instance-property');
|
|
96
91
|
let showErrorMessage = this.hasAttribute('show-error-message');
|
|
97
92
|
let inputId = this.getAttribute('input-id');
|
|
98
93
|
let autocapitalize = this.getAttribute('autocapitalize');
|
|
@@ -107,76 +102,43 @@ class ModelInput extends SocketConsumer {
|
|
|
107
102
|
let height = this.getAttribute('height');
|
|
108
103
|
let hideErrorLogs = this.hasAttribute('hide-error-logs');
|
|
109
104
|
let enableRebound = this.hasAttribute('enable-rebound');
|
|
110
|
-
|
|
111
|
-
let
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
collectionInstanceProperty = 'collection';
|
|
115
|
-
}
|
|
116
|
-
if (collectionInstanceProperty) {
|
|
117
|
-
let collection;
|
|
105
|
+
|
|
106
|
+
let socket;
|
|
107
|
+
if (socketInstanceProperty) {
|
|
108
|
+
let currentNode = this.parentNode;
|
|
118
109
|
while (currentNode) {
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
collection = null;
|
|
122
|
-
}
|
|
123
|
-
if (collection && (!collection.agModels || !collection.agModels[modelId])) {
|
|
124
|
-
collection = null;
|
|
125
|
-
}
|
|
126
|
-
if (collection) break;
|
|
110
|
+
socket = currentNode[socketInstanceProperty];
|
|
111
|
+
if (socket) break;
|
|
127
112
|
currentNode = currentNode.getRootNode().host || currentNode.parentNode;
|
|
128
113
|
}
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
114
|
+
if (!socket) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`The ${
|
|
117
|
+
this.nodeName.toLowerCase()
|
|
118
|
+
} element failed to bind to a socket via the ${
|
|
119
|
+
socketInstanceProperty
|
|
120
|
+
} socket-instance-property`
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
} else {
|
|
124
|
+
socket = this.getSocket();
|
|
135
125
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
if (model) break;
|
|
151
|
-
currentNode = currentNode.getRootNode().host || currentNode.parentNode;
|
|
152
|
-
}
|
|
153
|
-
if (!model) {
|
|
154
|
-
throw new Error(
|
|
155
|
-
`The ${
|
|
156
|
-
this.nodeName.toLowerCase()
|
|
157
|
-
} element failed to bind to a model - Ensure that the element is nested inside a parent element which exposes a model instance of the same type with a ${modelField} field`
|
|
126
|
+
this.socket = socket;
|
|
127
|
+
let model = new AGModel({
|
|
128
|
+
socket: this.socket,
|
|
129
|
+
type: modelType,
|
|
130
|
+
id: modelId,
|
|
131
|
+
fields: [ modelField ],
|
|
132
|
+
enableRebound
|
|
133
|
+
});
|
|
134
|
+
if (!hideErrorLogs) {
|
|
135
|
+
(async () => {
|
|
136
|
+
for await (let { error } of model.listener('error')) {
|
|
137
|
+
console.error(
|
|
138
|
+
`Model input encountered an error: ${error.message}`
|
|
158
139
|
);
|
|
159
|
-
};
|
|
160
|
-
} else {
|
|
161
|
-
this.socket = this.getSocket();
|
|
162
|
-
model = new AGModel({
|
|
163
|
-
socket: this.socket,
|
|
164
|
-
type: modelType,
|
|
165
|
-
id: modelId,
|
|
166
|
-
fields: [ modelField ],
|
|
167
|
-
enableRebound
|
|
168
|
-
});
|
|
169
|
-
if (!hideErrorLogs) {
|
|
170
|
-
(async () => {
|
|
171
|
-
for await (let { error } of model.listener('error')) {
|
|
172
|
-
console.error(
|
|
173
|
-
`Model input encountered an error: ${error.message}`
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
})();
|
|
177
140
|
}
|
|
178
|
-
|
|
179
|
-
}
|
|
141
|
+
})();
|
|
180
142
|
}
|
|
181
143
|
if (model.isLoaded) {
|
|
182
144
|
this.setAttribute('is-loaded', '');
|
|
@@ -240,9 +202,7 @@ class ModelInput extends SocketConsumer {
|
|
|
240
202
|
this.destroy = () => {
|
|
241
203
|
destroyInputSync();
|
|
242
204
|
this.isLoadedConsumer && this.isLoadedConsumer.kill();
|
|
243
|
-
|
|
244
|
-
model.destroy();
|
|
245
|
-
}
|
|
205
|
+
model.destroy();
|
|
246
206
|
};
|
|
247
207
|
}
|
|
248
208
|
|
|
@@ -304,8 +264,9 @@ class ModelInput extends SocketConsumer {
|
|
|
304
264
|
let debounce = debouncer();
|
|
305
265
|
|
|
306
266
|
let onInputChange = (event) => {
|
|
307
|
-
if (event.target.value === String(model.value[fieldName])) return;
|
|
308
267
|
debounce(async () => {
|
|
268
|
+
if (event.target.value === String(model.value[fieldName] || '')) return;
|
|
269
|
+
|
|
309
270
|
let providerTemplate = this.getAttribute('provider-template');
|
|
310
271
|
try {
|
|
311
272
|
if (inputElement.type === 'checkbox') {
|
|
@@ -342,6 +303,8 @@ class ModelInput extends SocketConsumer {
|
|
|
342
303
|
if (inputElement.type !== 'checkbox' && inputElement.type !== 'select') {
|
|
343
304
|
onInputKeyUp = async (event) => {
|
|
344
305
|
debounce(async () => {
|
|
306
|
+
if (event.target.value === String(model.value[fieldName] || '')) return;
|
|
307
|
+
|
|
345
308
|
let providerTemplate = this.getAttribute('provider-template');
|
|
346
309
|
try {
|
|
347
310
|
if (event.target.value === '') {
|
package/model-text.js
CHANGED
|
@@ -20,10 +20,7 @@ class ModelText extends SocketConsumer {
|
|
|
20
20
|
|
|
21
21
|
static get observedAttributes() {
|
|
22
22
|
return [
|
|
23
|
-
'
|
|
24
|
-
'collection-instance-property',
|
|
25
|
-
'bind-to-collection',
|
|
26
|
-
'bind-to-model',
|
|
23
|
+
'socket-instance-property',
|
|
27
24
|
'model-type',
|
|
28
25
|
'model-id',
|
|
29
26
|
'model-field',
|
|
@@ -39,84 +36,49 @@ class ModelText extends SocketConsumer {
|
|
|
39
36
|
|
|
40
37
|
render() {
|
|
41
38
|
this.innerHTML = '';
|
|
42
|
-
let
|
|
43
|
-
let modelInstanceProperty = this.getAttribute('model-instance-property');
|
|
44
|
-
let bindToCollection = this.hasAttribute('bind-to-collection');
|
|
45
|
-
let collectionInstanceProperty = this.getAttribute('collection-instance-property');
|
|
39
|
+
let socketInstanceProperty = this.getAttribute('socket-instance-property');
|
|
46
40
|
let modelType = this.getAttribute('model-type');
|
|
47
41
|
let modelId = this.getAttribute('model-id');
|
|
48
42
|
let modelField = this.getAttribute('model-field');
|
|
49
43
|
let hideErrorLogs = this.hasAttribute('hide-error-logs');
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
collectionInstanceProperty = 'collection';
|
|
55
|
-
}
|
|
56
|
-
if (collectionInstanceProperty) {
|
|
57
|
-
let collection;
|
|
44
|
+
|
|
45
|
+
let socket;
|
|
46
|
+
if (socketInstanceProperty) {
|
|
47
|
+
let currentNode = this.parentNode;
|
|
58
48
|
while (currentNode) {
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
collection = null;
|
|
62
|
-
}
|
|
63
|
-
if (collection && (!collection.agModels || !collection.agModels[modelId])) {
|
|
64
|
-
collection = null;
|
|
65
|
-
}
|
|
66
|
-
if (collection) break;
|
|
49
|
+
socket = currentNode[socketInstanceProperty];
|
|
50
|
+
if (socket) break;
|
|
67
51
|
currentNode = currentNode.getRootNode().host || currentNode.parentNode;
|
|
68
52
|
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
53
|
+
if (!socket) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`The ${
|
|
56
|
+
this.nodeName.toLowerCase()
|
|
57
|
+
} element failed to bind to a socket via the ${
|
|
58
|
+
socketInstanceProperty
|
|
59
|
+
} socket-instance-property`
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
socket = this.getSocket();
|
|
75
64
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
model = null;
|
|
89
|
-
}
|
|
90
|
-
if (model) break;
|
|
91
|
-
currentNode = currentNode.getRootNode().host || currentNode.parentNode;
|
|
92
|
-
}
|
|
93
|
-
if (!model) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
`The ${
|
|
96
|
-
this.nodeName.toLowerCase()
|
|
97
|
-
} element failed to bind to a model - Ensure that the element is nested inside a parent element which exposes a model instance of the same type with a ${modelField} field`
|
|
65
|
+
this.socket = socket;
|
|
66
|
+
let model = new AGModel({
|
|
67
|
+
socket: this.socket,
|
|
68
|
+
type: modelType,
|
|
69
|
+
id: modelId,
|
|
70
|
+
fields: [ modelField ]
|
|
71
|
+
});
|
|
72
|
+
if (!hideErrorLogs) {
|
|
73
|
+
(async () => {
|
|
74
|
+
for await (let { error } of model.listener('error')) {
|
|
75
|
+
console.error(
|
|
76
|
+
`Model text encountered an error: ${error.message}`
|
|
98
77
|
);
|
|
99
|
-
};
|
|
100
|
-
} else {
|
|
101
|
-
this.socket = this.getSocket();
|
|
102
|
-
model = new AGModel({
|
|
103
|
-
socket: this.socket,
|
|
104
|
-
type: modelType,
|
|
105
|
-
id: modelId,
|
|
106
|
-
fields: [ modelField ]
|
|
107
|
-
});
|
|
108
|
-
if (!hideErrorLogs) {
|
|
109
|
-
(async () => {
|
|
110
|
-
for await (let { error } of model.listener('error')) {
|
|
111
|
-
console.error(
|
|
112
|
-
`Model text encountered an error: ${error.message}`
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
})();
|
|
116
78
|
}
|
|
117
|
-
|
|
118
|
-
}
|
|
79
|
+
})();
|
|
119
80
|
}
|
|
81
|
+
|
|
120
82
|
if (model.isLoaded) {
|
|
121
83
|
this.setAttribute('is-loaded', '');
|
|
122
84
|
this.dispatchEvent(new CustomEvent('load', { bubbles: true }));
|
|
@@ -142,9 +104,7 @@ class ModelText extends SocketConsumer {
|
|
|
142
104
|
this.destroy = () => {
|
|
143
105
|
changeConsumer.kill();
|
|
144
106
|
this.isLoadedConsumer && this.isLoadedConsumer.kill();
|
|
145
|
-
|
|
146
|
-
model.destroy();
|
|
147
|
-
}
|
|
107
|
+
model.destroy();
|
|
148
108
|
};
|
|
149
109
|
}
|
|
150
110
|
}
|
package/model-viewer.js
CHANGED
|
@@ -16,19 +16,14 @@ class ModelViewer extends SocketConsumer {
|
|
|
16
16
|
|
|
17
17
|
connectedCallback() {
|
|
18
18
|
this.isReady = true;
|
|
19
|
-
this.socket = this.getSocket();
|
|
20
19
|
this.activeLoader = null;
|
|
21
20
|
this.shadowRoot.addEventListener('slotchange', this.handleSlotChangeEvent);
|
|
22
21
|
this.render();
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
disconnectedCallback() {
|
|
26
|
-
if (this.model
|
|
25
|
+
if (this.model) {
|
|
27
26
|
this.model.destroy();
|
|
28
|
-
} else {
|
|
29
|
-
if (this.modelLoadConsumer) this.modelLoadConsumer.kill();
|
|
30
|
-
if (this.modelChangeConsumer) this.modelChangeConsumer.kill();
|
|
31
|
-
if (this.modelErrorConsumer) this.modelErrorConsumer.kill();
|
|
32
27
|
}
|
|
33
28
|
this.shadowRoot.removeEventListener('slotchange', this.handleSlotChangeEvent);
|
|
34
29
|
}
|
|
@@ -93,43 +88,38 @@ class ModelViewer extends SocketConsumer {
|
|
|
93
88
|
let modelType = this.getAttribute('model-type');
|
|
94
89
|
let modelId = this.getAttribute('model-id');
|
|
95
90
|
let modelFields = this.getAttribute('model-fields') || '';
|
|
96
|
-
let
|
|
91
|
+
let socketInstanceProperty = this.getAttribute('socket-instance-property');
|
|
97
92
|
let hideErrorLogs = this.hasAttribute('hide-error-logs');
|
|
98
93
|
|
|
99
|
-
if (this.model
|
|
94
|
+
if (this.model) this.model.destroy();
|
|
100
95
|
|
|
101
|
-
let
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
let socket;
|
|
97
|
+
if (socketInstanceProperty) {
|
|
98
|
+
let currentNode = this.parentNode;
|
|
104
99
|
while (currentNode) {
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
model = null;
|
|
108
|
-
}
|
|
109
|
-
if (model && !model.agFields) {
|
|
110
|
-
model = null;
|
|
111
|
-
}
|
|
112
|
-
if (model) break;
|
|
100
|
+
socket = currentNode[socketInstanceProperty];
|
|
101
|
+
if (socket) break;
|
|
113
102
|
currentNode = currentNode.getRootNode().host || currentNode.parentNode;
|
|
114
103
|
}
|
|
115
|
-
if (!
|
|
104
|
+
if (!socket) {
|
|
116
105
|
throw new Error(
|
|
117
106
|
`The ${
|
|
118
107
|
this.nodeName.toLowerCase()
|
|
119
|
-
} element failed to
|
|
108
|
+
} element failed to bind to a socket via the ${
|
|
109
|
+
socketInstanceProperty
|
|
110
|
+
} socket-instance-property`
|
|
120
111
|
);
|
|
121
112
|
};
|
|
122
|
-
this.model = model;
|
|
123
|
-
this.isModelLocal = false;
|
|
124
113
|
} else {
|
|
125
|
-
|
|
126
|
-
socket: this.socket,
|
|
127
|
-
type: modelType,
|
|
128
|
-
id: modelId,
|
|
129
|
-
fields: modelFields.split(',').map(field => field.trim()).filter(field => field)
|
|
130
|
-
});
|
|
131
|
-
this.isModelLocal = true;
|
|
114
|
+
socket = this.getSocket();
|
|
132
115
|
}
|
|
116
|
+
this.socket = socket;
|
|
117
|
+
this.model = new AGModel({
|
|
118
|
+
socket: this.socket,
|
|
119
|
+
type: modelType,
|
|
120
|
+
id: modelId,
|
|
121
|
+
fields: modelFields.split(',').map(field => field.trim()).filter(field => field)
|
|
122
|
+
});
|
|
133
123
|
|
|
134
124
|
this.shadowRoot.innerHTML = `
|
|
135
125
|
<slot name="loader"></slot>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "saasufy-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Components for Saasufy.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"author": "Jonathan Gros-Dubois",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"ag-collection": "^
|
|
21
|
-
"ag-model": "^
|
|
20
|
+
"ag-collection": "^5.0.0",
|
|
21
|
+
"ag-model": "^3.0.0",
|
|
22
22
|
"capitalisk-auth-client": "^1.5.1",
|
|
23
23
|
"socketcluster-client": "^19.1.0"
|
|
24
24
|
},
|
package/utils.js
CHANGED
|
@@ -89,6 +89,10 @@ export function createReactiveCollection(collectionOptions, callback) {
|
|
|
89
89
|
}
|
|
90
90
|
})();
|
|
91
91
|
|
|
92
|
+
if (collection.isLoaded) {
|
|
93
|
+
collection.safeValue = collection.value.map(toSafeModelValue);
|
|
94
|
+
}
|
|
95
|
+
|
|
92
96
|
return collection;
|
|
93
97
|
}
|
|
94
98
|
|
|
@@ -120,6 +124,10 @@ export function createReactiveModel(modelOptions, callback) {
|
|
|
120
124
|
}
|
|
121
125
|
})();
|
|
122
126
|
|
|
127
|
+
if (model.isLoaded) {
|
|
128
|
+
model.safeValue = toSafeModelValue(model.value);
|
|
129
|
+
}
|
|
130
|
+
|
|
123
131
|
return model;
|
|
124
132
|
}
|
|
125
133
|
|
|
@@ -142,6 +150,10 @@ export function createCollection(collectionOptions) {
|
|
|
142
150
|
}
|
|
143
151
|
})();
|
|
144
152
|
|
|
153
|
+
if (collection.isLoaded) {
|
|
154
|
+
collection.safeValue = collection.value.map(toSafeModelValue);
|
|
155
|
+
}
|
|
156
|
+
|
|
145
157
|
return collection;
|
|
146
158
|
}
|
|
147
159
|
|
|
@@ -162,6 +174,10 @@ export function createModel(modelOptions) {
|
|
|
162
174
|
}
|
|
163
175
|
})();
|
|
164
176
|
|
|
177
|
+
if (model.isLoaded) {
|
|
178
|
+
model.safeValue = toSafeModelValue(model.value);
|
|
179
|
+
}
|
|
180
|
+
|
|
165
181
|
return model;
|
|
166
182
|
}
|
|
167
183
|
|