json-object-editor
Version:
JOE the Json Object Editor | Platform Edition
256 lines (250 loc) • 13.4 kB
JavaScript
var schema = function(){
return {
title : '${name}',
menuicon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-7 -7 40 40"><path d="M6 2L6 4 5 4C3.9 4 3 4.9 3 6L3 20C3 21.1 3.9 22 5 22L19 22C20.1 22 21 21.1 21 20L21 6C21 4.9 20.1 4 19 4L18 4 18 2 16 2 16 4 8 4 8 2 6 2zM5 9L19 9 19 20 5 20 5 9zM12 13L12 18 17 18 17 13 12 13z"/></svg>',
default_schema:true,
// Curated summary for agents
summary:{
description:'Scheduled occurrence with date/time, location, and attendees.',
purpose:'Events capture meetings or occurrences with optional leader and attendees. Use events for calendars, reminders, and participation tracking.',
labelField:'name',
defaultSort:{ field:'joeUpdated', dir:'desc' },
searchableFields:['name','info','description','city','state','street_address','zip','_id'],
allowedSorts:['joeUpdated','created','date','start_time','end_time','name'],
relationships:{
outbound:[
{ field:'status', targetSchema:'status', cardinality:'one' },
{ field:'leader', targetSchema:'user', cardinality:'one' },
{ field:'attendees', targetSchema:'user', cardinality:'many' },
{ field:'tags', targetSchema:'tag', cardinality:'many' }
],
inbound:{ graphRef:'server/relationships.graph.json' }
},
joeManagedFields:['created','joeUpdated'],
fields:[
{ name:'_id', type:'string', required:true },
{ name:'itemtype', type:'string', required:true, const:'event' },
{ name:'name', type:'string', required:true },
{ name:'info', type:'string' },
{ name:'date', type:'string', format:'date' },
{ name:'start_time', type:'string' },
{ name:'end_time', type:'string' },
{ name:'timezone_offset', type:'string' },
{ name:'street_address', type:'string' },
{ name:'city', type:'string' },
{ name:'state', type:'string' },
{ name:'zip', type:'string' },
{ name:'status', type:'string', isReference:true, targetSchema:'status' },
{ name:'leader', type:'string', isReference:true, targetSchema:'user' },
{ name:'attendees', type:'string', isArray:true, isReference:true, targetSchema:'user' },
{ name:'published', type:'boolean' },
{ name:'published_ts', type:'string', format:'date-time' },
{ name:'description', type:'string' },
{ name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
{ name:'joeUpdated', type:'string', format:'date-time', required:true },
{ name:'created', type:'string', format:'date-time', required:true }
]
},
listView:{
title:function(e){
/*var html = '<joe-full-right>'
+'<joe-subtitle>${date}</joe-subtitle>'
+'<joe-content>${start_time} - ${end_time}</joe-content>'
+'</joe-full-right>'+
*/
var html = "";
html+=
((e.date && '<joe-subtitle>'+$c.format(new Date(e.date),'D n/d/y')+'</joe-subtitle>')||'');
html+='<joe-title>${name}</joe-title>';
if(e.start_time){
html+=
'<joe-subtitle>'
//+$c.format(new Date(e.date),'D ')
+ $c.format(new Date('11/26/2016 '+e.start_time),'g:ia')
+' - '
+ (e.end_time && $c.format(new Date('11/26/2016 '+e.end_time),'g:ia') || '')
+'</joe-subtitle>'
}
/*
var key;
var base = e.leader && [e.leader] || [];
base.concat(e.attendees).map(function(user){
key = user+'-cube';
if(!_joe.Cache.static[key]){
_joe.Cache.static[key] =
_renderUserCubes(_joe.getDataItem(user,'user'));
}
html+= _joe.Cache.static[key];
})
*/
return html;
},
listWindowTitle: 'Events'
},
itemExpander:function(ev){
var html = "<joe-subtitle>${info}</joe-subtitle>";
if(ev.street_address || ev.location){
html+=
'<joe-title>address</joe-title>'+
'<joe-itemmenu-section class="padded joe-selectable">'
// +'<joe-section-label>address</joe-section-label>'
+'${street_address}, ${city} ${zip}</joe-itemmenu-section>'
}
if(ev.description){
html+='<joe-title>notes</joe-title>'+
'<joe-itemmenu-section class="padded joe-selectable">'+ev.description+'</joe-itemmenu-section>'
}
if((ev.attendees && ev.attendees.length)|| ev.leader){
html+='<joe-title>attendees</joe-title>';
var key;
var base = ev.leader && [ev.leader] || [];
base.concat(ev.attendees).map(function(user){
key = user+'-cube';
if(!_joe.Cache.static[key]){
_joe.Cache.static[key] =
_renderUserCubes(_joe.getDataItem(user,'user'));
}
html+= _joe.Cache.static[key];
})
}
return html;
},
onload:function(events_arr){
events_arr.map(function(event){
event.__date = $c.format(new Date(event.date),'Ymd');
})
},
hideNumbers:true,
sorter:['!__date','start_time','job','event_type'],
subsets:function(e){
_joe.Cache.static.todayString = _joe.Cache.static.todayString || $c.format(new Date(),'m/d/Y');
_joe.Cache.static.todayDate = _joe.Cache.static.todayDate || new Date();
_joe.Cache.static.todayDate.setHours(23,59);
var subs = [
{name:'today',filter:{date:_joe.Cache.static.todayString},sorter:['start_time','job']},
{name:'mine',filter:{$or:[{leader:_joe.User._id},{attendees:{$in:[_joe.User._id]}}]}},
// {name:'upcoming',default:true,filter:{date:{$gte:_joe.Cache.static.todayDate}},sorter:['date','job']}
{name:'upcoming',default:true,filter:{$where:function(){
var datecheck = new Date(this.date);
return datecheck >= _joe.Cache.static.todayDate;
}},sorter:['date','start_time','job']}
];
return subs;
},
checkbox:{prop:'published'},
fields:[
'name',
'info',
{section_start:'when'},
{name:'date', type:"date",/*rerender:'leader,attendees,timezone_offset',*/onblur:'_joe.Fields.rerender(\'leader,attendees,timezone_offset\')'},
{name:'start_time', display:"start time", type:"time",width:'50%',rerender:'leader,attendees'},
{name:'end_time', display:"end time", type:"time",width:'50%',rerender:'leader,attendees'},
'timezone_offset',
{section_end:'when'},
{section_start:'where'},
{name:'street_address', display:"street address"},
{name:'city', width:"40%"},
'state',
{name:'zip', display:"zip code", type:'number', width:'30%'},
// {name:'geo', display:"map location", type:'geo'},
{section_end:'where'},
{sidebar_start:'right'},
'status',
{section_start:'calendar'},
{name:'published_ts',label:false,passthrough:true, run:function(evt){
if(evt.published_ts){
return '<joe-subtitle>last published <b>'+_joe.Utils.prettyPrintDTS(evt.published_ts)+'</b></joe-subtitle>';
}
return '<joe-subtitle>never published</joe-subtitle>';
},type:'content',display:'published_ts'},
{name:'published',type:'boolean',label:'publish to calendar feed?', display:'publish/unpublish'},
{name:'publish_btn',type:'content', label:false,
template:function(evt){
var template = '<joe-button class="joe-button full-width joe-orange-button" onclick="_joe.Google.Calendar.Event.add(_jco()._id,true,true)" > Update in Calendar </joe-button>';
return template;
}
},
{name:'ics',type:'content', label:false, template:'<joe-button class="joe-button full-width" onclick="window.open(\'/API/plugin/calendar/events?event=${_id}\')" > download iCal(.ics) event</joe-button>'},
{section_end:'calendar'},
{section_start:'people'},
/* {name:'availability_check',type:'content',run:function(){
return '<joe-button class="joe-button" onclick="_joe.rerenderField(\'leader,attendees\')">check availability</joe-button>';
}},*/
{name:'leader',type:"select", values:"user",blank:true,idprop:"_id",
template:function(event,user){
var event = _jco(true);
var conflicts = _joe.Data.event.where({attendees:{$in:[user._id]},date:event.date,_id:{$ne:event._id}});
conflicts = conflicts.filter(function(event1){
return _joe.schemas.event.methods.timeConflict(event1,_jco(true));
})
/*var conflicts = _joe.Data.event.where({
$OR:{attendees:{$in:[user._id]},leader:user._id},
date:event.date,_id:{$ne:event._id}});
*/
return (user.fullname || user.name)+(conflicts.length && ' ['+conflicts.length+']' ||'');
}},
{name:'sendNotifications',type:'boolean',label:'send notifications to guests',display:'notifications'},
{name:'attendees', display:"attendees", type:"objectReference", values:"user", blank:true, idprop:"_id",
autocomplete_template:function(user,event){
var event = _jco(true);
var conflicts = _joe.Data.event.where({attendees:{$in:[user._id]},date:event.date,_id:{$ne:event._id}});
conflicts = conflicts.filter(function(event1){
return _joe.schemas.event.methods.timeConflict(event1,_jco(true));
})
/*_joe.Data.event.where({attendees:{$in:['9435b059-d470-4f34-81a4-f916ab51ee87']},date:'11/21/2016',_id:{$ne:'16456866-0e78-4ed9-b4a5-6de733d2cdfb'}})*/
var temp = "<joe-title>${name}</joe-title><joe-subtitle>${fullname}</joe-subtitle> ";
return temp;
},
template:function(user,event){
var event = _jco(true);
var conflicts = _joe.Data.event.where({attendees:{$in:[user._id]},date:event.date,_id:{$ne:event._id}});
conflicts = conflicts.filter(function(event1){
return _joe.schemas.event.methods.timeConflict(event1,_jco(true));
})
var temp = "<joe-title>${name}</joe-title><joe-subtitle>${fullname}</joe-subtitle>"
+'<joe-subtext>'+(conflicts.length && conflicts.length+" conflict"+(conflicts.length == 1?'':'s') || '')+'</joe-subtext>';
return temp;
},
expander:function(user,event){
var event = _jco(true);
var conflicts = _joe.Data.event.where({attendees:{$in:[user._id]},date:event.date,_id:{$ne:event._id}});
conflicts = conflicts.filter(function(event1){
return _joe.schemas.event.methods.timeConflict(event1,_jco(true));
})
if(conflicts.length){
var h = '';
conflicts.map(function(conflict){
h+= _joe.renderFieldListItem(conflict,null,'event');
})
return h;
}
return false;
}
},
{section_end:'people'},
/*'comments',*/
{sidebar_end:'right'},
{name:'description', type:"wysiwyg"},
'tags','_id','created','itemtype'
],
idprop : "_id",
methods:{
timeConflict:function(event1,event2){
if(event1.start_time == event2.start_time || event1.end_time == event2.end_time ){
return true;
}
if(event2.start_time < event1.start_time && event1.start_time < event2.end_time){
return true
}
if(event2.start_time < event1.end_time && event1.end_time < event2.end_time){
return true
}
if(event1.start_time < event2.start_time && event2.end_time < event1.end_time){
return true
}
return false;
}
}
}
};
module.exports = schema();