@flumens/models 0.5.2 → 0.6.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/dist/Collection.d.ts +1 -1
- package/dist/Collection.js +108 -1
- package/dist/Drupal/User.d.ts +2 -2
- package/dist/Drupal/User.js +433 -1
- package/dist/Indicia/Media.js +369 -1
- package/dist/Indicia/Occurrence.d.ts +7 -7
- package/dist/Indicia/Occurrence.js +220 -1
- package/dist/Indicia/Sample.d.ts +2 -2
- package/dist/Indicia/Sample.js +687 -1
- package/dist/Indicia/SampleCollection.js +77 -1
- package/dist/Indicia/helpers.d.ts +1 -1
- package/dist/Indicia/helpers.js +120 -1
- package/dist/Model.d.ts +1 -1
- package/dist/Model.js +191 -1
- package/dist/Stores/LocalForageStore.js +228 -1
- package/dist/Stores/SQLiteDatabase.d.ts +1 -1
- package/dist/Stores/SQLiteDatabase.js +221 -1
- package/dist/Stores/SQLiteStore.d.ts +4 -6
- package/dist/Stores/SQLiteStore.js +310 -1
- package/dist/Stores/Store.js +11 -1
- package/dist/Stores/utils.js +60 -1
- package/dist/index.js +29 -1
- package/package.json +14 -19
package/dist/Indicia/Media.js
CHANGED
|
@@ -1 +1,369 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var mobx = require('mobx');
|
|
7
|
+
var axios = require('axios');
|
|
8
|
+
var utils = require('@flumens/utils');
|
|
9
|
+
var Model = require('../Model.js');
|
|
10
|
+
var helpers = require('./helpers.js');
|
|
11
|
+
|
|
12
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
|
|
15
|
+
|
|
16
|
+
var THUMBNAIL_WIDTH = 100; // px
|
|
17
|
+
var THUMBNAIL_HEIGHT = 100; // px
|
|
18
|
+
var isHybrid = utils.isPlatform('hybrid');
|
|
19
|
+
var Media = /** @class */ (function (_super) {
|
|
20
|
+
tslib.__extends(Media, _super);
|
|
21
|
+
function Media(_a) {
|
|
22
|
+
if (_a === void 0) { _a = {}; }
|
|
23
|
+
var _this = this;
|
|
24
|
+
var _b = _a.metadata, metadata = _b === void 0 ? {} : _b, options = tslib.__rest(_a, ["metadata"]);
|
|
25
|
+
_this = _super.call(this, options) || this;
|
|
26
|
+
_this.remote = {
|
|
27
|
+
synchronising: false,
|
|
28
|
+
url: null, // must be set up for remote sync
|
|
29
|
+
headers: {}, // auth and other headers
|
|
30
|
+
timeout: 120000, // 120s
|
|
31
|
+
};
|
|
32
|
+
_this.debouncedValue = 300;
|
|
33
|
+
_this.parent = _this.parent;
|
|
34
|
+
_this.metadata = mobx.observable(metadata);
|
|
35
|
+
return _this;
|
|
36
|
+
}
|
|
37
|
+
Media.fromJSON = function (json) {
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
return new this(tslib.__assign(tslib.__assign({}, json), { createdAt: json.createdAt || ((_a = json.metadata) === null || _a === void 0 ? void 0 : _a.createdOn), updatedAt: json.updatedAt || ((_b = json.metadata) === null || _b === void 0 ? void 0 : _b.updatedOn), syncedAt: json.syncedAt || ((_c = json.metadata) === null || _c === void 0 ? void 0 : _c.syncedOn) }));
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Transforms and resizes an image file into a string.
|
|
43
|
+
* Can accept file image path and a file input file.
|
|
44
|
+
*
|
|
45
|
+
* @param onError
|
|
46
|
+
* @param file
|
|
47
|
+
* @param onSaveSuccess
|
|
48
|
+
* @returns {number}
|
|
49
|
+
*/
|
|
50
|
+
Media.getDataURI = function (file, options) {
|
|
51
|
+
if (options === void 0) { options = {}; }
|
|
52
|
+
var promise = new Promise(function (fulfill, reject) {
|
|
53
|
+
// file paths
|
|
54
|
+
if (typeof file === 'string') {
|
|
55
|
+
// get extension
|
|
56
|
+
var fileType_1 = file.replace(/.*\.([a-z]+)$/i, '$1');
|
|
57
|
+
if (fileType_1 === 'jpg')
|
|
58
|
+
fileType_1 = 'jpeg'; // to match media types image/jpeg
|
|
59
|
+
Media.resize(file, fileType_1, options.width, options.height).then(function (args) {
|
|
60
|
+
var image = args[0], dataURI = args[1];
|
|
61
|
+
fulfill([dataURI, fileType_1, image.width, image.height]);
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// file inputs
|
|
66
|
+
if (!window.FileReader) {
|
|
67
|
+
reject(new Error('No File Reader'));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
var reader = new FileReader();
|
|
71
|
+
reader.onload = function (event) {
|
|
72
|
+
var _a, _b;
|
|
73
|
+
if (options.width || options.height) {
|
|
74
|
+
// resize
|
|
75
|
+
Media.resize((_a = event.target) === null || _a === void 0 ? void 0 : _a.result, file.type, options.width, options.height).then(function (args) {
|
|
76
|
+
var image = args[0], dataURI = args[1];
|
|
77
|
+
fulfill([dataURI, file.type, image.width, image.height]);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
var image_1 = new window.Image(); // native one
|
|
82
|
+
image_1.onload = function () {
|
|
83
|
+
var _a;
|
|
84
|
+
var type = file.type.replace(/.*\/([a-z]+)$/i, '$1');
|
|
85
|
+
fulfill([(_a = event.target) === null || _a === void 0 ? void 0 : _a.result, type, image_1.width, image_1.height]);
|
|
86
|
+
};
|
|
87
|
+
image_1.src = (_b = event.target) === null || _b === void 0 ? void 0 : _b.result;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
reader.readAsDataURL(file);
|
|
91
|
+
});
|
|
92
|
+
return promise;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* http://stackoverflow.com/questions/2516117/how-to-scale-an-image-in-data-uri-format-in-javascript-real-scaling-not-usin
|
|
96
|
+
*/
|
|
97
|
+
Media.resize = function (data, fileType, MAX_WIDTH, MAX_HEIGHT) {
|
|
98
|
+
var promise = new Promise(function (fulfill) {
|
|
99
|
+
var image = new window.Image(); // native one
|
|
100
|
+
image.onload = function () {
|
|
101
|
+
var _a;
|
|
102
|
+
var width = image.width;
|
|
103
|
+
var height = image.height;
|
|
104
|
+
var maxWidth = !MAX_WIDTH || MAX_WIDTH > width ? width : MAX_WIDTH;
|
|
105
|
+
var maxHeight = !MAX_HEIGHT || MAX_HEIGHT > height ? height : MAX_HEIGHT;
|
|
106
|
+
var res = null;
|
|
107
|
+
// resizing
|
|
108
|
+
if (width > height) {
|
|
109
|
+
res = width / maxWidth;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
res = height / maxHeight;
|
|
113
|
+
}
|
|
114
|
+
width /= res;
|
|
115
|
+
height /= res;
|
|
116
|
+
// Create a canvas with the desired dimensions
|
|
117
|
+
var canvas = document.createElement('canvas');
|
|
118
|
+
canvas.width = width;
|
|
119
|
+
canvas.height = height;
|
|
120
|
+
// Scale and draw the source image to the canvas
|
|
121
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(image, 0, 0, width, height);
|
|
122
|
+
// Convert the canvas to a data URL in some format
|
|
123
|
+
fulfill([image, canvas.toDataURL(fileType)]);
|
|
124
|
+
};
|
|
125
|
+
image.src = data;
|
|
126
|
+
});
|
|
127
|
+
return promise;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Create new image model with a photo
|
|
131
|
+
* @param ImageModel Class representing the model.
|
|
132
|
+
* @param imageURL
|
|
133
|
+
* @param dataDirPath
|
|
134
|
+
* @returns
|
|
135
|
+
*/
|
|
136
|
+
Media.getImageModel = function (imageURL, dataDirPath, skipThumbnail) {
|
|
137
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
138
|
+
var MediaClass, width, height, data, image, imageModel;
|
|
139
|
+
var _a;
|
|
140
|
+
return tslib.__generator(this, function (_b) {
|
|
141
|
+
switch (_b.label) {
|
|
142
|
+
case 0:
|
|
143
|
+
MediaClass = this;
|
|
144
|
+
if (!imageURL) {
|
|
145
|
+
throw new Error('File not found while creating image model.');
|
|
146
|
+
}
|
|
147
|
+
if (!isHybrid) return [3 /*break*/, 2];
|
|
148
|
+
return [4 /*yield*/, utils.createImage(imageURL)];
|
|
149
|
+
case 1:
|
|
150
|
+
image = _b.sent();
|
|
151
|
+
width = image.width;
|
|
152
|
+
height = image.height;
|
|
153
|
+
data = imageURL.split('/').pop();
|
|
154
|
+
return [3 /*break*/, 4];
|
|
155
|
+
case 2: return [4 /*yield*/, MediaClass.getDataURI(imageURL, {
|
|
156
|
+
width: 2000,
|
|
157
|
+
height: 2000,
|
|
158
|
+
})];
|
|
159
|
+
case 3:
|
|
160
|
+
_a = _b.sent(), data = _a[0], width = _a[2], height = _a[3];
|
|
161
|
+
_b.label = 4;
|
|
162
|
+
case 4:
|
|
163
|
+
imageModel = new MediaClass({
|
|
164
|
+
attrs: {
|
|
165
|
+
data: data,
|
|
166
|
+
type: 'jpeg',
|
|
167
|
+
width: width,
|
|
168
|
+
height: height,
|
|
169
|
+
path: dataDirPath,
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
if (!!skipThumbnail) return [3 /*break*/, 6];
|
|
173
|
+
return [4 /*yield*/, imageModel.addThumbnail()];
|
|
174
|
+
case 5:
|
|
175
|
+
_b.sent();
|
|
176
|
+
_b.label = 6;
|
|
177
|
+
case 6: return [2 /*return*/, imageModel];
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
Media.prototype.toJSON = function () {
|
|
183
|
+
var data = _super.prototype.toJSON.call(this);
|
|
184
|
+
return JSON.parse(JSON.stringify(tslib.__assign(tslib.__assign({}, data), { metadata: mobx.toJS(this.metadata) || {} })));
|
|
185
|
+
};
|
|
186
|
+
Media.prototype.setupdatedAtTimestamp = function (newUpdatedAt) {
|
|
187
|
+
var _a;
|
|
188
|
+
_super.prototype.setUpdatedAtTimestamp.call(this, newUpdatedAt);
|
|
189
|
+
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.setUpdatedAtTimestamp(newUpdatedAt);
|
|
190
|
+
};
|
|
191
|
+
Media.prototype.getSubmission = function (warehouseMediaNames) {
|
|
192
|
+
if (warehouseMediaNames === void 0) { warehouseMediaNames = {}; }
|
|
193
|
+
var queued = warehouseMediaNames[this.cid];
|
|
194
|
+
if (!this.id && !queued) {
|
|
195
|
+
throw new Error('Image ID or queued ID is missing.');
|
|
196
|
+
}
|
|
197
|
+
var submission = {
|
|
198
|
+
values: {
|
|
199
|
+
caption: this.attrs.caption,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
if (this.id) {
|
|
203
|
+
submission.values.id = this.id;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
submission.values.queued = queued.name;
|
|
207
|
+
}
|
|
208
|
+
return submission;
|
|
209
|
+
};
|
|
210
|
+
Media.prototype.sync = function () {
|
|
211
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
212
|
+
return tslib.__generator(this, function (_a) {
|
|
213
|
+
return [2 /*return*/, this.parent ? this.parent.sync() : _super.prototype.sync.call(this)];
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
Media.prototype.uploadFile = function () {
|
|
218
|
+
return tslib.__awaiter(this, arguments, void 0, function (force) {
|
|
219
|
+
var twelveHrsAgo, alreadySynced, formData, data, headers, _a, res;
|
|
220
|
+
var _b;
|
|
221
|
+
var _c;
|
|
222
|
+
if (force === void 0) { force = false; }
|
|
223
|
+
return tslib.__generator(this, function (_d) {
|
|
224
|
+
switch (_d.label) {
|
|
225
|
+
case 0:
|
|
226
|
+
if (this.id) {
|
|
227
|
+
throw new Error('A file of a media on the remote cannot be uploaded again.');
|
|
228
|
+
}
|
|
229
|
+
twelveHrsAgo = Date.now() - 1000 * 60 * 60 * 12;
|
|
230
|
+
alreadySynced = this.syncedAt > twelveHrsAgo && this.attrs.queued;
|
|
231
|
+
if (!force && alreadySynced)
|
|
232
|
+
return [2 /*return*/];
|
|
233
|
+
return [4 /*yield*/, this.getFormData()];
|
|
234
|
+
case 1:
|
|
235
|
+
formData = _d.sent();
|
|
236
|
+
data = new FormData();
|
|
237
|
+
(_b = data).append.apply(_b, formData);
|
|
238
|
+
if (!(typeof this.remote.headers === 'function')) return [3 /*break*/, 3];
|
|
239
|
+
return [4 /*yield*/, this.remote.headers()];
|
|
240
|
+
case 2:
|
|
241
|
+
_a = _d.sent();
|
|
242
|
+
return [3 /*break*/, 4];
|
|
243
|
+
case 3:
|
|
244
|
+
_a = this.remote.headers;
|
|
245
|
+
_d.label = 4;
|
|
246
|
+
case 4:
|
|
247
|
+
headers = _a;
|
|
248
|
+
return [4 /*yield*/, axios__default["default"].post("".concat(this.remote.url, "/media-queue"), data, {
|
|
249
|
+
headers: headers,
|
|
250
|
+
timeout: 120000,
|
|
251
|
+
})];
|
|
252
|
+
case 5:
|
|
253
|
+
res = _d.sent();
|
|
254
|
+
if (!((_c = res.data[this.cid]) === null || _c === void 0 ? void 0 : _c.name))
|
|
255
|
+
throw new Error('New remote media name was not be found.');
|
|
256
|
+
this.attrs.queued = res.data[this.cid].name;
|
|
257
|
+
this.syncedAt = new Date().getTime();
|
|
258
|
+
return [2 /*return*/];
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
};
|
|
263
|
+
Media.prototype.getFormData = function () {
|
|
264
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
265
|
+
var type, extension, mediaType, url, blob, name;
|
|
266
|
+
var _a;
|
|
267
|
+
return tslib.__generator(this, function (_b) {
|
|
268
|
+
switch (_b.label) {
|
|
269
|
+
case 0:
|
|
270
|
+
type = this.attrs.type;
|
|
271
|
+
extension = type;
|
|
272
|
+
mediaType = type;
|
|
273
|
+
if (type === null || type === void 0 ? void 0 : type.match(/image.*/)) {
|
|
274
|
+
_a = type.split('/'), extension = _a[1];
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
mediaType = "image/".concat(mediaType);
|
|
278
|
+
}
|
|
279
|
+
url = this.getURL();
|
|
280
|
+
return [4 /*yield*/, helpers.getBlobFromURL(url, mediaType)];
|
|
281
|
+
case 1:
|
|
282
|
+
blob = _b.sent();
|
|
283
|
+
name = this.cid;
|
|
284
|
+
return [2 /*return*/, [name, blob, "".concat(name, ".").concat(extension)]];
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
Media.prototype.getRemoteURL = function () {
|
|
290
|
+
if (!this.remote.url) {
|
|
291
|
+
throw new Error('No remote url was set.');
|
|
292
|
+
}
|
|
293
|
+
if (!this.attrs.queued && !this.attrs.path) {
|
|
294
|
+
throw new Error('No media queued or path attribute.');
|
|
295
|
+
}
|
|
296
|
+
var baseRemoteURL = this.remote.url.replace('/index.php/services/rest', '');
|
|
297
|
+
if (this.attrs.queued) {
|
|
298
|
+
return "".concat(baseRemoteURL, "/upload-queue/").concat(this.attrs.queued);
|
|
299
|
+
}
|
|
300
|
+
return "".concat(baseRemoteURL, "/upload/").concat(this.attrs.path);
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Returns image's absolute URL or dataURI.
|
|
304
|
+
*/
|
|
305
|
+
Media.prototype.getURL = function () {
|
|
306
|
+
return this.attrs.data;
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Resizes itself.
|
|
310
|
+
*/
|
|
311
|
+
Media.prototype.resize = function (MAX_WIDTH, MAX_HEIGHT) {
|
|
312
|
+
var _this = this;
|
|
313
|
+
var that = this;
|
|
314
|
+
var promise = new Promise(function (fulfill, reject) {
|
|
315
|
+
Media.resize(_this.getURL(), _this.attrs.type, MAX_WIDTH, MAX_HEIGHT)
|
|
316
|
+
.then(function (args) {
|
|
317
|
+
var image = args[0], data = args[1];
|
|
318
|
+
that.attrs.data = data;
|
|
319
|
+
fulfill([image, data]);
|
|
320
|
+
})
|
|
321
|
+
.catch(reject);
|
|
322
|
+
});
|
|
323
|
+
return promise;
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* Adds a thumbnail to image model.
|
|
327
|
+
* @param options
|
|
328
|
+
*/
|
|
329
|
+
Media.prototype.addThumbnail = function (options) {
|
|
330
|
+
var _this = this;
|
|
331
|
+
var that = this;
|
|
332
|
+
var promise = new Promise(function (fulfill, reject) {
|
|
333
|
+
// check if data source is dataURI
|
|
334
|
+
var re = /^data:/i;
|
|
335
|
+
if (re.test(_this.getURL())) {
|
|
336
|
+
Media.resize(_this.getURL(), _this.attrs.type, THUMBNAIL_WIDTH , THUMBNAIL_WIDTH )
|
|
337
|
+
.then(function (args) {
|
|
338
|
+
var data = args[1];
|
|
339
|
+
that.attrs.thumbnail = data;
|
|
340
|
+
fulfill();
|
|
341
|
+
})
|
|
342
|
+
.catch(reject);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
Media.getDataURI(_this.getURL(), {
|
|
346
|
+
width: THUMBNAIL_WIDTH ,
|
|
347
|
+
height: THUMBNAIL_HEIGHT ,
|
|
348
|
+
})
|
|
349
|
+
.then(function (data) {
|
|
350
|
+
that.attrs.thumbnail = data[0];
|
|
351
|
+
fulfill();
|
|
352
|
+
})
|
|
353
|
+
.catch(reject);
|
|
354
|
+
});
|
|
355
|
+
return promise;
|
|
356
|
+
};
|
|
357
|
+
Media.prototype.isUploaded = function () {
|
|
358
|
+
if (!this.parent) {
|
|
359
|
+
throw new Error('No media parent to return disabled status.');
|
|
360
|
+
}
|
|
361
|
+
return this.parent.isUploaded();
|
|
362
|
+
};
|
|
363
|
+
Media.prototype.isDisabled = function () {
|
|
364
|
+
return this.isUploaded();
|
|
365
|
+
};
|
|
366
|
+
return Media;
|
|
367
|
+
}(Model["default"]));
|
|
368
|
+
|
|
369
|
+
exports["default"] = Media;
|
|
@@ -61,19 +61,19 @@ export default class Occurrence<T extends Attrs = Attrs, S extends Metadata = Me
|
|
|
61
61
|
};
|
|
62
62
|
training: {
|
|
63
63
|
id: string;
|
|
64
|
-
values: (val?: boolean | "t" | "f" | null
|
|
64
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
65
65
|
};
|
|
66
66
|
deleted: {
|
|
67
67
|
id: string;
|
|
68
|
-
values: (val?: boolean | "t" | "f" | null
|
|
68
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
69
69
|
};
|
|
70
70
|
confidential: {
|
|
71
71
|
id: string;
|
|
72
|
-
values: (val?: boolean | "t" | "f" | null
|
|
72
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
73
73
|
};
|
|
74
74
|
zeroAbundance: {
|
|
75
75
|
id: string;
|
|
76
|
-
values: (val?: boolean | "t" | "f" | null
|
|
76
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
77
77
|
};
|
|
78
78
|
};
|
|
79
79
|
metadata: S;
|
|
@@ -100,10 +100,10 @@ export default class Occurrence<T extends Attrs = Attrs, S extends Metadata = Me
|
|
|
100
100
|
getSurvey(): {
|
|
101
101
|
attrs?: {
|
|
102
102
|
[key: string]: {
|
|
103
|
-
remote?: RemoteConfig
|
|
103
|
+
remote?: RemoteConfig;
|
|
104
104
|
};
|
|
105
|
-
}
|
|
106
|
-
modifySubmission?: (
|
|
105
|
+
};
|
|
106
|
+
modifySubmission?: (submission: any, model: any) => any;
|
|
107
107
|
};
|
|
108
108
|
isUploaded(): boolean;
|
|
109
109
|
isDisabled(): boolean;
|
|
@@ -1 +1,220 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var mobx = require('mobx');
|
|
7
|
+
var lodash = require('lodash');
|
|
8
|
+
var Model = require('../Model.js');
|
|
9
|
+
var Media = require('./Media.js');
|
|
10
|
+
var helpers = require('./helpers.js');
|
|
11
|
+
|
|
12
|
+
var Occurrence = /** @class */ (function (_super) {
|
|
13
|
+
tslib.__extends(Occurrence, _super);
|
|
14
|
+
function Occurrence(_a) {
|
|
15
|
+
if (_a === void 0) { _a = {}; }
|
|
16
|
+
var _this = this;
|
|
17
|
+
var _b = _a.metadata, metadata = _b === void 0 ? {} : _b, _c = _a.media, media = _c === void 0 ? [] : _c, options = tslib.__rest(_a, ["metadata", "media"]);
|
|
18
|
+
_this = _super.call(this, options) || this;
|
|
19
|
+
_this.debouncedValue = 300;
|
|
20
|
+
_this.keys = function () {
|
|
21
|
+
var getRemoteProps = function (attrs) {
|
|
22
|
+
var extractRemoteIfExists = function (agg, key) {
|
|
23
|
+
var _a;
|
|
24
|
+
return (tslib.__assign(tslib.__assign({}, agg), (_a = {}, _a[key] = attrs[key].remote || attrs[key], _a)));
|
|
25
|
+
};
|
|
26
|
+
return Object.keys(attrs).reduce(extractRemoteIfExists, {});
|
|
27
|
+
};
|
|
28
|
+
return tslib.__assign(tslib.__assign({}, Occurrence.keys), getRemoteProps(_this.getSurvey().attrs || {}));
|
|
29
|
+
};
|
|
30
|
+
_this.metadata = mobx.observable(metadata);
|
|
31
|
+
_this.media = mobx.observable(media);
|
|
32
|
+
// eslint-disable-next-line no-param-reassign, no-return-assign
|
|
33
|
+
var attachParent = function (model) { return (model.parent = _this); };
|
|
34
|
+
_this.media.forEach(attachParent);
|
|
35
|
+
var onAddedSetParentAndUpdateTime = function (change) {
|
|
36
|
+
var _a;
|
|
37
|
+
if ((_a = change.added) === null || _a === void 0 ? void 0 : _a.length) {
|
|
38
|
+
change.added.forEach(attachParent);
|
|
39
|
+
_this.setUpdatedAtTimestamp(Date.now());
|
|
40
|
+
}
|
|
41
|
+
else if (change.removedCount) {
|
|
42
|
+
_this.setUpdatedAtTimestamp(Date.now());
|
|
43
|
+
}
|
|
44
|
+
return change;
|
|
45
|
+
};
|
|
46
|
+
mobx.intercept(_this.media, onAddedSetParentAndUpdateTime);
|
|
47
|
+
return _this;
|
|
48
|
+
}
|
|
49
|
+
Occurrence.fromJSON = function (json, MediaClass) {
|
|
50
|
+
var _a, _b, _c, _d;
|
|
51
|
+
if (MediaClass === void 0) { MediaClass = Media["default"]; }
|
|
52
|
+
var occurrence = new this(tslib.__assign(tslib.__assign({}, json), { createdAt: json.createdAt || ((_a = json.metadata) === null || _a === void 0 ? void 0 : _a.createdOn), updatedAt: json.updatedAt || ((_b = json.metadata) === null || _b === void 0 ? void 0 : _b.updatedOn), syncedAt: json.syncedAt || ((_c = json.metadata) === null || _c === void 0 ? void 0 : _c.syncedOn), media: (_d = json.media) === null || _d === void 0 ? void 0 : _d.map(function (mJson) { return MediaClass.fromJSON(mJson); }) }));
|
|
53
|
+
return occurrence;
|
|
54
|
+
};
|
|
55
|
+
Occurrence.prototype.setUpdatedAtTimestamp = function (newUpdatedAt) {
|
|
56
|
+
var _a;
|
|
57
|
+
_super.prototype.setUpdatedAtTimestamp.call(this, newUpdatedAt);
|
|
58
|
+
(_a = this.parent) === null || _a === void 0 ? void 0 : _a.setUpdatedAtTimestamp(newUpdatedAt);
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Save the model to the offline store.
|
|
62
|
+
*/
|
|
63
|
+
Occurrence.prototype.save = function () {
|
|
64
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
65
|
+
return tslib.__generator(this, function (_a) {
|
|
66
|
+
if (!this.parent) {
|
|
67
|
+
throw new Error('Trying to save locally without a parent');
|
|
68
|
+
}
|
|
69
|
+
this.parent.save();
|
|
70
|
+
return [2 /*return*/];
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Destroy the model and remove from the offline store.
|
|
76
|
+
*/
|
|
77
|
+
Occurrence.prototype.destroy = function (silent) {
|
|
78
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
79
|
+
return tslib.__generator(this, function (_a) {
|
|
80
|
+
switch (_a.label) {
|
|
81
|
+
case 0:
|
|
82
|
+
if (!this.parent) {
|
|
83
|
+
throw new Error('Trying to destroy locally without a parent');
|
|
84
|
+
}
|
|
85
|
+
this.parent.occurrences.remove(this);
|
|
86
|
+
return [4 /*yield*/, Promise.all(this.media.map(function (media) { return media.destroy(true); }))];
|
|
87
|
+
case 1:
|
|
88
|
+
_a.sent();
|
|
89
|
+
if (silent)
|
|
90
|
+
return [2 /*return*/];
|
|
91
|
+
return [4 /*yield*/, this.parent.save()];
|
|
92
|
+
case 2:
|
|
93
|
+
_a.sent();
|
|
94
|
+
return [2 /*return*/];
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
Occurrence.prototype.sync = function () {
|
|
100
|
+
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
101
|
+
return tslib.__generator(this, function (_a) {
|
|
102
|
+
return [2 /*return*/, this.parent ? this.parent.sync() : _super.prototype.sync.call(this)];
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Returns a clean (no observables) JSON representation of the model.
|
|
108
|
+
*/
|
|
109
|
+
Occurrence.prototype.toJSON = function () {
|
|
110
|
+
var _a;
|
|
111
|
+
var data = _super.prototype.toJSON.call(this);
|
|
112
|
+
return JSON.parse(JSON.stringify(tslib.__assign(tslib.__assign({}, data), { media: ((_a = this.media) === null || _a === void 0 ? void 0 : _a.map(function (model) { return model.toJSON(); })) || [], metadata: mobx.toJS(this.metadata) || {} })));
|
|
113
|
+
};
|
|
114
|
+
Occurrence.prototype.getSurvey = function () {
|
|
115
|
+
if (!this.parent)
|
|
116
|
+
return {};
|
|
117
|
+
var survey = this.parent.getSurvey();
|
|
118
|
+
return survey.occ || {};
|
|
119
|
+
};
|
|
120
|
+
Occurrence.prototype.isUploaded = function () {
|
|
121
|
+
if (!this.parent) {
|
|
122
|
+
throw new Error('No occurrence parent to return disabled status.');
|
|
123
|
+
}
|
|
124
|
+
return this.parent.isUploaded();
|
|
125
|
+
};
|
|
126
|
+
Occurrence.prototype.isDisabled = function () {
|
|
127
|
+
return this.isUploaded();
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Returns an object with attributes and their values
|
|
131
|
+
* mapped for warehouse submission.
|
|
132
|
+
*/
|
|
133
|
+
Occurrence.prototype.getSubmission = function (warehouseMediaNames) {
|
|
134
|
+
var _this = this;
|
|
135
|
+
if (warehouseMediaNames === void 0) { warehouseMediaNames = {}; }
|
|
136
|
+
var occKeys = typeof this.keys === 'function' ? this.keys() : this.keys;
|
|
137
|
+
var keys = tslib.__assign(tslib.__assign({}, Occurrence.keys), occKeys); // warehouse keys/values to transform
|
|
138
|
+
var submission = {
|
|
139
|
+
values: {
|
|
140
|
+
external_key: this.cid,
|
|
141
|
+
},
|
|
142
|
+
media: [],
|
|
143
|
+
};
|
|
144
|
+
if (this.id) {
|
|
145
|
+
submission.values.id = this.id;
|
|
146
|
+
}
|
|
147
|
+
var mapValue = function (attr, value) {
|
|
148
|
+
var valuesMapping = keys[attr].values;
|
|
149
|
+
if (!valuesMapping) {
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
if (typeof valuesMapping === 'function') {
|
|
153
|
+
return valuesMapping(value, submission, _this);
|
|
154
|
+
}
|
|
155
|
+
if (valuesMapping instanceof Array) {
|
|
156
|
+
var mapping = valuesMapping.find(function (_a) {
|
|
157
|
+
var val = _a.value;
|
|
158
|
+
return val === value;
|
|
159
|
+
});
|
|
160
|
+
if (!mapping || !mapping.id) {
|
|
161
|
+
throw new Error("A \"".concat(attr, "\" attribute \"").concat(value, "\" value could not be mapped to a remote database field."));
|
|
162
|
+
}
|
|
163
|
+
return mapping.id;
|
|
164
|
+
}
|
|
165
|
+
if (value instanceof Array) {
|
|
166
|
+
return value.map(function (v) { return valuesMapping[v]; });
|
|
167
|
+
}
|
|
168
|
+
return valuesMapping[value];
|
|
169
|
+
};
|
|
170
|
+
var getValue = function (attr) {
|
|
171
|
+
// no need to send attributes with no values
|
|
172
|
+
var value = _this.attrs[attr];
|
|
173
|
+
var isEmpty = function (val) { return val === null || val === undefined; };
|
|
174
|
+
if (isEmpty(value)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (!keys[attr]) {
|
|
178
|
+
attr = attr.includes('occAttr:') ? attr : lodash.snakeCase(attr);
|
|
179
|
+
submission.values[attr] = value;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
var warehouseAttr = keys[attr].id || attr;
|
|
183
|
+
value = mapValue(attr, value);
|
|
184
|
+
if (isEmpty(value)) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
var attrKey = !Number.isNaN(Number(warehouseAttr))
|
|
188
|
+
? "occAttr:".concat(warehouseAttr)
|
|
189
|
+
: warehouseAttr;
|
|
190
|
+
attrKey = attrKey.includes('occAttr:') ? attrKey : lodash.snakeCase(attrKey);
|
|
191
|
+
submission.values[attrKey] = value;
|
|
192
|
+
};
|
|
193
|
+
Object.keys(this.attrs).forEach(getValue);
|
|
194
|
+
this.media.forEach(function (model) {
|
|
195
|
+
var modelSubmission = model.getSubmission(warehouseMediaNames);
|
|
196
|
+
if (!modelSubmission) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
submission.media.push(modelSubmission);
|
|
200
|
+
});
|
|
201
|
+
var survey = this.getSurvey();
|
|
202
|
+
if (survey.modifySubmission) {
|
|
203
|
+
return survey.modifySubmission(submission, this);
|
|
204
|
+
}
|
|
205
|
+
return submission;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Warehouse attributes and their values.
|
|
209
|
+
*/
|
|
210
|
+
Occurrence.keys = {
|
|
211
|
+
taxon: { id: 'taxa_taxon_list_id' },
|
|
212
|
+
training: { id: 'training', values: helpers.boolToWarehouseValue },
|
|
213
|
+
deleted: { id: 'deleted', values: helpers.boolToWarehouseValue },
|
|
214
|
+
confidential: { id: 'confidential', values: helpers.boolToWarehouseValue },
|
|
215
|
+
zeroAbundance: { id: 'zero_abundance', values: helpers.boolToWarehouseValue },
|
|
216
|
+
};
|
|
217
|
+
return Occurrence;
|
|
218
|
+
}(Model["default"]));
|
|
219
|
+
|
|
220
|
+
exports["default"] = Occurrence;
|
package/dist/Indicia/Sample.d.ts
CHANGED
|
@@ -86,11 +86,11 @@ declare class Sample<T extends Attrs = Attrs, S extends Metadata = Metadata> ext
|
|
|
86
86
|
};
|
|
87
87
|
training: {
|
|
88
88
|
id: string;
|
|
89
|
-
values: (val?: boolean | "t" | "f" | null
|
|
89
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
90
90
|
};
|
|
91
91
|
deleted: {
|
|
92
92
|
id: string;
|
|
93
|
-
values: (val?: boolean | "t" | "f" | null
|
|
93
|
+
values: (val?: boolean | "t" | "f" | null) => "t" | "f";
|
|
94
94
|
};
|
|
95
95
|
};
|
|
96
96
|
/**
|