json-object-editor
Version:
JOE the Json Object Editor | Platform Edition
428 lines (405 loc) • 18.1 kB
JavaScript
var user = function(){return{
title : '${name}',
info:"Manage each user you've given access to supervise, edit, or view elements of your dashboard.",
default_schema:true,
searchable:['name','info','fullname','_id','email'],
listView:{
title: function(user){
var template =
'<joe-full-right>${role}</joe-full-right>'+
'<joe-title>${name}</joe-title><joe-subtitle>${fullname}</joe-subtitle><joe-subtext>${info}</joe-subtext>';
if (user.image_url){
template = '<joe-listitem-icon style="background-image:url(${image_url});"></joe-listitem-icon>'+template;
}
return template;
},
listWindowTitle: 'Users'/*,
icon:function(userobj){
if (userobj.image_url){
return {url:userobj.image_url,height:'100px'};
}
return false;
}*/
},
itemExpander:function(u){
return `<joe-subtext>email</joe-subtext>
${u.email}
<br/>
${u.description}`;
},
menuicon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-20 -20 140 140"><g><path d="M74 79.4c-4-6.8-13.3-14.9-24-14.9S30 72.6 26 79.4a44.1 44.1 0 0 0 24 6.7A44.1 44.1 0 0 0 74 79.4Z"/><circle cx="50" cy="39.3" r="18.8"/><path d="M50 14.9A35.1 35.1 0 1 1 14.9 50 35.1 35.1 0 0 1 50 14.9m0-1A36.1 36.1 0 1 0 86.1 50 36.1 36.1 0 0 0 50 13.9Z"/><path d="M90 50A40 40 0 1 1 50 10 40 40 0 0 1 90 50ZM50 13.9A36.1 36.1 0 1 0 86.1 50 36.1 36.1 0 0 0 50 13.9Z"/></g></svg>',
stripeColor:function(item){
return item.color;
},
subsets:function(item){
var subs = [];
subs.push({group_start:'roles',collapsed:true}),
['viewer','editor','admin','super'].map(function(role){
subs.push({name:role+'s',filter:{role:role}})
})
subs.push({group_end:'roles'})
subs.push({group_start:'groups',collapsed:true}),
_joe.Data.group.sortBy('name').map(function(g){
subs.push({name:g.name,filter:{_id:{$in:g.members}}});
})
subs.push({group_end:'groups'})
subs.push({group_start:'tags',collapsed:true});
subs = subs.concat(_joe.Filter.Options.tags());
subs.push({group_end:'tags'});
var roles = _joe.Utils.Settings('CUSTOM_ROLES') || [];
ss_roles = roles.map(r=>{
return{ name:r.name,
filter:{custom_roles:{$in:[r._id]}}
}
})
subs.push({group_start:'custom_roles',display:'custom roles',collapsed:true});
subs = subs.concat(ss_roles);
subs.push({group_end:'custom_roles'})
return subs;
},
fields:function(){ return [
{extend:'name',specs:{display:'username'}},
{name:'role',type:'select',display:'Primary Role',values:['','viewer','editor','admin','super'],
locked:function(item){
if(_joe.isNewItem()){
return false;
}
if(_joe.User.role == "super"){
return false;
}
return true;
}},
{name:'password',condition:function(item){
if(_joe.isNewItem()){
return true;
}
if(!_joe.User){
return false;
}
if(_joe.User._id == item._id ||_joe.User.role == "super"){
return true;
}
return false;
},
type:'password',
/*type:function(item){
if(_joe.User && _joe.User._id == item._id){
return 'text';
}else{
return 'password';
}
},*/
locked:function(item){
if(_joe.isNewItem()){
return false;
}
if(_joe.User && _joe.User._id == item._id){
return false;
}
if(_joe.User.role == 'super'){
return false;
}
return true;
}
},
// 'password:password',
// 'confirm_password:password',
{name:'fullname',width:'50%'},
{extend:'info',specs:{width:'50%'}},
{section_start:'contact'},
'email',
'phone',
{section_end:'contact'},
{section_start:'avatar',collapsed:true},
'color:color',
{name:'image_url',display:'image URL',
onchange:'_joe.current.object.image = this.value; $(\'.joe-image-field[name=image]\').val(this.value); _joe.Fields.rerender(\'image_upload\')'},
{name:'image_upload',type:'uploader',field:'image', url_field:'image_url', use_legacy:true,height:'300px',comment:'drag an image here to upload',onConfirm:_joe.SERVER.Plugins.awsConnect},
{name:'image',type:'image',hidden:true},
{section_end:'avatar'},
{section_start:'customization',collapsed:true},
{name:'styles',comment:'css to append to dashboard head',type:'code'},
{section_end:'customization'},
{section_start:'about',collapsed:true},
{extend:'description',specs:{display:'bio'}},
'tags',
{section_end:'about'},
{sidebar_start:'right'},
'status',
'updated',
'reports',
{section_start:'Apps',collapsed:true},
{
name:'apps',type:'group',
display:function(user){
return `user has access to ${user.apps.length} of ${all_apps.length} apps`;
},
values:function(){return all_apps;},
default:function(){return all_apps;},
locked:function(item){
if(['super','admin'].indexOf(_joe.User.role) != -1){
return false;
}
return true;
}
},
{section_end:'Apps'},
{section_start:'Schemas',collapsed:true},
{
name:'schemas',type:'group',
display:function(user){
return `user has access to ${user.schemas.length} of ${__collectionNames.length} schemas`;
},
values:function(){return __collectionNames;},
default:function(){return __collectionNames;},
locked:function(item){
if(['super'].indexOf(_joe.User.role) != -1){
return false;
}
return true;
}
},
{section_end:'Schemas'},
{section_start:'Items',collapsed:true},
{
name:'items',type:'objectReference',
values:function(u){
var haystack =[];
for(var d in _joe.Data){
haystack = haystack.concat(_joe.Data[d]);
}
return haystack;
}
},
{section_end:'Items'},
{section_start:'Roles',collapsed:true},
{
name:'custom_roles',type:'group',
display:function(user){
return `user holds ${(user.custom_roles || []).length} custom roles`;
},
values:function(){
var roles = _joe.Utils.Settings('CUSTOM_ROLES')
return roles;
},
//default:function(){return __collectionNames;},
locked:function(item){
if(['super','admin'].indexOf(_joe.User.role) != -1){
return false;
}
return true;
}
},
{section_end:'Roles'},
{sidebar_end:'right'},
{section_start:'system',collapsed:true},
'_id','created','itemtype','token',
{section_end:'system'}
];
},
reports:{
chore_assignee_screen:{
name:'Chore Assignee Screen',
template_type:'module',
template:function(data){
var CHORES_TAG = JOE.Utils.Settings('CHORES_TAG');
if(!CHORES_TAG){
return 'Error: Please configure a CHORES_TAG in the setting.'
}
var user = data.ITEM;
var icons = {
task:JOE.Schemas.raw_schemas.task.menuicon,
reward:JOE.Schemas.raw_schemas.reward.menuicon
}
var points = 0;
if(!user || user.itemtype !="user"){
return `Invalid user`;
}
//logit(data);
function toDateString(dt,specs){
var specs = specs || {};
var dt = dt || new Date();
if(typeof dt == 'string'){
dt = new Date(dt);
}
var dts_str = '';
var monthstr = (dt.getUTCMonth()+1);
monthstr = (monthstr < 10 ? '0' + monthstr : monthstr);
var dayStr =('0'+dt.getUTCDate()).slice(-2);
var yearStr = dt.getUTCFullYear().toString();
if(specs.format == "Y-m-d"){
dts_str = `${yearStr}-${monthstr}-${dayStr}`;
return dts_str;
}
dts_str += monthstr
+'/'+dayStr
+'/'+((specs.fullyear && yearStr)||yearStr.substr(2,4));
return dts_str;
}
function getHistory(){
let iPoints=0;
var pendingList = [];
var pending_instances = [];
var approved_instances = [];
var completed_instances = JOE.Data.instance.where({
instance_type:{$in:['reward','task']},
members:{$in:[user._id]}
})||[];
completed_instances.map(ci=>{
if(ci.instance_type == "task"){
if(ci.approved){
iPoints += parseInt(ci.points) || 0;
approved_instances.push(ci);
}else{
pending_instances.push(ci);
pendingList.push(ci.reference[0]);
}
}else{
if(ci.approved){
iPoints -= parseInt(ci.points) || 0;
approved_instances.push(ci);
}else{
pending_instances.push(ci);
pendingList.push(ci.reference[0]);
}
}
})
return {
pending:pending_instances,
history:completed_instances,
approved:approved_instances,
points:iPoints,
pendingList:pendingList
}
}
var instances = getHistory();
function getCurrentPoints(){
var pts = points;
return pts;
}
function getCurrentTaskLists(){
var activeStatus = JOE.Data.status.reduce((res,s)=>{
if(s.active){
res.push(s._id);
}
return res
},[])
//chores list
var choresLists = JOE.Data.list.where({
tags:{$in:[CHORES_TAG]},
status:{$in:activeStatus}
})
//lists where in active status
//console.log('choresLists',choresLists)
//finally get the lists
var chores = [];
choresLists.map(cl=>{
chores = chores.concat(cl.items);
})
//console.log(instances.pendingList,'chores '+ chores.length);
chores = chores.filter(ch=>{
return (instances.pendingList.indexOf(ch) == -1);
})
//console.log(chores.length);
logit('available',chores);
return chores;
}
var availableChores = getCurrentTaskLists();
function renderAvailableRow(task_id){
let task = task_id;
if(typeof task == "string"){
task = $J.get(task_id);
}
return `<card-row class="available"
onclick="takeOnTask('${task._id}','${task.itemtype}')">
<card-icon>${icons[task.itemtype]}</card-icon>
<card-pts ><b>${task.points}</b> pts</card-pts>
<joe-title>${task.name}</joe-title>
</card-row>`;
}
function renderCardRow(i){
return `<card-row class="${i.approved && 'approved' ||''} ${i.instance_type}" >
<card-icon>${icons[i.instance_type]}</card-icon>
<card-pts ><b>${i.points}</b> pts</card-pts>
<joe-title>${i.name}</joe-title>
<card-date>${toDateString(new Date(i.date))}</card-date>
</card-row>`;
}
function renderCardPanel(name,id,content,count){
return `<card-panel data-panel="${id}">
<card-panel-title>${name} [${count}]</card-panel-title>
${content || 'coming soon'}
</card-panel> `;
}
console.log('rewards',JOE.Data.reward)
var active = '';
if(instances.pending.length){
active = "pending";
}
var template =`
<html>
<head>
<script src="/JsonObjectEditor/js/libs/jquery-3.5.1.min.js"></script>
<script src="/JsonObjectEditor/js/libs/craydent-1.9.2.min.js"></script>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<link rel="stylesheet" href="/JsonObjectEditor/css/joe.css">
<link rel="stylesheet" href="/JsonObjectEditor/css/report-styles.css">
<link rel="stylesheet" href="/JsonObjectEditor/css/scorecard-styles.css">
<link rel="icon" href="/chore_favicon.ico?v=2" type="image/x-icon" />
<link rel="icon" sizes="192x192" href="/chore-192x192.png">
<meta name="mobile-web-app-capable" content="yes">
<title>Chore Assignee Screen</title>
<style>
html,body{
background:${user.color};
}
user-points {
text-shadow: 0 0 8px ${user.color};
background: ${user.color};
}
</style>
<script>
var user={
_id:'${user._id}'
}
var today = '${toDateString(null,{fullyear:true,format:'Y-m-d'})}';
</script>
</head>
<body>
<score-card>
<user-name>${user.fullname.split(' ')[0].toLowerCase()}'s scorecard
</user-name>
<user-points>${instances.points}
<pts-label> points </pts-label>
</user-points>
${renderCardPanel('Available tasks','available',
availableChores.map(renderAvailableRow).join(''),
availableChores.length
)}
${renderCardPanel('Claim Rewards','rewards',
JOE.Data.reward.sortBy('points').map(renderAvailableRow).join(''),JOE.Data.reward.length
)}
${renderCardPanel('Pending Approval','pending',
instances.pending.sortBy('!date').map(renderCardRow).join('')||'no pending tasks'
,instances.pending.length)}
${renderCardPanel('History','history',
instances.approved.sortBy('!date').map(renderCardRow).join('')
,instances.approved.length)}
<menu-nav>
<menu-nav-option data-panel="available">Available</menu-nav-option>
<menu-nav-option data-panel="rewards">Rewards</menu-nav-option>
<menu-nav-option data-panel="pending">Pending</menu-nav-option>
<menu-nav-option data-panel="history">History</menu-nav-option>
</menu-nav>
</score-card>
<script src="/JsonObjectEditor/js/scorecard-ux.js"></script>
</body>
</html>
`;
return template;
}
}
},
idprop : "_id"
}};
module.exports = user();