json-object-editor 0.10.622 → 0.10.623

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.
@@ -1,784 +1,784 @@
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
- {sidebar_start:'left'},
180
- {section_start:'JAI',display:'JOE Ai'},
181
- "objectChat",
182
- {section_end:'JAI'},
183
- {sidebar_end:'left'},
184
- {section_start:'overview'},
185
- 'name',
186
- 'info',
187
- 'description',
188
- {section_end:'overview'},
189
-
190
- {section_start:'subtasks'},
191
- {name:'subtasks',type:'objectList',label:false,
192
- template:function(obj,subobj){
193
- var done = (subobj.sub_complete)?'joe-strike':'';
194
- return '<joe-full-right>'+(subobj.assigned && _renderUserCubes(_joe.getDataItem(subobj.assigned,'user'))||'')+'</joe-full-right>'
195
- +'<joe-subtext>${sub_duedate}</joe-subtext>'
196
- +'<joe-title class="'+done+'">${info}</joe-title>'
197
- },
198
- properties:[
199
- {name:'info'},
200
-
201
- {name:'sub_duedate', display:'due', type:'date',width:'50px'},
202
- {name:'assigned',display:'asgt',type:'select',width:'50px',
203
- onchange:'_joe.schemas.task.methods.addUser(this.value);',
204
- values:function(item){
205
- var opts = [];
206
- var item = _jco(true);
207
- if(item.members && item.members.length){
208
- opts = opts.concat(item.members);
209
- }
210
- if(item.project){
211
- var proj = _joe.getDataItem(item.project,'project');
212
- if(proj.members && proj.members.length){
213
- opts = opts.concat(proj.members);
214
- }
215
- }
216
- //opts = $.unique(opts);
217
- //opts(new Set(opts));
218
- Array.from(new Set(opts));
219
- if(!opts || !opts.length){
220
- return [];
221
- }
222
- var users = _joe.Data.user.where({_id:{$in:opts}});
223
- return users;
224
- },blank:true,
225
- idprop:'_id',template:function(t,u){
226
- if(_joe.sizeClass == "large-size"){
227
- return u.name;
228
- }
229
- var name = (u.first_name && u.first_name+' '+u.last_name) ||u.fullname || u.name;
230
- if(!name){
231
- return '';
232
- }
233
- var initials = name[0]+ (((name.indexOf(' ') > 0) && name[name.indexOf(' ')+1])||'');
234
- return initials;
235
-
236
-
237
- }
238
- },
239
-
240
- {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
241
- ]
242
- },
243
- {section_end:'subtasks'},
244
- {section_start:'acceptance',collapsed:function(item){
245
- return !(item.scceptance_criteria && item.scceptance_criteria.length);
246
- }},
247
- {name:'scceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,
248
- template:function(obj,subobj){
249
- var done = (subobj.sub_complete)?'joe-strike':'';
250
- return '<joe-title class="'+done+'">${criteria}</joe-title>' ;
251
- },
252
- properties:[
253
- {name:'criteria'},
254
-
255
- {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
256
- ]
257
- },
258
- {section_end:'acceptance'},
259
- {section_start:'related',collapsed:function(item){
260
- return !(item.files && item.files.length);
261
- }},
262
- {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
263
- 'references',
264
-
265
- {section_end:'related'},
266
-
267
- {sidebar_start:'right',collapsed:function(item){
268
- if(_joe.sizeClass == "large-size"){
269
- return false;
270
- }
271
- return (item.priority && item.project && item.status && item.due_date);
272
- }},
273
- {section_start:'glance'},
274
- {name:'task_type',type:'select',display:'task type',
275
- values:function(){
276
- return (['']).concat(_joe.schemas.task.task_types);
277
- },
278
- onchange:'_joe.schemas.task.methods.setType(this.value);',
279
- onPanelShow:function(cur){
280
- console.log('CURRENT',cur);
281
- if(cur.task_type){
282
- _joe.schemas.task.methods.setType(cur.task_type);
283
- }
284
- }
285
- },
286
- 'status',
287
- {name:'due_date',type:'date',display:'due'},
288
- {name:'complete',type:'boolean',display:'complete task',label:'click to hide from list'},
289
- {section_end:'glance'},
290
- {section_start:'organize'},
291
-
292
- {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},
293
- {name:'parent_task', width:'50%',
294
- hidden:function(item){
295
- return !item.project;
296
- },goto:'task',
297
- type:'select',values:function(item){
298
- var query = {project:item.project};
299
- if(item.project_phase){
300
- query.project_phase = item.project_phase;
301
- }
302
- var tasks = _joe.Data.task.where(query).sortBy('project_phase,priority');
303
- return tasks;
304
- },icon:'task',
305
- schema:'task',blank:true
306
- },
307
- {name:'project_phase',
308
- type:'select',
309
- blank:true,
310
- rerender:'parent_task',
311
- values:function(item){
312
- if(!item.project){
313
- return [];
314
- }
315
- var proj = _joe.getDataItem(item.project,'project');
316
- if(!proj || !proj.phases || !proj.phases.length){
317
- return [];
318
- }
319
- var vals = [];
320
- proj.phases.map(function(phase){
321
- vals.push({name:phase.name+' '+(phase.end_date && ' - '+phase.end_date ||''),value:phase.id||phase.name})
322
- })
323
- return vals;
324
- },
325
- display:'phase',width:'50%',hidden:function(item){
326
- if(!item.project){
327
- return true;
328
- }
329
- var proj = _joe.getDataItem(item.project,'project');
330
- if(!proj || !proj.phases || !proj.phases.length){
331
- return true;
332
- }
333
-
334
- return false;
335
- }},
336
-
337
- 'priority',
338
- {section_end:'organize'},
339
- {section_start:'estimates'},
340
- {name:'points',comment:'fte, scrum, etc',type:'number',display:'story points'},
341
- {name:'time_estimate',comment:'minutes',type:'number',display:'time estimate'},
342
-
343
- {section_end:'estimates'},
344
- {section_start:'manage', collapsed:function(item){
345
- return false;
346
- return (item.members && item.members.length);
347
- }},
348
- {extend:'members',specs:{rerender:'subtasks'}},
349
- {label:'comments'},
350
- 'user_comments',
351
- {section_end:'manage'},
352
- {section_start:'reports',collapsed:true},
353
- 'reports',
354
- {section_end:'reports'},
355
- {section_start:'tags',collapsed:true},
356
- 'tags',
357
- {section_end:'tags'},
358
- {section_start:'access'},
359
- '_protected',
360
- {section_end:'access'},
361
-
362
- {sidebar_end:'right'},
363
- {section_start:'system',collapsed:true},
364
- '_id','created','itemtype',
365
- {section_end:'system'}
366
- ];
367
- return fields;
368
- },
369
- instance:{
370
- checkbox:function(instance){
371
- return {prop:'approved'}
372
- },
373
- fields:function(){
374
- return [
375
- {name:'approved',type:'boolean',display:'APPROVED','label':'click when task is approved',width:'50%'},
376
- {name:'date',type:'date',width:'50%',native:true},
377
- //'members',
378
- {name:'members',type:'group',label:'completed by -',
379
- values:function(){
380
- return _joe.Data.user.where({custom_roles:{$in:['chore_assignee']}});
381
- }
382
- },
383
- {name:'points',type:'number'},
384
- {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
385
-
386
-
387
-
388
- ];
389
- }
390
- },
391
- filters:function(){
392
- if(!_joe.Cache.static.weekstart){
393
- var curr = new Date;
394
- var startD,endD;
395
-
396
- startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
397
- startD.setHours(0,0,0);
398
- _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
399
- endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
400
- endD.setHours(0,0,0);
401
- _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
402
- }
403
- var filters = [];
404
- var others =[
405
- {group_start:'priorities',collapsed:true/*,name:'prioritized',
406
- filter:{$and:[{priority:{$nin:[null,'']}},{priority:{$exists:true}}]}*/
407
- },
408
- {name:'priority 1',filter:{priority:1},
409
- stripecolor:_joe.Colors.priority[1]},
410
- {name:'priority 2',filter:{priority:2},stripecolor:
411
- _joe.Colors.priority[2]},
412
- {name:'priority 3',filter:{priority:3},
413
- stripecolor:_joe.Colors.priority[3]},
414
- {name:'unprioritized',filter:{priority:1000}},
415
- {group_end:'priorities'},
416
-
417
- {name:'My Tasks',filter:{members:{$in:[_joe.User._id]}}},
418
- {name:'unassigned',filter:{complete:{$nin:['true',true]},$or:[{members:{$lte:0}},{members:{$exists:false}}]}},
419
- {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}}
420
-
421
- ];
422
-
423
- var stats = _joe.Filter.Options.status({
424
- schema:'task',
425
- group:'status',
426
- collapsed:true,
427
- none:true
428
- });
429
- filters = filters.concat(stats,
430
-
431
- _joe.Filter.Options.tags({
432
- schema:'task',
433
- group:'tags',
434
- collapsed:true
435
- }),
436
- _joe.Filter.Options.datasetProperty('user','members',{
437
- group:'members',
438
- collapsed:true
439
- }),
440
- others
441
- );
442
- /*_joe.Data.status.sortBy('index')
443
- .where({datasets:{$in:['task']}}).map(function(status){
444
- stats.push({name:status.name,filter:{status:status._id},bgcolor:status.color})
445
- })*/
446
-
447
-
448
-
449
- return filters;
450
- },
451
- stripeColor:function(item){
452
- if(item.priority && item.priority < 100){
453
- return {
454
- title:`P${item.priority}`,
455
- color:_joe.Colors.priority[item.priority]
456
- };
457
- }
458
- },
459
- bgColor:function(item){
460
- if(!item.status){
461
- return '';
462
- }
463
- var status = _joe.getDataItem(item.status,'status');
464
- /* var color = _joe.getDataItemProp(item.status,'status','color');*/
465
- return {color:status.color,title:status.name};
466
- },
467
- /* stripeColor:[
468
- {color:'#000',filter:{priority:1}},
469
- {color:'#999',filter:{priority:2}}
470
- ],*/
471
- checkbox:{prop:'complete',percentage:function(item){
472
- if(!item.subtasks || !item.subtasks.length){
473
- return false;
474
- }
475
- var subs = item.subtasks;
476
- return (subs.filter(function(sub){return sub.sub_complete;}).length/subs.length);
477
- }},
478
- subsets:function(){
479
- if(!_joe.Cache.static.weekstart){
480
- var curr = new Date;
481
- var startD,endD;
482
-
483
- startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
484
- startD.setHours(0,0,0);
485
- _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
486
- endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
487
- endD.setHours(0,0,0);
488
- _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
489
- }
490
- var sets = [
491
- {name:'ACTIVE',default:true,filter:
492
- function(){
493
- if(this.task_type == "chore"){
494
- return false;
495
- }
496
- if(this.complete){
497
- return false;
498
- }
499
- if(!this.status){
500
- return false;
501
- }
502
- else{
503
- //var s = _joe.Cache.get(this.status);
504
- var s = $.get(this.status);
505
- if(s.inactive || s.terminal || s.default){
506
- return false;
507
- }
508
- }
509
- return true;
510
- }
511
- },
512
- {name:'Incomplete',filter:
513
- function(){
514
- if(this.complete){
515
- return false;
516
- }
517
- if(this.status){
518
- if(_joe.Cache.get(this.status).inactive){
519
- return false;
520
- }
521
- }
522
- return true;
523
- }
524
- },
525
-
526
- {name:'inactive',filter:
527
- function(){
528
- if(this.complete){
529
- return false;
530
- }
531
- if(this.status){
532
- if(_joe.Cache.get(this.status).inactive){
533
- return true;
534
- }
535
- }
536
- return false;
537
- }
538
- },
539
- //{name:'My Tasks',default:true,filter:{complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}},
540
- {name:'My Tasks',filter:function(ind,item){
541
- if(parseBoolean(this.complete)){
542
- return false;
543
- }
544
- if((this.members||[]).indexOf(_joe.User._id) != -1){
545
- return true;
546
- }
547
- var subs = (this.subtasks ||[]).where({assigned:_joe.User._id});
548
- if(subs.length){
549
- return true;
550
- }
551
- }},
552
- // {complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}
553
-
554
-
555
- {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}},
556
- ];
557
-
558
-
559
-
560
- sets.push({group_start:'projects',collapsed:true, name:'projects',filter:{project:{$in:[null,'']}}})
561
- var projs = [];
562
- _joe.Data.project.map(function(p){
563
- if(p.complete != true){
564
- projs.push({name: p.name,filter:{project: p._id,complete:{$nin:['true',true]}}});
565
- }
566
- });
567
- sets = sets.concat(projs.sortBy('name'));
568
- sets.push({group_end:'projects'})
569
-
570
- var tts = [];
571
- sets.push({group_start:'task_type',collapsed:false, name:'task type',filter:{project:{$in:[null,'']}}})
572
- _joe.schemas.task.task_types.map(function(tt){
573
- tts.push({name: tt,filter:{task_type: tt}});
574
-
575
- });
576
- sets = sets.concat(tts);
577
- sets.push({group_end:'task_type'})
578
- sets.push({name:'completed',sorter:['!joeUpdated'],filter:{complete:{$in:['true',true]}}});
579
- return sets;
580
- },
581
-
582
-
583
- idprop : "_id",
584
- onDemandExpander:true,
585
- itemExpander:function(task){
586
- if(task.subtasks && task.subtasks.length){
587
- var subtask_html = '<joe-card><joe-title>Subtasks</joe-title>';
588
- task.subtasks.map(function(st){
589
- subtask_html +='<div class="joe-subtitle '+(st.assigned && "lh-30"||"")+' clear '
590
- +(st.sub_complete && 'joe-strike' || '')+'">'
591
- +((st.assigned && _renderUserCubes(_joe.getDataItem(st.assigned,'user')))||'')
592
- +st.info
593
- +((st.sub_duedate && ' - '+st.sub_duedate)||'')
594
- +'</div>';
595
- })
596
- subtask_html+='</joe-card>';
597
- //+fillTemplate('<div class="joe-subtitle">${info}</div>',task.subtasks);
598
- return subtask_html;
599
-
600
- }else{
601
- return '';
602
- }
603
- },
604
- new:function(){
605
- var payload = {
606
- itemtype:'task',
607
- created:(new Date).toISOString(),
608
- _id:cuid()
609
- };
610
- if(_joe.current.subset){
611
- payload.project = (_joe.Data.project.where({name:_joe.current.subset.name})[0]||{_id:null})._id;
612
- }
613
- return payload;
614
- },
615
- report:{
616
- name:'standard report',
617
- info:'the report that comes with joe',
618
- template:function(task,templateData){
619
- var content = ``;
620
- if(task.project){
621
- var projectSchema = JOE.Schemas.schema.project;
622
- var project = JOE.Cache.findByID("project",task.project);
623
- content+=`
624
- <report-section class="marginless">
625
- <a class="report-content-item" target="_blank" href="/API/plugin/reportbuilder/standard/?itemid=${task.project}">
626
- <report-icon>${projectSchema.menuicon}</report-icon>
627
- <joe-subtitle>Project</joe-subtitle><joe-title>${project.name}</joe-title>
628
- </a>
629
- <div style="clear:both;"></div>
630
- </report-section>
631
- `;
632
- }
633
- if(task.description){
634
- content+=`<report-section>
635
- <report-section-label>Description</report-section-label>
636
- ${task.description}
637
- </report-section>`;
638
- }
639
- if(task.subtasks && task.subtasks.length){
640
- content+=`<report-section>
641
- <report-section-label>Subtasks</report-section-label>
642
- ${task.subtasks.map(t=>{
643
- return `<report-subtask class="complete-${t.sub_complete}">${t.info}</report-subtask>`;
644
- }).join('')}
645
- </report-section>`;
646
- }
647
- return content;
648
- }
649
-
650
- },
651
- reports:{
652
- chore_cards:{
653
- name:'Chore Cards',
654
- template_type:'module',
655
- template:function(data){
656
- var schema = JOE.Schemas.raw_schemas.task;
657
- var icon = schema.menuicon;
658
- //var icon = JOE.SC
659
- var start=0,count=10,tasks;
660
- if(data.request.query && data.request.query.where){
661
-
662
- tasks = JOE.Data.task.where(eval('('+data.request.query.where+')'));
663
- }else{
664
- tasks = JOE.Data.task;
665
- }
666
- tasks = tasks.slice(start,count);
667
- logit(tasks);
668
- function renderCard(task){
669
- return `<task-card><card-front>
670
- <card-icon>${icon}</card-icon>
671
- <joe-title>${task.name}</joe-title>
672
- <card-points>${(task.points && `<pts-number>${task.points}</pts-number> pts`)||''}</card-points>
673
- </card-front>
674
- </task-card>`;
675
- }
676
- var template =`
677
- <html>
678
- <head>
679
- <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
680
- <link rel="stylesheet" href="/JsonObjectEditor/css/joe.css">
681
- <link rel="stylesheet" href="/JsonObjectEditor/css/report-styles.css">
682
- <link rel="icon" href="/chore_favicon.ico?v=2" type="image/x-icon" />
683
- <link rel="icon" sizes="192x192" href="/chore-192x192.png">
684
- <meta name="mobile-web-app-capable" content="yes">
685
- <title>Chore Cards</title>
686
- <style>
687
- html,body{
688
- background:#fff;
689
- }
690
- *{ padding:0; margin:0; position:relative;}
691
- task-card{
692
- width:calc(50% - 12px);
693
- margin:4px;
694
- height:198px;
695
- border:2px solid #999;
696
-
697
- display:block;
698
- float:left;
699
- }
700
- card-front{
701
- display:block;
702
- text-align:center;
703
- padding-top:20px;
704
- }
705
- card-icon {
706
- position: absolute;
707
- top: -10px;
708
- left: -10px;
709
- width: 80px;
710
- opacity:.8;
711
- }
712
- card-points{
713
- font-weight:bold;
714
- color:#999;
715
- font-size:24px;
716
- }
717
- card-front joe-title {
718
- font-size: 24px;
719
- margin: 30px 20px 10px 20px;
720
- }
721
- </style>
722
- </head>
723
- <body>
724
- ${tasks.map(renderCard).join('')}
725
- </body>
726
-
727
- </html>
728
- `;
729
- return template;
730
- }
731
- }
732
- },
733
- events:{
734
- create:function(item,specs){
735
- var members = item.members;
736
- var member;
737
- var status = JOE.Cache.findByID('status',item.status)||{};
738
- var project = JOE.Cache.findByID('project',item.project)||{};
739
- members.map(function(mem){
740
- member = JOE.Cache.findByID('user',mem);
741
- if(member){
742
- logit('sending assignment email to: '+member.email);
743
- /*cd75a051-dcec-4306-8894-e1dc64853306*/
744
- JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
745
- ASSIGNED:member,
746
- TASK:item,
747
- PROJECT:project,
748
- STATUS:status
749
- })
750
- }
751
- })
752
-
753
- },
754
- save:function(item,specs){
755
-
756
- $c.DEBUG_MODE =false;
757
- if(specs.cached && specs.historical_info.changes && specs.historical_info.changes.members){
758
- var cached_members = specs.cached.members;
759
- var members = item.members;
760
- var member;
761
- var status = JOE.Cache.findByID('status',item.status)||{};
762
- var project = JOE.Cache.findByID('project',item.project)||{};
763
- members.map(function(mem){
764
- if(cached_members.indexOf(mem) == -1){
765
- member = JOE.Cache.findByID('user',mem);
766
- if(member){
767
- logit('sending assignment email to: '+member.email);
768
- /*cd75a051-dcec-4306-8894-e1dc64853306*/
769
- JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
770
- ASSIGNED:member,
771
- TASK:item,
772
- PROJECT:project,
773
- STATUS:status
774
- })
775
- }
776
- }
777
- })
778
- }
779
- }
780
- }
781
- }
782
- };
783
-
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
+ {sidebar_start:'left'},
180
+ {section_start:'JAI',display:'JOE Ai'},
181
+ "objectChat",
182
+ {section_end:'JAI'},
183
+ {sidebar_end:'left'},
184
+ {section_start:'overview'},
185
+ 'name',
186
+ 'info',
187
+ 'description',
188
+ {section_end:'overview'},
189
+
190
+ {section_start:'subtasks'},
191
+ {name:'subtasks',type:'objectList',label:false,
192
+ template:function(obj,subobj){
193
+ var done = (subobj.sub_complete)?'joe-strike':'';
194
+ return '<joe-full-right>'+(subobj.assigned && _renderUserCubes(_joe.getDataItem(subobj.assigned,'user'))||'')+'</joe-full-right>'
195
+ +'<joe-subtext>${sub_duedate}</joe-subtext>'
196
+ +'<joe-title class="'+done+'">${info}</joe-title>'
197
+ },
198
+ properties:[
199
+ {name:'info'},
200
+
201
+ {name:'sub_duedate', display:'due', type:'date',width:'50px'},
202
+ {name:'assigned',display:'asgt',type:'select',width:'50px',
203
+ onchange:'_joe.schemas.task.methods.addUser(this.value);',
204
+ values:function(item){
205
+ var opts = [];
206
+ var item = _jco(true);
207
+ if(item.members && item.members.length){
208
+ opts = opts.concat(item.members);
209
+ }
210
+ if(item.project){
211
+ var proj = _joe.getDataItem(item.project,'project');
212
+ if(proj.members && proj.members.length){
213
+ opts = opts.concat(proj.members);
214
+ }
215
+ }
216
+ //opts = $.unique(opts);
217
+ //opts(new Set(opts));
218
+ Array.from(new Set(opts));
219
+ if(!opts || !opts.length){
220
+ return [];
221
+ }
222
+ var users = _joe.Data.user.where({_id:{$in:opts}});
223
+ return users;
224
+ },blank:true,
225
+ idprop:'_id',template:function(t,u){
226
+ if(_joe.sizeClass == "large-size"){
227
+ return u.name;
228
+ }
229
+ var name = (u.first_name && u.first_name+' '+u.last_name) ||u.fullname || u.name;
230
+ if(!name){
231
+ return '';
232
+ }
233
+ var initials = name[0]+ (((name.indexOf(' ') > 0) && name[name.indexOf(' ')+1])||'');
234
+ return initials;
235
+
236
+
237
+ }
238
+ },
239
+
240
+ {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
241
+ ]
242
+ },
243
+ {section_end:'subtasks'},
244
+ {section_start:'acceptance',collapsed:function(item){
245
+ return !(item.scceptance_criteria && item.scceptance_criteria.length);
246
+ }},
247
+ {name:'scceptance_criteria',display:'acceptance criteria',type:'objectList',label:false,
248
+ template:function(obj,subobj){
249
+ var done = (subobj.sub_complete)?'joe-strike':'';
250
+ return '<joe-title class="'+done+'">${criteria}</joe-title>' ;
251
+ },
252
+ properties:[
253
+ {name:'criteria'},
254
+
255
+ {name:'sub_complete',display:'done',type:'boolean',width:'50px'}
256
+ ]
257
+ },
258
+ {section_end:'acceptance'},
259
+ {section_start:'related',collapsed:function(item){
260
+ return !(item.files && item.files.length);
261
+ }},
262
+ {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
263
+ 'references',
264
+
265
+ {section_end:'related'},
266
+
267
+ {sidebar_start:'right',collapsed:function(item){
268
+ if(_joe.sizeClass == "large-size"){
269
+ return false;
270
+ }
271
+ return (item.priority && item.project && item.status && item.due_date);
272
+ }},
273
+ {section_start:'glance'},
274
+ {name:'task_type',type:'select',display:'task type',
275
+ values:function(){
276
+ return (['']).concat(_joe.schemas.task.task_types);
277
+ },
278
+ onchange:'_joe.schemas.task.methods.setType(this.value);',
279
+ onPanelShow:function(cur){
280
+ console.log('CURRENT',cur);
281
+ if(cur.task_type){
282
+ _joe.schemas.task.methods.setType(cur.task_type);
283
+ }
284
+ }
285
+ },
286
+ 'status',
287
+ {name:'due_date',type:'date',display:'due'},
288
+ {name:'complete',type:'boolean',display:'complete task',label:'click to hide from list'},
289
+ {section_end:'glance'},
290
+ {section_start:'organize'},
291
+
292
+ {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},
293
+ {name:'parent_task', width:'50%',
294
+ hidden:function(item){
295
+ return !item.project;
296
+ },goto:'task',
297
+ type:'select',values:function(item){
298
+ var query = {project:item.project};
299
+ if(item.project_phase){
300
+ query.project_phase = item.project_phase;
301
+ }
302
+ var tasks = _joe.Data.task.where(query).sortBy('project_phase,priority');
303
+ return tasks;
304
+ },icon:'task',
305
+ schema:'task',blank:true
306
+ },
307
+ {name:'project_phase',
308
+ type:'select',
309
+ blank:true,
310
+ rerender:'parent_task',
311
+ values:function(item){
312
+ if(!item.project){
313
+ return [];
314
+ }
315
+ var proj = _joe.getDataItem(item.project,'project');
316
+ if(!proj || !proj.phases || !proj.phases.length){
317
+ return [];
318
+ }
319
+ var vals = [];
320
+ proj.phases.map(function(phase){
321
+ vals.push({name:phase.name+' '+(phase.end_date && ' - '+phase.end_date ||''),value:phase.id||phase.name})
322
+ })
323
+ return vals;
324
+ },
325
+ display:'phase',width:'50%',hidden:function(item){
326
+ if(!item.project){
327
+ return true;
328
+ }
329
+ var proj = _joe.getDataItem(item.project,'project');
330
+ if(!proj || !proj.phases || !proj.phases.length){
331
+ return true;
332
+ }
333
+
334
+ return false;
335
+ }},
336
+
337
+ 'priority',
338
+ {section_end:'organize'},
339
+ {section_start:'estimates'},
340
+ {name:'points',comment:'fte, scrum, etc',type:'number',display:'story points'},
341
+ {name:'time_estimate',comment:'minutes',type:'number',display:'time estimate'},
342
+
343
+ {section_end:'estimates'},
344
+ {section_start:'manage', collapsed:function(item){
345
+ return false;
346
+ return (item.members && item.members.length);
347
+ }},
348
+ {extend:'members',specs:{rerender:'subtasks'}},
349
+ {label:'comments'},
350
+ 'user_comments',
351
+ {section_end:'manage'},
352
+ {section_start:'reports',collapsed:true},
353
+ 'reports',
354
+ {section_end:'reports'},
355
+ {section_start:'tags',collapsed:true},
356
+ 'tags',
357
+ {section_end:'tags'},
358
+ {section_start:'access'},
359
+ '_protected',
360
+ {section_end:'access'},
361
+
362
+ {sidebar_end:'right'},
363
+ {section_start:'system',collapsed:true},
364
+ '_id','created','itemtype',
365
+ {section_end:'system'}
366
+ ];
367
+ return fields;
368
+ },
369
+ instance:{
370
+ checkbox:function(instance){
371
+ return {prop:'approved'}
372
+ },
373
+ fields:function(){
374
+ return [
375
+ {name:'approved',type:'boolean',display:'APPROVED','label':'click when task is approved',width:'50%'},
376
+ {name:'date',type:'date',width:'50%',native:true},
377
+ //'members',
378
+ {name:'members',type:'group',label:'completed by -',
379
+ values:function(){
380
+ return _joe.Data.user.where({custom_roles:{$in:['chore_assignee']}});
381
+ }
382
+ },
383
+ {name:'points',type:'number'},
384
+ {name:'files',type:'uploader',allowmultiple:true, height:'300px',comment:'drag files here to upload', onConfirm:_joe.SERVER.Plugins.awsFileUpload},
385
+
386
+
387
+
388
+ ];
389
+ }
390
+ },
391
+ filters:function(){
392
+ if(!_joe.Cache.static.weekstart){
393
+ var curr = new Date;
394
+ var startD,endD;
395
+
396
+ startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
397
+ startD.setHours(0,0,0);
398
+ _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
399
+ endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
400
+ endD.setHours(0,0,0);
401
+ _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
402
+ }
403
+ var filters = [];
404
+ var others =[
405
+ {group_start:'priorities',collapsed:true/*,name:'prioritized',
406
+ filter:{$and:[{priority:{$nin:[null,'']}},{priority:{$exists:true}}]}*/
407
+ },
408
+ {name:'priority 1',filter:{priority:1},
409
+ stripecolor:_joe.Colors.priority[1]},
410
+ {name:'priority 2',filter:{priority:2},stripecolor:
411
+ _joe.Colors.priority[2]},
412
+ {name:'priority 3',filter:{priority:3},
413
+ stripecolor:_joe.Colors.priority[3]},
414
+ {name:'unprioritized',filter:{priority:1000}},
415
+ {group_end:'priorities'},
416
+
417
+ {name:'My Tasks',filter:{members:{$in:[_joe.User._id]}}},
418
+ {name:'unassigned',filter:{complete:{$nin:['true',true]},$or:[{members:{$lte:0}},{members:{$exists:false}}]}},
419
+ {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}}
420
+
421
+ ];
422
+
423
+ var stats = _joe.Filter.Options.status({
424
+ schema:'task',
425
+ group:'status',
426
+ collapsed:true,
427
+ none:true
428
+ });
429
+ filters = filters.concat(stats,
430
+
431
+ _joe.Filter.Options.tags({
432
+ schema:'task',
433
+ group:'tags',
434
+ collapsed:true
435
+ }),
436
+ _joe.Filter.Options.datasetProperty('user','members',{
437
+ group:'members',
438
+ collapsed:true
439
+ }),
440
+ others
441
+ );
442
+ /*_joe.Data.status.sortBy('index')
443
+ .where({datasets:{$in:['task']}}).map(function(status){
444
+ stats.push({name:status.name,filter:{status:status._id},bgcolor:status.color})
445
+ })*/
446
+
447
+
448
+
449
+ return filters;
450
+ },
451
+ stripeColor:function(item){
452
+ if(item.priority && item.priority < 100){
453
+ return {
454
+ title:`P${item.priority}`,
455
+ color:_joe.Colors.priority[item.priority]
456
+ };
457
+ }
458
+ },
459
+ bgColor:function(item){
460
+ if(!item.status){
461
+ return '';
462
+ }
463
+ var status = _joe.getDataItem(item.status,'status');
464
+ /* var color = _joe.getDataItemProp(item.status,'status','color');*/
465
+ return {color:status.color,title:status.name};
466
+ },
467
+ /* stripeColor:[
468
+ {color:'#000',filter:{priority:1}},
469
+ {color:'#999',filter:{priority:2}}
470
+ ],*/
471
+ checkbox:{prop:'complete',percentage:function(item){
472
+ if(!item.subtasks || !item.subtasks.length){
473
+ return false;
474
+ }
475
+ var subs = item.subtasks;
476
+ return (subs.filter(function(sub){return sub.sub_complete;}).length/subs.length);
477
+ }},
478
+ subsets:function(){
479
+ if(!_joe.Cache.static.weekstart){
480
+ var curr = new Date;
481
+ var startD,endD;
482
+
483
+ startD = new Date(curr.setDate(curr.getDate() - curr.getDay() +1));
484
+ startD.setHours(0,0,0);
485
+ _joe.Cache.static.weekstart = _joe.Utils.toDateString(startD,{fullyear:true})
486
+ endD = new Date(curr.setDate(curr.getDate() - curr.getDay() +8))
487
+ endD.setHours(0,0,0);
488
+ _joe.Cache.static.weekend = _joe.Utils.toDateString(endD,{fullyear:true})
489
+ }
490
+ var sets = [
491
+ {name:'ACTIVE',default:true,filter:
492
+ function(){
493
+ if(this.task_type == "chore"){
494
+ return false;
495
+ }
496
+ if(this.complete){
497
+ return false;
498
+ }
499
+ if(!this.status){
500
+ return false;
501
+ }
502
+ else{
503
+ //var s = _joe.Cache.get(this.status);
504
+ var s = $.get(this.status);
505
+ if(s.inactive || s.terminal || s.default){
506
+ return false;
507
+ }
508
+ }
509
+ return true;
510
+ }
511
+ },
512
+ {name:'Incomplete',filter:
513
+ function(){
514
+ if(this.complete){
515
+ return false;
516
+ }
517
+ if(this.status){
518
+ if(_joe.Cache.get(this.status).inactive){
519
+ return false;
520
+ }
521
+ }
522
+ return true;
523
+ }
524
+ },
525
+
526
+ {name:'inactive',filter:
527
+ function(){
528
+ if(this.complete){
529
+ return false;
530
+ }
531
+ if(this.status){
532
+ if(_joe.Cache.get(this.status).inactive){
533
+ return true;
534
+ }
535
+ }
536
+ return false;
537
+ }
538
+ },
539
+ //{name:'My Tasks',default:true,filter:{complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}},
540
+ {name:'My Tasks',filter:function(ind,item){
541
+ if(parseBoolean(this.complete)){
542
+ return false;
543
+ }
544
+ if((this.members||[]).indexOf(_joe.User._id) != -1){
545
+ return true;
546
+ }
547
+ var subs = (this.subtasks ||[]).where({assigned:_joe.User._id});
548
+ if(subs.length){
549
+ return true;
550
+ }
551
+ }},
552
+ // {complete:{$nin:['true',true]},members:{$in:[_joe.User._id]}}
553
+
554
+
555
+ {name:'this week',filter:{due_date:{$gte:_joe.Cache.static.weekstart,$lte:_joe.Cache.static.weekend}}},
556
+ ];
557
+
558
+
559
+
560
+ sets.push({group_start:'projects',collapsed:true, name:'projects',filter:{project:{$in:[null,'']}}})
561
+ var projs = [];
562
+ _joe.Data.project.map(function(p){
563
+ if(p.complete != true){
564
+ projs.push({name: p.name,filter:{project: p._id,complete:{$nin:['true',true]}}});
565
+ }
566
+ });
567
+ sets = sets.concat(projs.sortBy('name'));
568
+ sets.push({group_end:'projects'})
569
+
570
+ var tts = [];
571
+ sets.push({group_start:'task_type',collapsed:false, name:'task type',filter:{project:{$in:[null,'']}}})
572
+ _joe.schemas.task.task_types.map(function(tt){
573
+ tts.push({name: tt,filter:{task_type: tt}});
574
+
575
+ });
576
+ sets = sets.concat(tts);
577
+ sets.push({group_end:'task_type'})
578
+ sets.push({name:'completed',sorter:['!joeUpdated'],filter:{complete:{$in:['true',true]}}});
579
+ return sets;
580
+ },
581
+
582
+
583
+ idprop : "_id",
584
+ onDemandExpander:true,
585
+ itemExpander:function(task){
586
+ if(task.subtasks && task.subtasks.length){
587
+ var subtask_html = '<joe-card><joe-title>Subtasks</joe-title>';
588
+ task.subtasks.map(function(st){
589
+ subtask_html +='<div class="joe-subtitle '+(st.assigned && "lh-30"||"")+' clear '
590
+ +(st.sub_complete && 'joe-strike' || '')+'">'
591
+ +((st.assigned && _renderUserCubes(_joe.getDataItem(st.assigned,'user')))||'')
592
+ +st.info
593
+ +((st.sub_duedate && ' - '+st.sub_duedate)||'')
594
+ +'</div>';
595
+ })
596
+ subtask_html+='</joe-card>';
597
+ //+fillTemplate('<div class="joe-subtitle">${info}</div>',task.subtasks);
598
+ return subtask_html;
599
+
600
+ }else{
601
+ return '';
602
+ }
603
+ },
604
+ new:function(){
605
+ var payload = {
606
+ itemtype:'task',
607
+ created:(new Date).toISOString(),
608
+ _id:cuid()
609
+ };
610
+ if(_joe.current.subset){
611
+ payload.project = (_joe.Data.project.where({name:_joe.current.subset.name})[0]||{_id:null})._id;
612
+ }
613
+ return payload;
614
+ },
615
+ report:{
616
+ name:'standard report',
617
+ info:'the report that comes with joe',
618
+ template:function(task,templateData){
619
+ var content = ``;
620
+ if(task.project){
621
+ var projectSchema = JOE.Schemas.schema.project;
622
+ var project = JOE.Cache.findByID("project",task.project);
623
+ content+=`
624
+ <report-section class="marginless">
625
+ <a class="report-content-item" target="_blank" href="/API/plugin/reportbuilder/standard/?itemid=${task.project}">
626
+ <report-icon>${projectSchema.menuicon}</report-icon>
627
+ <joe-subtitle>Project</joe-subtitle><joe-title>${project.name}</joe-title>
628
+ </a>
629
+ <div style="clear:both;"></div>
630
+ </report-section>
631
+ `;
632
+ }
633
+ if(task.description){
634
+ content+=`<report-section>
635
+ <report-section-label>Description</report-section-label>
636
+ ${task.description}
637
+ </report-section>`;
638
+ }
639
+ if(task.subtasks && task.subtasks.length){
640
+ content+=`<report-section>
641
+ <report-section-label>Subtasks</report-section-label>
642
+ ${task.subtasks.map(t=>{
643
+ return `<report-subtask class="complete-${t.sub_complete}">${t.info}</report-subtask>`;
644
+ }).join('')}
645
+ </report-section>`;
646
+ }
647
+ return content;
648
+ }
649
+
650
+ },
651
+ reports:{
652
+ chore_cards:{
653
+ name:'Chore Cards',
654
+ template_type:'module',
655
+ template:function(data){
656
+ var schema = JOE.Schemas.raw_schemas.task;
657
+ var icon = schema.menuicon;
658
+ //var icon = JOE.SC
659
+ var start=0,count=10,tasks;
660
+ if(data.request.query && data.request.query.where){
661
+
662
+ tasks = JOE.Data.task.where(eval('('+data.request.query.where+')'));
663
+ }else{
664
+ tasks = JOE.Data.task;
665
+ }
666
+ tasks = tasks.slice(start,count);
667
+ logit(tasks);
668
+ function renderCard(task){
669
+ return `<task-card><card-front>
670
+ <card-icon>${icon}</card-icon>
671
+ <joe-title>${task.name}</joe-title>
672
+ <card-points>${(task.points && `<pts-number>${task.points}</pts-number> pts`)||''}</card-points>
673
+ </card-front>
674
+ </task-card>`;
675
+ }
676
+ var template =`
677
+ <html>
678
+ <head>
679
+ <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
680
+ <link rel="stylesheet" href="/JsonObjectEditor/css/joe.css">
681
+ <link rel="stylesheet" href="/JsonObjectEditor/css/report-styles.css">
682
+ <link rel="icon" href="/chore_favicon.ico?v=2" type="image/x-icon" />
683
+ <link rel="icon" sizes="192x192" href="/chore-192x192.png">
684
+ <meta name="mobile-web-app-capable" content="yes">
685
+ <title>Chore Cards</title>
686
+ <style>
687
+ html,body{
688
+ background:#fff;
689
+ }
690
+ *{ padding:0; margin:0; position:relative;}
691
+ task-card{
692
+ width:calc(50% - 12px);
693
+ margin:4px;
694
+ height:198px;
695
+ border:2px solid #999;
696
+
697
+ display:block;
698
+ float:left;
699
+ }
700
+ card-front{
701
+ display:block;
702
+ text-align:center;
703
+ padding-top:20px;
704
+ }
705
+ card-icon {
706
+ position: absolute;
707
+ top: -10px;
708
+ left: -10px;
709
+ width: 80px;
710
+ opacity:.8;
711
+ }
712
+ card-points{
713
+ font-weight:bold;
714
+ color:#999;
715
+ font-size:24px;
716
+ }
717
+ card-front joe-title {
718
+ font-size: 24px;
719
+ margin: 30px 20px 10px 20px;
720
+ }
721
+ </style>
722
+ </head>
723
+ <body>
724
+ ${tasks.map(renderCard).join('')}
725
+ </body>
726
+
727
+ </html>
728
+ `;
729
+ return template;
730
+ }
731
+ }
732
+ },
733
+ events:{
734
+ create:function(item,specs){
735
+ var members = item.members;
736
+ var member;
737
+ var status = JOE.Cache.findByID('status',item.status)||{};
738
+ var project = JOE.Cache.findByID('project',item.project)||{};
739
+ members.map(function(mem){
740
+ member = JOE.Cache.findByID('user',mem);
741
+ if(member){
742
+ logit('sending assignment email to: '+member.email);
743
+ /*cd75a051-dcec-4306-8894-e1dc64853306*/
744
+ JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
745
+ ASSIGNED:member,
746
+ TASK:item,
747
+ PROJECT:project,
748
+ STATUS:status
749
+ })
750
+ }
751
+ })
752
+
753
+ },
754
+ save:function(item,specs){
755
+
756
+ $c.DEBUG_MODE =false;
757
+ if(specs.cached && specs.historical_info.changes && specs.historical_info.changes.members){
758
+ var cached_members = specs.cached.members;
759
+ var members = item.members;
760
+ var member;
761
+ var status = JOE.Cache.findByID('status',item.status)||{};
762
+ var project = JOE.Cache.findByID('project',item.project)||{};
763
+ members.map(function(mem){
764
+ if(cached_members.indexOf(mem) == -1){
765
+ member = JOE.Cache.findByID('user',mem);
766
+ if(member){
767
+ logit('sending assignment email to: '+member.email);
768
+ /*cd75a051-dcec-4306-8894-e1dc64853306*/
769
+ JOE.Apps.plugins.notifier.sendNotification('TASK_ASSIGNED',{
770
+ ASSIGNED:member,
771
+ TASK:item,
772
+ PROJECT:project,
773
+ STATUS:status
774
+ })
775
+ }
776
+ }
777
+ })
778
+ }
779
+ }
780
+ }
781
+ }
782
+ };
783
+
784
784
  module.exports = task();