json-object-editor 0.10.425 → 0.10.431
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 +2 -0
- package/capp/capp.css +8 -1
- package/capp/capp.js +12 -5
- package/css/joe-ai.css +174 -0
- package/css/joe-styles.css +25 -1
- package/css/joe.css +25 -7
- package/js/JsonObjectEditor.jquery.craydent.js +28 -9
- package/js/joe-ai copy.js +517 -0
- package/js/joe-ai.js +287 -159
- package/js/joe-full.js +28 -9
- package/js/joe.js +28 -15
- package/package.json +1 -1
- package/pages/template.html +2 -1
- package/readme.md +2 -0
- package/server/app-config.js +2 -2
- package/server/fields/core.js +15 -7
- package/server/init.js +1 -1
- package/server/modules/Apps.js +49 -8
- package/server/modules/Server.js +29 -5
- package/server/modules/Storage.js +3 -0
- package/server/modules/UniversalShorthand.js +1 -2
- package/server/modules/Utils.js +62 -0
- package/server/plugins/chatgpt-assistants.js +359 -0
- package/server/plugins/chatgpt-tools.js +79 -0
- package/server/plugins/plugin-utils.js +46 -0
- package/server/schemas/ai_conversation.js +45 -14
- package/server/schemas/ai_tool.js +94 -0
package/js/joe-full.js
CHANGED
|
@@ -12369,6 +12369,8 @@ Column Count
|
|
|
12369
12369
|
this.Header = {}
|
|
12370
12370
|
this.toggleHelpMenu = function(show,target){
|
|
12371
12371
|
|
|
12372
|
+
}
|
|
12373
|
+
this.listUnsavedChanges = function(){
|
|
12372
12374
|
}
|
|
12373
12375
|
this.Header.Render = this.renderEditorHeader = function(specs){
|
|
12374
12376
|
var BM = new Benchmarker();
|
|
@@ -14531,6 +14533,7 @@ this.renderHTMLContent = function(specs){
|
|
|
14531
14533
|
+fillTemplate(fieldlabel,self.current.object)
|
|
14532
14534
|
+(required && '*' ||'')
|
|
14533
14535
|
+self.renderFieldTooltip(prop)
|
|
14536
|
+
+self.renderFieldReloadIcon(prop)
|
|
14534
14537
|
+'</label>';
|
|
14535
14538
|
|
|
14536
14539
|
//render comment
|
|
@@ -14623,7 +14626,15 @@ this.renderHTMLContent = function(specs){
|
|
|
14623
14626
|
|
|
14624
14627
|
return tooltip_html;
|
|
14625
14628
|
};
|
|
14629
|
+
this.renderFieldReloadIcon = function(prop){
|
|
14630
|
+
var reloadable = self.propAsFuncOrValue(prop.reloadable);
|
|
14631
|
+
if(!reloadable){return '';}
|
|
14632
|
+
//var comment = ($.type(prop.comment) == "function")?prop.comment():prop.comment;
|
|
14633
|
+
var comment_html = ` <joe-icon class="joe-reload-icon fright" title="Reload Field" onclick="_joe.Fields.rerender('${prop.name}')">⟳</joe-icon>`;
|
|
14626
14634
|
|
|
14635
|
+
return comment_html;
|
|
14636
|
+
};
|
|
14637
|
+
|
|
14627
14638
|
this.selectAndRenderFieldType = function(prop){
|
|
14628
14639
|
//var joeFieldBenchmarker = new Benchmarker();
|
|
14629
14640
|
|
|
@@ -15856,7 +15867,8 @@ this.renderHTMLContent = function(specs){
|
|
|
15856
15867
|
stripecolor:false,
|
|
15857
15868
|
bgcolor:false,
|
|
15858
15869
|
checkbox:false,
|
|
15859
|
-
value:''
|
|
15870
|
+
value:'',
|
|
15871
|
+
link:false
|
|
15860
15872
|
},specs);
|
|
15861
15873
|
var schemaprop = specs.schemaprop && self.propAsFuncOrValue(specs.schemaprop,item);
|
|
15862
15874
|
var schema = ((schemaprop && item[schemaprop])||schema||item.itemtype||item.type);
|
|
@@ -15867,7 +15879,7 @@ this.renderHTMLContent = function(specs){
|
|
|
15867
15879
|
|
|
15868
15880
|
var idprop = specs.idprop || (schemaobj && schemaobj.idprop) ||'_id';
|
|
15869
15881
|
var hasMenu = specs.itemMenu && specs.itemMenu.length;
|
|
15870
|
-
var action = specs.action || ' onclick="goJoe(_joe.search(\'${'+idprop+'}\')[0],{schema:\''+schema+'\'})" ';
|
|
15882
|
+
var action = self.propAsFuncOrValue(specs.action,item) || ' onclick="goJoe(_joe.search(\'${'+idprop+'}\')[0],{schema:\''+schema+'\'})" ';
|
|
15871
15883
|
var nonclickable = self.propAsFuncOrValue(specs.nonclickable,item);
|
|
15872
15884
|
var clickablelistitem = (!specs.gotoButton && !nonclickable/* && !hasMenu*/);
|
|
15873
15885
|
//var clickablelistitem = !!clickable && (!specs.gotoButton && !hasMenu);
|
|
@@ -15882,6 +15894,7 @@ this.renderHTMLContent = function(specs){
|
|
|
15882
15894
|
'data-value="' +encodeURI(JSON.stringify(specs.value))+ '" data-isObject=true'
|
|
15883
15895
|
:'data-value="' + specs.value + '"';
|
|
15884
15896
|
|
|
15897
|
+
var link = specs.link && self.propAsFuncOrValue(specs.link,item);
|
|
15885
15898
|
var html = fillTemplate(`<joe-list-item schema="${schema}"
|
|
15886
15899
|
itemId="${item[idprop]}"
|
|
15887
15900
|
idprop="${idprop}"
|
|
@@ -15904,13 +15917,13 @@ this.renderHTMLContent = function(specs){
|
|
|
15904
15917
|
|
|
15905
15918
|
+ self.Render.itemCheckbox(item,schemaobj)
|
|
15906
15919
|
|
|
15907
|
-
+((
|
|
15920
|
+
+((link && '<a class="non-link" onclick="__cancelClick();" href="'+link+'">')||'')
|
|
15908
15921
|
|
|
15909
15922
|
+ '<div class="joe-field-item-content '+(nonclickable && 'nonclickable' || '')+'" ' + click + ' >'
|
|
15910
15923
|
+ self.propAsFuncOrValue(contentTemplate+__clearDiv__, item)
|
|
15911
15924
|
+ __clearDiv__+'</div>'
|
|
15912
15925
|
|
|
15913
|
-
+((
|
|
15926
|
+
+((link && '</a>')||'')
|
|
15914
15927
|
+self.Render.stripeColor(item,specs.stripecolor)
|
|
15915
15928
|
+ self._renderExpanderButton(expanderContent, item)
|
|
15916
15929
|
+ (specs.deleteButton && deleteButton || '')
|
|
@@ -18685,6 +18698,7 @@ Field Rendering Helpers
|
|
|
18685
18698
|
var sortable_index;
|
|
18686
18699
|
this.Autosave = {
|
|
18687
18700
|
possibleChanges:true,
|
|
18701
|
+
unsavedChanges:false,
|
|
18688
18702
|
activate:function(){
|
|
18689
18703
|
if(!self.specs.autosave){
|
|
18690
18704
|
return;
|
|
@@ -18714,7 +18728,8 @@ Field Rendering Helpers
|
|
|
18714
18728
|
var showUnsaved = (hasChanged && self.getMode() == "details");
|
|
18715
18729
|
document.title =( showUnsaved && '*' ||'')
|
|
18716
18730
|
+document.title.replace('*','');
|
|
18717
|
-
self.overlay.toggleClass('unsaved-changes',showUnsaved)
|
|
18731
|
+
self.overlay.toggleClass('unsaved-changes',showUnsaved);
|
|
18732
|
+
self.Autosave.unsavedChanges = hasChanged;
|
|
18718
18733
|
},intercnt)
|
|
18719
18734
|
},
|
|
18720
18735
|
deactivate:function(){
|
|
@@ -18946,7 +18961,7 @@ Field Rendering Helpers
|
|
|
18946
18961
|
tocheck.map(field=>{
|
|
18947
18962
|
|
|
18948
18963
|
})
|
|
18949
|
-
return (tocheck.length > 0);
|
|
18964
|
+
return (tocheck.length > 0)?tocheck:false;
|
|
18950
18965
|
}
|
|
18951
18966
|
if(self.overlay.hasClass('active') && !listMode && !self.current.changesConfirmed && tocheck.length){
|
|
18952
18967
|
|
|
@@ -18954,7 +18969,7 @@ Field Rendering Helpers
|
|
|
18954
18969
|
self.current.changesConfirmed = confirmed;
|
|
18955
18970
|
return confirmed;
|
|
18956
18971
|
}
|
|
18957
|
-
return
|
|
18972
|
+
return tocheck;
|
|
18958
18973
|
}
|
|
18959
18974
|
/*-------------------------------------------------------------------->
|
|
18960
18975
|
J | MESSAGING
|
|
@@ -19585,7 +19600,10 @@ Field Rendering Helpers
|
|
|
19585
19600
|
|
|
19586
19601
|
for (const [field, val] of Object.entries(object)) {
|
|
19587
19602
|
if (val === undefined || val === null) continue;
|
|
19588
|
-
if (field == '_id')
|
|
19603
|
+
if (field == '_id'){
|
|
19604
|
+
flattened[field] = val;
|
|
19605
|
+
continue;
|
|
19606
|
+
}
|
|
19589
19607
|
|
|
19590
19608
|
if (typeof val === 'string' && $c.isCuid(val) && recursive && depth > 0) {
|
|
19591
19609
|
if (!visited.has(val)) {
|
|
@@ -21162,7 +21180,7 @@ logit(intent)
|
|
|
21162
21180
|
var users = _joe.Data[(user_dataset || 'user')].where({_id:{$in:ids}});
|
|
21163
21181
|
var html = '';
|
|
21164
21182
|
users.map(function(user){
|
|
21165
|
-
html += self.SERVER.User.Render.cube(user);
|
|
21183
|
+
html += self.SERVER.User.Render.cube(user,cssclass);
|
|
21166
21184
|
})
|
|
21167
21185
|
return html;
|
|
21168
21186
|
},
|
|
@@ -21683,6 +21701,7 @@ logit(intent)
|
|
|
21683
21701
|
var e = e || window.event;
|
|
21684
21702
|
if (e.stopPropagation) e.stopPropagation();
|
|
21685
21703
|
if (e.preventDefault) e.preventDefault();
|
|
21704
|
+
return false;
|
|
21686
21705
|
},
|
|
21687
21706
|
getPossibleValues:function(propertyName,schema,specs){
|
|
21688
21707
|
//TODO:
|
package/js/joe.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/* --------------------------------------------------------
|
|
2
|
-
*
|
|
3
|
-
* JOE - v1.5.0
|
|
4
|
-
* Created by: Corey Hadden
|
|
5
|
-
*
|
|
6
|
-
* -------------------------------------------------------- */
|
|
7
1
|
/* --------------------------------------------------------
|
|
8
2
|
*
|
|
9
3
|
* JOE - v1.5.0
|
|
@@ -1076,6 +1070,8 @@ Column Count
|
|
|
1076
1070
|
this.Header = {}
|
|
1077
1071
|
this.toggleHelpMenu = function(show,target){
|
|
1078
1072
|
|
|
1073
|
+
}
|
|
1074
|
+
this.listUnsavedChanges = function(){
|
|
1079
1075
|
}
|
|
1080
1076
|
this.Header.Render = this.renderEditorHeader = function(specs){
|
|
1081
1077
|
var BM = new Benchmarker();
|
|
@@ -3238,6 +3234,7 @@ this.renderHTMLContent = function(specs){
|
|
|
3238
3234
|
+fillTemplate(fieldlabel,self.current.object)
|
|
3239
3235
|
+(required && '*' ||'')
|
|
3240
3236
|
+self.renderFieldTooltip(prop)
|
|
3237
|
+
+self.renderFieldReloadIcon(prop)
|
|
3241
3238
|
+'</label>';
|
|
3242
3239
|
|
|
3243
3240
|
//render comment
|
|
@@ -3330,7 +3327,15 @@ this.renderHTMLContent = function(specs){
|
|
|
3330
3327
|
|
|
3331
3328
|
return tooltip_html;
|
|
3332
3329
|
};
|
|
3330
|
+
this.renderFieldReloadIcon = function(prop){
|
|
3331
|
+
var reloadable = self.propAsFuncOrValue(prop.reloadable);
|
|
3332
|
+
if(!reloadable){return '';}
|
|
3333
|
+
//var comment = ($.type(prop.comment) == "function")?prop.comment():prop.comment;
|
|
3334
|
+
var comment_html = ` <joe-icon class="joe-reload-icon fright" title="Reload Field" onclick="_joe.Fields.rerender('${prop.name}')">⟳</joe-icon>`;
|
|
3333
3335
|
|
|
3336
|
+
return comment_html;
|
|
3337
|
+
};
|
|
3338
|
+
|
|
3334
3339
|
this.selectAndRenderFieldType = function(prop){
|
|
3335
3340
|
//var joeFieldBenchmarker = new Benchmarker();
|
|
3336
3341
|
|
|
@@ -4563,7 +4568,8 @@ this.renderHTMLContent = function(specs){
|
|
|
4563
4568
|
stripecolor:false,
|
|
4564
4569
|
bgcolor:false,
|
|
4565
4570
|
checkbox:false,
|
|
4566
|
-
value:''
|
|
4571
|
+
value:'',
|
|
4572
|
+
link:false
|
|
4567
4573
|
},specs);
|
|
4568
4574
|
var schemaprop = specs.schemaprop && self.propAsFuncOrValue(specs.schemaprop,item);
|
|
4569
4575
|
var schema = ((schemaprop && item[schemaprop])||schema||item.itemtype||item.type);
|
|
@@ -4574,7 +4580,7 @@ this.renderHTMLContent = function(specs){
|
|
|
4574
4580
|
|
|
4575
4581
|
var idprop = specs.idprop || (schemaobj && schemaobj.idprop) ||'_id';
|
|
4576
4582
|
var hasMenu = specs.itemMenu && specs.itemMenu.length;
|
|
4577
|
-
var action = specs.action || ' onclick="goJoe(_joe.search(\'${'+idprop+'}\')[0],{schema:\''+schema+'\'})" ';
|
|
4583
|
+
var action = self.propAsFuncOrValue(specs.action,item) || ' onclick="goJoe(_joe.search(\'${'+idprop+'}\')[0],{schema:\''+schema+'\'})" ';
|
|
4578
4584
|
var nonclickable = self.propAsFuncOrValue(specs.nonclickable,item);
|
|
4579
4585
|
var clickablelistitem = (!specs.gotoButton && !nonclickable/* && !hasMenu*/);
|
|
4580
4586
|
//var clickablelistitem = !!clickable && (!specs.gotoButton && !hasMenu);
|
|
@@ -4589,6 +4595,7 @@ this.renderHTMLContent = function(specs){
|
|
|
4589
4595
|
'data-value="' +encodeURI(JSON.stringify(specs.value))+ '" data-isObject=true'
|
|
4590
4596
|
:'data-value="' + specs.value + '"';
|
|
4591
4597
|
|
|
4598
|
+
var link = specs.link && self.propAsFuncOrValue(specs.link,item);
|
|
4592
4599
|
var html = fillTemplate(`<joe-list-item schema="${schema}"
|
|
4593
4600
|
itemId="${item[idprop]}"
|
|
4594
4601
|
idprop="${idprop}"
|
|
@@ -4611,13 +4618,13 @@ this.renderHTMLContent = function(specs){
|
|
|
4611
4618
|
|
|
4612
4619
|
+ self.Render.itemCheckbox(item,schemaobj)
|
|
4613
4620
|
|
|
4614
|
-
+((
|
|
4621
|
+
+((link && '<a class="non-link" onclick="__cancelClick();" href="'+link+'">')||'')
|
|
4615
4622
|
|
|
4616
4623
|
+ '<div class="joe-field-item-content '+(nonclickable && 'nonclickable' || '')+'" ' + click + ' >'
|
|
4617
4624
|
+ self.propAsFuncOrValue(contentTemplate+__clearDiv__, item)
|
|
4618
4625
|
+ __clearDiv__+'</div>'
|
|
4619
4626
|
|
|
4620
|
-
+((
|
|
4627
|
+
+((link && '</a>')||'')
|
|
4621
4628
|
+self.Render.stripeColor(item,specs.stripecolor)
|
|
4622
4629
|
+ self._renderExpanderButton(expanderContent, item)
|
|
4623
4630
|
+ (specs.deleteButton && deleteButton || '')
|
|
@@ -7392,6 +7399,7 @@ Field Rendering Helpers
|
|
|
7392
7399
|
var sortable_index;
|
|
7393
7400
|
this.Autosave = {
|
|
7394
7401
|
possibleChanges:true,
|
|
7402
|
+
unsavedChanges:false,
|
|
7395
7403
|
activate:function(){
|
|
7396
7404
|
if(!self.specs.autosave){
|
|
7397
7405
|
return;
|
|
@@ -7421,7 +7429,8 @@ Field Rendering Helpers
|
|
|
7421
7429
|
var showUnsaved = (hasChanged && self.getMode() == "details");
|
|
7422
7430
|
document.title =( showUnsaved && '*' ||'')
|
|
7423
7431
|
+document.title.replace('*','');
|
|
7424
|
-
self.overlay.toggleClass('unsaved-changes',showUnsaved)
|
|
7432
|
+
self.overlay.toggleClass('unsaved-changes',showUnsaved);
|
|
7433
|
+
self.Autosave.unsavedChanges = hasChanged;
|
|
7425
7434
|
},intercnt)
|
|
7426
7435
|
},
|
|
7427
7436
|
deactivate:function(){
|
|
@@ -7653,7 +7662,7 @@ Field Rendering Helpers
|
|
|
7653
7662
|
tocheck.map(field=>{
|
|
7654
7663
|
|
|
7655
7664
|
})
|
|
7656
|
-
return (tocheck.length > 0);
|
|
7665
|
+
return (tocheck.length > 0)?tocheck:false;
|
|
7657
7666
|
}
|
|
7658
7667
|
if(self.overlay.hasClass('active') && !listMode && !self.current.changesConfirmed && tocheck.length){
|
|
7659
7668
|
|
|
@@ -7661,7 +7670,7 @@ Field Rendering Helpers
|
|
|
7661
7670
|
self.current.changesConfirmed = confirmed;
|
|
7662
7671
|
return confirmed;
|
|
7663
7672
|
}
|
|
7664
|
-
return
|
|
7673
|
+
return tocheck;
|
|
7665
7674
|
}
|
|
7666
7675
|
/*-------------------------------------------------------------------->
|
|
7667
7676
|
J | MESSAGING
|
|
@@ -8292,7 +8301,10 @@ Field Rendering Helpers
|
|
|
8292
8301
|
|
|
8293
8302
|
for (const [field, val] of Object.entries(object)) {
|
|
8294
8303
|
if (val === undefined || val === null) continue;
|
|
8295
|
-
if (field == '_id')
|
|
8304
|
+
if (field == '_id'){
|
|
8305
|
+
flattened[field] = val;
|
|
8306
|
+
continue;
|
|
8307
|
+
}
|
|
8296
8308
|
|
|
8297
8309
|
if (typeof val === 'string' && $c.isCuid(val) && recursive && depth > 0) {
|
|
8298
8310
|
if (!visited.has(val)) {
|
|
@@ -9869,7 +9881,7 @@ logit(intent)
|
|
|
9869
9881
|
var users = _joe.Data[(user_dataset || 'user')].where({_id:{$in:ids}});
|
|
9870
9882
|
var html = '';
|
|
9871
9883
|
users.map(function(user){
|
|
9872
|
-
html += self.SERVER.User.Render.cube(user);
|
|
9884
|
+
html += self.SERVER.User.Render.cube(user,cssclass);
|
|
9873
9885
|
})
|
|
9874
9886
|
return html;
|
|
9875
9887
|
},
|
|
@@ -10390,6 +10402,7 @@ logit(intent)
|
|
|
10390
10402
|
var e = e || window.event;
|
|
10391
10403
|
if (e.stopPropagation) e.stopPropagation();
|
|
10392
10404
|
if (e.preventDefault) e.preventDefault();
|
|
10405
|
+
return false;
|
|
10393
10406
|
},
|
|
10394
10407
|
getPossibleValues:function(propertyName,schema,specs){
|
|
10395
10408
|
//TODO:
|
package/package.json
CHANGED
package/pages/template.html
CHANGED
|
@@ -311,8 +311,9 @@
|
|
|
311
311
|
JOE.init();
|
|
312
312
|
//capp.init();
|
|
313
313
|
var capp_apps = '${USERAPPS}'.split(',') || [];
|
|
314
|
+
var caobj = ${USERAPPSOBJ};
|
|
314
315
|
var all_apps = '${APPS}'.split(',') || [];
|
|
315
|
-
capp.Menu.addFromApps(
|
|
316
|
+
capp.Menu.addFromApps(caobj,'<joe-subtext>${this.webconfig.name}</joe-subtext>${APPNAME}');
|
|
316
317
|
//capp.Button.add('Docs',null,'window.open(\'/JsonObjectEditor/docs.html\')','capp-header');
|
|
317
318
|
|
|
318
319
|
|
package/readme.md
CHANGED
|
@@ -198,11 +198,13 @@ a list of schema objects that can configure the editor fields, these can be give
|
|
|
198
198
|
alert(obj.name);
|
|
199
199
|
},*/
|
|
200
200
|
onblur:logit,
|
|
201
|
+
|
|
201
202
|
hideNumbers:boolean *toggle list numbers*
|
|
202
203
|
multipleCallback:function to be called after a multi-edit. passed list of edited items.
|
|
203
204
|
onUpdate: callback for after update. passed single edited items.
|
|
204
205
|
onMultipleUpdate:callback for after multi update.passed list of edited items.
|
|
205
206
|
filters: array of objects
|
|
207
|
+
checkChanges:(bool) whether or not to check for changes via interval and on leave
|
|
206
208
|
}
|
|
207
209
|
##Table View
|
|
208
210
|
- add tableView object to a schema;
|
package/server/app-config.js
CHANGED
|
@@ -28,10 +28,10 @@ var apps = function(){
|
|
|
28
28
|
var default_schemas = JOE.webconfig.default_schemas;
|
|
29
29
|
return{
|
|
30
30
|
joe:{
|
|
31
|
-
title:'Platform',
|
|
31
|
+
title:'JOE Platform',
|
|
32
32
|
info:'This is the master Data Model Management System (DMMS) admin page. It has access to all of your schemas and datasets.',
|
|
33
33
|
description:'JOE is the Json Object Editor. The Platform app has access to all your schemas and datasets.',
|
|
34
|
-
plugins:['auth.js','formBuilder.js','reportbuilder.js','callbackTester.js','memberRegistry.js','awsConnect.js','notifier.js','calendar.js','inventory.js','money.js'],
|
|
34
|
+
plugins:['auth.js','formBuilder.js','reportbuilder.js','callbackTester.js','memberRegistry.js','awsConnect.js','notifier.js','calendar.js','inventory.js','money.js','plugin-utils.js','chatgpt.js','chatgpt-assistants.js','chatgpt-tools.js'],
|
|
35
35
|
collections:((default_schemas.concat(['schema','group',
|
|
36
36
|
'site','page','post','layout','block','include','event',
|
|
37
37
|
'project','board','task',
|
package/server/fields/core.js
CHANGED
|
@@ -68,15 +68,15 @@ var fields = {
|
|
|
68
68
|
'coords':{type:'geo'},
|
|
69
69
|
'state':{type:'select',values:usStates,idprop:'code',template:'${code}',width:'25%',minwidth:'100px',blank:true},
|
|
70
70
|
'name':{type:'text',onblur:'_joe.TITLE.set()'},
|
|
71
|
-
instructions_format:{type:'select',values:['wysiwyg','code'], rerender:'instructions',display:'Instructions Format'},
|
|
71
|
+
instructions_format:{type:'select',values:['wysiwyg','code','text',], rerender:'instructions',display:'Instructions Format'},
|
|
72
72
|
instructions:{
|
|
73
|
-
height:'
|
|
73
|
+
height:'600px',
|
|
74
74
|
display:'Instructions',
|
|
75
75
|
type:function(item){
|
|
76
|
-
if(!item.instructions_format){
|
|
77
|
-
return '
|
|
76
|
+
if(!item.instructions_format || item.instructions_format == 'text'){
|
|
77
|
+
return 'rendering';
|
|
78
78
|
}
|
|
79
|
-
if(["code"].indexOf(item.instructions_format) != -1){
|
|
79
|
+
else if(["code"].indexOf(item.instructions_format) != -1){
|
|
80
80
|
return 'code';
|
|
81
81
|
}
|
|
82
82
|
return item.instructions_format;
|
|
@@ -86,8 +86,16 @@ var fields = {
|
|
|
86
86
|
type: "select",
|
|
87
87
|
display: "Ai Model",
|
|
88
88
|
values: [
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
{ value: "gpt-4o", name: "GPT-4o (Fast, 128k)" },
|
|
90
|
+
{ value: "gpt-4.1", name: "GPT-4.1 (Strong, 1M)" },
|
|
91
|
+
{ value: "gpt-4.1-mini", name: "4.1-mini (Cheap, 1M)" },
|
|
92
|
+
{ value: "gpt-4.1-nano", name: "4.1-nano (Fastest, light tasks)" }
|
|
93
|
+
],
|
|
94
|
+
tooltip:`Ai Model Guide -
|
|
95
|
+
GPT-4o is the default for fast, responsive tasks and supports up to 128k tokens. It’s ideal for short completions, summaries, and dynamic UI tools.
|
|
96
|
+
GPT-4.1 and 4.1-mini support a massive 1 million token context, making them perfect for large inputs like full business profiles, long strategy texts, and multi-object analysis.
|
|
97
|
+
4.1-mini is significantly cheaper than full 4.1, with great balance for most structured AI workflows.
|
|
98
|
+
4.1-nano is best for lightweight classification or routing logic where speed and cost matter more than depth.`,
|
|
91
99
|
default: "gpt-4o",
|
|
92
100
|
},
|
|
93
101
|
template:{
|
package/server/init.js
CHANGED
package/server/modules/Apps.js
CHANGED
|
@@ -495,16 +495,54 @@ function Apps(){
|
|
|
495
495
|
return app;
|
|
496
496
|
}
|
|
497
497
|
this.loadPlugin = function(p){
|
|
498
|
-
logit(moduleName+'loading plugin '+p);
|
|
498
|
+
//logit(moduleName+'loading plugin '+p);
|
|
499
|
+
let _joeSrc='';
|
|
500
|
+
console.log(JOE.Utils.color('[plugin]', 'plugin'), 'loaded: '+p);
|
|
499
501
|
var plugin;
|
|
500
502
|
if(p.indexOf('.js') == -1){p+= '.js';}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
503
|
+
|
|
504
|
+
const candidateDirs = [
|
|
505
|
+
pluginsDir,
|
|
506
|
+
internalPluginsDir
|
|
507
|
+
];
|
|
508
|
+
let pluginpath = null;
|
|
509
|
+
let override = false;
|
|
510
|
+
//for (let dir of candidateDirs) {
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
try {
|
|
514
|
+
let attempt = internalPluginsDir + p;
|
|
515
|
+
fs.accessSync(attempt, fs.F_OK);
|
|
516
|
+
pluginpath = attempt;
|
|
504
517
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
518
|
+
|
|
519
|
+
} catch (e) {
|
|
520
|
+
// continue
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
let attempt = pluginsDir + p;
|
|
524
|
+
fs.accessSync(attempt, fs.F_OK);
|
|
525
|
+
if(pluginpath){
|
|
526
|
+
override = true;
|
|
527
|
+
}
|
|
528
|
+
pluginpath = attempt;
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
} catch (e) {
|
|
532
|
+
|
|
533
|
+
// continue
|
|
534
|
+
}
|
|
535
|
+
// }
|
|
536
|
+
// try{
|
|
537
|
+
// //first try the pluginsDir, then the internalPluginsDir
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
// var pluginpath = internalPluginsDir + p;
|
|
541
|
+
// fs.accessSync(pluginpath, fs.F_OK);
|
|
542
|
+
|
|
543
|
+
// }catch(e){
|
|
544
|
+
// var pluginpath = pluginsDir + p;
|
|
545
|
+
// }
|
|
508
546
|
try{
|
|
509
547
|
try{
|
|
510
548
|
delete require.cache[require.resolve(pluginpath)];
|
|
@@ -512,12 +550,15 @@ function Apps(){
|
|
|
512
550
|
console.log(moduleName+'[error] '+p+' not deleted');
|
|
513
551
|
}
|
|
514
552
|
plugin = require(pluginpath);
|
|
515
|
-
|
|
553
|
+
_joeSrc = pluginpath;
|
|
516
554
|
}catch(e){
|
|
517
555
|
plugin = {error:'plugin '+p+' not found'};
|
|
518
556
|
console.log(e,plugin);
|
|
519
557
|
}
|
|
558
|
+
plugin._pathname = _joeSrc;
|
|
559
|
+
plugin._override = override;
|
|
520
560
|
self.plugins[p.replace('.js','')] = plugin;
|
|
561
|
+
|
|
521
562
|
return plugin;
|
|
522
563
|
}
|
|
523
564
|
|
package/server/modules/Server.js
CHANGED
|
@@ -16,6 +16,9 @@ var os = require('os');
|
|
|
16
16
|
const $J = require('./UniversalShorthand');
|
|
17
17
|
var rd = require('renderizer')({templatesDir:path.resolve(JOE.joedir,JOE.webconfig.templatesDir)});
|
|
18
18
|
|
|
19
|
+
function coloredLog(message) {
|
|
20
|
+
console.log(JOE.Utils.color('[server]', 'module'), message);
|
|
21
|
+
}
|
|
19
22
|
var authBool = JOE.isAuthorized = function(req,res){
|
|
20
23
|
var users = (JOE.Data && JOE.Data.user) || [];
|
|
21
24
|
|
|
@@ -140,7 +143,23 @@ server.get(['/API/user/:method'],auth,function(req,res,next){
|
|
|
140
143
|
res.jsonp({logout:true});
|
|
141
144
|
return next();
|
|
142
145
|
break;
|
|
143
|
-
|
|
146
|
+
case 'apps':
|
|
147
|
+
logit('getting apps for '+req.User.name);
|
|
148
|
+
userApps = [];
|
|
149
|
+
if (req.User.apps && req.User.apps.length) {
|
|
150
|
+
req.User.apps.map(function (app) {
|
|
151
|
+
if (JOE.Apps.cache[app]) {
|
|
152
|
+
userApps.push({
|
|
153
|
+
name: app,
|
|
154
|
+
title: JOE.Apps.cache[app].title,
|
|
155
|
+
description: JOE.Apps.cache[app].description
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
res.jsonp({userApps});
|
|
161
|
+
return;//return next();
|
|
162
|
+
break;
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
165
|
|
|
@@ -711,12 +730,17 @@ server.get(['/JOE/','/JOE/:appname'],auth,function(req,res,next){
|
|
|
711
730
|
}
|
|
712
731
|
|
|
713
732
|
//var collections = [];
|
|
714
|
-
|
|
733
|
+
let uappsObj = [];
|
|
734
|
+
USER.apps.map(a=>{
|
|
735
|
+
let aa = Apps[a]||{};
|
|
736
|
+
uappsObj.push({name:a,title:aa.title,description:aa.description});
|
|
737
|
+
});
|
|
715
738
|
var payload = {
|
|
716
739
|
APPNAME:currentApp.title || appname,
|
|
717
740
|
APPINFO:JSON.stringify(stringFunctions(currentApp)),
|
|
718
741
|
APPS:apps.join(','),
|
|
719
742
|
USERAPPS:(USER.apps||apps||[]).join(','),
|
|
743
|
+
USERAPPSOBJ:JSON.stringify(uappsObj),
|
|
720
744
|
webconfig:JOE.webconfig,
|
|
721
745
|
settings:settings,
|
|
722
746
|
JOEPATH:JOE.webconfig.joepath,
|
|
@@ -761,21 +785,21 @@ server.get(['/RENDER/:contentType/:templateName'],function(req,res){
|
|
|
761
785
|
|
|
762
786
|
JOE.webDir = webDir = JOE.appDir+'/'+JOE.webconfig.webDir+'/';
|
|
763
787
|
JOE.Utils.setupFileFolder(webDir,'web');
|
|
764
|
-
|
|
788
|
+
coloredLog('listening on '+JOE.webconfig.port);
|
|
765
789
|
|
|
766
790
|
|
|
767
791
|
server.use('/',express.static(JOE.webDir));
|
|
768
792
|
|
|
769
793
|
http.listen(JOE.webconfig.port,function(){
|
|
770
794
|
//console.log('joe listening on '+JOE.webconfig.port);
|
|
771
|
-
|
|
795
|
+
coloredLog('using webDir: '+JOE.webDir);
|
|
772
796
|
});
|
|
773
797
|
JOE.httpServer = http;
|
|
774
798
|
var httpsPort = JOE.webconfig.httpsPort;
|
|
775
799
|
if(httpsPort){
|
|
776
800
|
var httpsServer = https.Server({key: JOE.Pem.serviceKey, cert: JOE.Pem.certificate}, server);
|
|
777
801
|
httpsServer.listen(httpsPort);
|
|
778
|
-
|
|
802
|
+
coloredLog(' https on '+httpsPort);
|
|
779
803
|
JOE.httpsServer = httpsServer;
|
|
780
804
|
// pem.createCertificate({selfSigned:true}, function(err, keys){
|
|
781
805
|
// if(err){
|
|
@@ -102,6 +102,9 @@ function Storage(specs){
|
|
|
102
102
|
|
|
103
103
|
var save_callback = function(err,data){
|
|
104
104
|
callback(err,data);
|
|
105
|
+
if (!specs || specs.push !== false) {
|
|
106
|
+
JOE.io.emit('item_updated', { results: [data] });
|
|
107
|
+
}
|
|
105
108
|
if(!err){
|
|
106
109
|
var ts = new Date().toISOString();
|
|
107
110
|
var cached = JOE.Cache.findByID(data.itemtype,data._id);
|
package/server/modules/Utils.js
CHANGED
|
@@ -174,6 +174,68 @@ var utils = function(){
|
|
|
174
174
|
}
|
|
175
175
|
return finalItems;
|
|
176
176
|
}
|
|
177
|
+
this.flattenObject = function(id, options = {}) {
|
|
178
|
+
const { recursive = true, depth = 1, visited = new Set() } = options;
|
|
179
|
+
|
|
180
|
+
let object = null;
|
|
181
|
+
|
|
182
|
+
if (id) {
|
|
183
|
+
object = $J.get(id);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (!object) return null;
|
|
187
|
+
|
|
188
|
+
const flattened = {};
|
|
189
|
+
const currentId = object._id || object.id;
|
|
190
|
+
if (currentId) visited.add(currentId);
|
|
191
|
+
|
|
192
|
+
for (const [field, val] of Object.entries(object)) {
|
|
193
|
+
if (val === undefined || val === null) continue;
|
|
194
|
+
if (field == '_id'){
|
|
195
|
+
flattened[field] = val;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if(field == 'password'){
|
|
199
|
+
flattened[field] = '********';
|
|
200
|
+
continue;
|
|
201
|
+
|
|
202
|
+
}
|
|
203
|
+
if(field =="status"){
|
|
204
|
+
flattened[field] = $J.get(val);
|
|
205
|
+
continue
|
|
206
|
+
}
|
|
207
|
+
if (typeof val === 'string' && $c.isCuid(val) && recursive && depth > 0) {
|
|
208
|
+
if (!visited.has(val)) {
|
|
209
|
+
const expanded = JOE.Utils.flattenObject(val, {
|
|
210
|
+
recursive,
|
|
211
|
+
depth: depth - 1,
|
|
212
|
+
visited: new Set(visited)
|
|
213
|
+
});
|
|
214
|
+
flattened[field] = expanded || val;
|
|
215
|
+
} else {
|
|
216
|
+
flattened[field] = val;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else if (Array.isArray(val) && val.every(v => typeof v === 'string' && $c.isCuid(v)) && recursive && depth > 0) {
|
|
220
|
+
flattened[field] = val.map(refId => {
|
|
221
|
+
if (!visited.has(refId)) {
|
|
222
|
+
const expanded = JOE.Utils.flattenObject(refId, {
|
|
223
|
+
recursive,
|
|
224
|
+
depth: depth - 1,
|
|
225
|
+
visited: new Set(visited)
|
|
226
|
+
});
|
|
227
|
+
return expanded || refId;
|
|
228
|
+
}
|
|
229
|
+
return refId;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
flattened[field] = val;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return flattened;
|
|
238
|
+
};
|
|
177
239
|
|
|
178
240
|
return this;
|
|
179
241
|
};
|