@livinglogic/livingapi 0.10.0 → 0.13.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/CHANGELOG.md +68 -0
- package/README.md +2 -2
- package/dist/esm-node/livingapi.js +1 -1823
- package/dist/esm-node/livingapi.js.map +1 -1
- package/dist/esm-static/livingapi.js +1 -1823
- package/dist/esm-static/livingapi.js.map +1 -1
- package/dist/umd/livingapi.js +1 -1
- package/dist/umd/livingapi.js.map +1 -1
- package/package.json +14 -11
- package/rollup.config.js +1 -1
- package/src/livingapi.js +1641 -186
package/src/livingapi.js
CHANGED
|
@@ -1,15 +1,50 @@
|
|
|
1
|
-
|
|
1
|
+
/*!
|
|
2
|
+
* LivingAPI JavaScript Library
|
|
3
|
+
* https://my.living-apps.de/docs/LivingAPI.html
|
|
4
|
+
*
|
|
5
|
+
* Copyright 2017-2019 by LivingLogic AG, Bayreuth/Germany
|
|
6
|
+
* Copyright 2017-2019 by Walter Dörwald
|
|
7
|
+
*
|
|
8
|
+
* All Rights Reserved
|
|
9
|
+
*
|
|
10
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
* in the Software without restriction, including without limitation the rights
|
|
13
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
* furnished to do so, subject to the following conditions:
|
|
16
|
+
*
|
|
17
|
+
* The above copyright notice and this permission notice shall be included in
|
|
18
|
+
* all copies or substantial portions of the Software.
|
|
19
|
+
*
|
|
20
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
+
* THE SOFTWARE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// Version of this Javascript package
|
|
2
30
|
import { version } from '../package.json';
|
|
3
31
|
|
|
4
32
|
export { version };
|
|
5
33
|
|
|
6
34
|
import * as ul4 from '@livinglogic/ul4';
|
|
7
35
|
|
|
36
|
+
|
|
8
37
|
export class Base extends ul4.Proto
|
|
9
38
|
{
|
|
10
|
-
constructor()
|
|
39
|
+
constructor(id)
|
|
11
40
|
{
|
|
12
41
|
super();
|
|
42
|
+
this.id = id;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get ul4onid()
|
|
46
|
+
{
|
|
47
|
+
return this.id;
|
|
13
48
|
}
|
|
14
49
|
|
|
15
50
|
ul4ondump(encoder)
|
|
@@ -48,7 +83,7 @@ export class Base extends ul4.Proto
|
|
|
48
83
|
this[name] = null;
|
|
49
84
|
}
|
|
50
85
|
|
|
51
|
-
|
|
86
|
+
[ul4.symbols.getattr](name)
|
|
52
87
|
{
|
|
53
88
|
if (this._ul4attrs.has(name))
|
|
54
89
|
{
|
|
@@ -67,12 +102,18 @@ export class Base extends ul4.Proto
|
|
|
67
102
|
throw new ul4.AttributeError(this, name);
|
|
68
103
|
}
|
|
69
104
|
|
|
70
|
-
|
|
105
|
+
[ul4.symbols.repr]()
|
|
71
106
|
{
|
|
72
107
|
return "<" + this.constructor.name + ">";
|
|
73
108
|
}
|
|
109
|
+
|
|
110
|
+
toString()
|
|
111
|
+
{
|
|
112
|
+
return this[ul4.symbols.repr]();
|
|
113
|
+
}
|
|
74
114
|
};
|
|
75
115
|
|
|
116
|
+
|
|
76
117
|
export class Handler
|
|
77
118
|
{
|
|
78
119
|
save(record)
|
|
@@ -84,14 +125,21 @@ export class Handler
|
|
|
84
125
|
}
|
|
85
126
|
};
|
|
86
127
|
|
|
128
|
+
|
|
87
129
|
export class Globals extends Base
|
|
88
130
|
{
|
|
89
|
-
|
|
131
|
+
static classdoc = "Global information";
|
|
132
|
+
|
|
133
|
+
constructor(id)
|
|
90
134
|
{
|
|
91
|
-
super();
|
|
135
|
+
super(id);
|
|
92
136
|
this.version = null;
|
|
137
|
+
this.hostname = null;
|
|
93
138
|
this.platform = null;
|
|
94
139
|
this.user = null;
|
|
140
|
+
this.lang = null;
|
|
141
|
+
this.app = null;
|
|
142
|
+
this.record = null;
|
|
95
143
|
this.maxdbactions = null;
|
|
96
144
|
this.maxtemplateruntime = null;
|
|
97
145
|
this.flashmessages = null;
|
|
@@ -125,67 +173,137 @@ export class Globals extends Base
|
|
|
125
173
|
return s;
|
|
126
174
|
}
|
|
127
175
|
|
|
128
|
-
|
|
176
|
+
scaledURL(url, width, height, type="fill", enlarge=true, gravity="sm", quality=null, rotate=null, blur=null, sharpen=null, format=null, cache=true)
|
|
177
|
+
{
|
|
178
|
+
let filename = null;
|
|
179
|
+
|
|
180
|
+
if (url instanceof File)
|
|
181
|
+
{
|
|
182
|
+
url = "https://" + this.hostname + url.url;
|
|
183
|
+
filename = encodeURIComponent(url.filename);
|
|
184
|
+
if (filename != url.filename)
|
|
185
|
+
filename = null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let result = "";
|
|
189
|
+
|
|
190
|
+
if (cache)
|
|
191
|
+
result += "/imgproxycache/insecure";
|
|
192
|
+
else
|
|
193
|
+
result += "/imgproxy/insecure";
|
|
194
|
+
|
|
195
|
+
if (type !== "fit")
|
|
196
|
+
result += "/rt:" + type;
|
|
197
|
+
|
|
198
|
+
if (width !== null && width !== undefined)
|
|
199
|
+
result += "/w:" + width;
|
|
200
|
+
|
|
201
|
+
if (height !== null && height !== undefined)
|
|
202
|
+
result += "/h:" + height;
|
|
203
|
+
|
|
204
|
+
if (enlarge)
|
|
205
|
+
result += "/el:1";
|
|
206
|
+
|
|
207
|
+
if (gravity !== null && gravity !== undefined)
|
|
208
|
+
result += "/g:" + gravity;
|
|
209
|
+
|
|
210
|
+
if (quality !== null && quality !== undefined)
|
|
211
|
+
result += "/q:" + quality;
|
|
212
|
+
|
|
213
|
+
if (rotate !== null && rotate % 360 != 0)
|
|
214
|
+
result += "/rot:" + rotatet;
|
|
215
|
+
|
|
216
|
+
if (blur !== null && blur !== undefined)
|
|
217
|
+
result += "/bl:" + blur;
|
|
218
|
+
|
|
219
|
+
if (sharpen !== null && sharpen !== undefined)
|
|
220
|
+
result += "/sh:" + sharpen;
|
|
221
|
+
|
|
222
|
+
if (format !== null && format !== undefined)
|
|
223
|
+
result += "/f:" + format;
|
|
224
|
+
|
|
225
|
+
if (filename !== null && filename !== undefined)
|
|
226
|
+
result += "/fn:" + filename;
|
|
227
|
+
|
|
228
|
+
result += "/plain/" + encodeURIComponent(url);
|
|
229
|
+
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
[ul4.symbols.repr]()
|
|
129
234
|
{
|
|
130
235
|
return "<Globals version=" + ul4._repr(this.version) + ">";
|
|
131
236
|
}
|
|
132
237
|
};
|
|
133
238
|
|
|
134
|
-
Globals.prototype._ul4onattrs = ["version", "platform", "user", "maxdbactions", "maxtemplateruntime", "flashmessages"];
|
|
135
|
-
Globals.prototype._ul4attrs =
|
|
239
|
+
Globals.prototype._ul4onattrs = ["version", "platform", "user", "maxdbactions", "maxtemplateruntime", "flashmessages", "lang", "datasources", "hostname", "app", "record", "google_api_key", "mode", "view_template_id", "email_template_id", "view_id"];
|
|
240
|
+
Globals.prototype._ul4attrs = new Set(["version", "hostname", "platform", "user", "lang", "app", "record", "maxdbactions", "maxtemplateruntime", "flashmessages", "mode"]);
|
|
241
|
+
|
|
136
242
|
|
|
137
243
|
export class FlashMessage extends Base
|
|
138
244
|
{
|
|
139
|
-
|
|
245
|
+
static classdoc = "A flash message in a web page";
|
|
246
|
+
|
|
247
|
+
[ul4.symbols.repr]()
|
|
140
248
|
{
|
|
141
249
|
return "<FlashMessage type=" + ul4._repr(this.type) + " title=" + ul4._repr(this.title) + ">";
|
|
142
250
|
}
|
|
143
251
|
};
|
|
144
252
|
|
|
145
253
|
FlashMessage.prototype._ul4onattrs = ["timestamp", "type", "title", "message"];
|
|
146
|
-
FlashMessage.prototype._ul4attrs =
|
|
254
|
+
FlashMessage.prototype._ul4attrs = new Set(["timestamp", "type", "title", "message"]);
|
|
255
|
+
|
|
147
256
|
|
|
148
257
|
export class App extends Base
|
|
149
258
|
{
|
|
150
|
-
|
|
259
|
+
static classdoc = "A LivingApps application";
|
|
260
|
+
|
|
261
|
+
[ul4.symbols.repr]()
|
|
151
262
|
{
|
|
152
263
|
return "<App id=" + ul4._repr(this.id) + " name=" + ul4._repr(this.name) + ">";
|
|
153
264
|
}
|
|
154
265
|
|
|
155
266
|
insert(values={})
|
|
156
267
|
{
|
|
157
|
-
let record = this.
|
|
268
|
+
let record = this[ul4.symbols.call](values);
|
|
158
269
|
this.globals.handler.save(this);
|
|
159
270
|
return record;
|
|
160
271
|
}
|
|
161
272
|
|
|
162
|
-
|
|
273
|
+
get layout_controls()
|
|
274
|
+
{
|
|
275
|
+
if (this.active_view === null)
|
|
276
|
+
return new Map();
|
|
277
|
+
return this.active_view.layout_controls;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
[ul4.symbols.call](values={})
|
|
163
281
|
{
|
|
164
|
-
let record = new Record(this);
|
|
282
|
+
let record = new Record(null, this);
|
|
165
283
|
if (ul4._ismap(values))
|
|
166
284
|
{
|
|
167
|
-
for (let
|
|
285
|
+
for (let identifier of values.keys())
|
|
168
286
|
{
|
|
169
|
-
if (!record.fields.has(
|
|
170
|
-
throw new ul4.ArgumentError("
|
|
171
|
-
record.fields.get(key).value = value;
|
|
287
|
+
if (!record.fields.has(identifier))
|
|
288
|
+
throw new ul4.ArgumentError(ul4._repr(this) + "() get an unexpected keyword argument " + ul4._repr(identifier));
|
|
172
289
|
}
|
|
290
|
+
record._make_fields(true, values, null, null);
|
|
173
291
|
}
|
|
174
292
|
else if (ul4._isobject(values))
|
|
175
293
|
{
|
|
176
|
-
for (let
|
|
294
|
+
for (let identifier in values)
|
|
177
295
|
{
|
|
178
|
-
if (!record.fields.has(
|
|
179
|
-
throw new ul4.ArgumentError("
|
|
180
|
-
record.fields.get(key).value = values[key];
|
|
296
|
+
if (!record.fields.has(identifier))
|
|
297
|
+
throw new ul4.ArgumentError(ul4._repr(this) + "() get an unexpected keyword argument " + ul4._repr(identifier));
|
|
181
298
|
}
|
|
299
|
+
record._make_fields(true, new Map(ul4._list(ul4.dicttype.items(values))), null, null);
|
|
182
300
|
}
|
|
183
301
|
else
|
|
184
302
|
throw new ul4.TypeError("values must be an object or a Map");
|
|
185
303
|
return record;
|
|
186
304
|
}
|
|
187
305
|
|
|
188
|
-
|
|
306
|
+
[ul4.symbols.getattr](name)
|
|
189
307
|
{
|
|
190
308
|
if (name.startsWith("c_"))
|
|
191
309
|
{
|
|
@@ -194,43 +312,83 @@ export class App extends Base
|
|
|
194
312
|
return this.controls.get(name.substr(2));
|
|
195
313
|
}
|
|
196
314
|
else
|
|
197
|
-
return super.
|
|
315
|
+
return super[ul4.symbols.getattr](name);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
get active_view()
|
|
319
|
+
{
|
|
320
|
+
return this._active_view;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
set active_view(view)
|
|
324
|
+
{
|
|
325
|
+
if (view === null)
|
|
326
|
+
;
|
|
327
|
+
else if (typeof(view) === "string")
|
|
328
|
+
{
|
|
329
|
+
if (this.views !== null && this.views.has(view))
|
|
330
|
+
view = this.views.get(view);
|
|
331
|
+
else
|
|
332
|
+
throw new ul4.ValueError("View " + ul4._repr(view) + " not found!");
|
|
333
|
+
}
|
|
334
|
+
else if (view instanceof View)
|
|
335
|
+
{
|
|
336
|
+
if (view.app === this)
|
|
337
|
+
;
|
|
338
|
+
else
|
|
339
|
+
throw new ul4.ValueError("View " + ul4._repr(view) + " belongs to the wrong app!");
|
|
340
|
+
}
|
|
341
|
+
else
|
|
342
|
+
{
|
|
343
|
+
throw new ul4.TypeError(ul4._repr(view) + " is not a view!");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
this._active_view = view;
|
|
198
347
|
}
|
|
199
348
|
};
|
|
200
349
|
|
|
201
|
-
|
|
202
|
-
App.prototype.
|
|
203
|
-
|
|
350
|
+
|
|
351
|
+
App.prototype._ul4onattrs = ["globals", "name", "description", "lang", "startlink", "iconlarge", "iconsmall", "createdby", "controls", "records", "recordcount", "installation", "categories", "params", "views", "datamanagement_identifier", "basetable", "primarykey", "insertprocedure", "updateprocedure", "deleteprocedure", "templates", "createdat", "updatedat", "updatedby", "superid", "favorite", "_active_view"];
|
|
352
|
+
App.prototype._ul4attrs = new Set(["id", "globals", "name", "description", "lang", "startlink", "iconlarge", "iconsmall", "createdat", "createdby", "updatedat", "updatedby", "controls", "records", "recordcount", "installation", "categories", "params", "views", "datamanagement_identifier", "insert", "favorite", "_active_view"]);
|
|
353
|
+
ul4.expose(App.prototype[ul4.symbols.call], ["**values"], {"needsobject": true});
|
|
204
354
|
ul4.expose(App.prototype.insert, ["**values"], {"needsobject": true});
|
|
205
355
|
|
|
356
|
+
|
|
206
357
|
export class View extends Base
|
|
207
358
|
{
|
|
208
|
-
|
|
359
|
+
static classdoc = "An input form for a LivingApps application";
|
|
360
|
+
|
|
361
|
+
[ul4.symbols.repr]()
|
|
209
362
|
{
|
|
210
363
|
return "<View id=" + ul4._repr(this.id) + " name=" + ul4._repr(this.name) + ">";
|
|
211
364
|
}
|
|
212
365
|
};
|
|
213
366
|
|
|
214
|
-
View.prototype._ul4onattrs = ["
|
|
215
|
-
View.prototype._ul4attrs =
|
|
367
|
+
View.prototype._ul4onattrs = ["name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang"];
|
|
368
|
+
View.prototype._ul4attrs = new Set(["id", "name", "combined_type", "app", "order", "width", "height", "start", "end", "controls", "layout_controls", "lang"]);
|
|
369
|
+
|
|
216
370
|
|
|
217
371
|
export class DataSourceData extends Base
|
|
218
372
|
{
|
|
219
|
-
|
|
373
|
+
static classdoc = "The data resulting from a data source configuration";
|
|
374
|
+
|
|
375
|
+
[ul4.symbols.repr]()
|
|
220
376
|
{
|
|
221
377
|
return "<DataSource.Data id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
|
|
222
378
|
}
|
|
223
379
|
};
|
|
224
380
|
|
|
225
|
-
DataSourceData.prototype._ul4onattrs = ["
|
|
226
|
-
DataSourceData.prototype._ul4attrs =
|
|
381
|
+
DataSourceData.prototype._ul4onattrs = ["identifier", "app", "apps"];
|
|
382
|
+
DataSourceData.prototype._ul4attrs = new Set(["id", "identifier", "app", "apps"]);
|
|
383
|
+
|
|
227
384
|
|
|
228
385
|
export class Record extends Base
|
|
229
386
|
{
|
|
230
|
-
|
|
387
|
+
static classdoc = "A record of a LivingApp application";
|
|
388
|
+
|
|
389
|
+
constructor(id, app)
|
|
231
390
|
{
|
|
232
|
-
super();
|
|
233
|
-
this.id = null;
|
|
391
|
+
super(id);
|
|
234
392
|
this.app = app;
|
|
235
393
|
this.createdat = null;
|
|
236
394
|
this.createdby = null;
|
|
@@ -243,15 +401,47 @@ export class Record extends Base
|
|
|
243
401
|
this.children = new Map();
|
|
244
402
|
this.attachments = null;
|
|
245
403
|
this.errors = [];
|
|
404
|
+
this._sparsefielderrors = null;
|
|
405
|
+
this._sparsefieldlookupdata = null;
|
|
246
406
|
this._is_deleted = false;
|
|
407
|
+
this._is_new = true;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
_make_fields(defaults, values, errors, lookupdata)
|
|
411
|
+
{
|
|
412
|
+
let fields = new Map();
|
|
413
|
+
|
|
414
|
+
for (let control of this.app.controls.values())
|
|
415
|
+
{
|
|
416
|
+
let identifier = control.identifier;
|
|
417
|
+
let value = null;
|
|
418
|
+
if (values !== null)
|
|
419
|
+
{
|
|
420
|
+
if (defaults && !values.has(identifier))
|
|
421
|
+
value = control.default;
|
|
422
|
+
else if (values.has(identifier))
|
|
423
|
+
value = values.get(identifier);
|
|
424
|
+
}
|
|
425
|
+
let field = new Field(control, this, value);
|
|
426
|
+
fields.set(identifier, field);
|
|
427
|
+
if (errors !== null && errors.has(identifier))
|
|
428
|
+
field.errors = errors.get(identifier);
|
|
429
|
+
if (lookupdata !== null && lookupdata.has(identifier))
|
|
430
|
+
field.lookupdata = lookupdata.get(identifier);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
this._fields = fields;
|
|
434
|
+
this._sparsevalues = null;
|
|
435
|
+
this._sparsefielderrors = null;
|
|
436
|
+
this._sparselookupdata = null;
|
|
247
437
|
}
|
|
248
438
|
|
|
249
|
-
|
|
439
|
+
[ul4.symbols.repr]()
|
|
250
440
|
{
|
|
251
441
|
let v = ["<Record id=", ul4._repr(this.id)];
|
|
252
442
|
for (let field of this.fields.values())
|
|
253
443
|
{
|
|
254
|
-
if (field.control.priority)
|
|
444
|
+
if (field.control.priority && !field.is_empty())
|
|
255
445
|
{
|
|
256
446
|
v.push(" v_");
|
|
257
447
|
v.push(field.control.identifier);
|
|
@@ -259,21 +449,32 @@ export class Record extends Base
|
|
|
259
449
|
v.push(ul4._repr(field.value)); // FIXME: This might lead to infinite recursions
|
|
260
450
|
}
|
|
261
451
|
}
|
|
262
|
-
v.push("
|
|
452
|
+
v.push(" state=");
|
|
453
|
+
v.push(ul4._repr(this.state));
|
|
454
|
+
v.push(">");
|
|
263
455
|
return v.join("");
|
|
264
456
|
}
|
|
265
457
|
|
|
458
|
+
get state()
|
|
459
|
+
{
|
|
460
|
+
if (this._is_deleted)
|
|
461
|
+
return "deleted";
|
|
462
|
+
else if (this._is_new)
|
|
463
|
+
return "new";
|
|
464
|
+
else if (this.is_dirty())
|
|
465
|
+
return "dirty";
|
|
466
|
+
else
|
|
467
|
+
return "saved";
|
|
468
|
+
}
|
|
469
|
+
|
|
266
470
|
get values()
|
|
267
471
|
{
|
|
268
472
|
if (this._values === null)
|
|
269
473
|
{
|
|
270
|
-
this._values =
|
|
271
|
-
for (let
|
|
474
|
+
this._values = new Map();
|
|
475
|
+
for (let field of this.fields.values())
|
|
272
476
|
{
|
|
273
|
-
|
|
274
|
-
if (typeof(fieldvalue) === "undefined")
|
|
275
|
-
fieldvalue = null;
|
|
276
|
-
this._values.set(identifier, fieldvalue);
|
|
477
|
+
this._values.set(field.control.identifier, field.value);
|
|
277
478
|
}
|
|
278
479
|
}
|
|
279
480
|
return this._values;
|
|
@@ -282,14 +483,7 @@ export class Record extends Base
|
|
|
282
483
|
get fields()
|
|
283
484
|
{
|
|
284
485
|
if (this._fields === null)
|
|
285
|
-
|
|
286
|
-
this._fields = ul4._havemap ? new Map() : {};
|
|
287
|
-
for (let [identifier, value] of this.values.entries())
|
|
288
|
-
{
|
|
289
|
-
let field = new Field(this.app.controls.get(identifier), this, value);
|
|
290
|
-
this._fields.set(identifier, field);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
486
|
+
this._make_fields(false, this._sparsevalues, this._sparsefielderrors, this._sparsefieldlookupdata)
|
|
293
487
|
return this._fields;
|
|
294
488
|
}
|
|
295
489
|
|
|
@@ -319,7 +513,9 @@ export class Record extends Base
|
|
|
319
513
|
|
|
320
514
|
delete()
|
|
321
515
|
{
|
|
322
|
-
|
|
516
|
+
let result = this.app.globals.handler.delete(this);
|
|
517
|
+
this._is_deleted = true;
|
|
518
|
+
return result;
|
|
323
519
|
}
|
|
324
520
|
|
|
325
521
|
save()
|
|
@@ -367,6 +563,12 @@ export class Record extends Base
|
|
|
367
563
|
return true;
|
|
368
564
|
}
|
|
369
565
|
|
|
566
|
+
ul4onload(decoder)
|
|
567
|
+
{
|
|
568
|
+
super.ul4onload(decoder);
|
|
569
|
+
this._is_new = false;
|
|
570
|
+
}
|
|
571
|
+
|
|
370
572
|
_dumpUL4ONAttr(name)
|
|
371
573
|
{
|
|
372
574
|
if (name === "values")
|
|
@@ -375,54 +577,879 @@ export class Record extends Base
|
|
|
375
577
|
return this[name];
|
|
376
578
|
}
|
|
377
579
|
|
|
378
|
-
_loadUL4ONAttr(name, value)
|
|
580
|
+
_loadUL4ONAttr(name, value)
|
|
581
|
+
{
|
|
582
|
+
if (name === "values")
|
|
583
|
+
{
|
|
584
|
+
this._sparsevalues = value;
|
|
585
|
+
this._values = null;
|
|
586
|
+
this._fields = null;
|
|
587
|
+
}
|
|
588
|
+
else
|
|
589
|
+
this[name] = value;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
[ul4.symbols.getattr](name)
|
|
593
|
+
{
|
|
594
|
+
if (name.startsWith("c_"))
|
|
595
|
+
return this.children.get(name.substr(2))
|
|
596
|
+
else if (name.startsWith("f_"))
|
|
597
|
+
return this.fields.get(name.substr(2))
|
|
598
|
+
else if (name.startsWith("v_"))
|
|
599
|
+
return this.values.get(name.substr(2))
|
|
600
|
+
else
|
|
601
|
+
return this[name];
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
[ul4.symbols.setattr](name, value)
|
|
605
|
+
{
|
|
606
|
+
if (name.startsWith("c_"))
|
|
607
|
+
this.children[name.substr(2)] = value;
|
|
608
|
+
else if (name.startsWith("v_"))
|
|
609
|
+
this.fields.get(name.substr(2)).value = value;
|
|
610
|
+
else
|
|
611
|
+
throw new ul4.AttributeError(this, name);
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
Record.prototype._ul4onattrs = ["app", "createdat", "createdby", "updatedat", "updatedby", "updatecount", "_sparsevalues", "attachments", "children", "errors", "_sparsefielderrors", "_sparsefieldlookupdata"];
|
|
616
|
+
Record.prototype._ul4attrs = new Set(["id", "app", "createdat", "createdby", "updatedat", "updatedby", "updatecount", "values", "attachments", "children", "errors"]);
|
|
617
|
+
ul4.expose(Record.prototype.is_dirty, []);
|
|
618
|
+
ul4.expose(Record.prototype.has_errors, []);
|
|
619
|
+
ul4.expose(Record.prototype.delete, []);
|
|
620
|
+
ul4.expose(Record.prototype.save, []);
|
|
621
|
+
ul4.expose(Record.prototype.update, ["**values"], {"needsobject": true});
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
export class Field extends Base
|
|
625
|
+
{
|
|
626
|
+
static classdoc = "Holds the value of a field of a record (and related information)";
|
|
627
|
+
|
|
628
|
+
constructor(control, record, value)
|
|
629
|
+
{
|
|
630
|
+
super(null);
|
|
631
|
+
this.control = control;
|
|
632
|
+
this.record = record;
|
|
633
|
+
this._label = null;
|
|
634
|
+
this._value = value;
|
|
635
|
+
this._dirty = false;
|
|
636
|
+
this._lookupdate = null;
|
|
637
|
+
this.errors = [];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
get value()
|
|
641
|
+
{
|
|
642
|
+
return this._value;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
set value(value)
|
|
646
|
+
{
|
|
647
|
+
let oldvalue = this._value;
|
|
648
|
+
|
|
649
|
+
let change = {value: value, errors: []};
|
|
650
|
+
this._validate(change);
|
|
651
|
+
|
|
652
|
+
if (ul4._ne(oldvalue, change.value))
|
|
653
|
+
{
|
|
654
|
+
this.record.values.set(this.control.identifier, change.value);
|
|
655
|
+
this._value = change.value;
|
|
656
|
+
this._dirty = true;
|
|
657
|
+
}
|
|
658
|
+
this.errors = change.errors;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
_validate(change)
|
|
662
|
+
{
|
|
663
|
+
// Do nothing, i.e. accept the value unchanged and without errors
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
get label()
|
|
667
|
+
{
|
|
668
|
+
if (this._label !== null)
|
|
669
|
+
return this._label;
|
|
670
|
+
return this.control.label;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
set label(value)
|
|
674
|
+
{
|
|
675
|
+
this._label = value;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
get globals()
|
|
679
|
+
{
|
|
680
|
+
return this.control.globals;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
is_empty()
|
|
684
|
+
{
|
|
685
|
+
return this._value === null || (ul4._islist(this._value) && this._value.length === 0);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
is_dirty()
|
|
689
|
+
{
|
|
690
|
+
return this._dirty;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
has_errors()
|
|
694
|
+
{
|
|
695
|
+
return this.errors.length !== 0;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
search(searchvalue)
|
|
699
|
+
{
|
|
700
|
+
return this.control.search(this.value, searchvalue);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
msg_field_required(value)
|
|
704
|
+
{
|
|
705
|
+
switch (this.globals.lang)
|
|
706
|
+
{
|
|
707
|
+
case "de":
|
|
708
|
+
return `"${this.label}" wird benötigt!`;
|
|
709
|
+
default:
|
|
710
|
+
return `"${this.label}" is required!`;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
msg_field_wrong_type(value)
|
|
715
|
+
{
|
|
716
|
+
return `"${this.label}" doesn't support the type ${ul4._type(value).name}!`;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
msg_bool_truerequired(value)
|
|
720
|
+
{
|
|
721
|
+
return `"${this.label}" only accepts "Yes"!`;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
msg_string_tooshort(value)
|
|
725
|
+
{
|
|
726
|
+
return `"${this.label}" is too short. Tou must use at least ${this.control.minlength} characters!`;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
msg_string_toolong(value)
|
|
730
|
+
{
|
|
731
|
+
return `"${this.label}" is too long. You may use at most ${this.control.maxlength} characters!`;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
msg_email_format(value)
|
|
735
|
+
{
|
|
736
|
+
return `"${this.label}" must be a valid email address!`;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
msg_url_format(value)
|
|
740
|
+
{
|
|
741
|
+
return `"${this.label}" must be a valid URL!`;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
msg_tel_format(value)
|
|
745
|
+
{
|
|
746
|
+
return `"${this.label}" must be a valid phone number!`;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
msg_date_format(value)
|
|
750
|
+
{
|
|
751
|
+
return `"${this.label}" doesn't support this date format!`;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
msg_lookup_wrongitem(value)
|
|
755
|
+
{
|
|
756
|
+
return `The option ${ul4._repr(value)} for "${this.label}" doesn't belong to this lookup!`;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
msg_lookup_unknownkey(value)
|
|
760
|
+
{
|
|
761
|
+
return `The option ${ul4._repr(value)} for "${this.label}" is unknown!`;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
msg_applookup_wrongrecord(value)
|
|
765
|
+
{
|
|
766
|
+
return `The record ${ul4._repr(value)} for "${this.label}" doesn't belong to the correct app!`;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
msg_applookup_unknownkey(value)
|
|
770
|
+
{
|
|
771
|
+
return `The record ${ul4._repr(value)} for "${this.label}" can't be found!`;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
[ul4.symbols.repr]()
|
|
775
|
+
{
|
|
776
|
+
let s = "<Field identifier=";
|
|
777
|
+
s += ul4._repr(this.control.identifier)
|
|
778
|
+
if (this._dirty)
|
|
779
|
+
s += " is_dirty()=True";
|
|
780
|
+
if (this.errors.length > 0)
|
|
781
|
+
s += " has_errors()=True";
|
|
782
|
+
s += ">"
|
|
783
|
+
return s;
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
Field.prototype._ul4onattrs = ["control", "record", "label", "value", "errors", "enabled", "writable", "visible"];
|
|
788
|
+
Field.prototype._ul4attrs = new Set(["control", "record", "label", "value", "errors", "enabled", "writable", "visible"]);
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
export class BoolField extends Field
|
|
792
|
+
{
|
|
793
|
+
static classdoc = "Holds the value of a bool field of a record (and related information)";
|
|
794
|
+
|
|
795
|
+
_validate(change)
|
|
796
|
+
{
|
|
797
|
+
if (change.value === null)
|
|
798
|
+
{
|
|
799
|
+
if (this.control.required)
|
|
800
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
801
|
+
}
|
|
802
|
+
else if (typeof(change.value) === "boolean")
|
|
803
|
+
{
|
|
804
|
+
if (this.control.required && !change.value)
|
|
805
|
+
change.errors.push(this.msg_bool_truerequired(change.value));
|
|
806
|
+
}
|
|
807
|
+
else
|
|
808
|
+
{
|
|
809
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
810
|
+
change.value = null;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
export class IntField extends Field
|
|
817
|
+
{
|
|
818
|
+
static classdoc = "Holds the value of an int field of a record (and related information)";
|
|
819
|
+
|
|
820
|
+
_validate(change)
|
|
821
|
+
{
|
|
822
|
+
if (change.value === null)
|
|
823
|
+
{
|
|
824
|
+
if (this.control.required)
|
|
825
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
826
|
+
}
|
|
827
|
+
else if (typeof(change.value) !== "number" || Math.round(change.value) !== change.value)
|
|
828
|
+
{
|
|
829
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
export class NumberField extends Field
|
|
836
|
+
{
|
|
837
|
+
static classdoc = "Holds the value of a number field of a record (and related information)";
|
|
838
|
+
|
|
839
|
+
_validate(change)
|
|
840
|
+
{
|
|
841
|
+
if (change.value === null || change.value === "")
|
|
842
|
+
{
|
|
843
|
+
if (this.control.required)
|
|
844
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
845
|
+
change.value = null;
|
|
846
|
+
}
|
|
847
|
+
else if (typeof(change.value) !== "number")
|
|
848
|
+
{
|
|
849
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
export class StringField extends Field
|
|
856
|
+
{
|
|
857
|
+
static classdoc = "Holds the value of a string field of a record (and related information)";
|
|
858
|
+
|
|
859
|
+
_validate(change)
|
|
860
|
+
{
|
|
861
|
+
if (change.value === null || change.value === "")
|
|
862
|
+
{
|
|
863
|
+
if (this.control.required)
|
|
864
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
865
|
+
change.value = null;
|
|
866
|
+
}
|
|
867
|
+
else if (typeof(change.value) === "string")
|
|
868
|
+
{
|
|
869
|
+
let minlength = this.control.minlength;
|
|
870
|
+
let maxlength = this.control.maxlength;
|
|
871
|
+
if (minlength !== null && change.value.length < minlength)
|
|
872
|
+
change.errors.push(this.msg_string_tooshort(change.value))
|
|
873
|
+
if (maxlength !== null && change.value.length > maxlength)
|
|
874
|
+
change.errors.push(this.msg_string_toolong(change.value))
|
|
875
|
+
}
|
|
876
|
+
else
|
|
877
|
+
{
|
|
878
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
879
|
+
change.value = null;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
export class EmailField extends StringField
|
|
886
|
+
{
|
|
887
|
+
static classdoc = "Holds the value of a string/email field of a record (and related information)";
|
|
888
|
+
|
|
889
|
+
_validate(change)
|
|
890
|
+
{
|
|
891
|
+
if (typeof(change.value) === "string" && change.value.length > 0)
|
|
892
|
+
{
|
|
893
|
+
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i;
|
|
894
|
+
if (!re.test(change.value))
|
|
895
|
+
change.errors.push(this.msg_email_format(change.value));
|
|
896
|
+
}
|
|
897
|
+
super._validate(change);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
export class URLField extends StringField
|
|
903
|
+
{
|
|
904
|
+
static classdoc = "Holds the value of a string/url field of a record (and related information)";
|
|
905
|
+
|
|
906
|
+
_validate(change)
|
|
907
|
+
{
|
|
908
|
+
if (typeof(change.value) === "string" && change.value.length > 0)
|
|
909
|
+
{
|
|
910
|
+
let url = null;
|
|
911
|
+
try
|
|
912
|
+
{
|
|
913
|
+
url = new URL(change.value);
|
|
914
|
+
}
|
|
915
|
+
catch (exc)
|
|
916
|
+
{
|
|
917
|
+
change.errors.push(this.msg_url_format(change.value));
|
|
918
|
+
}
|
|
919
|
+
if (url !== null && url.protocol !== "http:" && url.protocol !== "https:")
|
|
920
|
+
{
|
|
921
|
+
change.errors.push(this.msg_url_format(change.value));
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
super._validate(change);
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
export class TelField extends StringField
|
|
930
|
+
{
|
|
931
|
+
static classdoc = "Holds the value of a string/tel field of a record (and related information)";
|
|
932
|
+
|
|
933
|
+
_validate(change)
|
|
934
|
+
{
|
|
935
|
+
if (typeof(change.value) === "string" && change.value.length > 0)
|
|
936
|
+
{
|
|
937
|
+
const re = /^\\+?[0-9 /()-]+$/;
|
|
938
|
+
if (!re.test(change.value))
|
|
939
|
+
change.errors.push(this.msg_tel_format(change.value));
|
|
940
|
+
}
|
|
941
|
+
super._validate(change);
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
export class TextAreaField extends StringField
|
|
947
|
+
{
|
|
948
|
+
static classdoc = "Holds the value of a string/textarea field of a record (and related information)";
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
export class HTMLField extends StringField
|
|
953
|
+
{
|
|
954
|
+
static classdoc = "Holds the value of a string/html field of a record (and related information)";
|
|
955
|
+
};
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
export class GeoField extends Field
|
|
959
|
+
{
|
|
960
|
+
static classdoc = "Holds the value of a geo field of a record (and related information)";
|
|
961
|
+
|
|
962
|
+
_validate(change)
|
|
963
|
+
{
|
|
964
|
+
if (change.value === null || change.value === "")
|
|
965
|
+
{
|
|
966
|
+
if (this.control.required)
|
|
967
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
968
|
+
change.value = null;
|
|
969
|
+
}
|
|
970
|
+
else if (!(change.value instanceof Geo))
|
|
971
|
+
{
|
|
972
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
973
|
+
change.value = null;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
export class FileField extends Field
|
|
980
|
+
{
|
|
981
|
+
static classdoc = "Holds the value of a file field of a record (and related information)";
|
|
982
|
+
|
|
983
|
+
_validate(change)
|
|
984
|
+
{
|
|
985
|
+
if (change.value === null || change.value === "")
|
|
986
|
+
{
|
|
987
|
+
if (this.control.required)
|
|
988
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
989
|
+
change.value = null;
|
|
990
|
+
}
|
|
991
|
+
else if (!(change.value instanceof File))
|
|
992
|
+
{
|
|
993
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
994
|
+
change.value = null;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
export class FileSignatureField extends FileField
|
|
1001
|
+
{
|
|
1002
|
+
static classdoc = "Holds the value of a file/signature field of a record (and related information)";
|
|
1003
|
+
|
|
1004
|
+
_validate(change)
|
|
1005
|
+
{
|
|
1006
|
+
// FIXME: Implement handling of data URLs.
|
|
1007
|
+
super._validate(change);
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
export class DateFieldBase extends Field
|
|
1013
|
+
{
|
|
1014
|
+
static classdoc = "Holds the value of a date field of a record (and related information)";
|
|
1015
|
+
|
|
1016
|
+
_validate(change)
|
|
1017
|
+
{
|
|
1018
|
+
if (change.value === null || change.value === "")
|
|
1019
|
+
{
|
|
1020
|
+
if (this.control.required)
|
|
1021
|
+
change.errors.push(this.msg_field_required(change.value));
|
|
1022
|
+
change.value = null;
|
|
1023
|
+
}
|
|
1024
|
+
else if (change.value instanceof Date)
|
|
1025
|
+
{
|
|
1026
|
+
change.value = this._convert(new Date(change.value.getTime()));
|
|
1027
|
+
}
|
|
1028
|
+
else if (typeof(change.value) === "string")
|
|
1029
|
+
{
|
|
1030
|
+
let value = null;
|
|
1031
|
+
if (change.value.length === 10)
|
|
1032
|
+
value = new Date(change.value + "T00:00:00");
|
|
1033
|
+
else if (change.value.length === 16)
|
|
1034
|
+
value = new Date(change.value + ":00");
|
|
1035
|
+
else if (change.value.length === 19)
|
|
1036
|
+
value = new Date(change.value);
|
|
1037
|
+
|
|
1038
|
+
if (value === null || Number.isNaN(value.getYear()))
|
|
1039
|
+
{
|
|
1040
|
+
change.errors.push(this.msg_date_format(change.value));
|
|
1041
|
+
// Keep original invalid string
|
|
1042
|
+
}
|
|
1043
|
+
else
|
|
1044
|
+
{
|
|
1045
|
+
change.value = this._convert(value);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
else
|
|
1049
|
+
{
|
|
1050
|
+
change.errors.push(this.msg_field_wrong_type(change.value));
|
|
1051
|
+
change.value = null;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
export class DateField extends DateFieldBase
|
|
1058
|
+
{
|
|
1059
|
+
static classdoc = "Holds the value of a date/date field of a record (and related information)";
|
|
1060
|
+
|
|
1061
|
+
_convert(date)
|
|
1062
|
+
{
|
|
1063
|
+
return new ul4.Date_(date.getFullYear(), date.getMonth()+1, date.getDate());
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
export class DatetimeMinuteField extends DateFieldBase
|
|
1069
|
+
{
|
|
1070
|
+
static classdoc = "Holds the value of a date/datetimeminute field of a record (and related information)";
|
|
1071
|
+
|
|
1072
|
+
_convert(date)
|
|
1073
|
+
{
|
|
1074
|
+
// Get rid of seconds and milliseconds
|
|
1075
|
+
date.setSeconds(0);
|
|
1076
|
+
date.setMilliseconds(0);
|
|
1077
|
+
return date;
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
export class DatetimeSecondField extends DateFieldBase
|
|
1083
|
+
{
|
|
1084
|
+
static classdoc = "Holds the value of a date/datetimesecond field of a record (and related information)";
|
|
1085
|
+
|
|
1086
|
+
_convert(date)
|
|
1087
|
+
{
|
|
1088
|
+
// Get rid of milliseconds
|
|
1089
|
+
date.setMilliseconds(0);
|
|
1090
|
+
return date;
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
export class LookupFieldBase extends Field
|
|
1096
|
+
{
|
|
1097
|
+
static classdoc = "Base type of LookupField and MultipleLookupField";
|
|
1098
|
+
|
|
1099
|
+
get lookupdata()
|
|
1100
|
+
{
|
|
1101
|
+
if (this._lookupdate !== null)
|
|
1102
|
+
return this._lookupdate;
|
|
1103
|
+
else
|
|
1104
|
+
return this.control.lookupdata;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
set lookupdata(value)
|
|
1108
|
+
{
|
|
1109
|
+
this._lookupdate = value;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
_find_lookupitem(change)
|
|
1113
|
+
{
|
|
1114
|
+
let v = change.value;
|
|
1115
|
+
if (typeof(v) === "string")
|
|
1116
|
+
{
|
|
1117
|
+
// If `lookupdata`} is `null`, this is probably an interface,
|
|
1118
|
+
// so we can't validate anything (note that interfaces will however go
|
|
1119
|
+
// away in the future)
|
|
1120
|
+
if (this.lookupdata === null)
|
|
1121
|
+
return;
|
|
1122
|
+
let lookupitem = this.lookupdata.get(v);
|
|
1123
|
+
if (lookupitem === undefined)
|
|
1124
|
+
{
|
|
1125
|
+
// If the lookup control is auto expandable,
|
|
1126
|
+
// the user may have given us a label
|
|
1127
|
+
if (this.control.autoexpandable)
|
|
1128
|
+
{
|
|
1129
|
+
// Search for the LookupItem with that label
|
|
1130
|
+
for (let search_lookupitem of this.lookupdata.values())
|
|
1131
|
+
{
|
|
1132
|
+
if (v === search_lookupitem.label)
|
|
1133
|
+
{
|
|
1134
|
+
change.value = search_lookupitem;
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
// If we couldn't find the label, keep the label as it is.
|
|
1139
|
+
}
|
|
1140
|
+
else
|
|
1141
|
+
{
|
|
1142
|
+
change.errors.push(this.msg_lookup_unknownkey(v))
|
|
1143
|
+
change.value = null;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
else
|
|
1147
|
+
{
|
|
1148
|
+
change.value = lookupitem;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
else if (v instanceof LookupItem)
|
|
1152
|
+
{
|
|
1153
|
+
let value = this.control.lookupdata.get(v.key);
|
|
1154
|
+
if (value !== v)
|
|
1155
|
+
{
|
|
1156
|
+
change.errors.push(this.msg_lookup_wrongitem(v));
|
|
1157
|
+
change.value = null;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
else
|
|
1161
|
+
{
|
|
1162
|
+
change.errors.push(this.msg_field_wrong_type(v));
|
|
1163
|
+
change.value = null;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
export class LookupField extends LookupFieldBase
|
|
1170
|
+
{
|
|
1171
|
+
static classdoc = "Holds the value of a lookup field of a record (and related information)";
|
|
1172
|
+
|
|
1173
|
+
_validate(change)
|
|
1174
|
+
{
|
|
1175
|
+
let v = change.value;
|
|
1176
|
+
if (v === null || v === "" || this.control.nonekey === v)
|
|
1177
|
+
{
|
|
1178
|
+
if (this.control.required)
|
|
1179
|
+
change.errors.push(this.msg_field_required(v));
|
|
1180
|
+
change.value = null;
|
|
1181
|
+
}
|
|
1182
|
+
else
|
|
1183
|
+
{
|
|
1184
|
+
this._find_lookupitem(change);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
export class MultipleLookupField extends LookupFieldBase
|
|
1191
|
+
{
|
|
1192
|
+
static classdoc = "Holds the value of a multiple lookup field of a record (and related information)";
|
|
1193
|
+
|
|
1194
|
+
_validate(change)
|
|
1195
|
+
{
|
|
1196
|
+
let v = change.value;
|
|
1197
|
+
let islist = (Object.prototype.toString.call(v) === "[object Array]");
|
|
1198
|
+
|
|
1199
|
+
if (v === null || v === "" || this.control.nonekey === v || (islist && v.length === 0))
|
|
1200
|
+
{
|
|
1201
|
+
if (this.control.required)
|
|
1202
|
+
change.errors.push(this.msg_field_required(v));
|
|
1203
|
+
change.value = [];
|
|
1204
|
+
}
|
|
1205
|
+
else if (islist)
|
|
1206
|
+
{
|
|
1207
|
+
let newvalue = [];
|
|
1208
|
+
for (let item of v)
|
|
1209
|
+
{
|
|
1210
|
+
let singlechange = {value: item, errors: []};
|
|
1211
|
+
this._find_lookupitem(singlechange);
|
|
1212
|
+
if (singlechange.errors.length > 0)
|
|
1213
|
+
change.errors = [...change.errors, ...singlechange.errors];
|
|
1214
|
+
else
|
|
1215
|
+
newvalue.push(singlechange.value);
|
|
1216
|
+
}
|
|
1217
|
+
change.value = newvalue;
|
|
1218
|
+
}
|
|
1219
|
+
else
|
|
1220
|
+
{
|
|
1221
|
+
this._find_lookupitem(change);
|
|
1222
|
+
if (change.errors.length > 0)
|
|
1223
|
+
change.value = [];
|
|
1224
|
+
else
|
|
1225
|
+
change.value = [change.value];
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
export class AppLookupFieldBase extends Field
|
|
1232
|
+
{
|
|
1233
|
+
static classdoc = "Base type of AppLookupField and MultipleAppLookupField";
|
|
1234
|
+
|
|
1235
|
+
get lookupdata()
|
|
1236
|
+
{
|
|
1237
|
+
if (this._lookupdate !== null)
|
|
1238
|
+
return this._lookupdate;
|
|
1239
|
+
else
|
|
1240
|
+
{
|
|
1241
|
+
if (this.control.lookup_app.records !== null)
|
|
1242
|
+
return this.control.lookup_app.records;
|
|
1243
|
+
}
|
|
1244
|
+
return new Map();
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
set lookupdata(value)
|
|
1248
|
+
{
|
|
1249
|
+
this._lookupdate = value;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
_find_record(change)
|
|
1253
|
+
{
|
|
1254
|
+
let v = change.value;
|
|
1255
|
+
if (typeof(v) === "string")
|
|
1256
|
+
{
|
|
1257
|
+
let record = this.lookupdata.get(v);
|
|
1258
|
+
if (record === undefined)
|
|
1259
|
+
{
|
|
1260
|
+
change.errors.push(this.msg_applookup_unknownkey(v))
|
|
1261
|
+
change.value = null;
|
|
1262
|
+
}
|
|
1263
|
+
else
|
|
1264
|
+
{
|
|
1265
|
+
change.value = record;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
else if (v instanceof Record)
|
|
1269
|
+
{
|
|
1270
|
+
if (v.app !== this.control.lookup_app)
|
|
1271
|
+
{
|
|
1272
|
+
change.errors.push(this.msg_applookup_wrongrecord(v));
|
|
1273
|
+
change.value = null;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
else
|
|
1277
|
+
{
|
|
1278
|
+
change.errors.push(this.msg_field_wrong_type(v));
|
|
1279
|
+
change.value = null;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
export class AppLookupField extends AppLookupFieldBase
|
|
1286
|
+
{
|
|
1287
|
+
static classdoc = "Holds the value of a applookup field of a record (and related information)";
|
|
1288
|
+
|
|
1289
|
+
_validate(change)
|
|
1290
|
+
{
|
|
1291
|
+
this._find_record(change);
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
export class MultipleAppLookupField extends AppLookupFieldBase
|
|
1297
|
+
{
|
|
1298
|
+
static classdoc = "Holds the value of a multiple applookup field of a record (and related information)";
|
|
1299
|
+
|
|
1300
|
+
_validate(change)
|
|
1301
|
+
{
|
|
1302
|
+
let v = change.value;
|
|
1303
|
+
let islist = (Object.prototype.toString.call(v) === "[object Array]");
|
|
1304
|
+
|
|
1305
|
+
if (v === null || v === "" || this.control.nonekey === v || (islist && v.length === 0))
|
|
1306
|
+
{
|
|
1307
|
+
if (this.control.required)
|
|
1308
|
+
change.errors.push(this.msg_field_required(v));
|
|
1309
|
+
change.value = [];
|
|
1310
|
+
}
|
|
1311
|
+
else if (islist)
|
|
1312
|
+
{
|
|
1313
|
+
let newvalue = [];
|
|
1314
|
+
for (let item of v)
|
|
1315
|
+
{
|
|
1316
|
+
let singlechange = {value: item, errors: []};
|
|
1317
|
+
this._find_record(singlechange);
|
|
1318
|
+
if (singlechange.errors.length > 0)
|
|
1319
|
+
change.errors = [...change.errors, ...singlechange.errors];
|
|
1320
|
+
else
|
|
1321
|
+
newvalue.push(singlechange.value);
|
|
1322
|
+
}
|
|
1323
|
+
change.value = newvalue;
|
|
1324
|
+
}
|
|
1325
|
+
else
|
|
1326
|
+
{
|
|
1327
|
+
this._find_record(change);
|
|
1328
|
+
if (change.errors.length > 0)
|
|
1329
|
+
change.value = [];
|
|
1330
|
+
else
|
|
1331
|
+
change.value = [change.value];
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
export class Control extends Base
|
|
1338
|
+
{
|
|
1339
|
+
[ul4.symbols.repr]()
|
|
1340
|
+
{
|
|
1341
|
+
return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
get globals()
|
|
1345
|
+
{
|
|
1346
|
+
return this.app.globals;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
get fulltype()
|
|
1350
|
+
{
|
|
1351
|
+
return this.subtype ? this.type + "/" + this.subtype : this.type;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
get label()
|
|
1355
|
+
{
|
|
1356
|
+
let view_control = this._view_control();
|
|
1357
|
+
if (view_control === null)
|
|
1358
|
+
return this._label;
|
|
1359
|
+
let label = view_control.label;
|
|
1360
|
+
if (label === null)
|
|
1361
|
+
return this._label;
|
|
1362
|
+
return label;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
set label(value)
|
|
1366
|
+
{
|
|
1367
|
+
this._label = value;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
get default()
|
|
1371
|
+
{
|
|
1372
|
+
return null;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
get top()
|
|
1376
|
+
{
|
|
1377
|
+
let view_control = this._view_control();
|
|
1378
|
+
return view_control !== null ? view_control.top : null;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
get left()
|
|
1382
|
+
{
|
|
1383
|
+
let view_control = this._view_control();
|
|
1384
|
+
return view_control !== null ? view_control.left : null;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
get width()
|
|
1388
|
+
{
|
|
1389
|
+
let view_control = this._view_control();
|
|
1390
|
+
return view_control !== null ? view_control.width : null;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
get height()
|
|
1394
|
+
{
|
|
1395
|
+
let view_control = this._view_control();
|
|
1396
|
+
return view_control !== null ? view_control.height : null;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
get liveupdate()
|
|
1400
|
+
{
|
|
1401
|
+
let view_control = this._view_control();
|
|
1402
|
+
return view_control !== null ? view_control.liveupdate : false;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
get tabindex()
|
|
1406
|
+
{
|
|
1407
|
+
let view_control = this._view_control();
|
|
1408
|
+
return view_control !== null ? view_control.tabindex : null;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
get required()
|
|
1412
|
+
{
|
|
1413
|
+
let view_control = this._view_control();
|
|
1414
|
+
return view_control !== null ? view_control.required : false;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
get mode()
|
|
379
1418
|
{
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this._sparsevalues = value;
|
|
383
|
-
this._values = null;
|
|
384
|
-
this._fields = null;
|
|
385
|
-
}
|
|
386
|
-
else
|
|
387
|
-
this[name] = value;
|
|
1419
|
+
let view_control = this._view_control();
|
|
1420
|
+
return view_control !== null ? view_control.mode : "edit";
|
|
388
1421
|
}
|
|
389
1422
|
|
|
390
|
-
|
|
1423
|
+
get labelpos()
|
|
391
1424
|
{
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
else if (name.startsWith("f_"))
|
|
395
|
-
return this.fields.get(name.substr(2))
|
|
396
|
-
else if (name.startsWith("v_"))
|
|
397
|
-
return this.values.get(name.substr(2))
|
|
398
|
-
else
|
|
399
|
-
return this[name];
|
|
1425
|
+
let view_control = this._view_control();
|
|
1426
|
+
return view_control !== null ? view_control.labelpos : "left";
|
|
400
1427
|
}
|
|
401
1428
|
|
|
402
|
-
|
|
1429
|
+
get labelwidth()
|
|
403
1430
|
{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
else if (name.startsWith("v_"))
|
|
407
|
-
this.fields.get(name.substr(2)).value = value;
|
|
408
|
-
else
|
|
409
|
-
throw new ul4.AttributeError(this, name);
|
|
1431
|
+
let view_control = this._view_control();
|
|
1432
|
+
return view_control !== null ? view_control.labelwidth : null;
|
|
410
1433
|
}
|
|
411
|
-
};
|
|
412
1434
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
ul4.expose(Record.prototype.save, []);
|
|
419
|
-
ul4.expose(Record.prototype.update, ["**values"], {"needsobject": true});
|
|
1435
|
+
get autoalign()
|
|
1436
|
+
{
|
|
1437
|
+
let view_control = this._view_control();
|
|
1438
|
+
return view_control !== null ? view_control.autoalign : true;
|
|
1439
|
+
}
|
|
420
1440
|
|
|
421
|
-
|
|
422
|
-
{
|
|
423
|
-
|
|
1441
|
+
get in_active_view()
|
|
1442
|
+
{
|
|
1443
|
+
let view_control = this._view_control();
|
|
1444
|
+
return view_control !== null;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
_view_control()
|
|
424
1448
|
{
|
|
425
|
-
|
|
1449
|
+
if (this.app._active_view === null)
|
|
1450
|
+
return null;
|
|
1451
|
+
let view_control = this.app._active_view.controls.get(this.identifier);
|
|
1452
|
+
return view_control ?? null;
|
|
426
1453
|
}
|
|
427
1454
|
|
|
428
1455
|
_logsearch(value, search)
|
|
@@ -442,11 +1469,14 @@ export class Control extends Base
|
|
|
442
1469
|
|
|
443
1470
|
Control.prototype.type = null;
|
|
444
1471
|
Control.prototype.subtype = null;
|
|
445
|
-
Control.prototype._ul4onattrs = ["
|
|
446
|
-
Control.prototype._ul4attrs =
|
|
1472
|
+
Control.prototype._ul4onattrs = ["identifier", "fieldname", "app", "_label", "priority", "order", "ininsertprocedure", "inupdateprocedure"];
|
|
1473
|
+
Control.prototype._ul4attrs = new Set(["id", "identifier", "fieldname", "app", "priority", "order", "ininsertprocedure", "inupdateprocedure", "fulltype", "label", "top", "left", "width", "height", "liveupdate", "tabindex", "required", "mode", "labelpos", "autoalign", "in_active_view"]);
|
|
1474
|
+
|
|
447
1475
|
|
|
448
1476
|
export class BoolControl extends Control
|
|
449
1477
|
{
|
|
1478
|
+
static classdoc = "A LivingApps boolean field (type 'bool')";
|
|
1479
|
+
|
|
450
1480
|
// ``search`` must by ``null``, ``false`` or ``true``
|
|
451
1481
|
search(value, search)
|
|
452
1482
|
{
|
|
@@ -459,9 +1489,13 @@ export class BoolControl extends Control
|
|
|
459
1489
|
};
|
|
460
1490
|
|
|
461
1491
|
BoolControl.prototype.type = "bool";
|
|
1492
|
+
BoolControl.prototype.fieldtype = BoolField;
|
|
1493
|
+
|
|
462
1494
|
|
|
463
1495
|
export class IntControl extends Control
|
|
464
1496
|
{
|
|
1497
|
+
static classdoc = "A LivingApps integer field (type 'int')";
|
|
1498
|
+
|
|
465
1499
|
// ``search.value`` must by ``null`` or an integer
|
|
466
1500
|
search(value, search)
|
|
467
1501
|
{
|
|
@@ -474,9 +1508,29 @@ export class IntControl extends Control
|
|
|
474
1508
|
};
|
|
475
1509
|
|
|
476
1510
|
IntControl.prototype.type = "int";
|
|
1511
|
+
IntControl.prototype.fieldtype = IntField;
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
class PlaceholderControl extends Control
|
|
1515
|
+
{
|
|
1516
|
+
static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/select')";
|
|
1517
|
+
|
|
1518
|
+
get placeholder()
|
|
1519
|
+
{
|
|
1520
|
+
let view_control = this._view_control();
|
|
1521
|
+
if (view_control === null)
|
|
1522
|
+
return null;
|
|
1523
|
+
return view_control.placeholder;
|
|
1524
|
+
}
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
PlaceholderControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "placeholder"]);
|
|
477
1528
|
|
|
478
|
-
|
|
1529
|
+
|
|
1530
|
+
export class NumberControl extends PlaceholderControl
|
|
479
1531
|
{
|
|
1532
|
+
static classdoc = "A LivingApps number field (type 'number')";
|
|
1533
|
+
|
|
480
1534
|
// ``search.value`` must by ``null`` or an integer
|
|
481
1535
|
search(value, search)
|
|
482
1536
|
{
|
|
@@ -495,9 +1549,103 @@ export class NumberControl extends Control
|
|
|
495
1549
|
};
|
|
496
1550
|
|
|
497
1551
|
NumberControl.prototype.type = "number";
|
|
1552
|
+
NumberControl.prototype.fieldtype = NumberField;
|
|
498
1553
|
|
|
499
|
-
|
|
1554
|
+
|
|
1555
|
+
export class StringControl extends PlaceholderControl
|
|
500
1556
|
{
|
|
1557
|
+
_user_placeholder(user, placeholder)
|
|
1558
|
+
{
|
|
1559
|
+
if (placeholder === null)
|
|
1560
|
+
return null;
|
|
1561
|
+
switch (placeholder)
|
|
1562
|
+
{
|
|
1563
|
+
case "{gender}":
|
|
1564
|
+
return user !== null ? user.gender : null;
|
|
1565
|
+
case "{title}":
|
|
1566
|
+
return user !== null ? user.title : null;
|
|
1567
|
+
case "{firstname}":
|
|
1568
|
+
return user !== null ? user.firstname : null;
|
|
1569
|
+
case "{surname}":
|
|
1570
|
+
return user !== null ? user.surname : null;
|
|
1571
|
+
case "{account}":
|
|
1572
|
+
return user !== null ? user.email : null;
|
|
1573
|
+
case "{streetname}":
|
|
1574
|
+
return user !== null ? user.streetname : null;
|
|
1575
|
+
case "{streetnumber}":
|
|
1576
|
+
return user !== null ? user.streetnumber : null;
|
|
1577
|
+
case "{street}":
|
|
1578
|
+
if (user === null)
|
|
1579
|
+
return null;
|
|
1580
|
+
else if (user.street === null)
|
|
1581
|
+
return user.streetnumber;
|
|
1582
|
+
else if (user.streetnumber === null)
|
|
1583
|
+
return user.street;
|
|
1584
|
+
else
|
|
1585
|
+
return user.street + " " + user.streetnumber;
|
|
1586
|
+
case "{zip}":
|
|
1587
|
+
return user !== null ? user.zip : null;
|
|
1588
|
+
case "{phone}":
|
|
1589
|
+
return user !== null ? user.phone : null;
|
|
1590
|
+
case "{fax}":
|
|
1591
|
+
return user !== null ? user.fax : null;
|
|
1592
|
+
case "{company}":
|
|
1593
|
+
return user !== null ? user.company : null;
|
|
1594
|
+
case "{city}":
|
|
1595
|
+
return user !== null ? user.city : null;
|
|
1596
|
+
case "{summary}":
|
|
1597
|
+
return user !== null ? user.summary : null;
|
|
1598
|
+
case "{interests}":
|
|
1599
|
+
return user !== null ? user.interests : null;
|
|
1600
|
+
case "{personal_website}":
|
|
1601
|
+
return user !== null ? user.personal_website : null;
|
|
1602
|
+
case "{company_website}":
|
|
1603
|
+
return user !== null ? user.company_website : null;
|
|
1604
|
+
case "{position}":
|
|
1605
|
+
return user !== null ? user.position : null;
|
|
1606
|
+
case "{department}":
|
|
1607
|
+
return user !== null ? user.department : null;
|
|
1608
|
+
case "{today}":
|
|
1609
|
+
return ul4.today();
|
|
1610
|
+
default:
|
|
1611
|
+
return placeholder;
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
get default()
|
|
1616
|
+
{
|
|
1617
|
+
let view_control = this._view_control();
|
|
1618
|
+
|
|
1619
|
+
if (view_control === null)
|
|
1620
|
+
return null;
|
|
1621
|
+
|
|
1622
|
+
return this._user_placeholder(this.app.globals.user, view_control.default);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
get minlength()
|
|
1626
|
+
{
|
|
1627
|
+
let view_control = this._view_control();
|
|
1628
|
+
|
|
1629
|
+
if (view_control === null)
|
|
1630
|
+
return 0;
|
|
1631
|
+
let minlength = view_control.minlength;
|
|
1632
|
+
if (minlength === null || minlength < 0)
|
|
1633
|
+
return 0;
|
|
1634
|
+
return minlength;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
get maxlength()
|
|
1638
|
+
{
|
|
1639
|
+
let view_control = this._view_control();
|
|
1640
|
+
|
|
1641
|
+
if (view_control === null)
|
|
1642
|
+
return 4000;
|
|
1643
|
+
let maxlength = view_control.maxlength;
|
|
1644
|
+
if (maxlength === null || maxlength < 0 || maxlength > 4000)
|
|
1645
|
+
return 4000;
|
|
1646
|
+
return maxlength;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
501
1649
|
search(value, search)
|
|
502
1650
|
{
|
|
503
1651
|
this._logsearch(value, search);
|
|
@@ -515,46 +1663,92 @@ export class StringControl extends Control
|
|
|
515
1663
|
|
|
516
1664
|
StringControl.prototype.type = "string";
|
|
517
1665
|
|
|
1666
|
+
|
|
518
1667
|
export class TextControl extends StringControl
|
|
519
1668
|
{
|
|
1669
|
+
static classdoc = "A LivingApps text field (type 'string/text')";
|
|
520
1670
|
};
|
|
521
1671
|
|
|
522
1672
|
TextControl.prototype.subtype = "text";
|
|
1673
|
+
TextControl.prototype.fieldtype = StringField;
|
|
1674
|
+
|
|
523
1675
|
|
|
524
1676
|
export class EmailControl extends StringControl
|
|
525
1677
|
{
|
|
1678
|
+
static classdoc = "A LivingApps email field (type 'string/email')";
|
|
526
1679
|
};
|
|
527
1680
|
|
|
528
1681
|
EmailControl.prototype.subtype = "email";
|
|
1682
|
+
EmailControl.prototype.fieldtype = EmailField;
|
|
1683
|
+
|
|
529
1684
|
|
|
530
1685
|
export class URLControl extends StringControl
|
|
531
1686
|
{
|
|
1687
|
+
static classdoc = "A LivingApps URL field (type 'string/url')";
|
|
532
1688
|
};
|
|
533
1689
|
|
|
534
1690
|
URLControl.prototype.subtype = "url";
|
|
1691
|
+
URLControl.prototype.fieldtype = URLField;
|
|
1692
|
+
|
|
535
1693
|
|
|
536
1694
|
export class TelControl extends StringControl
|
|
537
1695
|
{
|
|
1696
|
+
static classdoc = "A LivingApps phone number field (type 'string/tel')";
|
|
538
1697
|
};
|
|
539
1698
|
|
|
540
1699
|
TelControl.prototype.subtype = "tel";
|
|
1700
|
+
TelControl.prototype.fieldtype = TelField;
|
|
1701
|
+
|
|
541
1702
|
|
|
542
|
-
export class
|
|
1703
|
+
export class TextAreaControl extends StringControl
|
|
543
1704
|
{
|
|
1705
|
+
static classdoc = "A LivingApps textarea field (type 'string/textarea')";
|
|
1706
|
+
|
|
1707
|
+
get maxlength()
|
|
1708
|
+
{
|
|
1709
|
+
let view_control = this._view_control();
|
|
1710
|
+
|
|
1711
|
+
if (view_control === null)
|
|
1712
|
+
return null;
|
|
1713
|
+
// We only get the encrypted text in encryption mode, so we can't check its length
|
|
1714
|
+
if (this.encrypted !== null)
|
|
1715
|
+
return null;
|
|
1716
|
+
let maxlength = view_control.maxlength;
|
|
1717
|
+
if (maxlength < 0)
|
|
1718
|
+
return null;
|
|
1719
|
+
return maxlength;
|
|
1720
|
+
}
|
|
544
1721
|
};
|
|
545
1722
|
|
|
546
|
-
|
|
1723
|
+
TextAreaControl.prototype.subtype = "textarea";
|
|
1724
|
+
TextAreaControl.prototype.fieldtype = TextAreaField;
|
|
1725
|
+
TextAreaControl.prototype._ul4onattrs = [...StringControl.prototype._ul4onattrs, "encrypted"];
|
|
1726
|
+
TextAreaControl.prototype._ul4attrs = new Set([...StringControl.prototype._ul4attrs, "encrypted"]);
|
|
1727
|
+
|
|
547
1728
|
|
|
548
|
-
export class
|
|
1729
|
+
export class HTMLControl extends StringControl
|
|
549
1730
|
{
|
|
1731
|
+
static classdoc = "A LivingApps HTML field (type 'string/html')";
|
|
550
1732
|
};
|
|
551
1733
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
1734
|
+
HTMLControl.prototype.subtype = "html";
|
|
1735
|
+
HTMLControl.prototype.fieldtype = HTMLField;
|
|
1736
|
+
|
|
555
1737
|
|
|
556
|
-
export class DateControl extends
|
|
1738
|
+
export class DateControl extends PlaceholderControl
|
|
557
1739
|
{
|
|
1740
|
+
static classdoc = "A LivingApps date field (type 'date/date')";
|
|
1741
|
+
|
|
1742
|
+
get default()
|
|
1743
|
+
{
|
|
1744
|
+
let view_control = this._view_control();
|
|
1745
|
+
|
|
1746
|
+
if (view_control === null)
|
|
1747
|
+
return null;
|
|
1748
|
+
|
|
1749
|
+
return view_control.default === "{today}" ? ul4.today() : null;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
558
1752
|
formatstring(language)
|
|
559
1753
|
{
|
|
560
1754
|
language = language || this.app.language;
|
|
@@ -592,9 +1786,31 @@ export class DateControl extends Control
|
|
|
592
1786
|
|
|
593
1787
|
DateControl.prototype.type = "date";
|
|
594
1788
|
DateControl.prototype.subtype = "date";
|
|
1789
|
+
DateControl.prototype.fieldtype = DateField;
|
|
1790
|
+
|
|
595
1791
|
|
|
596
1792
|
export class DatetimeMinuteControl extends DateControl
|
|
597
1793
|
{
|
|
1794
|
+
static classdoc = "A LivingApps date field (type 'date/datetimeminute')";
|
|
1795
|
+
|
|
1796
|
+
get default()
|
|
1797
|
+
{
|
|
1798
|
+
let view_control = this._view_control();
|
|
1799
|
+
|
|
1800
|
+
if (view_control === null)
|
|
1801
|
+
return null;
|
|
1802
|
+
|
|
1803
|
+
if (view_control.default === "{today}")
|
|
1804
|
+
{
|
|
1805
|
+
let now = new Date();
|
|
1806
|
+
now.setSeconds(0);
|
|
1807
|
+
now.setMilliseconds(0);
|
|
1808
|
+
return now;
|
|
1809
|
+
}
|
|
1810
|
+
else
|
|
1811
|
+
return null;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
598
1814
|
formatstring(language)
|
|
599
1815
|
{
|
|
600
1816
|
language = language || this.app.language;
|
|
@@ -607,9 +1823,30 @@ export class DatetimeMinuteControl extends DateControl
|
|
|
607
1823
|
};
|
|
608
1824
|
|
|
609
1825
|
DatetimeMinuteControl.prototype.subtype = "datetimeminute";
|
|
1826
|
+
DatetimeMinuteControl.prototype.fieldtype = DatetimeMinuteField;
|
|
1827
|
+
|
|
610
1828
|
|
|
611
1829
|
export class DatetimeSecondControl extends DateControl
|
|
612
1830
|
{
|
|
1831
|
+
static classdoc = "A LivingApps date field (type 'date/datetimesecond')";
|
|
1832
|
+
|
|
1833
|
+
get default()
|
|
1834
|
+
{
|
|
1835
|
+
let view_control = this._view_control();
|
|
1836
|
+
|
|
1837
|
+
if (view_control === null)
|
|
1838
|
+
return null;
|
|
1839
|
+
|
|
1840
|
+
if (view_control.default === "{today}")
|
|
1841
|
+
{
|
|
1842
|
+
let now = new Date();
|
|
1843
|
+
now.setMilliseconds(0);
|
|
1844
|
+
return now;
|
|
1845
|
+
}
|
|
1846
|
+
else
|
|
1847
|
+
return null;
|
|
1848
|
+
}
|
|
1849
|
+
|
|
613
1850
|
formatstring(language)
|
|
614
1851
|
{
|
|
615
1852
|
language = language || this.app.language;
|
|
@@ -622,9 +1859,45 @@ export class DatetimeSecondControl extends DateControl
|
|
|
622
1859
|
};
|
|
623
1860
|
|
|
624
1861
|
DatetimeSecondControl.prototype.subtype = "datetimesecond";
|
|
1862
|
+
DatetimeSecondControl.prototype.fieldtype = DatetimeSecondField;
|
|
1863
|
+
|
|
625
1864
|
|
|
626
1865
|
export class LookupControl extends Control
|
|
627
1866
|
{
|
|
1867
|
+
get default()
|
|
1868
|
+
{
|
|
1869
|
+
let view_control = this._view_control();
|
|
1870
|
+
|
|
1871
|
+
if (view_control === null)
|
|
1872
|
+
return null;
|
|
1873
|
+
|
|
1874
|
+
return this.lookupdata.get(view_control) ?? null;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
get autoexpandable()
|
|
1878
|
+
{
|
|
1879
|
+
let view_control = this._view_control();
|
|
1880
|
+
if (view_control === null)
|
|
1881
|
+
return false;
|
|
1882
|
+
return view_control.autoexpandable;
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
get nonekey()
|
|
1886
|
+
{
|
|
1887
|
+
let view_control = this._view_control();
|
|
1888
|
+
if (view_control === null)
|
|
1889
|
+
return null;
|
|
1890
|
+
return view_control.lookupnonekey;
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
get nonelabel()
|
|
1894
|
+
{
|
|
1895
|
+
let view_control = this._view_control();
|
|
1896
|
+
if (view_control === null)
|
|
1897
|
+
return null;
|
|
1898
|
+
return view_control.lookupnonelabel;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
628
1901
|
// ``search.value`` must be ``null`` or a ``LookupItem`` key
|
|
629
1902
|
search(value, search)
|
|
630
1903
|
{
|
|
@@ -641,27 +1914,38 @@ export class LookupControl extends Control
|
|
|
641
1914
|
};
|
|
642
1915
|
|
|
643
1916
|
LookupControl.prototype.type = "lookup";
|
|
644
|
-
LookupControl.prototype.
|
|
645
|
-
LookupControl.prototype.
|
|
1917
|
+
LookupControl.prototype.fieldtype = LookupField;
|
|
1918
|
+
LookupControl.prototype._ul4onattrs = [...Control.prototype._ul4onattrs, "lookupdata"];
|
|
1919
|
+
LookupControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "lookupdata"]);
|
|
1920
|
+
|
|
646
1921
|
|
|
647
1922
|
export class LookupSelectControl extends LookupControl
|
|
648
1923
|
{
|
|
1924
|
+
static classdoc = "A LivingApps lookup field (type 'lookup/select')";
|
|
1925
|
+
|
|
649
1926
|
};
|
|
650
1927
|
|
|
651
1928
|
LookupSelectControl.prototype.subtype = "select";
|
|
652
1929
|
|
|
1930
|
+
|
|
653
1931
|
export class LookupRadioControl extends LookupControl
|
|
654
1932
|
{
|
|
1933
|
+
static classdoc = "A LivingApps lookup field (type 'lookup/radio')";
|
|
1934
|
+
|
|
655
1935
|
};
|
|
656
1936
|
|
|
657
1937
|
LookupRadioControl.prototype.subtype = "radio";
|
|
658
1938
|
|
|
1939
|
+
|
|
659
1940
|
export class LookupChoiceControl extends LookupControl
|
|
660
1941
|
{
|
|
1942
|
+
static classdoc = "A LivingApps lookup field (type 'lookup/choice')";
|
|
1943
|
+
|
|
661
1944
|
};
|
|
662
1945
|
|
|
663
1946
|
LookupChoiceControl.prototype.subtype = "choice";
|
|
664
1947
|
|
|
1948
|
+
|
|
665
1949
|
export class AppLookupControl extends Control
|
|
666
1950
|
{
|
|
667
1951
|
// ``search.value`` must be an object containing the search criteria for the referenced record
|
|
@@ -675,29 +1959,52 @@ export class AppLookupControl extends Control
|
|
|
675
1959
|
};
|
|
676
1960
|
|
|
677
1961
|
AppLookupControl.prototype.type = "applookup";
|
|
678
|
-
AppLookupControl.prototype.
|
|
679
|
-
AppLookupControl.prototype.
|
|
1962
|
+
AppLookupControl.prototype.fieldtype = AppLookupField;
|
|
1963
|
+
AppLookupControl.prototype._ul4onattrs = [...Control.prototype._ul4onattrs, "lookup_app", "lookup_controls", "local_master_control", "local_detail_controls", "remote_master_control"];
|
|
1964
|
+
AppLookupControl.prototype._ul4attrs = new Set([...Control.prototype._ul4attrs, "lookup_app", "lookup_controls", "local_master_control", "local_detail_controls", "remote_master_control"]);
|
|
1965
|
+
|
|
680
1966
|
|
|
681
1967
|
export class AppLookupSelectControl extends AppLookupControl
|
|
682
1968
|
{
|
|
1969
|
+
static classdoc = "A LivingApps applookup field (type 'applookup/select')";
|
|
1970
|
+
|
|
683
1971
|
};
|
|
684
1972
|
|
|
685
1973
|
AppLookupSelectControl.prototype.subtype = "select";
|
|
686
1974
|
|
|
1975
|
+
|
|
687
1976
|
export class AppLookupRadioControl extends AppLookupControl
|
|
688
1977
|
{
|
|
1978
|
+
static classdoc = "A LivingApps applookup field (type 'applookup/radio')";
|
|
1979
|
+
|
|
689
1980
|
};
|
|
690
1981
|
|
|
691
1982
|
AppLookupRadioControl.prototype.subtype = "radio";
|
|
692
1983
|
|
|
1984
|
+
|
|
693
1985
|
export class AppLookupChoiceControl extends AppLookupControl
|
|
694
1986
|
{
|
|
1987
|
+
static classdoc = "A LivingApps applookup field (type 'applookup/choice')";
|
|
1988
|
+
|
|
695
1989
|
};
|
|
696
1990
|
|
|
697
1991
|
AppLookupChoiceControl.prototype.subtype = "choice";
|
|
698
1992
|
|
|
1993
|
+
|
|
699
1994
|
export class MultipleLookupControl extends LookupControl
|
|
700
1995
|
{
|
|
1996
|
+
get default()
|
|
1997
|
+
{
|
|
1998
|
+
let view_control = this._view_control();
|
|
1999
|
+
|
|
2000
|
+
if (view_control === null)
|
|
2001
|
+
return null;
|
|
2002
|
+
|
|
2003
|
+
let defaultValue = this.lookupdata.get(view_control)
|
|
2004
|
+
|
|
2005
|
+
return (defaultValue !== undefined) ? [defaultValue] : [];
|
|
2006
|
+
}
|
|
2007
|
+
|
|
701
2008
|
// search.value must be ``null`` or a ``LookupItem`` key
|
|
702
2009
|
search(value, search)
|
|
703
2010
|
{
|
|
@@ -716,25 +2023,36 @@ export class MultipleLookupControl extends LookupControl
|
|
|
716
2023
|
};
|
|
717
2024
|
|
|
718
2025
|
MultipleLookupControl.prototype.subtype = "multiplelookup";
|
|
2026
|
+
MultipleLookupControl.prototype.fieldtype = MultipleLookupField;
|
|
2027
|
+
|
|
719
2028
|
|
|
720
2029
|
export class MultipleLookupSelectControl extends MultipleLookupControl
|
|
721
2030
|
{
|
|
2031
|
+
static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/select')";
|
|
2032
|
+
|
|
722
2033
|
};
|
|
723
2034
|
|
|
724
2035
|
MultipleLookupSelectControl.prototype.subtype = "select";
|
|
725
2036
|
|
|
2037
|
+
|
|
726
2038
|
export class MultipleLookupCheckboxControl extends MultipleLookupControl
|
|
727
2039
|
{
|
|
2040
|
+
static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/checkbox')";
|
|
2041
|
+
|
|
728
2042
|
};
|
|
729
2043
|
|
|
730
2044
|
MultipleLookupCheckboxControl.prototype.subtype = "checkbox";
|
|
731
2045
|
|
|
2046
|
+
|
|
732
2047
|
export class MultipleLookupChoiceControl extends MultipleLookupControl
|
|
733
2048
|
{
|
|
2049
|
+
static classdoc = "A LivingApps multiplelookup field (type 'multiplelookup/choice')";
|
|
2050
|
+
|
|
734
2051
|
};
|
|
735
2052
|
|
|
736
2053
|
MultipleLookupChoiceControl.prototype.subtype = "choice";
|
|
737
2054
|
|
|
2055
|
+
|
|
738
2056
|
export class MultipleAppLookupControl extends AppLookupControl
|
|
739
2057
|
{
|
|
740
2058
|
// ``search.value`` must be an object containing the search criteria for the referenced record
|
|
@@ -760,36 +2078,61 @@ export class MultipleAppLookupControl extends AppLookupControl
|
|
|
760
2078
|
};
|
|
761
2079
|
|
|
762
2080
|
MultipleAppLookupControl.prototype.type = "multipleapplookup";
|
|
2081
|
+
MultipleAppLookupControl.prototype.fieldtype = MultipleAppLookupField;
|
|
2082
|
+
|
|
763
2083
|
|
|
764
2084
|
export class MultipleAppLookupSelectControl extends MultipleAppLookupControl
|
|
765
2085
|
{
|
|
2086
|
+
static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/select')";
|
|
2087
|
+
|
|
766
2088
|
};
|
|
767
2089
|
|
|
768
2090
|
MultipleAppLookupSelectControl.prototype.subtype = "select";
|
|
769
2091
|
|
|
2092
|
+
|
|
770
2093
|
export class MultipleAppLookupCheckboxControl extends MultipleAppLookupControl
|
|
771
2094
|
{
|
|
2095
|
+
static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/checkbox')";
|
|
2096
|
+
|
|
772
2097
|
};
|
|
773
2098
|
|
|
774
2099
|
MultipleAppLookupCheckboxControl.prototype.subtype = "checkbox";
|
|
775
2100
|
|
|
2101
|
+
|
|
776
2102
|
export class MultipleAppLookupChoiceControl extends MultipleAppLookupControl
|
|
777
2103
|
{
|
|
2104
|
+
static classdoc = "A LivingApps multiple applookup field (type 'multipleapplookup/choice')";
|
|
778
2105
|
};
|
|
779
2106
|
|
|
780
2107
|
MultipleAppLookupChoiceControl.prototype.subtype = "choice";
|
|
781
2108
|
|
|
2109
|
+
|
|
782
2110
|
export class GeoControl extends Control
|
|
783
2111
|
{
|
|
2112
|
+
static classdoc = "A LivingApps geo field (type 'geo')";
|
|
784
2113
|
};
|
|
785
2114
|
|
|
786
2115
|
GeoControl.prototype.type = "geo";
|
|
2116
|
+
GeoControl.prototype.fieldtype = GeoField;
|
|
2117
|
+
|
|
787
2118
|
|
|
788
2119
|
export class FileControl extends Control
|
|
789
2120
|
{
|
|
2121
|
+
static classdoc = "A LivingApps upload field (type 'file')";
|
|
790
2122
|
};
|
|
791
2123
|
|
|
792
2124
|
FileControl.prototype.type = "file";
|
|
2125
|
+
FileControl.prototype.fieldtype = FileField;
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
export class FileSignatureControl extends FileControl
|
|
2129
|
+
{
|
|
2130
|
+
static classdoc = "A LivingApps signature image field (type 'file/signature')";
|
|
2131
|
+
};
|
|
2132
|
+
|
|
2133
|
+
FileSignatureControl.prototype.subtype = "signature";
|
|
2134
|
+
FileSignatureControl.prototype.fieldtype = FileSignatureField;
|
|
2135
|
+
|
|
793
2136
|
|
|
794
2137
|
export class ButtonControl extends Control
|
|
795
2138
|
{
|
|
@@ -797,165 +2140,237 @@ export class ButtonControl extends Control
|
|
|
797
2140
|
|
|
798
2141
|
ButtonControl.prototype.type = "button";
|
|
799
2142
|
|
|
800
|
-
|
|
2143
|
+
|
|
2144
|
+
export class LookupItem extends Base
|
|
801
2145
|
{
|
|
802
|
-
|
|
2146
|
+
static classdoc = "An option in a lookup control/field";
|
|
2147
|
+
|
|
2148
|
+
get label()
|
|
803
2149
|
{
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
2150
|
+
if (this.control === null)
|
|
2151
|
+
return this._label;
|
|
2152
|
+
let view_lookupitem = this._view_lookupitem();
|
|
2153
|
+
if (view_lookupitem === null)
|
|
2154
|
+
return this._label;
|
|
2155
|
+
let label = view_lookupitem.label;
|
|
2156
|
+
if (label === null)
|
|
2157
|
+
return this._label;
|
|
2158
|
+
return label;
|
|
810
2159
|
}
|
|
811
2160
|
|
|
812
|
-
get
|
|
2161
|
+
get visible()
|
|
813
2162
|
{
|
|
814
|
-
|
|
2163
|
+
if (this.control === null)
|
|
2164
|
+
return true;
|
|
2165
|
+
let view_lookupitem = this._view_lookupitem();
|
|
2166
|
+
if (view_lookupitem === null)
|
|
2167
|
+
return true;
|
|
2168
|
+
return view_lookupitem.visible;
|
|
815
2169
|
}
|
|
816
2170
|
|
|
817
|
-
|
|
2171
|
+
_view_lookupitem()
|
|
818
2172
|
{
|
|
819
|
-
let
|
|
820
|
-
|
|
821
|
-
if (
|
|
2173
|
+
let identifier = this.control.identifier;
|
|
2174
|
+
let active_view = this.control.app.active_view;
|
|
2175
|
+
if (active_view !== null && active_view.controls !== null)
|
|
822
2176
|
{
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
2177
|
+
let view_control = active_view.controls.get(identifier);
|
|
2178
|
+
if (view_control !== undefined && view_control.lookupdata !== undefined && view_control.lookupdata !== null)
|
|
2179
|
+
{
|
|
2180
|
+
let view_lookupitem = view_control.lookupdata.get(this.key);
|
|
2181
|
+
if (view_lookupitem !== undefined)
|
|
2182
|
+
return view_lookupitem;
|
|
2183
|
+
}
|
|
826
2184
|
}
|
|
2185
|
+
return null;
|
|
827
2186
|
}
|
|
828
2187
|
|
|
829
|
-
|
|
2188
|
+
[ul4.symbols.repr]()
|
|
830
2189
|
{
|
|
831
|
-
|
|
2190
|
+
let repr = "<LookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
|
|
2191
|
+
if (!this.visible)
|
|
2192
|
+
repr += "visible=False"
|
|
2193
|
+
return repr + ">";
|
|
832
2194
|
}
|
|
2195
|
+
};
|
|
833
2196
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
return this._dirty;
|
|
837
|
-
}
|
|
2197
|
+
LookupItem.prototype._ul4onattrs = ["control", "key", "_label"];
|
|
2198
|
+
LookupItem.prototype._ul4attrs = new Set(["id", "control", "key", "label"]);
|
|
838
2199
|
|
|
839
|
-
has_errors()
|
|
840
|
-
{
|
|
841
|
-
return this.errors.length !== 0;
|
|
842
|
-
}
|
|
843
2200
|
|
|
844
|
-
|
|
2201
|
+
export class ViewLookupItem extends Base
|
|
2202
|
+
{
|
|
2203
|
+
static classdoc = "View specific information about a lookup item";
|
|
2204
|
+
|
|
2205
|
+
[ul4.symbols.repr]()
|
|
845
2206
|
{
|
|
846
|
-
|
|
2207
|
+
let repr = "<ViewLookupItem key=" + ul4._repr(this.key) + " label=" + ul4._repr(this.label);
|
|
2208
|
+
if (!this.visible)
|
|
2209
|
+
repr += " visible=False"
|
|
2210
|
+
return repr + ">";
|
|
847
2211
|
}
|
|
2212
|
+
};
|
|
2213
|
+
|
|
2214
|
+
ViewLookupItem.prototype._ul4onattrs = ["key", "label", "visible"];
|
|
2215
|
+
ViewLookupItem.prototype._ul4attrs = new Set(["key", "label", "visible"]);
|
|
848
2216
|
|
|
849
|
-
|
|
2217
|
+
|
|
2218
|
+
export class LayoutControl extends Base
|
|
2219
|
+
{
|
|
2220
|
+
static classdoc = "A decoration in an input form";
|
|
2221
|
+
|
|
2222
|
+
[ul4.symbols.repr]()
|
|
850
2223
|
{
|
|
851
|
-
|
|
852
|
-
s += ul4._repr(this.control.identifier)
|
|
853
|
-
if (this._dirty)
|
|
854
|
-
s += " is_dirty()=True";
|
|
855
|
-
if (this.errors.length !== 0)
|
|
856
|
-
s += " has_errors()=True";
|
|
857
|
-
s += ">"
|
|
858
|
-
return s;
|
|
2224
|
+
return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
|
|
859
2225
|
}
|
|
860
2226
|
};
|
|
861
2227
|
|
|
862
|
-
|
|
2228
|
+
LayoutControl.prototype._ul4onattrs = ["label", "identifier", "view", "top", "left", "width", "height"];
|
|
2229
|
+
LayoutControl.prototype._ul4attrs = new Set(["id", "label", "identifier", "view", "top", "left", "width", "height"]);
|
|
2230
|
+
|
|
2231
|
+
|
|
2232
|
+
export class HTMLLayoutControl extends LayoutControl
|
|
2233
|
+
{
|
|
2234
|
+
static classdoc = "An HTML decoration in an input form";
|
|
2235
|
+
};
|
|
2236
|
+
|
|
2237
|
+
HTMLLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "value"];
|
|
2238
|
+
HTMLLayoutControl.prototype._ul4attrs = new Set([LayoutControl.prototype._ul4attrs, "value"]);
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
export class ImageLayoutControl extends LayoutControl
|
|
2242
|
+
{
|
|
2243
|
+
static classdoc = "An image decoration in an input form";
|
|
2244
|
+
};
|
|
2245
|
+
|
|
2246
|
+
ImageLayoutControl.prototype._ul4onattrs = [...LayoutControl.prototype._ul4onattrs, "original", "scaled"];
|
|
2247
|
+
ImageLayoutControl.prototype._ul4attrs = new Set([LayoutControl.prototype._ul4attrs, "original", "scaled"]);
|
|
2248
|
+
|
|
2249
|
+
|
|
2250
|
+
export class ViewControl extends Base
|
|
863
2251
|
{
|
|
864
|
-
|
|
2252
|
+
static classdoc = "Contains view specific information aboutn a control";
|
|
2253
|
+
|
|
2254
|
+
get mode()
|
|
865
2255
|
{
|
|
866
|
-
return
|
|
2256
|
+
return this._mode ? "display" : "edit";
|
|
867
2257
|
}
|
|
868
2258
|
};
|
|
869
2259
|
|
|
870
|
-
|
|
871
|
-
|
|
2260
|
+
ViewControl.prototype._ul4onattrs = ["view", "control", "top", "left", "width", "height", "liveupdate", "default", "tabindex", "minlength", "maxlength", "required", "placeholder", "_mode", "labelpos", "lookupnonekey", "lookupnonelabel", "label", "autoalign", "labelwidth", "lookupdata", "autoexpandable"];
|
|
2261
|
+
ViewControl.prototype._ul4attrs = new Set(["id", "view", "control", "top", "left", "width", "height", "liveupdate", "default", "tabindex", "minlength", "maxlength", "required", "placeholder", "mode", "labelpos", "lookupnonekey", "lookupnonelabel", "label", "autoalign", "labelwidth", "lookupdata", "autoexpandable"]);
|
|
2262
|
+
|
|
872
2263
|
|
|
873
2264
|
export class User extends Base
|
|
874
2265
|
{
|
|
875
|
-
|
|
2266
|
+
static classdoc = "A LivingApps user/account";
|
|
2267
|
+
|
|
2268
|
+
[ul4.symbols.repr]()
|
|
876
2269
|
{
|
|
877
2270
|
return "<User id=" + ul4._repr(this.id) + " firstname=" + ul4._repr(this.firstname) + " surname=" + ul4._repr(this.surname) + " email=" + ul4._repr(this.email) + ">";
|
|
878
2271
|
}
|
|
879
2272
|
};
|
|
880
2273
|
|
|
881
|
-
User.prototype._ul4onattrs = ["_id", "
|
|
882
|
-
User.prototype._ul4attrs =
|
|
2274
|
+
User.prototype._ul4onattrs = ["_id", "gender", "title", "firstname", "surname", "initials", "email", "streetname", "streetnumber", "zip", "city", "phone", "fax", "lang", "avatarsmall", "avatarlarge", "summary", "interests", "personalwebsite", "companywebsite", "company", "position", "department", "keyviews"];
|
|
2275
|
+
User.prototype._ul4attrs = new Set(["id", "_id", "gender", "title", "firstname", "surname", "initials", "email", "streetname", "streetnumber", "zip", "city", "phone", "fax", "lang", "avatarsmall", "avatarlarge", "summary", "interests", "personalwebsite", "companywebsite", "company", "position", "department", "keyviews"]);
|
|
2276
|
+
|
|
883
2277
|
|
|
884
2278
|
export class File extends Base
|
|
885
2279
|
{
|
|
886
|
-
|
|
2280
|
+
static classdoc = "An uploaded file";
|
|
2281
|
+
|
|
2282
|
+
[ul4.symbols.repr]()
|
|
887
2283
|
{
|
|
888
2284
|
return "<File id=" + ul4._repr(this.id) + " url=" + ul4._repr(this.url) + " filename=" + ul4._repr(this.filename) + ">";
|
|
889
2285
|
}
|
|
890
2286
|
};
|
|
891
2287
|
|
|
892
|
-
File.prototype._ul4onattrs = ["
|
|
893
|
-
File.prototype._ul4attrs =
|
|
2288
|
+
File.prototype._ul4onattrs = ["url", "filename", "mimetype", "width", "height", "internalid", "createdat", "size"];
|
|
2289
|
+
File.prototype._ul4attrs = new Set(["id", "url", "filename", "mimetype", "width", "height", "size", "createdat"]);
|
|
2290
|
+
|
|
894
2291
|
|
|
895
2292
|
export class Geo extends Base
|
|
896
2293
|
{
|
|
2294
|
+
static classdoc = "Geographical coordinates and location information";
|
|
2295
|
+
|
|
897
2296
|
constructor(lat, long, info)
|
|
898
2297
|
{
|
|
899
|
-
super();
|
|
2298
|
+
super(null);
|
|
900
2299
|
this.lat = lat;
|
|
901
2300
|
this.long = long;
|
|
902
2301
|
this.info = info;
|
|
903
2302
|
}
|
|
904
2303
|
|
|
905
|
-
|
|
2304
|
+
[ul4.symbols.repr]()
|
|
906
2305
|
{
|
|
907
2306
|
return "<Geo lat=" + ul4._repr(this.lat) + " long=" + ul4._repr(this.long) + " info=" + ul4._repr(this.info) + ">";
|
|
908
2307
|
}
|
|
909
2308
|
};
|
|
910
2309
|
|
|
911
2310
|
Geo.prototype._ul4onattrs = ["lat", "long", "info"];
|
|
912
|
-
Geo.prototype._ul4attrs =
|
|
2311
|
+
Geo.prototype._ul4attrs = new Set(["lat", "long", "info"]);
|
|
2312
|
+
|
|
913
2313
|
|
|
914
2314
|
export class Attachment extends Base
|
|
915
2315
|
{
|
|
916
|
-
|
|
2316
|
+
[ul4.symbols.repr]()
|
|
917
2317
|
{
|
|
918
|
-
return "<" + this.
|
|
2318
|
+
return "<" + this.constructor.name + " id=" + ul4._repr(this.id) + " label=" + ul4._repr(this.label) + ">";
|
|
919
2319
|
}
|
|
920
2320
|
};
|
|
921
2321
|
|
|
922
|
-
Attachment.prototype._ul4onattrs = ["
|
|
923
|
-
Attachment.prototype._ul4attrs =
|
|
2322
|
+
Attachment.prototype._ul4onattrs = ["record", "label", "active"];
|
|
2323
|
+
Attachment.prototype._ul4attrs = new Set(["id", "record", "label", "active"]);
|
|
2324
|
+
|
|
924
2325
|
|
|
925
2326
|
export class NoteAttachment extends Attachment
|
|
926
2327
|
{
|
|
2328
|
+
static classdoc = "A note attachment of a record";
|
|
2329
|
+
|
|
927
2330
|
};
|
|
928
2331
|
|
|
929
2332
|
NoteAttachment.prototype.type = "noteattachment";
|
|
930
|
-
NoteAttachment.prototype._ul4onattrs = Attachment.prototype._ul4onattrs
|
|
931
|
-
NoteAttachment.prototype._ul4attrs =
|
|
2333
|
+
NoteAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "value"];
|
|
2334
|
+
NoteAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
|
|
2335
|
+
|
|
932
2336
|
|
|
933
2337
|
export class URLAttachment extends Attachment
|
|
934
2338
|
{
|
|
2339
|
+
static classdoc = "A URL attachment of a record";
|
|
2340
|
+
|
|
935
2341
|
};
|
|
936
2342
|
|
|
937
2343
|
URLAttachment.prototype.type = "urlattachment";
|
|
938
|
-
URLAttachment.prototype._ul4onattrs = Attachment.prototype._ul4onattrs
|
|
939
|
-
URLAttachment.prototype._ul4attrs =
|
|
2344
|
+
URLAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "value"];
|
|
2345
|
+
URLAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
|
|
2346
|
+
|
|
940
2347
|
|
|
941
2348
|
export class FileAttachment extends Attachment
|
|
942
2349
|
{
|
|
2350
|
+
static classdoc = "A file attachment of a record";
|
|
2351
|
+
|
|
943
2352
|
};
|
|
944
2353
|
|
|
945
2354
|
FileAttachment.prototype.type = "fileattachment";
|
|
946
|
-
FileAttachment.prototype._ul4onattrs = Attachment.prototype._ul4onattrs
|
|
947
|
-
FileAttachment.prototype._ul4attrs =
|
|
2355
|
+
FileAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "value"];
|
|
2356
|
+
FileAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
|
|
2357
|
+
|
|
948
2358
|
|
|
949
2359
|
export class ImageAttachment extends Attachment
|
|
950
2360
|
{
|
|
2361
|
+
static classdoc = "An image attachment of a record";
|
|
2362
|
+
|
|
951
2363
|
};
|
|
952
2364
|
|
|
953
2365
|
ImageAttachment.prototype.type = "imageattachment";
|
|
954
|
-
ImageAttachment.prototype._ul4onattrs = Attachment.prototype._ul4onattrs
|
|
955
|
-
ImageAttachment.prototype._ul4attrs =
|
|
2366
|
+
ImageAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "original", "thumb", "small", "medium","large"];
|
|
2367
|
+
ImageAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "original", "thumb", "small", "medium", "large"]);
|
|
2368
|
+
|
|
956
2369
|
|
|
957
2370
|
export class JSONAttachment extends Attachment
|
|
958
2371
|
{
|
|
2372
|
+
static classdoc = "A JSON attachment of a record";
|
|
2373
|
+
|
|
959
2374
|
_dumpUL4ONAttr(name)
|
|
960
2375
|
{
|
|
961
2376
|
if (name === "value")
|
|
@@ -974,23 +2389,29 @@ export class JSONAttachment extends Attachment
|
|
|
974
2389
|
};
|
|
975
2390
|
|
|
976
2391
|
JSONAttachment.prototype.type = "jsonattachment";
|
|
977
|
-
JSONAttachment.prototype._ul4onattrs = Attachment.prototype._ul4onattrs
|
|
978
|
-
JSONAttachment.prototype._ul4attrs =
|
|
2392
|
+
JSONAttachment.prototype._ul4onattrs = [...Attachment.prototype._ul4onattrs, "value"];
|
|
2393
|
+
JSONAttachment.prototype._ul4attrs = new Set([...Attachment.prototype._ul4onattrs, "value"]);
|
|
2394
|
+
|
|
979
2395
|
|
|
980
2396
|
export class Installation extends Base
|
|
981
2397
|
{
|
|
982
|
-
|
|
2398
|
+
static classdoc = "The installation that created an app";
|
|
2399
|
+
|
|
2400
|
+
[ul4.symbols.repr]()
|
|
983
2401
|
{
|
|
984
2402
|
return "<Installation id=" + ul4._repr(this.id) + " name=" + ul4._repr(this.name) + ">";
|
|
985
2403
|
}
|
|
986
2404
|
};
|
|
987
2405
|
|
|
988
|
-
Installation.prototype._ul4onattrs = ["
|
|
989
|
-
Installation.prototype._ul4attrs =
|
|
2406
|
+
Installation.prototype._ul4onattrs = ["name"];
|
|
2407
|
+
Installation.prototype._ul4attrs = new Set(["id", "name"]);
|
|
2408
|
+
|
|
990
2409
|
|
|
991
2410
|
export class Category extends Base
|
|
992
2411
|
{
|
|
993
|
-
|
|
2412
|
+
static classdoc = "A navigation category";
|
|
2413
|
+
|
|
2414
|
+
[ul4.symbols.repr]()
|
|
994
2415
|
{
|
|
995
2416
|
let v = [];
|
|
996
2417
|
let category = this;
|
|
@@ -1003,30 +2424,37 @@ export class Category extends Base
|
|
|
1003
2424
|
}
|
|
1004
2425
|
};
|
|
1005
2426
|
|
|
1006
|
-
Category.prototype._ul4onattrs = ["
|
|
1007
|
-
Category.prototype._ul4attrs =
|
|
2427
|
+
Category.prototype._ul4onattrs = ["identifier", "name", "order", "parent", "children", "apps"];
|
|
2428
|
+
Category.prototype._ul4attrs = new Set(["id", "identifier", "name", "order", "parent", "children", "apps"]);
|
|
2429
|
+
|
|
1008
2430
|
|
|
1009
2431
|
export class KeyView extends Base
|
|
1010
2432
|
{
|
|
1011
|
-
|
|
2433
|
+
static classdoc = "Object granting access to a view template";
|
|
2434
|
+
|
|
2435
|
+
[ul4.symbols.repr]()
|
|
1012
2436
|
{
|
|
1013
2437
|
return "<KeyView id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
|
|
1014
2438
|
}
|
|
1015
2439
|
};
|
|
1016
2440
|
|
|
1017
|
-
KeyView.prototype._ul4onattrs = ["
|
|
1018
|
-
KeyView.prototype._ul4attrs =
|
|
2441
|
+
KeyView.prototype._ul4onattrs = ["identifier", "name", "key", "user"];
|
|
2442
|
+
KeyView.prototype._ul4attrs = new Set(["id", "identifier", "name", "key", "user"]);
|
|
2443
|
+
|
|
1019
2444
|
|
|
1020
2445
|
export class AppParameter extends Base
|
|
1021
2446
|
{
|
|
1022
|
-
|
|
2447
|
+
static classdoc = "A parameter of a LivingApps application";
|
|
2448
|
+
|
|
2449
|
+
[ul4.symbols.repr]()
|
|
1023
2450
|
{
|
|
1024
2451
|
return "<AppParameter id=" + ul4._repr(this.id) + " identifier=" + ul4._repr(this.identifier) + ">";
|
|
1025
2452
|
}
|
|
1026
2453
|
};
|
|
1027
2454
|
|
|
1028
|
-
AppParameter.prototype._ul4onattrs = ["
|
|
1029
|
-
AppParameter.prototype._ul4attrs =
|
|
2455
|
+
AppParameter.prototype._ul4onattrs = ["app", "identifier", "description", "value"];
|
|
2456
|
+
AppParameter.prototype._ul4attrs = new Set(["id", "app", "identifier", "description", "value"]);
|
|
2457
|
+
|
|
1030
2458
|
|
|
1031
2459
|
let classes = [
|
|
1032
2460
|
Globals,
|
|
@@ -1042,7 +2470,6 @@ let classes = [
|
|
|
1042
2470
|
EmailControl,
|
|
1043
2471
|
URLControl,
|
|
1044
2472
|
TelControl,
|
|
1045
|
-
PasswordControl,
|
|
1046
2473
|
TextAreaControl,
|
|
1047
2474
|
DateControl,
|
|
1048
2475
|
DatetimeMinuteControl,
|
|
@@ -1065,9 +2492,37 @@ let classes = [
|
|
|
1065
2492
|
MultipleAppLookupChoiceControl,
|
|
1066
2493
|
GeoControl,
|
|
1067
2494
|
FileControl,
|
|
2495
|
+
FileSignatureControl,
|
|
1068
2496
|
ButtonControl,
|
|
1069
2497
|
Field,
|
|
2498
|
+
BoolField,
|
|
2499
|
+
StringField,
|
|
2500
|
+
EmailField,
|
|
2501
|
+
URLField,
|
|
2502
|
+
TelField,
|
|
2503
|
+
TextAreaField,
|
|
2504
|
+
HTMLField,
|
|
2505
|
+
IntField,
|
|
2506
|
+
NumberField,
|
|
2507
|
+
GeoField,
|
|
2508
|
+
FileField,
|
|
2509
|
+
FileSignatureField,
|
|
2510
|
+
DateFieldBase,
|
|
2511
|
+
DateField,
|
|
2512
|
+
DatetimeMinuteField,
|
|
2513
|
+
DatetimeSecondField,
|
|
2514
|
+
LookupFieldBase,
|
|
2515
|
+
LookupField,
|
|
2516
|
+
MultipleLookupField,
|
|
2517
|
+
AppLookupFieldBase,
|
|
2518
|
+
AppLookupField,
|
|
2519
|
+
MultipleAppLookupField,
|
|
1070
2520
|
LookupItem,
|
|
2521
|
+
ViewLookupItem,
|
|
2522
|
+
LayoutControl,
|
|
2523
|
+
HTMLLayoutControl,
|
|
2524
|
+
ImageLayoutControl,
|
|
2525
|
+
ViewControl,
|
|
1071
2526
|
User,
|
|
1072
2527
|
File,
|
|
1073
2528
|
Geo,
|