json-object-editor 0.10.509 → 0.10.521

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/_www/mcp-export.html +11 -4
  3. package/_www/mcp-nav.js +8 -4
  4. package/_www/mcp-prompt.html +96 -121
  5. package/_www/mcp-schemas.html +294 -0
  6. package/_www/mcp-test.html +86 -0
  7. package/docs/JOE_Master_Knowledge_Export.md +135 -0
  8. package/docs/joe_agent_custom_gpt_instructions_v_2.md +54 -0
  9. package/docs/joe_agent_spec_v_2.2.md +64 -0
  10. package/docs/schema_summary_guidelines.md +128 -0
  11. package/package.json +1 -1
  12. package/readme.md +525 -469
  13. package/server/modules/MCP.js +606 -405
  14. package/server/modules/Schemas.js +321 -111
  15. package/server/modules/Server.js +26 -15
  16. package/server/modules/Storage.js +9 -0
  17. package/server/relationships.graph.json +5 -0
  18. package/server/schemas/block.js +37 -0
  19. package/server/schemas/board.js +2 -1
  20. package/server/schemas/budget.js +28 -1
  21. package/server/schemas/event.js +42 -0
  22. package/server/schemas/financial_account.js +35 -0
  23. package/server/schemas/goal.js +30 -0
  24. package/server/schemas/group.js +31 -0
  25. package/server/schemas/include.js +28 -0
  26. package/server/schemas/ingredient.js +28 -0
  27. package/server/schemas/initiative.js +32 -0
  28. package/server/schemas/instance.js +31 -1
  29. package/server/schemas/layout.js +31 -0
  30. package/server/schemas/ledger.js +30 -0
  31. package/server/schemas/list.js +33 -0
  32. package/server/schemas/meal.js +30 -0
  33. package/server/schemas/note.js +30 -0
  34. package/server/schemas/notification.js +33 -1
  35. package/server/schemas/page.js +43 -0
  36. package/server/schemas/post.js +32 -0
  37. package/server/schemas/project.js +36 -0
  38. package/server/schemas/recipe.js +32 -0
  39. package/server/schemas/report.js +32 -0
  40. package/server/schemas/setting.js +22 -0
  41. package/server/schemas/site.js +30 -0
  42. package/server/schemas/status.js +33 -0
  43. package/server/schemas/tag.js +28 -1
  44. package/server/schemas/task.js +778 -737
  45. package/server/schemas/transaction.js +43 -0
  46. package/server/schemas/user.js +36 -1
  47. package/server/schemas/workflow.js +30 -1
@@ -1,738 +1,779 @@
1
- var task = function(){return{
2
- title : '${name}',
3
- info:"Create a new task and assign it to a team member in the project panel.",
4
- ai_instructions:"",
5
- listWindowTitle: 'Tasks',
6
- gridView:{
7
- cols:[
8
- {name:'priority 1',filter:{priority:1}},
9
- {name:'priority 2',filter:{priority:2}},
10
- {name:'priority 3',filter:{priority:3}},
11
- {name:'unprioritized',filter:{priority:1000}}
12
- ]
13
- },
14
- tableView:{
15
-
16
- },
17
- columns:3,
18
- // shortTemplate:function(currentitem,asset){
19
- // var asset = asset || currentitem || {};
20
- // var imageURL = (asset.tcin && parseInt(asset.tcin) && 'https://target.scene7.com/is/image/Target/'+asset.tcin)||
21
- // asset.thumbnail_url;
22
- // var t = '<img class="asset-icon" src='+imageURL+' />'
23
- // +'<joe-subtitle>${name}</joe-subtitle>'
24
- // +'${if (${tcin})}<joe-subtext>tcin <b>${tcin}</b></joe-subtext>${end if}'
25
- // +'<joe-subtext>#${asset_id}</joe-subtext>'
26
- // +'<joe-subtext>${asset_type_name}</joe-subtext>'
27
- // ;
28
- // return t;
29
- // },
30
- menuicon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 120"><path d="M71.51,28.79a30,30,0,1,0,0,42.43A29.9,29.9,0,0,0,71.51,28.79ZM68.19,67.9a25.31,25.31,0,1,1,0-35.8A25.15,25.15,0,0,1,68.19,67.9Z"/><polygon points="47.65 50.21 39.03 40.84 29.5 50.37 29.5 50.37 47.46 68.33 83.8 34.99 82.87 24.94 47.65 50.21"/></svg>',
31
- listTitle:function(item){
32
- var project ={},phase = '',phasename='';
33
- if(item.project){
34
- project = _joe.getDataItem(item.project,"project");
35
- if(item.project_phase){
36
- phase = project.phases.where({id:item.project_phase})[0]||{name:''};
37
- phasename = (phase.name)?' > '+phase.name:'';
38
- }
39
- }
40
- return'<joe-full-right>'
41
- +'<joe-subtitle>'+((item.points && item.points+' pts' )||'')+'</joe-subtitle>'
42
- +'<joe-title>${RUN[_joe.SERVER.User.Render.cubes;${members};]}</joe-title></joe-full-right>'
43
- //+'<joe-subtext>${RUN[_joe.getDataItemProp;${project};"project"]} </joe-subtext>'
44
- +'<joe-subtext>'+(project.name||'')+phasename+' </joe-subtext>'
45
- +`<joe-title>${item.name}</joe-title><joe-subtitle>${item.info}</joe-subtitle>
46
- ${item.due_date && `<joe-subtext>due ${item.due_date}</joe-subtext>`||''}`
47
- },
48
- searchables:['name','info','description','_id'],
49
- sorter:[
50
- 'priority','project','status',
51
- {field:'!due_date',display:'due'},
52
- 'name',
53
- {field:'!joeUpdated',display:'updated'},
54
- {field:'!points',display:'points'},
55
- {field:'project_phase',display:'phase'},
56
-
57
- ],
58
- task_types:['chore','epic'],
59
- methods:{
60
- addUser:function(userid,goto){
61
- var current = _jco(true);
62
- if(current.members.indexOf(userid) == -1){
63
- current.members.push(userid);
64
- _joe.Fields.rerender('members',{members:current.members});
65
- }
66
- if(goto){
67
- _joe.gotoSection('manage');
68
- }
69
- },
70
- doToday:function(){
71
- var current = _jco(true);
72
-
73
- var todaystr = $c.format(new Date(),'m/d/Y');
74
- var overwrites = {due_date:todaystr};
75
- var active_status = _joe.Data.status.where({
76
- datasets:{$in:[current.itemtype]},
77
- active:true,
78
- }).sortBy('index')[0] || false;
79
- if(active_status){
80
- overwrites.status = active_status._id;
81
- }
82
-
83
- _joe.Fields.rerender('due_date,status',overwrites);
84
-
85
- },
86
- assigned:function(task,userid){
87
- var userid = userid ||_joe.User._id;
88
- if((task.members||[]).indexOf(userid) != -1){
89
- return true;
90
- }
91
- var subs = (task.subtasks ||[]).where({assigned:userid});
92
- if(subs.length){
93
- return true;
94
- }
95
- return false;
96
- },
97
- setType:function(type){
98
- if(type == "chore"){
99
- _joe.Sections.unFocusAll();
100
- _joe.gotoSection('tags',{focus:'tags',activate:'true'})
101
- _joe.gotoSection('overview',{focus:'overview',activate:'true'})
102
- _joe.gotoSection('glance',{focus:'glance',activate:'true'})
103
- _joe.gotoSection('estimates',{focus:'estimates',activate:'true'})
104
- _joe.gotoSection('subtasks',{focus:'subtasks',activate:'true'})
105
-
106
- _joe.Sections.setTabbedMode(true);
107
- _joe.Sections.toggleSome(['overview','glance','estimates'],true);
108
-
109
- var wkflw = _joe.getData({query:{workflow_id:'chore'}})[0]||false;
110
- if(wkflw && wkflw.statuses && wkflw.statuses[0]){
111
- _joe.Fields.set('status',wkflw.statuses[0]);
112
- }
113
-
114
- }else{
115
- _joe.Sections.unFocusAll();
116
- _joe.Sections.setTabbedMode(false);
117
- }
118
- }
119
- },
120
- onPanelShow:function(state){
121
-
122
- },
123
- menu:function(){
124
- if(__jsu && ['super','admin','editor'].indexOf(__jsu.role) != -1 || $c.isEmpty(self.Data.user)){
125
- return [
126
- __exportBtn__,
127
- _joe.SERVER.History.button,
128
- {name:'assingme',title:'assign task to me', label:_joe.schemas.user.menuicon+'<button-text>Assign Me</button-text>', action:'_joe.schemas.task.methods.addUser(_joe.User._id,true)', css:'joe-left-button joe-orange-button joe-svg-button'},
129
- {name:'dotoday',title:'today', label:_joe.schemas.event.menuicon+'<button-text>Today</button-text>', action:'_joe.schemas.task.methods.doToday()', css:'joe-left-button joe-orange-button joe-svg-button'},
130
- __quicksaveBtn__,
131
- __deleteBtn__
132
- ];
133
- }
134
- return [];
135
- },
136
- fields:function(){
137
- var fields = [
138
- {section_start:'overview'},
139
- 'name',
140
- 'info',
141
- 'description',
142
- {section_end:'overview'},
143
-
144
- {section_start:'subtasks'},
145
- {name:'subtasks',type:'objectList',label:false,
146
- template:function(obj,subobj){
147
- var done = (subobj.sub_complete)?'joe-strike':'';
148
- return '<joe-full-right>'+(subobj.assigned && _renderUserCubes(_joe.getDataItem(subobj.assigned,'user'))||'')+'</joe-full-right>'
149
- +'<joe-subtext>${sub_duedate}</joe-subtext>'
150
- +'<joe-title class="'+done+'">${info}</joe-title>'
151
- },
152
- properties:[
153
- {name:'info'},
154
-
155
- {name:'sub_duedate', display:'due', type:'date',width:'50px'},
156
- {name:'assigned',display:'asgt',type:'select',width:'50px',
157
- onchange:'_joe.schemas.task.methods.addUser(this.value);',
158
- values:function(item){
159
- var opts = [];
160
- var item = _jco(true);
161
- if(item.members && item.members.length){
162
- opts = opts.concat(item.members);
163
- }
164
- if(item.project){
165
- var proj = _joe.getDataItem(item.project,'project');
166
- if(proj.members && proj.members.length){
167
- opts = opts.concat(proj.members);
168
- }
169
- }
170
- //opts = $.unique(opts);
171
- //opts(new Set(opts));
172
- Array.from(new Set(opts));
173
- if(!opts || !opts.length){
174
- return [];
175
- }
176
- var users = _joe.Data.user.where({_id:{$in:opts}});
177
- return users;
178
- },blank:true,
179
- idprop:'_id',template:function(t,u){
180
- if(_joe.sizeClass == "large-size"){
181
- return u.name;
182
- }
183
- var name = (u.first_name && u.first_name+' '+u.last_name) ||u.fullname || u.name;
184
- if(!name){
185
- return '';
186
- }
187
- var initials = name[0]+ (((name.indexOf(' ') > 0) && name[name.indexOf(' ')+1])||'');
188
- return initials;
189
-
190
-
191
- }
192
- },
193
-
194
- {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
195
- ]
196
- },
197
- {section_end:'subtasks'},
198
- {section_start:'acceptance',collapsed:function(item){
199
- return !(item.scceptance_criteria && item.scceptance_criteria.length);
200
- }},
201
- {name:'scceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,
202
- template:function(obj,subobj){
203
- var done = (subobj.sub_complete)?'joe-strike':'';
204
- return '<joe-title class="'+done+'">${criteria}</joe-title>' ;
205
- },
206
- properties:[
207
- {name:'criteria'},
208
-
209
- {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
210
- ]
211
- },
212
- {section_end:'acceptance'},
213
- {section_start:'related',collapsed:function(item){
214
- return !(item.files && item.files.length);
215
- }},
216
- {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
217
- 'references',
218
-
219
- {section_end:'related'},
220
-
221
- {sidebar_start:'right',collapsed:function(item){
222
- if(_joe.sizeClass == "large-size"){
223
- return false;
224
- }
225
- return (item.priority && item.project && item.status && item.due_date);
226
- }},
227
- {section_start:'glance'},
228
- {name:'task_type',type:'select',display:'task type',
229
- values:function(){
230
- return (['']).concat(_joe.schemas.task.task_types);
231
- },
232
- onchange:'_joe.schemas.task.methods.setType(this.value);',
233
- onPanelShow:function(cur){
234
- console.log('CURRENT',cur);
235
- if(cur.task_type){
236
- _joe.schemas.task.methods.setType(cur.task_type);
237
- }
238
- }
239
- },
240
- 'status',
241
- {name:'due_date',type:'date',display:'due'},
242
- {name:'complete',type:'boolean',display:'complete task',label:'click to hide from list'},
243
- {section_end:'glance'},
244
- {section_start:'organize'},
245
-
246
- {name:'project',type:'select',values:'project',goto:'project',idprop:'_id',width:'50%',blank:true,rerender:'project_phase,subtasks,parent_task',icon:_joe.schemas.project.menuicon},
247
- {name:'parent_task', width:'50%',
248
- hidden:function(item){
249
- return !item.project;
250
- },goto:'task',
251
- type:'select',values:function(item){
252
- var query = {project:item.project};
253
- if(item.project_phase){
254
- query.project_phase = item.project_phase;
255
- }
256
- var tasks = _joe.Data.task.where(query).sortBy('project_phase,priority');
257
- return tasks;
258
- },icon:'task',
259
- schema:'task',blank:true
260
- },
261
- {name:'project_phase',
262
- type:'select',
263
- blank:true,
264
- rerender:'parent_task',
265
- values:function(item){
266
- if(!item.project){
267
- return [];
268
- }
269
- var proj = _joe.getDataItem(item.project,'project');
270
- if(!proj || !proj.phases || !proj.phases.length){
271
- return [];
272
- }
273
- var vals = [];
274
- proj.phases.map(function(phase){
275
- vals.push({name:phase.name+' '+(phase.end_date && ' - '+phase.end_date ||''),value:phase.id||phase.name})
276
- })
277
- return vals;
278
- },
279
- display:'phase',width:'50%',hidden:function(item){
280
- if(!item.project){
281
- return true;
282
- }
283
- var proj = _joe.getDataItem(item.project,'project');
284
- if(!proj || !proj.phases || !proj.phases.length){
285
- return true;
286
- }
287
-
288
- return false;
289
- }},
290
-
291
- 'priority',
292
- {section_end:'organize'},
293
- {section_start:'estimates'},
294
- {name:'points',comment:'fte, scrum, etc',type:'number',display:'story points'},
295
- {name:'time_estimate',comment:'minutes',type:'number',display:'time estimate'},
296
-
297
- {section_end:'estimates'},
298
- {section_start:'manage', collapsed:function(item){
299
- return false;
300
- return (item.members && item.members.length);
301
- }},
302
- {extend:'members',specs:{rerender:'subtasks'}},
303
- {label:'comments'},
304
- 'user_comments',
305
- {section_end:'manage'},
306
- {section_start:'reports',collapsed:true},
307
- 'reports',
308
- {section_end:'reports'},
309
- {section_start:'tags',collapsed:true},
310
- 'tags',
311
- {section_end:'tags'},
312
- {section_start:'access'},
313
- '_protected',
314
- {section_end:'access'},
315
-
316
- {sidebar_end:'right'},
317
- {section_start:'system',collapsed:true},
318
- '_id','created','itemtype',
319
- {section_end:'system'}
320
- ];
321
- return fields;
322
- },
323
- instance:{
324
- checkbox:function(instance){
325
- return {prop:'approved'}
326
- },
327
- fields:function(){
328
- return [
329
- {name:'approved',type:'boolean',display:'APPROVED','label':'click when task is approved',width:'50%'},
330
- {name:'date',type:'date',width:'50%',native:true},
331
- //'members',
332
- {name:'members',type:'group',label:'completed by -',
333
- values:function(){
334
- return _joe.Data.user.where({custom_roles:{$in:['chore_assignee']}});
335
- }
336
- },
337
- {name:'points',type:'number'},
338
- {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
339
-
340
-
341
-
342
- ];
343
- }
344
- },
345
- filters:function(){
346
- if(!_joe.Cache.static.weekstart){
347
- var curr = new Date;
348
- var startD,endD;
349
-
350
- startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
351
- startD.setHours(0,0,0);
352
- _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
353
- endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
354
- endD.setHours(0,0,0);
355
- _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
356
- }
357
- var filters = [];
358
- var others =[
359
- {group_start:'priorities',collapsed:true/*,name:'prioritized',
360
- filter:{$and:[{priority:{$nin:[null,'']}},{priority:{$exists:true}}]}*/
361
- },
362
- {name:'priority 1',filter:{priority:1},
363
- stripecolor:_joe.Colors.priority[1]},
364
- {name:'priority 2',filter:{priority:2},stripecolor:
365
- _joe.Colors.priority[2]},
366
- {name:'priority 3',filter:{priority:3},
367
- stripecolor:_joe.Colors.priority[3]},
368
- {name:'unprioritized',filter:{priority:1000}},
369
- {group_end:'priorities'},
370
-
371
- {name:'My Tasks',filter:{members:{$in:[_joe.User._id]}}},
372
- {name:'unassigned',filter:{complete:{$nin:['true',true]},$or:[{members:{$lte:0}},{members:{$exists:false}}]}},
373
- {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}}
374
-
375
- ];
376
-
377
- var stats = _joe.Filter.Options.status({
378
- schema:'task',
379
- group:'status',
380
- collapsed:true,
381
- none:true
382
- });
383
- filters = filters.concat(stats,
384
-
385
- _joe.Filter.Options.tags({
386
- schema:'task',
387
- group:'tags',
388
- collapsed:true
389
- }),
390
- _joe.Filter.Options.datasetProperty('user','members',{
391
- group:'members',
392
- collapsed:true
393
- }),
394
- others
395
- );
396
- /*_joe.Data.status.sortBy('index')
397
- .where({datasets:{$in:['task']}}).map(function(status){
398
- stats.push({name:status.name,filter:{status:status._id},bgcolor:status.color})
399
- })*/
400
-
401
-
402
-
403
- return filters;
404
- },
405
- stripeColor:function(item){
406
- if(item.priority && item.priority < 100){
407
- return {
408
- title:`P${item.priority}`,
409
- color:_joe.Colors.priority[item.priority]
410
- };
411
- }
412
- },
413
- bgColor:function(item){
414
- if(!item.status){
415
- return '';
416
- }
417
- var status = _joe.getDataItem(item.status,'status');
418
- /* var color = _joe.getDataItemProp(item.status,'status','color');*/
419
- return {color:status.color,title:status.name};
420
- },
421
- /* stripeColor:[
422
- {color:'#000',filter:{priority:1}},
423
- {color:'#999',filter:{priority:2}}
424
- ],*/
425
- checkbox:{prop:'complete',percentage:function(item){
426
- if(!item.subtasks || !item.subtasks.length){
427
- return false;
428
- }
429
- var subs = item.subtasks;
430
- return (subs.filter(function(sub){return sub.sub_complete;}).length/subs.length);
431
- }},
432
- subsets:function(){
433
- if(!_joe.Cache.static.weekstart){
434
- var curr = new Date;
435
- var startD,endD;
436
-
437
- startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
438
- startD.setHours(0,0,0);
439
- _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
440
- endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
441
- endD.setHours(0,0,0);
442
- _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
443
- }
444
- var sets = [
445
- {name:'ACTIVE',default:true,filter:
446
- function(){
447
- if(this.task_type == "chore"){
448
- return false;
449
- }
450
- if(this.complete){
451
- return false;
452
- }
453
- if(!this.status){
454
- return false;
455
- }
456
- else{
457
- //var s = _joe.Cache.get(this.status);
458
- var s = $.get(this.status);
459
- if(s.inactive || s.terminal || s.default){
460
- return false;
461
- }
462
- }
463
- return true;
464
- }
465
- },
466
- {name:'Incomplete',filter:
467
- function(){
468
- if(this.complete){
469
- return false;
470
- }
471
- if(this.status){
472
- if(_joe.Cache.get(this.status).inactive){
473
- return false;
474
- }
475
- }
476
- return true;
477
- }
478
- },
479
-
480
- {name:'inactive',filter:
481
- function(){
482
- if(this.complete){
483
- return false;
484
- }
485
- if(this.status){
486
- if(_joe.Cache.get(this.status).inactive){
487
- return true;
488
- }
489
- }
490
- return false;
491
- }
492
- },
493
- //{name:'My Tasks',default:true,filter:{complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}},
494
- {name:'My Tasks',filter:function(ind,item){
495
- if(parseBoolean(this.complete)){
496
- return false;
497
- }
498
- if((this.members||[]).indexOf(_joe.User._id) != -1){
499
- return true;
500
- }
501
- var subs = (this.subtasks ||[]).where({assigned:_joe.User._id});
502
- if(subs.length){
503
- return true;
504
- }
505
- }},
506
- // {complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}
507
-
508
-
509
- {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}},
510
- ];
511
-
512
-
513
-
514
- sets.push({group_start:'projects',collapsed:true, name:'projects',filter:{project:{$in:[null,'']}}})
515
- var projs = [];
516
- _joe.Data.project.map(function(p){
517
- if(p.complete != true){
518
- projs.push({name: p.name,filter:{project: p._id,complete:{$nin:['true',true]}}});
519
- }
520
- });
521
- sets = sets.concat(projs.sortBy('name'));
522
- sets.push({group_end:'projects'})
523
-
524
- var tts = [];
525
- sets.push({group_start:'task_type',collapsed:false, name:'task type',filter:{project:{$in:[null,'']}}})
526
- _joe.schemas.task.task_types.map(function(tt){
527
- tts.push({name: tt,filter:{task_type: tt}});
528
-
529
- });
530
- sets = sets.concat(tts);
531
- sets.push({group_end:'task_type'})
532
- sets.push({name:'completed',sorter:['!joeUpdated'],filter:{complete:{$in:['true',true]}}});
533
- return sets;
534
- },
535
-
536
-
537
- idprop : "_id",
538
- onDemandExpander:true,
539
- itemExpander:function(task){
540
- if(task.subtasks && task.subtasks.length){
541
- var subtask_html = '<joe-card><joe-title>Subtasks</joe-title>';
542
- task.subtasks.map(function(st){
543
- subtask_html +='<div class="joe-subtitle '+(st.assigned && "lh-30"||"")+' clear '
544
- +(st.sub_complete && 'joe-strike' || '')+'">'
545
- +((st.assigned && _renderUserCubes(_joe.getDataItem(st.assigned,'user')))||'')
546
- +st.info
547
- +((st.sub_duedate && ' - '+st.sub_duedate)||'')
548
- +'</div>';
549
- })
550
- subtask_html+='</joe-card>';
551
- //+fillTemplate('<div class="joe-subtitle">${info}</div>',task.subtasks);
552
- return subtask_html;
553
-
554
- }else{
555
- return '';
556
- }
557
- },
558
- new:function(){
559
- var payload = {
560
- itemtype:'task',
561
- created:(new Date).toISOString(),
562
- _id:cuid()
563
- };
564
- if(_joe.current.subset){
565
- payload.project = (_joe.Data.project.where({name:_joe.current.subset.name})[0]||{_id:null})._id;
566
- }
567
- return payload;
568
- },
569
- report:{
570
- name:'standard report',
571
- info:'the report that comes with joe',
572
- template:function(task,templateData){
573
- var content = ``;
574
- if(task.project){
575
- var projectSchema = JOE.Schemas.schema.project;
576
- var project = JOE.Cache.findByID("project",task.project);
577
- content+=`
578
- <report-section class="marginless">
579
- <a class="report-content-item" target="_blank" href="/API/plugin/reportbuilder/standard/?itemid=${task.project}">
580
- <report-icon>${projectSchema.menuicon}</report-icon>
581
- <joe-subtitle>Project</joe-subtitle><joe-title>${project.name}</joe-title>
582
- </a>
583
- <div style="clear:both;"></div>
584
- </report-section>
585
- `;
586
- }
587
- if(task.description){
588
- content+=`<report-section>
589
- <report-section-label>Description</report-section-label>
590
- ${task.description}
591
- </report-section>`;
592
- }
593
- if(task.subtasks && task.subtasks.length){
594
- content+=`<report-section>
595
- <report-section-label>Subtasks</report-section-label>
596
- ${task.subtasks.map(t=>{
597
- return `<report-subtask class="complete-${t.sub_complete}">${t.info}</report-subtask>`;
598
- }).join('')}
599
- </report-section>`;
600
- }
601
- return content;
602
- }
603
-
604
- },
605
- reports:{
606
- chore_cards:{
607
- name:'Chore Cards',
608
- template_type:'module',
609
- template:function(data){
610
- var schema = JOE.Schemas.raw_schemas.task;
611
- var icon = schema.menuicon;
612
- //var icon = JOE.SC
613
- var start=0,count=10,tasks;
614
- if(data.request.query && data.request.query.where){
615
-
616
- tasks = JOE.Data.task.where(eval('('+data.request.query.where+')'));
617
- }else{
618
- tasks = JOE.Data.task;
619
- }
620
- tasks = tasks.slice(start,count);
621
- logit(tasks);
622
- function renderCard(task){
623
- return `<task-card><card-front>
624
- <card-icon>${icon}</card-icon>
625
- <joe-title>${task.name}</joe-title>
626
- <card-points>${(task.points && `<pts-number>${task.points}</pts-number> pts`)||''}</card-points>
627
- </card-front>
628
- </task-card>`;
629
- }
630
- var template =`
631
- <html>
632
- <head>
633
- <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
634
- <link rel="stylesheet" href="/JsonObjectEditor/css/joe.css">
635
- <link rel="stylesheet" href="/JsonObjectEditor/css/report-styles.css">
636
- <link rel="icon" href="/chore_favicon.ico?v=2" type="image/x-icon" />
637
- <link rel="icon" sizes="192x192" href="/chore-192x192.png">
638
- <meta name="mobile-web-app-capable" content="yes">
639
- <title>Chore Cards</title>
640
- <style>
641
- html,body{
642
- background:#fff;
643
- }
644
- *{ padding:0; margin:0; position:relative;}
645
- task-card{
646
- width:calc(50% - 12px);
647
- margin:4px;
648
- height:198px;
649
- border:2px solid #999;
650
-
651
- display:block;
652
- float:left;
653
- }
654
- card-front{
655
- display:block;
656
- text-align:center;
657
- padding-top:20px;
658
- }
659
- card-icon {
660
- position: absolute;
661
- top: -10px;
662
- left: -10px;
663
- width: 80px;
664
- opacity:.8;
665
- }
666
- card-points{
667
- font-weight:bold;
668
- color:#999;
669
- font-size:24px;
670
- }
671
- card-front joe-title {
672
- font-size: 24px;
673
- margin: 30px 20px 10px 20px;
674
- }
675
- </style>
676
- </head>
677
- <body>
678
- ${tasks.map(renderCard).join('')}
679
- </body>
680
-
681
- </html>
682
- `;
683
- return template;
684
- }
685
- }
686
- },
687
- events:{
688
- create:function(item,specs){
689
- var members = item.members;
690
- var member;
691
- var status = JOE.Cache.findByID('status',item.status)||{};
692
- var project = JOE.Cache.findByID('project',item.project)||{};
693
- members.map(function(mem){
694
- member = JOE.Cache.findByID('user',mem);
695
- if(member){
696
- logit('sending assignment email to: '+member.email);
697
- /*cd75a051-dcec-4306-8894-e1dc64853306*/
698
- JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
699
- ASSIGNED:member,
700
- TASK:item,
701
- PROJECT:project,
702
- STATUS:status
703
- })
704
- }
705
- })
706
-
707
- },
708
- save:function(item,specs){
709
-
710
- $c.DEBUG_MODE =false;
711
- if(specs.cached && specs.historical_info.changes && specs.historical_info.changes.members){
712
- var cached_members = specs.cached.members;
713
- var members = item.members;
714
- var member;
715
- var status = JOE.Cache.findByID('status',item.status)||{};
716
- var project = JOE.Cache.findByID('project',item.project)||{};
717
- members.map(function(mem){
718
- if(cached_members.indexOf(mem) == -1){
719
- member = JOE.Cache.findByID('user',mem);
720
- if(member){
721
- logit('sending assignment email to: '+member.email);
722
- /*cd75a051-dcec-4306-8894-e1dc64853306*/
723
- JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
724
- ASSIGNED:member,
725
- TASK:item,
726
- PROJECT:project,
727
- STATUS:status
728
- })
729
- }
730
- }
731
- })
732
- }
733
- }
734
- }
735
- }
736
- };
737
-
1
+ var task = function(){return{
2
+ title : '${name}',
3
+ info:"Create a new task and assign it to a team member in the project panel.",
4
+ ai_instructions:"",
5
+ listWindowTitle: 'Tasks',
6
+ gridView:{
7
+ cols:[
8
+ {name:'priority 1',filter:{priority:1}},
9
+ {name:'priority 2',filter:{priority:2}},
10
+ {name:'priority 3',filter:{priority:3}},
11
+ {name:'unprioritized',filter:{priority:1000}}
12
+ ]
13
+ },
14
+ tableView:{
15
+
16
+ },
17
+ columns:3,
18
+ // shortTemplate:function(currentitem,asset){
19
+ // var asset = asset || currentitem || {};
20
+ // var imageURL = (asset.tcin && parseInt(asset.tcin) && 'https://target.scene7.com/is/image/Target/'+asset.tcin)||
21
+ // asset.thumbnail_url;
22
+ // var t = '<img class="asset-icon" src='+imageURL+' />'
23
+ // +'<joe-subtitle>${name}</joe-subtitle>'
24
+ // +'${if (${tcin})}<joe-subtext>tcin <b>${tcin}</b></joe-subtext>${end if}'
25
+ // +'<joe-subtext>#${asset_id}</joe-subtext>'
26
+ // +'<joe-subtext>${asset_type_name}</joe-subtext>'
27
+ // ;
28
+ // return t;
29
+ // },
30
+ menuicon:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 120"><path d="M71.51,28.79a30,30,0,1,0,0,42.43A29.9,29.9,0,0,0,71.51,28.79ZM68.19,67.9a25.31,25.31,0,1,1,0-35.8A25.15,25.15,0,0,1,68.19,67.9Z"/><polygon points="47.65 50.21 39.03 40.84 29.5 50.37 29.5 50.37 47.46 68.33 83.8 34.99 82.87 24.94 47.65 50.21"/></svg>',
31
+ listTitle:function(item){
32
+ var project ={},phase = '',phasename='';
33
+ if(item.project){
34
+ project = _joe.getDataItem(item.project,"project");
35
+ if(item.project_phase){
36
+ phase = project.phases.where({id:item.project_phase})[0]||{name:''};
37
+ phasename = (phase.name)?' > '+phase.name:'';
38
+ }
39
+ }
40
+ return'<joe-full-right>'
41
+ +'<joe-subtitle>'+((item.points && item.points+' pts' )||'')+'</joe-subtitle>'
42
+ +'<joe-title>${RUN[_joe.SERVER.User.Render.cubes;${members};]}</joe-title></joe-full-right>'
43
+ //+'<joe-subtext>${RUN[_joe.getDataItemProp;${project};"project"]} </joe-subtext>'
44
+ +'<joe-subtext>'+(project.name||'')+phasename+' </joe-subtext>'
45
+ +`<joe-title>${item.name}</joe-title><joe-subtitle>${item.info}</joe-subtitle>
46
+ ${item.due_date && `<joe-subtext>due ${item.due_date}</joe-subtext>`||''}`
47
+ },
48
+ searchables:['name','info','description','_id'],
49
+ sorter:[
50
+ 'priority','project','status',
51
+ {field:'!due_date',display:'due'},
52
+ 'name',
53
+ {field:'!joeUpdated',display:'updated'},
54
+ {field:'!points',display:'points'},
55
+ {field:'project_phase',display:'phase'},
56
+
57
+ ],
58
+ // Curated summary for agents (normalized, stable)
59
+ summary:{
60
+ description:'Work item tracked against projects and users; used for planning and execution.',
61
+ purpose:'Tasks track units of work for users and projects. A task belongs to a single project (optional), has a single status, may have a single parent task, and can be associated to many users (members) and many tags. Use the task schema to manage actionable items, planning, and execution state; resolve related names via project/status/user/tag when presenting to users.',
62
+ labelField:'name',
63
+ defaultSort:{ field:'joeUpdated', dir:'desc' },
64
+ searchableFields:['name','info','description','_id'],
65
+ allowedSorts:['priority','project','status','due_date','name','joeUpdated','points','project_phase','created'],
66
+ relationships:{
67
+ outbound:[
68
+ { field:'status', targetSchema:'status', cardinality:'one' },
69
+ { field:'project', targetSchema:'project', cardinality:'one' },
70
+ { field:'parent_task', targetSchema:'task', cardinality:'one' },
71
+ { field:'members', targetSchema:'user', cardinality:'many' },
72
+ { field:'tags', targetSchema:'tag', cardinality:'many' }
73
+ ],
74
+ inbound:{ graphRef:'server/relationships.graph.json' }
75
+ },
76
+ joeManagedFields:['created','joeUpdated'],
77
+ fields:[
78
+ { name:'_id', type:'string', required:true },
79
+ { name:'itemtype', type:'string', required:true, const:'task' },
80
+ { name:'name', type:'string', required:true },
81
+ { name:'info', type:'string' },
82
+ { name:'description', type:'string' },
83
+ { name:'task_type', type:'string', enumValues:['chore','epic'] },
84
+ { name:'status', type:'string', isReference:true, targetSchema:'status', required:true },
85
+ { name:'project', type:'string', isReference:true, targetSchema:'project' },
86
+ { name:'parent_task', type:'string', isReference:true, targetSchema:'task' },
87
+ { name:'project_phase', type:'string' },
88
+ { name:'priority', type:'number', enumValues:[1,2,3,1000] },
89
+ { name:'due_date', type:'string', format:'date-time' },
90
+ { name:'complete', type:'boolean' },
91
+ { name:'members', type:'string', isArray:true, isReference:true, targetSchema:'user' },
92
+ { name:'tags', type:'string', isArray:true, isReference:true, targetSchema:'tag' },
93
+ { name:'points', type:'number' },
94
+ { name:'time_estimate', type:'number' },
95
+ { name:'joeUpdated', type:'string', format:'date-time', required:true },
96
+ { name:'created', type:'string', format:'date-time', required:true }
97
+ ]
98
+ },
99
+ task_types:['chore','epic'],
100
+ methods:{
101
+ addUser:function(userid,goto){
102
+ var current = _jco(true);
103
+ if(current.members.indexOf(userid) == -1){
104
+ current.members.push(userid);
105
+ _joe.Fields.rerender('members',{members:current.members});
106
+ }
107
+ if(goto){
108
+ _joe.gotoSection('manage');
109
+ }
110
+ },
111
+ doToday:function(){
112
+ var current = _jco(true);
113
+
114
+ var todaystr = $c.format(new Date(),'m/d/Y');
115
+ var overwrites = {due_date:todaystr};
116
+ var active_status = _joe.Data.status.where({
117
+ datasets:{$in:[current.itemtype]},
118
+ active:true,
119
+ }).sortBy('index')[0] || false;
120
+ if(active_status){
121
+ overwrites.status = active_status._id;
122
+ }
123
+
124
+ _joe.Fields.rerender('due_date,status',overwrites);
125
+
126
+ },
127
+ assigned:function(task,userid){
128
+ var userid = userid ||_joe.User._id;
129
+ if((task.members||[]).indexOf(userid) != -1){
130
+ return true;
131
+ }
132
+ var subs = (task.subtasks ||[]).where({assigned:userid});
133
+ if(subs.length){
134
+ return true;
135
+ }
136
+ return false;
137
+ },
138
+ setType:function(type){
139
+ if(type == "chore"){
140
+ _joe.Sections.unFocusAll();
141
+ _joe.gotoSection('tags',{focus:'tags',activate:'true'})
142
+ _joe.gotoSection('overview',{focus:'overview',activate:'true'})
143
+ _joe.gotoSection('glance',{focus:'glance',activate:'true'})
144
+ _joe.gotoSection('estimates',{focus:'estimates',activate:'true'})
145
+ _joe.gotoSection('subtasks',{focus:'subtasks',activate:'true'})
146
+
147
+ _joe.Sections.setTabbedMode(true);
148
+ _joe.Sections.toggleSome(['overview','glance','estimates'],true);
149
+
150
+ var wkflw = _joe.getData({query:{workflow_id:'chore'}})[0]||false;
151
+ if(wkflw && wkflw.statuses && wkflw.statuses[0]){
152
+ _joe.Fields.set('status',wkflw.statuses[0]);
153
+ }
154
+
155
+ }else{
156
+ _joe.Sections.unFocusAll();
157
+ _joe.Sections.setTabbedMode(false);
158
+ }
159
+ }
160
+ },
161
+ onPanelShow:function(state){
162
+
163
+ },
164
+ menu:function(){
165
+ if(__jsu && ['super','admin','editor'].indexOf(__jsu.role) != -1 || $c.isEmpty(self.Data.user)){
166
+ return [
167
+ __exportBtn__,
168
+ _joe.SERVER.History.button,
169
+ {name:'assingme',title:'assign task to me', label:_joe.schemas.user.menuicon+'<button-text>Assign Me</button-text>', action:'_joe.schemas.task.methods.addUser(_joe.User._id,true)', css:'joe-left-button joe-orange-button joe-svg-button'},
170
+ {name:'dotoday',title:'today', label:_joe.schemas.event.menuicon+'<button-text>Today</button-text>', action:'_joe.schemas.task.methods.doToday()', css:'joe-left-button joe-orange-button joe-svg-button'},
171
+ __quicksaveBtn__,
172
+ __deleteBtn__
173
+ ];
174
+ }
175
+ return [];
176
+ },
177
+ fields:function(){
178
+ var fields = [
179
+ {section_start:'overview'},
180
+ 'name',
181
+ 'info',
182
+ 'description',
183
+ {section_end:'overview'},
184
+
185
+ {section_start:'subtasks'},
186
+ {name:'subtasks',type:'objectList',label:false,
187
+ template:function(obj,subobj){
188
+ var done = (subobj.sub_complete)?'joe-strike':'';
189
+ return '<joe-full-right>'+(subobj.assigned && _renderUserCubes(_joe.getDataItem(subobj.assigned,'user'))||'')+'</joe-full-right>'
190
+ +'<joe-subtext>${sub_duedate}</joe-subtext>'
191
+ +'<joe-title class="'+done+'">${info}</joe-title>'
192
+ },
193
+ properties:[
194
+ {name:'info'},
195
+
196
+ {name:'sub_duedate', display:'due', type:'date',width:'50px'},
197
+ {name:'assigned',display:'asgt',type:'select',width:'50px',
198
+ onchange:'_joe.schemas.task.methods.addUser(this.value);',
199
+ values:function(item){
200
+ var opts = [];
201
+ var item = _jco(true);
202
+ if(item.members && item.members.length){
203
+ opts = opts.concat(item.members);
204
+ }
205
+ if(item.project){
206
+ var proj = _joe.getDataItem(item.project,'project');
207
+ if(proj.members && proj.members.length){
208
+ opts = opts.concat(proj.members);
209
+ }
210
+ }
211
+ //opts = $.unique(opts);
212
+ //opts(new Set(opts));
213
+ Array.from(new Set(opts));
214
+ if(!opts || !opts.length){
215
+ return [];
216
+ }
217
+ var users = _joe.Data.user.where({_id:{$in:opts}});
218
+ return users;
219
+ },blank:true,
220
+ idprop:'_id',template:function(t,u){
221
+ if(_joe.sizeClass == "large-size"){
222
+ return u.name;
223
+ }
224
+ var name = (u.first_name && u.first_name+' '+u.last_name) ||u.fullname || u.name;
225
+ if(!name){
226
+ return '';
227
+ }
228
+ var initials = name[0]+ (((name.indexOf(' ') > 0) && name[name.indexOf(' ')+1])||'');
229
+ return initials;
230
+
231
+
232
+ }
233
+ },
234
+
235
+ {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
236
+ ]
237
+ },
238
+ {section_end:'subtasks'},
239
+ {section_start:'acceptance',collapsed:function(item){
240
+ return !(item.scceptance_criteria && item.scceptance_criteria.length);
241
+ }},
242
+ {name:'scceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,
243
+ template:function(obj,subobj){
244
+ var done = (subobj.sub_complete)?'joe-strike':'';
245
+ return '<joe-title class="'+done+'">${criteria}</joe-title>' ;
246
+ },
247
+ properties:[
248
+ {name:'criteria'},
249
+
250
+ {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
251
+ ]
252
+ },
253
+ {section_end:'acceptance'},
254
+ {section_start:'related',collapsed:function(item){
255
+ return !(item.files && item.files.length);
256
+ }},
257
+ {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
258
+ 'references',
259
+
260
+ {section_end:'related'},
261
+
262
+ {sidebar_start:'right',collapsed:function(item){
263
+ if(_joe.sizeClass == "large-size"){
264
+ return false;
265
+ }
266
+ return (item.priority && item.project && item.status && item.due_date);
267
+ }},
268
+ {section_start:'glance'},
269
+ {name:'task_type',type:'select',display:'task type',
270
+ values:function(){
271
+ return (['']).concat(_joe.schemas.task.task_types);
272
+ },
273
+ onchange:'_joe.schemas.task.methods.setType(this.value);',
274
+ onPanelShow:function(cur){
275
+ console.log('CURRENT',cur);
276
+ if(cur.task_type){
277
+ _joe.schemas.task.methods.setType(cur.task_type);
278
+ }
279
+ }
280
+ },
281
+ 'status',
282
+ {name:'due_date',type:'date',display:'due'},
283
+ {name:'complete',type:'boolean',display:'complete task',label:'click to hide from list'},
284
+ {section_end:'glance'},
285
+ {section_start:'organize'},
286
+
287
+ {name:'project',type:'select',values:'project',goto:'project',idprop:'_id',width:'50%',blank:true,rerender:'project_phase,subtasks,parent_task',icon:_joe.schemas.project.menuicon},
288
+ {name:'parent_task', width:'50%',
289
+ hidden:function(item){
290
+ return !item.project;
291
+ },goto:'task',
292
+ type:'select',values:function(item){
293
+ var query = {project:item.project};
294
+ if(item.project_phase){
295
+ query.project_phase = item.project_phase;
296
+ }
297
+ var tasks = _joe.Data.task.where(query).sortBy('project_phase,priority');
298
+ return tasks;
299
+ },icon:'task',
300
+ schema:'task',blank:true
301
+ },
302
+ {name:'project_phase',
303
+ type:'select',
304
+ blank:true,
305
+ rerender:'parent_task',
306
+ values:function(item){
307
+ if(!item.project){
308
+ return [];
309
+ }
310
+ var proj = _joe.getDataItem(item.project,'project');
311
+ if(!proj || !proj.phases || !proj.phases.length){
312
+ return [];
313
+ }
314
+ var vals = [];
315
+ proj.phases.map(function(phase){
316
+ vals.push({name:phase.name+' '+(phase.end_date && ' - '+phase.end_date ||''),value:phase.id||phase.name})
317
+ })
318
+ return vals;
319
+ },
320
+ display:'phase',width:'50%',hidden:function(item){
321
+ if(!item.project){
322
+ return true;
323
+ }
324
+ var proj = _joe.getDataItem(item.project,'project');
325
+ if(!proj || !proj.phases || !proj.phases.length){
326
+ return true;
327
+ }
328
+
329
+ return false;
330
+ }},
331
+
332
+ 'priority',
333
+ {section_end:'organize'},
334
+ {section_start:'estimates'},
335
+ {name:'points',comment:'fte, scrum, etc',type:'number',display:'story points'},
336
+ {name:'time_estimate',comment:'minutes',type:'number',display:'time estimate'},
337
+
338
+ {section_end:'estimates'},
339
+ {section_start:'manage', collapsed:function(item){
340
+ return false;
341
+ return (item.members && item.members.length);
342
+ }},
343
+ {extend:'members',specs:{rerender:'subtasks'}},
344
+ {label:'comments'},
345
+ 'user_comments',
346
+ {section_end:'manage'},
347
+ {section_start:'reports',collapsed:true},
348
+ 'reports',
349
+ {section_end:'reports'},
350
+ {section_start:'tags',collapsed:true},
351
+ 'tags',
352
+ {section_end:'tags'},
353
+ {section_start:'access'},
354
+ '_protected',
355
+ {section_end:'access'},
356
+
357
+ {sidebar_end:'right'},
358
+ {section_start:'system',collapsed:true},
359
+ '_id','created','itemtype',
360
+ {section_end:'system'}
361
+ ];
362
+ return fields;
363
+ },
364
+ instance:{
365
+ checkbox:function(instance){
366
+ return {prop:'approved'}
367
+ },
368
+ fields:function(){
369
+ return [
370
+ {name:'approved',type:'boolean',display:'APPROVED','label':'click when task is approved',width:'50%'},
371
+ {name:'date',type:'date',width:'50%',native:true},
372
+ //'members',
373
+ {name:'members',type:'group',label:'completed by -',
374
+ values:function(){
375
+ return _joe.Data.user.where({custom_roles:{$in:['chore_assignee']}});
376
+ }
377
+ },
378
+ {name:'points',type:'number'},
379
+ {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
380
+
381
+
382
+
383
+ ];
384
+ }
385
+ },
386
+ filters:function(){
387
+ if(!_joe.Cache.static.weekstart){
388
+ var curr = new Date;
389
+ var startD,endD;
390
+
391
+ startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
392
+ startD.setHours(0,0,0);
393
+ _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
394
+ endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
395
+ endD.setHours(0,0,0);
396
+ _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
397
+ }
398
+ var filters = [];
399
+ var others =[
400
+ {group_start:'priorities',collapsed:true/*,name:'prioritized',
401
+ filter:{$and:[{priority:{$nin:[null,'']}},{priority:{$exists:true}}]}*/
402
+ },
403
+ {name:'priority 1',filter:{priority:1},
404
+ stripecolor:_joe.Colors.priority[1]},
405
+ {name:'priority 2',filter:{priority:2},stripecolor:
406
+ _joe.Colors.priority[2]},
407
+ {name:'priority 3',filter:{priority:3},
408
+ stripecolor:_joe.Colors.priority[3]},
409
+ {name:'unprioritized',filter:{priority:1000}},
410
+ {group_end:'priorities'},
411
+
412
+ {name:'My Tasks',filter:{members:{$in:[_joe.User._id]}}},
413
+ {name:'unassigned',filter:{complete:{$nin:['true',true]},$or:[{members:{$lte:0}},{members:{$exists:false}}]}},
414
+ {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}}
415
+
416
+ ];
417
+
418
+ var stats = _joe.Filter.Options.status({
419
+ schema:'task',
420
+ group:'status',
421
+ collapsed:true,
422
+ none:true
423
+ });
424
+ filters = filters.concat(stats,
425
+
426
+ _joe.Filter.Options.tags({
427
+ schema:'task',
428
+ group:'tags',
429
+ collapsed:true
430
+ }),
431
+ _joe.Filter.Options.datasetProperty('user','members',{
432
+ group:'members',
433
+ collapsed:true
434
+ }),
435
+ others
436
+ );
437
+ /*_joe.Data.status.sortBy('index')
438
+ .where({datasets:{$in:['task']}}).map(function(status){
439
+ stats.push({name:status.name,filter:{status:status._id},bgcolor:status.color})
440
+ })*/
441
+
442
+
443
+
444
+ return filters;
445
+ },
446
+ stripeColor:function(item){
447
+ if(item.priority && item.priority < 100){
448
+ return {
449
+ title:`P${item.priority}`,
450
+ color:_joe.Colors.priority[item.priority]
451
+ };
452
+ }
453
+ },
454
+ bgColor:function(item){
455
+ if(!item.status){
456
+ return '';
457
+ }
458
+ var status = _joe.getDataItem(item.status,'status');
459
+ /* var color = _joe.getDataItemProp(item.status,'status','color');*/
460
+ return {color:status.color,title:status.name};
461
+ },
462
+ /* stripeColor:[
463
+ {color:'#000',filter:{priority:1}},
464
+ {color:'#999',filter:{priority:2}}
465
+ ],*/
466
+ checkbox:{prop:'complete',percentage:function(item){
467
+ if(!item.subtasks || !item.subtasks.length){
468
+ return false;
469
+ }
470
+ var subs = item.subtasks;
471
+ return (subs.filter(function(sub){return sub.sub_complete;}).length/subs.length);
472
+ }},
473
+ subsets:function(){
474
+ if(!_joe.Cache.static.weekstart){
475
+ var curr = new Date;
476
+ var startD,endD;
477
+
478
+ startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
479
+ startD.setHours(0,0,0);
480
+ _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
481
+ endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
482
+ endD.setHours(0,0,0);
483
+ _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
484
+ }
485
+ var sets = [
486
+ {name:'ACTIVE',default:true,filter:
487
+ function(){
488
+ if(this.task_type == "chore"){
489
+ return false;
490
+ }
491
+ if(this.complete){
492
+ return false;
493
+ }
494
+ if(!this.status){
495
+ return false;
496
+ }
497
+ else{
498
+ //var s = _joe.Cache.get(this.status);
499
+ var s = $.get(this.status);
500
+ if(s.inactive || s.terminal || s.default){
501
+ return false;
502
+ }
503
+ }
504
+ return true;
505
+ }
506
+ },
507
+ {name:'Incomplete',filter:
508
+ function(){
509
+ if(this.complete){
510
+ return false;
511
+ }
512
+ if(this.status){
513
+ if(_joe.Cache.get(this.status).inactive){
514
+ return false;
515
+ }
516
+ }
517
+ return true;
518
+ }
519
+ },
520
+
521
+ {name:'inactive',filter:
522
+ function(){
523
+ if(this.complete){
524
+ return false;
525
+ }
526
+ if(this.status){
527
+ if(_joe.Cache.get(this.status).inactive){
528
+ return true;
529
+ }
530
+ }
531
+ return false;
532
+ }
533
+ },
534
+ //{name:'My Tasks',default:true,filter:{complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}},
535
+ {name:'My Tasks',filter:function(ind,item){
536
+ if(parseBoolean(this.complete)){
537
+ return false;
538
+ }
539
+ if((this.members||[]).indexOf(_joe.User._id) != -1){
540
+ return true;
541
+ }
542
+ var subs = (this.subtasks ||[]).where({assigned:_joe.User._id});
543
+ if(subs.length){
544
+ return true;
545
+ }
546
+ }},
547
+ // {complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}
548
+
549
+
550
+ {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}},
551
+ ];
552
+
553
+
554
+
555
+ sets.push({group_start:'projects',collapsed:true, name:'projects',filter:{project:{$in:[null,'']}}})
556
+ var projs = [];
557
+ _joe.Data.project.map(function(p){
558
+ if(p.complete != true){
559
+ projs.push({name: p.name,filter:{project: p._id,complete:{$nin:['true',true]}}});
560
+ }
561
+ });
562
+ sets = sets.concat(projs.sortBy('name'));
563
+ sets.push({group_end:'projects'})
564
+
565
+ var tts = [];
566
+ sets.push({group_start:'task_type',collapsed:false, name:'task type',filter:{project:{$in:[null,'']}}})
567
+ _joe.schemas.task.task_types.map(function(tt){
568
+ tts.push({name: tt,filter:{task_type: tt}});
569
+
570
+ });
571
+ sets = sets.concat(tts);
572
+ sets.push({group_end:'task_type'})
573
+ sets.push({name:'completed',sorter:['!joeUpdated'],filter:{complete:{$in:['true',true]}}});
574
+ return sets;
575
+ },
576
+
577
+
578
+ idprop : "_id",
579
+ onDemandExpander:true,
580
+ itemExpander:function(task){
581
+ if(task.subtasks && task.subtasks.length){
582
+ var subtask_html = '<joe-card><joe-title>Subtasks</joe-title>';
583
+ task.subtasks.map(function(st){
584
+ subtask_html +='<div class="joe-subtitle '+(st.assigned && "lh-30"||"")+' clear '
585
+ +(st.sub_complete && 'joe-strike' || '')+'">'
586
+ +((st.assigned && _renderUserCubes(_joe.getDataItem(st.assigned,'user')))||'')
587
+ +st.info
588
+ +((st.sub_duedate && ' - '+st.sub_duedate)||'')
589
+ +'</div>';
590
+ })
591
+ subtask_html+='</joe-card>';
592
+ //+fillTemplate('<div class="joe-subtitle">${info}</div>',task.subtasks);
593
+ return subtask_html;
594
+
595
+ }else{
596
+ return '';
597
+ }
598
+ },
599
+ new:function(){
600
+ var payload = {
601
+ itemtype:'task',
602
+ created:(new Date).toISOString(),
603
+ _id:cuid()
604
+ };
605
+ if(_joe.current.subset){
606
+ payload.project = (_joe.Data.project.where({name:_joe.current.subset.name})[0]||{_id:null})._id;
607
+ }
608
+ return payload;
609
+ },
610
+ report:{
611
+ name:'standard report',
612
+ info:'the report that comes with joe',
613
+ template:function(task,templateData){
614
+ var content = ``;
615
+ if(task.project){
616
+ var projectSchema = JOE.Schemas.schema.project;
617
+ var project = JOE.Cache.findByID("project",task.project);
618
+ content+=`
619
+ <report-section class="marginless">
620
+ <a class="report-content-item" target="_blank" href="/API/plugin/reportbuilder/standard/?itemid=${task.project}">
621
+ <report-icon>${projectSchema.menuicon}</report-icon>
622
+ <joe-subtitle>Project</joe-subtitle><joe-title>${project.name}</joe-title>
623
+ </a>
624
+ <div style="clear:both;"></div>
625
+ </report-section>
626
+ `;
627
+ }
628
+ if(task.description){
629
+ content+=`<report-section>
630
+ <report-section-label>Description</report-section-label>
631
+ ${task.description}
632
+ </report-section>`;
633
+ }
634
+ if(task.subtasks && task.subtasks.length){
635
+ content+=`<report-section>
636
+ <report-section-label>Subtasks</report-section-label>
637
+ ${task.subtasks.map(t=>{
638
+ return `<report-subtask class="complete-${t.sub_complete}">${t.info}</report-subtask>`;
639
+ }).join('')}
640
+ </report-section>`;
641
+ }
642
+ return content;
643
+ }
644
+
645
+ },
646
+ reports:{
647
+ chore_cards:{
648
+ name:'Chore Cards',
649
+ template_type:'module',
650
+ template:function(data){
651
+ var schema = JOE.Schemas.raw_schemas.task;
652
+ var icon = schema.menuicon;
653
+ //var icon = JOE.SC
654
+ var start=0,count=10,tasks;
655
+ if(data.request.query && data.request.query.where){
656
+
657
+ tasks = JOE.Data.task.where(eval('('+data.request.query.where+')'));
658
+ }else{
659
+ tasks = JOE.Data.task;
660
+ }
661
+ tasks = tasks.slice(start,count);
662
+ logit(tasks);
663
+ function renderCard(task){
664
+ return `<task-card><card-front>
665
+ <card-icon>${icon}</card-icon>
666
+ <joe-title>${task.name}</joe-title>
667
+ <card-points>${(task.points && `<pts-number>${task.points}</pts-number> pts`)||''}</card-points>
668
+ </card-front>
669
+ </task-card>`;
670
+ }
671
+ var template =`
672
+ <html>
673
+ <head>
674
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
675
+ <link rel="stylesheet" href="/JsonObjectEditor/css/joe.css">
676
+ <link rel="stylesheet" href="/JsonObjectEditor/css/report-styles.css">
677
+ <link rel="icon" href="/chore_favicon.ico?v=2" type="image/x-icon" />
678
+ <link rel="icon" sizes="192x192" href="/chore-192x192.png">
679
+ <meta name="mobile-web-app-capable" content="yes">
680
+ <title>Chore Cards</title>
681
+ <style>
682
+ html,body{
683
+ background:#fff;
684
+ }
685
+ *{ padding:0; margin:0; position:relative;}
686
+ task-card{
687
+ width:calc(50% - 12px);
688
+ margin:4px;
689
+ height:198px;
690
+ border:2px solid #999;
691
+
692
+ display:block;
693
+ float:left;
694
+ }
695
+ card-front{
696
+ display:block;
697
+ text-align:center;
698
+ padding-top:20px;
699
+ }
700
+ card-icon {
701
+ position: absolute;
702
+ top: -10px;
703
+ left: -10px;
704
+ width: 80px;
705
+ opacity:.8;
706
+ }
707
+ card-points{
708
+ font-weight:bold;
709
+ color:#999;
710
+ font-size:24px;
711
+ }
712
+ card-front joe-title {
713
+ font-size: 24px;
714
+ margin: 30px 20px 10px 20px;
715
+ }
716
+ </style>
717
+ </head>
718
+ <body>
719
+ ${tasks.map(renderCard).join('')}
720
+ </body>
721
+
722
+ </html>
723
+ `;
724
+ return template;
725
+ }
726
+ }
727
+ },
728
+ events:{
729
+ create:function(item,specs){
730
+ var members = item.members;
731
+ var member;
732
+ var status = JOE.Cache.findByID('status',item.status)||{};
733
+ var project = JOE.Cache.findByID('project',item.project)||{};
734
+ members.map(function(mem){
735
+ member = JOE.Cache.findByID('user',mem);
736
+ if(member){
737
+ logit('sending assignment email to: '+member.email);
738
+ /*cd75a051-dcec-4306-8894-e1dc64853306*/
739
+ JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
740
+ ASSIGNED:member,
741
+ TASK:item,
742
+ PROJECT:project,
743
+ STATUS:status
744
+ })
745
+ }
746
+ })
747
+
748
+ },
749
+ save:function(item,specs){
750
+
751
+ $c.DEBUG_MODE =false;
752
+ if(specs.cached && specs.historical_info.changes && specs.historical_info.changes.members){
753
+ var cached_members = specs.cached.members;
754
+ var members = item.members;
755
+ var member;
756
+ var status = JOE.Cache.findByID('status',item.status)||{};
757
+ var project = JOE.Cache.findByID('project',item.project)||{};
758
+ members.map(function(mem){
759
+ if(cached_members.indexOf(mem) == -1){
760
+ member = JOE.Cache.findByID('user',mem);
761
+ if(member){
762
+ logit('sending assignment email to: '+member.email);
763
+ /*cd75a051-dcec-4306-8894-e1dc64853306*/
764
+ JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
765
+ ASSIGNED:member,
766
+ TASK:item,
767
+ PROJECT:project,
768
+ STATUS:status
769
+ })
770
+ }
771
+ }
772
+ })
773
+ }
774
+ }
775
+ }
776
+ }
777
+ };
778
+
738
779
  module.exports = task();