@azrico/webobject 1.5.58 → 1.5.61
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 +9 -9
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/src/WebObjects/ParentWebObject.d.ts +24 -0
- package/dist/src/WebObjects/ParentWebObject.js +77 -0
- package/dist/src/WebObjects/WebObject.d.ts +153 -0
- package/dist/src/WebObjects/WebObject.js +654 -0
- package/dist/src/WebObjects/WebObjectHelper.d.ts +9 -0
- package/dist/src/WebObjects/WebObjectHelper.js +18 -0
- package/dist/src/WebObjects/WebObjectHelper.test.d.ts +1 -0
- package/dist/src/WebObjects/WebObjectHelper.test.js +45 -0
- package/dist/src/WebObjects/WebObjectManager.d.ts +68 -0
- package/dist/src/WebObjects/WebObjectManager.js +290 -0
- package/dist/src/WebObjects/WebObjectPathHelper.d.ts +36 -0
- package/dist/src/WebObjects/WebObjectPathHelper.js +84 -0
- package/dist/src/WebObjects/WebObjectPathHelper.test.d.ts +1 -0
- package/dist/src/WebObjects/WebObjectPathHelper.test.js +31 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +10 -0
- package/dist/src/structs/DummyObject.d.ts +5 -0
- package/dist/src/structs/DummyObject.js +8 -0
- package/dist/src/structs/MapableObject.d.ts +43 -0
- package/dist/src/structs/MapableObject.js +77 -0
- package/dist/src/structs/MetaObject.d.ts +15 -0
- package/dist/src/structs/MetaObject.js +35 -0
- package/dist/src/structs/ObjectArray.d.ts +10 -0
- package/dist/src/structs/ObjectArray.js +43 -0
- package/dist/src/structs/ObjectManager.d.ts +136 -0
- package/dist/src/structs/ObjectManager.js +332 -0
- package/dist/src/structs/ObjectWithTemp.d.ts +16 -0
- package/dist/src/structs/ObjectWithTemp.js +35 -0
- package/dist/src/structs/SimpleObject.js +1138 -0
- package/package.json +1 -1
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
import { SimpleObject } from "../index";
|
|
2
|
+
import { array_chunks, array_first, array_intersection, array_merge, array_remove_duplicates, fn_eval_this, object_clean, object_equals, object_getStatic, object_isEmpty, wrap_array, } from "@azrico/object";
|
|
3
|
+
import { string_compress, string_decompress } from "@azrico/string";
|
|
4
|
+
import { gcache, gfunc } from "@azrico/global";
|
|
5
|
+
import FormatHelper from "@azrico/convert";
|
|
6
|
+
import WebObjectPathHelper from "./WebObjectPathHelper";
|
|
7
|
+
import WebObjectHelper from "./WebObjectHelper";
|
|
8
|
+
export class WebObject extends SimpleObject {
|
|
9
|
+
static __web_path = "";
|
|
10
|
+
static __protectedProperties = ["_users"];
|
|
11
|
+
//you cant create a new weboject without these properties
|
|
12
|
+
static __requiredProperties = [];
|
|
13
|
+
meta_data;
|
|
14
|
+
//created date
|
|
15
|
+
_created_date;
|
|
16
|
+
//the owner of the object
|
|
17
|
+
_creator;
|
|
18
|
+
//multiple users can work on one object
|
|
19
|
+
_users;
|
|
20
|
+
constructor(is_readonly = false) {
|
|
21
|
+
super(is_readonly);
|
|
22
|
+
this.meta_data = {};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* get a list of all user ids that work on the given object
|
|
26
|
+
* _creator + _users + attentions(old)
|
|
27
|
+
* removes duplicates
|
|
28
|
+
* @returns array of ids
|
|
29
|
+
*/
|
|
30
|
+
getAllUsers() {
|
|
31
|
+
return WebObject.getAllUsers(this);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* get a unique list of all user ids that work on the given object
|
|
35
|
+
* `_creator + _users + attentions`
|
|
36
|
+
* @returns array of ids
|
|
37
|
+
*/
|
|
38
|
+
static getAllUsers(obj) {
|
|
39
|
+
if (typeof obj != "object")
|
|
40
|
+
return [];
|
|
41
|
+
return array_remove_duplicates(array_merge(obj._creator, wrap_array(obj._users), wrap_array(obj.attentions))
|
|
42
|
+
.map((r) => String(typeof r === "object" ? WebObject.getID(r) : r))
|
|
43
|
+
.filter((s) => s));
|
|
44
|
+
}
|
|
45
|
+
/* -------------------------------------------------------------------------- */
|
|
46
|
+
/* Meta data */
|
|
47
|
+
/* -------------------------------------------------------------------------- */
|
|
48
|
+
/**
|
|
49
|
+
* Update meta value of this object , meta data is stored in meta_data variable
|
|
50
|
+
* @param key
|
|
51
|
+
* @param value
|
|
52
|
+
* @param sendChange
|
|
53
|
+
* @returns
|
|
54
|
+
*/
|
|
55
|
+
async setMetaValue(key, value, sendChange = "auto") {
|
|
56
|
+
if (!this.canModify) {
|
|
57
|
+
if (this.__throw_errors !== false)
|
|
58
|
+
throw Error(`Cant use setMetaValue on ${key} when on readonly mode`);
|
|
59
|
+
else
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!key || typeof key != "string") {
|
|
63
|
+
if (this.__throw_errors !== false)
|
|
64
|
+
throw Error(`Bad key at setMetaValue`);
|
|
65
|
+
else
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const old_value = WebObject.getMetaValue(this, key);
|
|
69
|
+
if (object_equals(old_value, value))
|
|
70
|
+
return false; //same value, no changes
|
|
71
|
+
const new_metalist = { ...this.get("meta_data") };
|
|
72
|
+
new_metalist[key] = value;
|
|
73
|
+
await this.set("meta_data", new_metalist);
|
|
74
|
+
if (sendChange !== false)
|
|
75
|
+
await this.notifyChanged("meta", key, value);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get meta value by key
|
|
80
|
+
* @param key
|
|
81
|
+
* @returns value or undefined
|
|
82
|
+
*/
|
|
83
|
+
getMetaValue(key) {
|
|
84
|
+
return WebObject.getMetaValue(this, key);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get meta value by key
|
|
88
|
+
* @param o
|
|
89
|
+
* @param key
|
|
90
|
+
* @returns value or undefined
|
|
91
|
+
*/
|
|
92
|
+
static getMetaValue(o, key) {
|
|
93
|
+
if (o == null)
|
|
94
|
+
return null;
|
|
95
|
+
if (!key || typeof key != "string")
|
|
96
|
+
return undefined;
|
|
97
|
+
let metalist = {};
|
|
98
|
+
if (typeof o === "object") {
|
|
99
|
+
metalist =
|
|
100
|
+
typeof o.get === "function" ? o.get("meta_data") : o.meta_data;
|
|
101
|
+
}
|
|
102
|
+
return metalist[key];
|
|
103
|
+
}
|
|
104
|
+
/* -------------------------------------------------------------------------- */
|
|
105
|
+
/* Save */
|
|
106
|
+
/* -------------------------------------------------------------------------- */
|
|
107
|
+
static zipSaveList(svlist) {
|
|
108
|
+
if (typeof svlist === "object")
|
|
109
|
+
svlist = JSON.stringify(svlist);
|
|
110
|
+
return string_compress(svlist);
|
|
111
|
+
}
|
|
112
|
+
static unzipSaveList(svlist) {
|
|
113
|
+
try {
|
|
114
|
+
if (typeof svlist === "object") {
|
|
115
|
+
if (Array.isArray(svlist))
|
|
116
|
+
return svlist;
|
|
117
|
+
if (svlist.__save_list)
|
|
118
|
+
return this.unzipSaveList(svlist.__save_list);
|
|
119
|
+
}
|
|
120
|
+
else if (typeof svlist === "string")
|
|
121
|
+
return wrap_array(JSON.parse(string_decompress(svlist)));
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
return wrap_array(svlist);
|
|
125
|
+
}
|
|
126
|
+
static async saveList(itemList, extraOptions = {}) {
|
|
127
|
+
if (!extraOptions)
|
|
128
|
+
extraOptions = {};
|
|
129
|
+
const chunks = array_chunks(itemList, extraOptions.chunksize ?? 50);
|
|
130
|
+
delete extraOptions.chunksize;
|
|
131
|
+
const putAddress = this.get_webpath();
|
|
132
|
+
for (let index = 0; index < chunks.length; index++) {
|
|
133
|
+
const items_to_save = chunks[index];
|
|
134
|
+
const save_array = [];
|
|
135
|
+
for (let k = 0; k < items_to_save.length; k++) {
|
|
136
|
+
const item = items_to_save[k];
|
|
137
|
+
const dlt = await item.get_deltaObject();
|
|
138
|
+
save_array.push(item.isNew
|
|
139
|
+
? {
|
|
140
|
+
...dlt,
|
|
141
|
+
}
|
|
142
|
+
: {
|
|
143
|
+
_id: item.getID(),
|
|
144
|
+
...dlt,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const resultObject = await gfunc.run_action("post", putAddress, {
|
|
148
|
+
__save_list: WebObject.zipSaveList(save_array),
|
|
149
|
+
...extraOptions,
|
|
150
|
+
});
|
|
151
|
+
if (Array.isArray(resultObject)) {
|
|
152
|
+
for (let index = 0; index < Math.min(resultObject.length, items_to_save.length); index++) {
|
|
153
|
+
const res = resultObject[index];
|
|
154
|
+
const item = items_to_save[index];
|
|
155
|
+
item.setSaveResult(res);
|
|
156
|
+
await item.onSave();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
for (let index = 0; index < itemList.length; index++) {
|
|
161
|
+
const item = itemList[index];
|
|
162
|
+
if (!item.isSaved)
|
|
163
|
+
return false;
|
|
164
|
+
if (item.getSaveResultType() != "normal")
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
async Save() {
|
|
170
|
+
try {
|
|
171
|
+
if (this.manager) {
|
|
172
|
+
await this.manager.setOption("saving", true);
|
|
173
|
+
await this.manager.setOption("loading", true);
|
|
174
|
+
}
|
|
175
|
+
const deltaObject = await this.get_deltaObject();
|
|
176
|
+
const putAction = "post";
|
|
177
|
+
const usepath = await WebObjectPathHelper.get_path(this, this.isNew ? "new" : "save");
|
|
178
|
+
/* ---------------------------------- save ---------------------------------- */
|
|
179
|
+
if (!object_isEmpty(deltaObject)) {
|
|
180
|
+
const canSaveResult = this.canSave(deltaObject);
|
|
181
|
+
if (canSaveResult !== true) {
|
|
182
|
+
WebObject.addError(this, "Save not allowed", String(canSaveResult), true);
|
|
183
|
+
this.setSaveResult(false, "canceled");
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
const resultObject = await gfunc.run_action(putAction, usepath, deltaObject);
|
|
187
|
+
this.setSaveResult(resultObject, "auto", true);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
/* nothing to save */
|
|
191
|
+
this.setSaveResult(null, "nothing");
|
|
192
|
+
}
|
|
193
|
+
if (this.isSaved) {
|
|
194
|
+
await this.onSave();
|
|
195
|
+
return this.getSaveResult();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
if (this.manager) {
|
|
200
|
+
await this.manager.setOption("saving", false);
|
|
201
|
+
await this.manager.setOption("loading", false);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async Delete() {
|
|
206
|
+
if (this.isNew)
|
|
207
|
+
return;
|
|
208
|
+
const usepath = await WebObjectPathHelper.get_path(this, "delete");
|
|
209
|
+
const resultObject = await gfunc.run_action("delete", usepath);
|
|
210
|
+
this.setSaveResult(resultObject, "auto", true);
|
|
211
|
+
await this.onDelete();
|
|
212
|
+
return resultObject;
|
|
213
|
+
}
|
|
214
|
+
async Lock() {
|
|
215
|
+
if (this.isNew || this.isArchived)
|
|
216
|
+
return;
|
|
217
|
+
const usepath = await WebObjectPathHelper.get_path(this, "lock");
|
|
218
|
+
const resultObject = await gfunc.run_action("post", usepath);
|
|
219
|
+
this.setSaveResult(resultObject, "auto", true);
|
|
220
|
+
await this.onLock();
|
|
221
|
+
return resultObject;
|
|
222
|
+
}
|
|
223
|
+
async UnLock() {
|
|
224
|
+
if (this.isNew || this.isArchived)
|
|
225
|
+
return;
|
|
226
|
+
const usepath = await WebObjectPathHelper.get_path(this, "unlock");
|
|
227
|
+
const resultObject = await gfunc.run_action("post", usepath);
|
|
228
|
+
this.setSaveResult(resultObject, "auto", true);
|
|
229
|
+
await this.onUnLock();
|
|
230
|
+
return resultObject;
|
|
231
|
+
}
|
|
232
|
+
async Archive() {
|
|
233
|
+
if (this.isNew || this.isArchived)
|
|
234
|
+
return;
|
|
235
|
+
const usepath = await WebObjectPathHelper.get_path(this, "archive");
|
|
236
|
+
const resultObject = await gfunc.run_action("post", usepath);
|
|
237
|
+
this.setSaveResult(resultObject, "auto", true);
|
|
238
|
+
await this.onArchive();
|
|
239
|
+
return resultObject;
|
|
240
|
+
}
|
|
241
|
+
async UnArchive() {
|
|
242
|
+
if (this.isNew || !this.isArchived)
|
|
243
|
+
return;
|
|
244
|
+
const usepath = await WebObjectPathHelper.get_path(this, "unarchive");
|
|
245
|
+
const resultObject = await gfunc.run_action("post", usepath);
|
|
246
|
+
await this.onUnArchive();
|
|
247
|
+
return resultObject;
|
|
248
|
+
}
|
|
249
|
+
/* -------------------------------------------------------------------------- */
|
|
250
|
+
canSave(deltaObj) {
|
|
251
|
+
const deltaRes = this.deltaIsValid(deltaObj);
|
|
252
|
+
if (deltaRes !== true)
|
|
253
|
+
return deltaRes;
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
canDelete() {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
canArchive() {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
deltaIsValid(d) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
/* -------------------------------------------------------------------------- */
|
|
266
|
+
/* get delta */
|
|
267
|
+
/* -------------------------------------------------------------------------- */
|
|
268
|
+
/**
|
|
269
|
+
* converts this object to an basic object
|
|
270
|
+
* that can be passed into client components from server components
|
|
271
|
+
*
|
|
272
|
+
* uses `get_fullDeltaObject`
|
|
273
|
+
* @param p
|
|
274
|
+
* @returns
|
|
275
|
+
*/
|
|
276
|
+
async get_basicObject() {
|
|
277
|
+
const fullobject = await this.get_fullObject();
|
|
278
|
+
for (const key in fullobject) {
|
|
279
|
+
const element = fullobject[key];
|
|
280
|
+
/* --------------------------- check for id fields -------------------------- */
|
|
281
|
+
if (element != null && typeof element === "object") {
|
|
282
|
+
if ((key === "id" || key.endsWith("_id")) &&
|
|
283
|
+
typeof element.toString === "function") {
|
|
284
|
+
fullobject[key] = String(element);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
fullobject[key] = JSON.parse(JSON.stringify(element));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return fullobject;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* calls the `get_deltaObject` with
|
|
295
|
+
* `allProperties` `extraProperties`
|
|
296
|
+
* set to true
|
|
297
|
+
*
|
|
298
|
+
* @returns
|
|
299
|
+
*/
|
|
300
|
+
async get_fullDeltaObject(p) {
|
|
301
|
+
return await this.get_deltaObject({
|
|
302
|
+
allProperties: true,
|
|
303
|
+
extraProperties: true,
|
|
304
|
+
...p,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* calls the `get_deltaObject` with
|
|
309
|
+
* `allProperties` `extraProperties` `tempProperties`
|
|
310
|
+
* set to true
|
|
311
|
+
*
|
|
312
|
+
* @returns
|
|
313
|
+
*/
|
|
314
|
+
async get_fullObject(p) {
|
|
315
|
+
return await this.get_deltaObject({
|
|
316
|
+
allProperties: true,
|
|
317
|
+
extraProperties: true,
|
|
318
|
+
tempProperties: true,
|
|
319
|
+
...p,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* You will post this to the server for saving
|
|
324
|
+
* automatically removes unchangeable fields
|
|
325
|
+
* @returns
|
|
326
|
+
*/
|
|
327
|
+
async get_deltaObject(p) {
|
|
328
|
+
if (!p)
|
|
329
|
+
p = {};
|
|
330
|
+
const final_object = {};
|
|
331
|
+
const useDelta = Boolean(this.__use_delta || p.useDelta);
|
|
332
|
+
/**
|
|
333
|
+
* child objects usually dont update their __delta
|
|
334
|
+
* so we read info from all of its properties
|
|
335
|
+
*/
|
|
336
|
+
const changedFields = Boolean(p.allProperties || p.isChild || !useDelta)
|
|
337
|
+
? { ...this.allproperties }
|
|
338
|
+
: { ...this.__delta };
|
|
339
|
+
/* ------------- parse children that have WebObject as delta ------------- */
|
|
340
|
+
for (const key in this) {
|
|
341
|
+
if (key.startsWith("__") || key in changedFields)
|
|
342
|
+
continue;
|
|
343
|
+
if (WebObjectHelper.isChangedWebObjectField(this[key])) {
|
|
344
|
+
/**
|
|
345
|
+
* if a child has any change we must add it into our delta
|
|
346
|
+
* notice that the changes may not be saved to database depending on __changeables
|
|
347
|
+
* but they are changes nevertheless
|
|
348
|
+
*/
|
|
349
|
+
changedFields[key] = this[key];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* get keys that can be changed.
|
|
354
|
+
* intersection of keys in delta and keys that are defined as changeable
|
|
355
|
+
*/
|
|
356
|
+
let changeableKeys = array_intersection(Object.keys(changedFields), WebObject.getChangeableKeys(this, p));
|
|
357
|
+
/**
|
|
358
|
+
* if parameter of changeableKeys is given, limit our keys with that param
|
|
359
|
+
*/
|
|
360
|
+
if (p.changeableKeys) {
|
|
361
|
+
changeableKeys = array_intersection(changeableKeys, p.changeableKeys);
|
|
362
|
+
}
|
|
363
|
+
/* -------------------------------------------------------------------------- */
|
|
364
|
+
FormatHelper.format({
|
|
365
|
+
original: this,
|
|
366
|
+
inputobject: changedFields,
|
|
367
|
+
formats: object_getStatic(this, "__formatList"),
|
|
368
|
+
isNew: this.isNew,
|
|
369
|
+
changeableKeys: changeableKeys,
|
|
370
|
+
applyDefaults: true,
|
|
371
|
+
});
|
|
372
|
+
/* -------------------------------------------------------------------------- */
|
|
373
|
+
/* __functionProperties */
|
|
374
|
+
/* -------------------------------------------------------------------------- */
|
|
375
|
+
const functionProps = object_getStatic(this, "__functionProperties");
|
|
376
|
+
for (let index = 0; index < functionProps.length; index++) {
|
|
377
|
+
const fp = functionProps[index];
|
|
378
|
+
if (changedFields[fp])
|
|
379
|
+
changedFields[fp] = fn_eval_this(this, changedFields[fp]);
|
|
380
|
+
}
|
|
381
|
+
/* -------------------------------------------------------------------------- */
|
|
382
|
+
/* parse all changeableKeys */
|
|
383
|
+
/* -------------------------------------------------------------------------- */
|
|
384
|
+
async function parseObj(key, obj) {
|
|
385
|
+
if (obj == null)
|
|
386
|
+
return undefined;
|
|
387
|
+
if (Array.isArray(obj))
|
|
388
|
+
return await Promise.all(obj.map(async (r, i) => await parseObj(key, r)));
|
|
389
|
+
if (obj instanceof WebObject &&
|
|
390
|
+
typeof obj.get_deltaObject === "function") {
|
|
391
|
+
/* -------------------- parse changeableKeys for children -------------------- */
|
|
392
|
+
const keydot = `${key}.`;
|
|
393
|
+
let child_changeableKeys = p?.changeableKeys
|
|
394
|
+
?.filter((s) => s.startsWith(keydot))
|
|
395
|
+
.map((r) => r.substring(keydot.length));
|
|
396
|
+
/**
|
|
397
|
+
* if no key is set for children consider it as undefined
|
|
398
|
+
* if we send the empty array to get_delta we get no keys
|
|
399
|
+
*/
|
|
400
|
+
if (child_changeableKeys == null ||
|
|
401
|
+
child_changeableKeys?.length === 0) {
|
|
402
|
+
child_changeableKeys = undefined;
|
|
403
|
+
}
|
|
404
|
+
/* -------------------------------------------------------------------------- */
|
|
405
|
+
//child elements have different kind of delta
|
|
406
|
+
const newobj_dlt = await obj.get_deltaObject({
|
|
407
|
+
...p,
|
|
408
|
+
isChild: true,
|
|
409
|
+
changeableKeys: child_changeableKeys,
|
|
410
|
+
});
|
|
411
|
+
if (!object_isEmpty(newobj_dlt))
|
|
412
|
+
return newobj_dlt;
|
|
413
|
+
else
|
|
414
|
+
return obj;
|
|
415
|
+
}
|
|
416
|
+
return obj;
|
|
417
|
+
}
|
|
418
|
+
for (const key of changeableKeys) {
|
|
419
|
+
final_object[key] = await parseObj(key, changedFields[key]);
|
|
420
|
+
}
|
|
421
|
+
/* -------------------- add acrhived and date properties -------------------- */
|
|
422
|
+
if (p.allProperties) {
|
|
423
|
+
final_object["_created_date"] = this["_created_date"];
|
|
424
|
+
final_object["_archived"] = this.isArchived;
|
|
425
|
+
final_object["_deleted"] = this.isDeleted;
|
|
426
|
+
}
|
|
427
|
+
if (p.tempProperties) {
|
|
428
|
+
final_object["__temp"] = this.__temp;
|
|
429
|
+
}
|
|
430
|
+
/* ---------------------------- add id properties --------------------------- */
|
|
431
|
+
if (p.allProperties || p.needId || p.isChild) {
|
|
432
|
+
if (this["_index_key"])
|
|
433
|
+
final_object["_index_key"] = this["_index_key"];
|
|
434
|
+
const gotIndex = this.getIndex();
|
|
435
|
+
const gotId = this.getID();
|
|
436
|
+
if (gotIndex && gotIndex >= 0)
|
|
437
|
+
final_object["_index_value"] = gotIndex;
|
|
438
|
+
if (gotId)
|
|
439
|
+
final_object["_id"] = gotId;
|
|
440
|
+
}
|
|
441
|
+
/* -------------------------------------------------------------------------- */
|
|
442
|
+
/* fix _user property */
|
|
443
|
+
/* -------------------------------------------------------------------------- */
|
|
444
|
+
if (final_object["_users"]) {
|
|
445
|
+
let tempusers = final_object["_users"];
|
|
446
|
+
if (typeof tempusers === "string")
|
|
447
|
+
tempusers = tempusers.split(",").filter((s) => s);
|
|
448
|
+
final_object["_users"] = wrap_array(tempusers);
|
|
449
|
+
}
|
|
450
|
+
if (p.clean)
|
|
451
|
+
return object_clean(final_object, false, true);
|
|
452
|
+
return final_object;
|
|
453
|
+
}
|
|
454
|
+
/* --------------------------------- Getters -------------------------------- */
|
|
455
|
+
get manager() {
|
|
456
|
+
return this.get_managerClass() || undefined;
|
|
457
|
+
}
|
|
458
|
+
get __web_path() {
|
|
459
|
+
return this.constructor["__web_path"] || this.__db_name;
|
|
460
|
+
}
|
|
461
|
+
get_webpath() {
|
|
462
|
+
return this.__web_path || this.__db_name || "";
|
|
463
|
+
}
|
|
464
|
+
static get_webpath() {
|
|
465
|
+
return this.__web_path || this.__db_name || "";
|
|
466
|
+
}
|
|
467
|
+
static get_dbname() {
|
|
468
|
+
return this.__db_name || this.__web_path || "";
|
|
469
|
+
}
|
|
470
|
+
/* -------------------------------------------------------------------------- */
|
|
471
|
+
async onDelete(...p) {
|
|
472
|
+
if (this.isSaved)
|
|
473
|
+
this.isDeleted = true;
|
|
474
|
+
return await this.manager?.onDelete(...p); //events are handled by the manager
|
|
475
|
+
}
|
|
476
|
+
async onArchive(...p) {
|
|
477
|
+
if (this.isSaved)
|
|
478
|
+
this.isArchived = true;
|
|
479
|
+
return await this.manager?.onArchive(...p); //events are handled by the manager
|
|
480
|
+
}
|
|
481
|
+
async onUnArchive(...p) {
|
|
482
|
+
if (this.isSaved)
|
|
483
|
+
this.isArchived = false;
|
|
484
|
+
return await this.manager?.onUnArchive(...p); //events are handled by the manager
|
|
485
|
+
}
|
|
486
|
+
async onLock(...p) {
|
|
487
|
+
if (this.isSaved)
|
|
488
|
+
this.isLocked = true;
|
|
489
|
+
return await this.manager?.onLock(...p); //events are handled by the manager
|
|
490
|
+
}
|
|
491
|
+
async onUnLock(...p) {
|
|
492
|
+
if (this.isSaved)
|
|
493
|
+
this.isLocked = false;
|
|
494
|
+
return await this.manager?.onUnLock(...p); //events are handled by the manager
|
|
495
|
+
}
|
|
496
|
+
async onLoad(...p) {
|
|
497
|
+
this.isDeleted = false;
|
|
498
|
+
return await this.manager?.onLoad(...p); //events are handled by the manager
|
|
499
|
+
}
|
|
500
|
+
async onSave(...p) {
|
|
501
|
+
if (this.isSaved) {
|
|
502
|
+
this.apply_changes();
|
|
503
|
+
var srObject = this.getSaveResult(true);
|
|
504
|
+
if (this.saveResultHasID(srObject)) {
|
|
505
|
+
/* -------------------------------------------------------------------------- */
|
|
506
|
+
WebObject.LoadIdsFromSaveResult(this, srObject);
|
|
507
|
+
await this.manager?.event_run("on_id_change");
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
await this.manager?.onSave(...p); //events are handled by the manager
|
|
511
|
+
await this.onAfterSave();
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
async onAfterSave(...p) {
|
|
515
|
+
await this.manager?.onAfterSave(...p); //events are handled by the manager
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
getSaveResult(original = false) {
|
|
519
|
+
let srObject = super.getSaveResult(original);
|
|
520
|
+
if (!srObject)
|
|
521
|
+
return false;
|
|
522
|
+
if (Array.isArray(srObject)) {
|
|
523
|
+
const actual_sr = srObject.find((s) => this.saveResultHasID(s));
|
|
524
|
+
if (actual_sr)
|
|
525
|
+
srObject = actual_sr;
|
|
526
|
+
}
|
|
527
|
+
return srObject;
|
|
528
|
+
}
|
|
529
|
+
async onNew(...p) {
|
|
530
|
+
return await this.manager?.onNew(...p); //events are handled by the manager
|
|
531
|
+
}
|
|
532
|
+
/* -------------------------------------------------------------------------- */
|
|
533
|
+
saveResultHasID(s) {
|
|
534
|
+
return WebObject.saveResultHasID(s);
|
|
535
|
+
}
|
|
536
|
+
static saveResultHasID(s) {
|
|
537
|
+
if (typeof s !== "object" || s == null || !s)
|
|
538
|
+
return false;
|
|
539
|
+
return (s.insertedId ||
|
|
540
|
+
s._id ||
|
|
541
|
+
(s._index_value && !Number.isNaN(s._index_value)));
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Load Id and _index_value from the given save result into our object
|
|
545
|
+
* @param o
|
|
546
|
+
* @param srObject
|
|
547
|
+
* @returns
|
|
548
|
+
*/
|
|
549
|
+
static LoadIdsFromSaveResult(o, srObject) {
|
|
550
|
+
if (typeof o !== "object" || typeof srObject !== "object")
|
|
551
|
+
return;
|
|
552
|
+
/* -------------------------------------------------------------------------- */
|
|
553
|
+
const srID = srObject.insertedId || srObject._id || WebObject.getID(srObject);
|
|
554
|
+
if (srID) {
|
|
555
|
+
o._id = srID;
|
|
556
|
+
}
|
|
557
|
+
/* -------------------------------------------------------------------------- */
|
|
558
|
+
if (srObject._index_value && !Number.isNaN(srObject._index_value)) {
|
|
559
|
+
o._index_value = Number(srObject._index_value);
|
|
560
|
+
}
|
|
561
|
+
/* -------------------------------------------------------------------------- */
|
|
562
|
+
if (srObject._index_key) {
|
|
563
|
+
o._index_key = srObject._index_key;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
/* -------------------------------------------------------------------------- */
|
|
567
|
+
/**
|
|
568
|
+
* get a single web object
|
|
569
|
+
* default order of parameters : search,readonly,fetchID
|
|
570
|
+
*/
|
|
571
|
+
static async get_single(...p) {
|
|
572
|
+
let search = p.shift();
|
|
573
|
+
let readonly = p.shift() ?? false;
|
|
574
|
+
let fetchID = p.shift();
|
|
575
|
+
if (object_isEmpty(search))
|
|
576
|
+
return undefined;
|
|
577
|
+
let result;
|
|
578
|
+
const params = {};
|
|
579
|
+
params.__context = readonly ? "view" : "edit";
|
|
580
|
+
switch (typeof search) {
|
|
581
|
+
case "string":
|
|
582
|
+
case "number":
|
|
583
|
+
search = String(search);
|
|
584
|
+
// const usepath =
|
|
585
|
+
// (await WebObjectPathHelper.get_path(this, "get")) +
|
|
586
|
+
// "/" +
|
|
587
|
+
// search;
|
|
588
|
+
// res = await gfunc.run_action("get", usepath, params, {
|
|
589
|
+
// fetchID: fetchID,
|
|
590
|
+
// });
|
|
591
|
+
result = await this.get_list({ __searchid: search }, readonly, fetchID);
|
|
592
|
+
break;
|
|
593
|
+
case "object":
|
|
594
|
+
default:
|
|
595
|
+
result = await this.get_list(search, readonly, fetchID);
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
if (result)
|
|
599
|
+
result = array_first(result);
|
|
600
|
+
if (!object_isEmpty(result)) {
|
|
601
|
+
result = this.ensure(this, result);
|
|
602
|
+
WebObject.setReadonly(result, readonly);
|
|
603
|
+
}
|
|
604
|
+
return result;
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Get a list of web objects
|
|
608
|
+
* default order of parameters : search,readonly,fetchID
|
|
609
|
+
*/
|
|
610
|
+
static async get_list(...p) {
|
|
611
|
+
let search = p.shift();
|
|
612
|
+
let readonly = p.shift() ?? false;
|
|
613
|
+
let fetchID = p.shift();
|
|
614
|
+
if (!search)
|
|
615
|
+
search = {};
|
|
616
|
+
const usepath = await WebObjectPathHelper.get_path(this, "get");
|
|
617
|
+
let result_items = await gfunc.run_action("get", usepath, search, { fetchID: fetchID });
|
|
618
|
+
// const selftype = (this.constructor ||
|
|
619
|
+
// Object.getPrototypeOf(this)) as any;
|
|
620
|
+
const res = WebObject.map_rowindex(WebObject.mapto(this, result_items, readonly));
|
|
621
|
+
WebObject.setReadonly(res, readonly);
|
|
622
|
+
return res;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* uses `get_list` and then saves the result to `gcache`
|
|
626
|
+
* then uses the `equals` function to return matched results
|
|
627
|
+
* @param search
|
|
628
|
+
* @returns
|
|
629
|
+
*/
|
|
630
|
+
static async get_list_cache(search) {
|
|
631
|
+
const all_data = await gcache.get_temp_cache(this.get_webpath(), async () => await this.get_list());
|
|
632
|
+
if (!search)
|
|
633
|
+
return all_data;
|
|
634
|
+
return all_data.filter((s) => this.equals(s, search));
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* uses `get_list_cache` then the `equals` function to return matched result
|
|
638
|
+
* @param search
|
|
639
|
+
* @returns
|
|
640
|
+
*/
|
|
641
|
+
static async get_single_cache(search) {
|
|
642
|
+
return (await this.get_list_cache()).find((s) => this.equals(s, search));
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Get a list of web objects and convert them to basic objects
|
|
646
|
+
* can be passed to client components
|
|
647
|
+
* default order of parameters : search,readonly,fetchID
|
|
648
|
+
*/
|
|
649
|
+
static async get_basicList(...p) {
|
|
650
|
+
const itemlist = await this.get_list(...p);
|
|
651
|
+
return await Promise.all(itemlist.map(async (r) => await r.get_basicObject()));
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
export default WebObject;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import WebObject from "./WebObject";
|
|
2
|
+
export declare class WebObjectHelper {
|
|
3
|
+
/**
|
|
4
|
+
* check if the given WebObject is changed or given WebObject array has any changed element
|
|
5
|
+
* @param obj
|
|
6
|
+
*/
|
|
7
|
+
static isChangedWebObjectField(obj: WebObject | WebObject[] | any): boolean;
|
|
8
|
+
}
|
|
9
|
+
export default WebObjectHelper;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import WebObject from "./WebObject";
|
|
2
|
+
export class WebObjectHelper {
|
|
3
|
+
/**
|
|
4
|
+
* check if the given WebObject is changed or given WebObject array has any changed element
|
|
5
|
+
* @param obj
|
|
6
|
+
*/
|
|
7
|
+
static isChangedWebObjectField(obj) {
|
|
8
|
+
if (typeof obj !== "object")
|
|
9
|
+
return false;
|
|
10
|
+
if (Array.isArray(obj)) {
|
|
11
|
+
const arrCheck = obj;
|
|
12
|
+
return (arrCheck.find((r) => r instanceof WebObject && r.isChanged) !=
|
|
13
|
+
undefined);
|
|
14
|
+
}
|
|
15
|
+
return obj instanceof WebObject && obj.isChanged;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export default WebObjectHelper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|