UNPKG

json-object-editor

Version:

JOE the Json Object Editor | Platform Edition

596 lines (568 loc) 26.8 kB
var usStates = [ { name: 'Alabama', code: 'AL'}, { name: 'Alaska', code: 'AK'}, { name: 'American Samoa', code: 'AS'}, { name: 'Arizona', code: 'AZ'}, { name: 'Arkansas', code: 'AR'}, { name: 'California', code: 'CA'}, { name: 'Colorado', code: 'CO'}, { name: 'Connecticut', code: 'CT'}, { name: 'Delaware', code: 'DE'}, { name: 'District of Columbia', code: 'DC'}, { name: 'Federated States of Micronesia', code: 'FM'}, { name: 'Florida', code: 'FL'}, { name: 'Georgia', code: 'GA'}, { name: 'Guam', code: 'GU'}, { name: 'Hawaii', code: 'HI'}, { name: 'Idaho', code: 'ID'}, { name: 'Illinois', code: 'IL'}, { name: 'Indiana', code: 'IN'}, { name: 'Iowa', code: 'IA'}, { name: 'Kansas', code: 'KS'}, { name: 'Kentucky', code: 'KY'}, { name: 'Louisiana', code: 'LA'}, { name: 'Maine', code: 'ME'}, { name: 'Marshall Islands', code: 'MH'}, { name: 'Maryland', code: 'MD'}, { name: 'Massachusetts', code: 'MA'}, { name: 'Michigan', code: 'MI'}, { name: 'Minnesota', code: 'MN'}, { name: 'Mississippi', code: 'MS'}, { name: 'Missouri', code: 'MO'}, { name: 'Montana', code: 'MT'}, { name: 'Nebraska', code: 'NE'}, { name: 'Nevada', code: 'NV'}, { name: 'New Hampshire', code: 'NH'}, { name: 'New Jersey', code: 'NJ'}, { name: 'New Mexico', code: 'NM'}, { name: 'New York', code: 'NY'}, { name: 'North Carolina', code: 'NC'}, { name: 'North Dakota', code: 'ND'}, { name: 'Northern Mariana Islands', code: 'MP'}, { name: 'Ohio', code: 'OH'}, { name: 'Oklahoma', code: 'OK'}, { name: 'Oregon', code: 'OR'}, { name: 'Palau', code: 'PW'}, { name: 'Pennsylvania', code: 'PA'}, { name: 'Puerto Rico', code: 'PR'}, { name: 'Rhode Island', code: 'RI'}, { name: 'South Carolina', code: 'SC'}, { name: 'South Dakota', code: 'SD'}, { name: 'Tennessee', code: 'TN'}, { name: 'Texas', code: 'TX'}, { name: 'Utah', code: 'UT'}, { name: 'Vermont', code: 'VT'}, { name: 'Virgin Islands', code: 'VI'}, { name: 'Virginia', code: 'VA'}, { name: 'Washington', code: 'WA'}, { name: 'West Virginia', code: 'WV'}, { name: 'Wisconsin', code: 'WI'}, { name: 'Wyoming', code: 'WY' } ]; var fields = { '_id':{type:'guid',width:'50%'}, 'token':{type:'guid'}, url:{type:'url'}, 'description':{type:'wysiwyg'}, 'coords':{type:'geo'}, 'state':{type:'select',values:usStates,idprop:'code',template:'${code}',width:'25%',minwidth:'100px',blank:true}, 'name':{type:'text',onblur:'_joe.TITLE.set()'}, instructions_format:{type:'select',values:['wysiwyg','code','text',], rerender:'instructions',display:'Instructions Format'}, instructions:{ height:'500px', display:'Instructions', default:'code', type:function(item){ if(!item.instructions_format || item.instructions_format == 'text'){ return 'rendering'; } else if(["code"].indexOf(item.instructions_format) != -1){ return 'code'; } return item.instructions_format; } }, template:{ height:'600px', type:function(item){ if(!item.template_type){ return 'code'; } if(["code","module"].indexOf(item.template_type) != -1){ return 'code'; } return item.template_type; } }, created:{locked:true,width:'50%'}, itemtype:{locked:true, hidden:true}, priority:{type:'select',values:[{name:'',value:1000},{name:1},{name:2},{name:3}]}, site:{type:'select',values:'site',goto:'site',idprop:'_id',blank:true,icon:'site'}, group:{name:'group',type:'select',values:'group',blank:true, idprop:'_id',icon:'group'}, members:{type:'objectReference',values:'user',icon:'user', after:function(item){ var action = `_joe.getField('members').methods.addUser('${_joe.User._id}');`; var template = `<joe-button class="joe-button joe-svg-button joe-orangegrey-button joe-svg-button joe-left-button" onclick="${action}"> ${_joe.schemas.user.menuicon} assign this to me </joe-button>`; return template; }, template:'<joe-subtext>${name}</joe-subtext><joe-title>${fullname}</joe-title><joe-subtext>${info}</joe-subtext>', autocomplete_template:'<joe-title>${name}</joe-title><joe-subtitle>${fullname}</joe-subtitle>', reference_specs:{stripecolor:'${color}'}, methods:{ addUser:function(userid,goto){ var current = _jco(true); if(current.members.indexOf(userid) == -1){ current.members.push(userid); _joe.Fields.rerender('members',{members:current.members}); } } } }, people:{name:'people',type:'objectList',width:'50%',properties:[ 'name', {name:'role',width:'30%'} ]}, user_comments:{ type:'comments', label:'add a comment' }, content_type:{type:'select',values:['wysiwyg','code'], rerender:'content'}, content:{type:'code',height:'600px'}, template_type:{type:'select',values:['wysiwyg','code','module'], rerender:'template'}, updated:{type:'content', label:false,run:function(item){ if(item.joeUpdated){ return '<joe-subtext><small>updated</small> '+_joe.Utils.prettyPrintDTS(item.joeUpdated) +`<a class="fright" href="/API/object/${item.itemtype}/_id/${item._id}" target="_blank">[JSON]</a></joe-subtext><clear-fix></clear-fix>`; } return 'new item'; }}, status:{type:'select',rerender:'status',icon:'status', after:function(item){ if(item.joeUpdated){ var cont =` <joe-subtext style="padding-top:5px; text-align: right;"><a class="fleft" href="/API/object/${item.itemtype}/_id/${item._id}" target="_blank">[JSON]</a><small>updated</small> ${_joe.Utils.prettyPrintDTS(item.joeUpdated)}</joe-subtext> <clear-fix></clear-fix>` return cont; } return ''; }, values:function(item){ var statuses = _joe.Data.status.where({datasets:{$in:[item.itemtype]}}).sortBy('index'); return statuses; },blank:true,idprop:'_id', value:function(item){ var status = _joe.Data.status.where({datasets:{$in:[item.itemtype]},default:true}).sortBy('index')[0]; if(!status){return null;} return status._id; }, hidden:function(item){ var statuses = _joe.Data.status.where({datasets:{$in:[item.itemtype]}}) return !statuses.length; }, containercolor:function(item,statusid){ var status = _joe.getDataItem(statusid,'status'); return status.color||''; } }, tags:{type:'group',icon:'tag',hidden:function(obj){ let tags = _joe.Data.tag.filter(function(tag){ return !(tag.datasets.indexOf(item.itemtype) == -1); }); if(!tags.length){ return true; } }, values:function(item){ var tags = _joe.Data.tag.filter(function(tag){ return !(tag.datasets.indexOf(item.itemtype) == -1); }); return tags.sortBy('name'); } }, reports:{type:'content', icon:'report',run:function(item){ var html = ''; var rep_url; var standard_reports = []; //single report structure if(_joe.schemas[item.itemtype] && _joe.schemas[item.itemtype].report){ var rep = _joe.schemas[item.itemtype].report rep_url = `/API/plugin/reportbuilder/standard?itemid=${item._id}`; html += _joe.renderFieldListItem(rep, '<joe-title>${name}</joe-title>\ <joe-subtext>${info}</joe-subtext>', 'report', {action:'onclick="window.open(\''+rep_url+'\');"'}); } //multiple report structure if(_joe.schemas[item.itemtype] && _joe.schemas[item.itemtype].reports){ Object.keys(_joe.schemas[item.itemtype].reports).map(repId=>{ var repObj = _joe.schemas[item.itemtype].reports[repId]; rep_url = `/API/plugin/reportbuilder?reportid=${repId}&itemid=${item._id}`; html += _joe.renderFieldListItem(repObj, `<joe-title>${repObj.name}</joe-title> <joe-subtext>${repObj.info || repId || ''}</joe-subtext>`, 'report', {action:'onclick="window.open(\''+rep_url+'\');"'}); }) } //get any reports for this schema type var reportReference = ''; var report_options = _joe.Data.report.filter(function(rep){ if(!rep.content_items || !rep.content_items.length) { return false; } for(var r = 0,tot = rep.content_items.length; r < tot; r++){ if(rep.content_items[r].itemtype == item.itemtype){ reportReference = rep.content_items[r].reference; return true; } } return false; }) report_options.map(function(rep){ console.log(rep); rep_url = '/API/plugin/reportbuilder'+'?reportid='+rep._id+'&'+reportReference+'='+item._id; html += _joe.renderFieldListItem(rep, '<joe-title>${name}</joe-title>\ <joe-subtext>${info}</joe-subtext>', 'report', {action:'onclick="window.open(\''+rep_url+'\');"'}); }) return html; }}, milestone:{name:'milestone',width:'100px'}, tasks:{display:'Incomplete Tasks',type:'content',icon:'task',reloadable:true, run:function(item){ var tasks = (_joe.Data.task.where({$and:[{project:item._id},{complete:{$in:[false,'false',undefined]}}]})||[]).sortBy('priority,!due_date,project_phase'); var html = ''; html+= _joe.renderMenuButtons({display:'view all '+tasks.length+' tasks', css:'joe-view-button joe-iconed-button full-width', action:'goJoe(_joe.Data.task,{schema:\'task\', subset:\''+(item.name||'').replace(/\'/g,"\\'")+'\'})' }); tasks.map(function(t){ var phasename = ''; if(t.project_phase){ phasename = (item.phases.where({id:t.project_phase})[0]||{name: '['+ t.project_phase+']'}).name; } html += _joe.renderFieldListItem(t, '<joe-subtext>'+phasename+' ${due_date}</joe-subtext>'+ '<joe-subtitle>${name}</joe-subtitle>' +'<joe-subtext>${info}</joe-subtext>', 'task', {bgcolor:function(task){ if(task.status){ var status = _joe.Cache.get(task.status)||false; if(status){ return {color:status.color,title:status.name} } return false; } return false; },stripecolor:function(item){ if(item.priority && item.priority < 100){ return { title:`P${item.priority}`, color:_joe.Colors.priority[item.priority] }; } }, }); }); return html; }}, includes:{type:'objectReference',values:'include',icon:'include', template:'<joe-title>${name} (.${filetype})</joe-title><joe-subtext>${info}</joe-subtext><joe-subtext>${_id}</joe-subtext>', autocomplete_template:'<joe-title>${name} (.${filetype})</joe-title><joe-subtext>${info}</joe-subtext>' }, /* file_upload:{type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload,use_legacy:true},*/ datasets:{type:'group',cols:2, comment:'which itemtypes(schemas) does this pertain to',values:function(){ if(typeof(__collectionNames) != undefined){ var opts = [],name; __collectionNames.map(function(collName){ let schemaObj = _joe.schemas[collName] || {name:collName}; name = (schemaObj && schemaObj.menuicon)? '<joe-icon class="fleft icon-30 icon-grey" style="padding-bottom:5px; padding-right:5px;">' +schemaObj.menuicon+'</joe-icon>'+(schemaObj.display||schemaObj.name) :'<joe-icon class="fleft icon-30 icon-grey" style="padding-bottom:5px; padding-right:5px;">'+'</joe-icon>'+(schemaObj.display||schemaObj.name); opts.push({name:name,_id:collName}); }) return opts; } return ['none']; } }, dataset:{type:'select',blank:true,values:function(){ return (typeof(__collectionNames) != undefined && __collectionNames) || ['none']; }}, notes:{type:'objectReference',values:'note',schema:'note',icon:'note', template:'<joe-title>${name}</joe-title><joe-subtitle>${info}</joe-subtitle>', callback:function(values){ logit(values); }}, timezone_offset:{ format:function(i,v){ var item = _jco(true); var event_date =(item.date)? new Date(item.date) : new Date(); var tzo = event_date.getTimezoneOffset()/-60; var absNum = Math.abs(tzo); var nnum = ('0'+absNum).substr(-2); f = ((tzo < 0)?'-':'+')+nnum+':00'; if(item.timezone_offset && f!=item.timezone_offset){alert('timezone offset will change from '+item.timezone_offset+' to '+f);} return f; }, value:function(item){ if(item.timezone_offset){return item.timezone_offset;} var event_date =(item.date)? new Date(item.date) : new Date(); var tzo = event_date.getTimezoneOffset()/-60; var absNum = Math.abs(tzo); var nnum = ('0'+absNum).substr(-2); f = ((tzo < 0)?'-':'+')+nnum+':00'; /*if(item.timezone_offset && f!=item.timezone_offset){alert('timezone offset will change from '+item.timezone_offset+' to '+f);}*/ return f; }, comment:function(item){ var event_date =(item.date)? new Date(item.date) : new Date(); var tzo = event_date.getTimezoneOffset()/-60; return 'offset on event date is <b>'+tzo+'</b>'; } },//end timezone_offset blocks:{type:'objectList', reinherit:function(){ var item = _jco(true); var blocks = item.blocks.slice(0); if(item.layout){ if(item.syncLayoutBlocks){ var lblocks = (_joe.getDataItem(item.layout,'layout')||{blocks:[]}).blocks.slice(0); //remove layout blocks blocks = blocks.filter(function(bl){ return bl.src != 'layout'; }) blocks = blocks.concat(lblocks); } } _joe.Fields.rerender('blocks',{'blocks':blocks}); }, sectsToArray:function(sect_item,raw){ console.log('itemtype',sect_item.itemtype); var sects = _joe.schemas.layout.methods.getSections(sect_item.content || sect_item.template); sect_item.blocks.map(function(block){ sects.push(block.section); }) if(raw){ return sects; } sects = sects.condense(true).sort(); return sects; }, comment:function(item){ var btns=['<joe-button class="joe-button fleft" style="margin-bottom:5px;" onclick="_joe.Fields.rerender(\'blocks\');">update sections</joe-button>'] if(item.itemtype == "page"){ btns.push('<joe-button class="joe-button fright" style="margin-bottom:5px;" onclick="_joe.getField(\'blocks\').reinherit();" title="reinherit blocks from layout or site">reinherit</joe-button>'); } return btns.join(' ');}, value:function(item){ if(item.layout){ var blocks = (_joe.getDataItem(item.layout,'layout')||{blocks:[]}).blocks.slice(0); //blocks.map(function(block){ // block.layout = true; //}) return blocks; } _joe.Fields.rerender('blocks',{'blocks':_joe.getField('blocks').reinherit()}); return []; }, properties:[ {name:'block',type:'select',values:function(){ return _joe.Data.block.where({is_template:{$in:[false,'',null]}}).sortBy('name'); },idprop:'_id'}, {name:'section',type:'select',values:function(item){ var new_item = _jco(true); var sections = []; //get layout sections (if layout) if(new_item.layout){//something that uses layout only var layout = _joe.getDataItem(new_item.layout,'layout'); sections = sections.concat(_joe.getField('blocks').sectsToArray(layout)); } var con_str = new_item.template || new_item.content; if(con_str){//page or layout sections = sections.concat(_joe.getField('blocks').sectsToArray(new_item)); } sections = [''].concat(sections); return sections; }}, {name:'src',width:'15%',type:'select',locked:true, values:['page','layout','site'], value:function(item){ if(_jco().itemtype =="layout"){return 'layout'} }} ] },//end blocks _protected:{ type:'boolean', display:'protect item', icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-6 -4 36 36"><path d="M12 1C8.7 1 6 3.7 6 7L6 8C4.9 8 4 8.9 4 10L4 20C4 21.1 4.9 22 6 22L18 22C19.1 22 20 21.1 20 20L20 10C20 8.9 19.1 8 18 8L18 7C18 3.7 15.3 1 12 1ZM12 3C14.3 3 16 4.7 16 7L16 8 8 8 8 7C8 4.7 9.7 3 12 3ZM12 13C13.1 13 14 13.9 14 15 14 16.1 13.1 17 12 17 10.9 17 10 16.1 10 15 10 13.9 10.9 13 12 13Z"/></svg>', label:'users must be logged in to view this item and reports' }, favorite:{ type:'boolean', byUser:true, display:'favorite', icon:'<?xml version="1.0" encoding="UTF-8"?><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M4 2h16a1 1 0 0 1 1 1v19.276a.5.5 0 0 1-.704.457L12 19.03l-8.296 3.702A.5.5 0 0 1 3 22.276V3a1 1 0 0 1 1-1zm8 11.5l2.939 1.545-.561-3.272 2.377-2.318-3.286-.478L12 6l-1.47 2.977-3.285.478 2.377 2.318-.56 3.272L12 13.5z"/></svg>', label:'one of your favorites', hidelabel:true }, // favorite:{ // type:'userfavorite', // display:'favorite', // icon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-6 -4 36 36"><path d="M12 1C8.7 1 6 3.7 6 7L6 8C4.9 8 4 8.9 4 10L4 20C4 21.1 4.9 22 6 22L18 22C19.1 22 20 21.1 20 20L20 10C20 8.9 19.1 8 18 8L18 7C18 3.7 15.3 1 12 1ZM12 3C14.3 3 16 4.7 16 7L16 8 8 8 8 7C8 4.7 9.7 3 12 3ZM12 13C13.1 13 14 13.9 14 15 14 16.1 13.1 17 12 17 10.9 17 10 16.1 10 15 10 13.9 10.9 13 12 13Z"/></svg>', // label:'items that have been favorited' // }, // favorite:{ // type:'objectReference',values:'user',icon:'user', // after:function(item){ // var action = `_joe.getField('members').methods.addUser('${_joe.User._id}');`; // var template = `<joe-button class="joe-button joe-svg-button joe-orangegrey-button joe-svg-button" onclick="${action}"> // favorite this // </joe-button>`; // return template; // }, // disabled:true, // template:'<joe-subtext>${name}</joe-subtext><joe-title>${fullname}</joe-title><joe-subtext>${info}</joe-subtext>', // autocomplete_template:'<joe-title>${name}</joe-title><joe-subtitle>${fullname}</joe-subtitle>', // reference_specs:{stripecolor:'${color}'}, // methods:{ // toggleFavorite:function(userid){ // }, // addUser:function(userid,goto){ // var current = _jco(true); // if(current.favorite.indexOf(userid) == -1){ // current.favorite.push(userid); // _joe.Fields.rerender('members',{members:current.members}); // } // } // } // }, references:{ display:'related joe items', type:'objectReference', values:function(list){ var haystack = []; for(var d in _joe.Data){ haystack = haystack.concat(_joe.Data[d]); } return haystack; } }, reference:{ display:'Instance of', type:'objectReference', values:function(list){ var haystack = []; for(var d in _joe.Data){ haystack = haystack.concat(_joe.Data[d]); } return haystack; } }, referencedBy:{ type:'content', /*display:function(item){ var items = _joe.getData.where({referneces:{$in:[item._id]}}); return ('<joe-title>'+items.length +(items.length == 1 && ' item references'||' items reference') +' this item</joe-title>'); },*/ run:function(item){ var items = _joe.getData().filter(i=>{ if(!i.references || !i.references.length || i.references.indexOf(item._id) == -1){ return false; } return true; }) var html = ''; items.map(function(item){ let schema = item.itemtype && _joe.schemas[item.itemtype]; let temp = `${(schema && schema.menuicon) || ''} <joe-subtitle>${item.name}</joe-subtitle> <joe-subtext>${item.info||item.date||''}</joe-subtext>` html += _joe.renderFieldListItem(item,temp,item.itemtype); }); return html; }}, //AI Fields ai_model:{ type: "select", display: "Ai Model", values: [ { value:"gpt-5.1", name: "GPT-5.1 (Strong, 128k)" }, { value:"gpt-5", name: "GPT-5 (Strong, 128K)" }, { value:"gpt-5-mini", name: "GPT-5-mini (Cheap, 1M)" }, { value:"gpt-5-nano", name: "GPT-5-nano (Fastest, light tasks)" }, { value: "gpt-4o", name: "GPT-4o (Fast, 128k)" }, { value: "gpt-4.1", name: "GPT-4.1 (Strong, 1M)" }, { value: "gpt-4.1-mini", name: "4.1-mini (Cheap, 1M)" }, { value: "gpt-4.1-nano", name: "4.1-nano (Fastest, light tasks)" } ], tooltip:`Ai Model Guide - 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. 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. 4.1-mini is significantly cheaper than full 4.1, with great balance for most structured AI workflows. 4.1-nano is best for lightweight classification or routing logic where speed and cost matter more than depth.`, default: "gpt-4o", }, objectChat:{ type:'button', display:'Start Chat', icon:'ai_assistant', onclick:function(object){ if (!object || !object._id) return ''; return `_joe.Ai.spawnChatHelper('${object._id}');`; }, }, listConversations:{display:'Ai Conversations', type:"content",reloadable:true,run:function(obj){ return _joe.schemas.ai_conversation.methods.listConversations(obj,true); }}, ai_responses:{ display:'AI Responses', type:'content', reloadable:true, run:function(obj){ return _joe.schemas.ai_response.methods.listResponses(obj); } }, proposeThought:{ display:'Propose Thought', type:'content', reloadable:true, run:function(obj){ if (!obj || !obj._id) { return '<joe-text>Save this item before proposing Thoughts.</joe-text>'; } var schema = _joe.current && _joe.current.schema || null; var itemtype = (obj && obj.itemtype) || (schema && schema.name) || 'item'; // Allow schemas to override the default prompt via extend:'proposeThought',specs:{prompt:'...'} var fieldDef = null; if (_joe && typeof _joe.getField === 'function') { try { fieldDef = _joe.getField('proposeThought'); } catch(_e) {} } var overridePrompt = fieldDef && fieldDef.prompt; var defaultPrompt = overridePrompt || ( 'Propose 1–2 concise hypotheses or links about this ' + itemtype + ' and its related objects (risks, dependencies, or next steps). ' + 'Base them only on the object fields and related records. ' + 'Avoid meta-thoughts about prompts or schemas.' ); var taId = 'propose_thought_prompt_' + obj._id; var html = ''; html += '<joe-text>Thought prompt</joe-text>'; html += '<textarea id="'+taId+'" style="width:100%;min-height:80px;">'+defaultPrompt+'</textarea>'; // For now, use the generic Thought agent; scope_id is the current object id. html += "<joe-button class=\"joe-button joe-blue-button\" "; html += "onclick=\"_joe.Ai.runProposeThought('"+obj._id+"','"+taId+"')\">Run Thought Agent</joe-button>"; return html; } }, }; module.exports = fields;