@outliant/sunrise-utils 1.1.26 → 1.1.28
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.
- package/CHANGELOG.md +16 -0
- package/constants.js +17 -5
- package/helpers/projectFilter/criticalPathAgeFilter.js +1 -1
- package/helpers/projectFilter/index.js +1 -1
- package/helpers/sortScript.js +22 -0
- package/helpers/taskFilter/index.js +11 -2
- package/helpers/taskFilter/isStarredFilter.js +50 -0
- package/lib/fieldConditions.js +10 -0
- package/lib/taskPipeline.js +12 -11
- package/package.json +1 -1
- package/test/helpers/projectFilter/projectFieldFilter.spec.js +1 -1
- package/test/helpers/sortScript.spec.js +28 -0
- package/test/helpers/taskFilter/index.spec.js +71 -9
package/CHANGELOG.md
CHANGED
|
@@ -4,10 +4,26 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [1.1.28](https://github.com/outliant/sunrise-utils/compare/1.1.27...1.1.28)
|
|
8
|
+
|
|
9
|
+
- task starred column #86azquc2z [`#36`](https://github.com/outliant/sunrise-utils/pull/36)
|
|
10
|
+
- banners name and options update #85ztcymgr [`#37`](https://github.com/outliant/sunrise-utils/pull/37)
|
|
11
|
+
- starredTaskIds parameter default value [`d1f69b5`](https://github.com/outliant/sunrise-utils/commit/d1f69b59611dc6b31d7c68a43e18b2920ea46c27)
|
|
12
|
+
|
|
13
|
+
#### [1.1.27](https://github.com/outliant/sunrise-utils/compare/1.1.26...1.1.27)
|
|
14
|
+
|
|
15
|
+
> 2 April 2024
|
|
16
|
+
|
|
17
|
+
- critical path age color display fix utils #86azmbay5 [`#35`](https://github.com/outliant/sunrise-utils/pull/35)
|
|
18
|
+
- chore(release): 1.1.27 [`3401e5a`](https://github.com/outliant/sunrise-utils/commit/3401e5a3f7a56ab1d8e8faf0b28e00015ed770a8)
|
|
19
|
+
|
|
7
20
|
#### [1.1.26](https://github.com/outliant/sunrise-utils/compare/1.1.25...1.1.26)
|
|
8
21
|
|
|
22
|
+
> 27 March 2024
|
|
23
|
+
|
|
9
24
|
- project critical path age column with sort and filter [`#34`](https://github.com/outliant/sunrise-utils/pull/34)
|
|
10
25
|
- unit test [`72423f0`](https://github.com/outliant/sunrise-utils/commit/72423f0178f7b17d7c667675cf1ec96afe19002f)
|
|
26
|
+
- chore(release): 1.1.26 [`85f06fb`](https://github.com/outliant/sunrise-utils/commit/85f06fbb98f4acd9dc6df8a57e5f787a27d3419c)
|
|
11
27
|
|
|
12
28
|
#### [1.1.25](https://github.com/outliant/sunrise-utils/compare/1.1.24...1.1.25)
|
|
13
29
|
|
package/constants.js
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
module.exports.PROJECT_BANNERS = [
|
|
2
2
|
{
|
|
3
3
|
label: 'Whale',
|
|
4
|
-
value: 'whale'
|
|
4
|
+
value: 'whale'
|
|
5
5
|
},
|
|
6
6
|
{
|
|
7
7
|
label: 'VIP',
|
|
8
|
-
value: 'vip'
|
|
8
|
+
value: 'vip'
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
label: 'Legal',
|
|
12
|
-
value: 'legal'
|
|
12
|
+
value: 'legal'
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
label: 'Escalation',
|
|
16
|
-
value: 'escalation'
|
|
16
|
+
value: 'escalation'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: 'Loan Risk',
|
|
20
|
+
value: 'loan-risk'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
label: 'Not Serviceable',
|
|
24
|
+
value: 'not-serviceable'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
label: 'Roof Leak',
|
|
28
|
+
value: 'roof-leak'
|
|
17
29
|
}
|
|
18
|
-
];
|
|
30
|
+
];
|
|
@@ -3,7 +3,7 @@ const _ = require('lodash');
|
|
|
3
3
|
const criticalPathAgeFilterScript = `
|
|
4
4
|
try {
|
|
5
5
|
if (doc.containsKey('critical_path.date_added') && !doc['critical_path.date_added'].empty) {
|
|
6
|
-
def now = new Date().
|
|
6
|
+
def now = new Date().toInstant().toEpochMilli();
|
|
7
7
|
def dateAdded = doc['critical_path.date_added'].value.millis;
|
|
8
8
|
double ageDays = Math.floor((now - dateAdded)/(1000 * 3600 * 24));
|
|
9
9
|
|
package/helpers/sortScript.js
CHANGED
|
@@ -328,6 +328,28 @@ module.exports.wasMarkedIncomplete = (order) => {
|
|
|
328
328
|
};
|
|
329
329
|
};
|
|
330
330
|
|
|
331
|
+
module.exports.isStarred = (order, starredTaskIds) => {
|
|
332
|
+
return {
|
|
333
|
+
_script: {
|
|
334
|
+
type: 'number',
|
|
335
|
+
script: {
|
|
336
|
+
lang: 'painless',
|
|
337
|
+
source: `
|
|
338
|
+
if (params.starredTaskIds.contains(doc._id.value)) {
|
|
339
|
+
return 1;
|
|
340
|
+
} else {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
`,
|
|
344
|
+
params: {
|
|
345
|
+
starredTaskIds: starredTaskIds || []
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
order
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
|
|
331
353
|
module.exports.projectFieldNumeric = (order, value) => {
|
|
332
354
|
return {
|
|
333
355
|
_script: {
|
|
@@ -6,6 +6,7 @@ const buildTaskFieldFilter = require('./taskFieldFilter');
|
|
|
6
6
|
const buildCriticalPathFilter = require('./criticalPathFilter');
|
|
7
7
|
const buildOnHoldFilter = require('./onHoldFilter');
|
|
8
8
|
const buildIsPausedFilter = require('./isPausedFilter');
|
|
9
|
+
const buildIsStarredFilter = require('./isStarredFilter');
|
|
9
10
|
const buildDaysToCompleteFilter = require('./daysToComplete');
|
|
10
11
|
const buildAgeColorFilter = require('./buildAgeColorFilter');
|
|
11
12
|
const buildProjectFieldFilter = require('../projectFilter/projectFieldFilter');
|
|
@@ -217,11 +218,17 @@ module.exports.defaultCustomColumns = [
|
|
|
217
218
|
field_type: 'date'
|
|
218
219
|
},
|
|
219
220
|
{
|
|
220
|
-
name: '
|
|
221
|
+
name: 'Banners',
|
|
221
222
|
value: 'project_banner',
|
|
222
223
|
type: 'project_banner',
|
|
223
224
|
field_type: 'checkbox',
|
|
224
225
|
options: PROJECT_BANNERS
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: 'Is Starred',
|
|
229
|
+
value: 'is_starred',
|
|
230
|
+
type: 'is_starred',
|
|
231
|
+
field_type: 'boolean'
|
|
225
232
|
}
|
|
226
233
|
];
|
|
227
234
|
|
|
@@ -272,7 +279,7 @@ module.exports.defaultFilterSetting = {
|
|
|
272
279
|
}
|
|
273
280
|
};
|
|
274
281
|
|
|
275
|
-
module.exports.buildTaskPipelineFilter = (filter) => {
|
|
282
|
+
module.exports.buildTaskPipelineFilter = (filter, starredTaskIds) => {
|
|
276
283
|
switch (filter.type) {
|
|
277
284
|
case 'status':
|
|
278
285
|
return buildStatusFilter(filter);
|
|
@@ -329,6 +336,8 @@ module.exports.buildTaskPipelineFilter = (filter) => {
|
|
|
329
336
|
case 'ticketinformation':
|
|
330
337
|
case 'taskfield':
|
|
331
338
|
return buildProjectFieldFilter(filter);
|
|
339
|
+
case 'is_starred':
|
|
340
|
+
return buildIsStarredFilter(filter, starredTaskIds);
|
|
332
341
|
default:
|
|
333
342
|
// Task Fields
|
|
334
343
|
return buildTaskFieldFilter(filter);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module.exports = (filter, starredTaskIds = []) => {
|
|
2
|
+
switch (filter.condition) {
|
|
3
|
+
case 'is_true':
|
|
4
|
+
return module.exports.isTrue(starredTaskIds);
|
|
5
|
+
case 'is_false':
|
|
6
|
+
return module.exports.isFalse(starredTaskIds);
|
|
7
|
+
default:
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports.isTrue = (starredTaskIds = []) => {
|
|
13
|
+
return {
|
|
14
|
+
script: {
|
|
15
|
+
script: {
|
|
16
|
+
lang: 'painless',
|
|
17
|
+
source: `
|
|
18
|
+
if (params.starredTaskIds.contains(doc._id.value)) {
|
|
19
|
+
return true;
|
|
20
|
+
} else {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
params: {
|
|
25
|
+
starredTaskIds
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
module.exports.isFalse = (starredTaskIds = []) => {
|
|
33
|
+
return {
|
|
34
|
+
script: {
|
|
35
|
+
script: {
|
|
36
|
+
lang: 'painless',
|
|
37
|
+
source: `
|
|
38
|
+
if (params.starredTaskIds.contains(doc._id.value)) {
|
|
39
|
+
return false;
|
|
40
|
+
} else {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
`,
|
|
44
|
+
params: {
|
|
45
|
+
starredTaskIds
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
package/lib/fieldConditions.js
CHANGED
|
@@ -212,6 +212,16 @@ module.exports.conditions = {
|
|
|
212
212
|
label: 'Is None Of',
|
|
213
213
|
value: 'is_none_of'
|
|
214
214
|
}
|
|
215
|
+
],
|
|
216
|
+
boolean: [
|
|
217
|
+
{
|
|
218
|
+
label: 'Is True',
|
|
219
|
+
value: 'is_true'
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
label: 'Is False',
|
|
223
|
+
value: 'is_false'
|
|
224
|
+
}
|
|
215
225
|
]
|
|
216
226
|
};
|
|
217
227
|
|
package/lib/taskPipeline.js
CHANGED
|
@@ -25,7 +25,8 @@ class TaskPipeline {
|
|
|
25
25
|
departmentId,
|
|
26
26
|
filters = [],
|
|
27
27
|
query = {},
|
|
28
|
-
searchFields = []
|
|
28
|
+
searchFields = [],
|
|
29
|
+
starredTaskIds = []
|
|
29
30
|
) {
|
|
30
31
|
const mustQuery = [
|
|
31
32
|
{
|
|
@@ -76,7 +77,7 @@ class TaskPipeline {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
for (const filter of filters) {
|
|
79
|
-
const queryFilter = buildTaskPipelineFilter(filter);
|
|
80
|
+
const queryFilter = buildTaskPipelineFilter(filter, starredTaskIds);
|
|
80
81
|
|
|
81
82
|
if (queryFilter) {
|
|
82
83
|
mustQuery.push(queryFilter);
|
|
@@ -90,7 +91,7 @@ class TaskPipeline {
|
|
|
90
91
|
return { bool: { must: mustQuery } };
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
buildSortScript(query = {}, customSort = []) {
|
|
94
|
+
buildSortScript(query = {}, customSort = [], starredTaskIds = []) {
|
|
94
95
|
const sortMultiple = (query.sort || 'desc').split(',');
|
|
95
96
|
const sortByMultiple = (query.sortBy || 'created_at').split(',');
|
|
96
97
|
let taskPipelinesSort = [];
|
|
@@ -110,8 +111,8 @@ class TaskPipeline {
|
|
|
110
111
|
taskPipelinesSort.push(sortScript.isPaused(sort));
|
|
111
112
|
break;
|
|
112
113
|
|
|
113
|
-
case s === 'owner'
|
|
114
|
-
case s === 'completed_by'
|
|
114
|
+
case s === 'owner':
|
|
115
|
+
case s === 'completed_by':
|
|
115
116
|
taskPipelinesSort.push(sortScript.owner(sort));
|
|
116
117
|
break;
|
|
117
118
|
|
|
@@ -158,6 +159,10 @@ class TaskPipeline {
|
|
|
158
159
|
taskPipelinesSort.push(sortScript.projectFieldText(sort, s));
|
|
159
160
|
break;
|
|
160
161
|
|
|
162
|
+
case s === 'is_starred':
|
|
163
|
+
taskPipelinesSort.push(sortScript.isStarred(sort, starredTaskIds));
|
|
164
|
+
break;
|
|
165
|
+
|
|
161
166
|
default:
|
|
162
167
|
taskPipelinesSort.push({
|
|
163
168
|
[s]: { order: sort, missing: '_last' }
|
|
@@ -187,12 +192,8 @@ class TaskPipeline {
|
|
|
187
192
|
return;
|
|
188
193
|
}
|
|
189
194
|
|
|
190
|
-
const readyAt = moment(task.ready_at)
|
|
191
|
-
|
|
192
|
-
.startOf('day');
|
|
193
|
-
const completedAt = moment(task.completed_at)
|
|
194
|
-
.utc()
|
|
195
|
-
.startOf('day');
|
|
195
|
+
const readyAt = moment(task.ready_at).utc().startOf('day');
|
|
196
|
+
const completedAt = moment(task.completed_at).utc().startOf('day');
|
|
196
197
|
|
|
197
198
|
return completedAt.diff(readyAt, 'days');
|
|
198
199
|
};
|
package/package.json
CHANGED
|
@@ -1318,7 +1318,7 @@ describe('projectFilter/criticalPathAgeFilter', () => {
|
|
|
1318
1318
|
const criticalPathAgeFilterScript = `
|
|
1319
1319
|
try {
|
|
1320
1320
|
if (doc.containsKey('critical_path.date_added') && !doc['critical_path.date_added'].empty) {
|
|
1321
|
-
def now = new Date().
|
|
1321
|
+
def now = new Date().toInstant().toEpochMilli();
|
|
1322
1322
|
def dateAdded = doc['critical_path.date_added'].value.millis;
|
|
1323
1323
|
double ageDays = Math.floor((now - dateAdded)/(1000 * 3600 * 24));
|
|
1324
1324
|
|
|
@@ -45,4 +45,32 @@ describe('sortScript', function () {
|
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
+
describe('task/is_starred', function () {
|
|
49
|
+
const orders = ['desc', 'asc'];
|
|
50
|
+
for (const order of orders) {
|
|
51
|
+
it(`should handle \`${order}\` sort order`, () => {
|
|
52
|
+
const sort = sortScript.isStarred(order, []);
|
|
53
|
+
expect(sort).to.be.deep.equal({
|
|
54
|
+
_script: {
|
|
55
|
+
type: 'number',
|
|
56
|
+
script: {
|
|
57
|
+
lang: 'painless',
|
|
58
|
+
source:
|
|
59
|
+
'\n' +
|
|
60
|
+
' if (params.starredTaskIds.contains(doc._id.value)) {\n' +
|
|
61
|
+
' return 1;\n' +
|
|
62
|
+
' } else {\n' +
|
|
63
|
+
' return 0;\n' +
|
|
64
|
+
' }\n' +
|
|
65
|
+
' ',
|
|
66
|
+
params: {
|
|
67
|
+
starredTaskIds: []
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
order
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
48
76
|
});
|
|
@@ -425,12 +425,12 @@ describe('taskFilter', function () {
|
|
|
425
425
|
must_not: {
|
|
426
426
|
range: {
|
|
427
427
|
'last_comment_data.created_at': {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
428
|
+
gte: 1704038400000,
|
|
429
|
+
lte: 1704124799999
|
|
431
430
|
}
|
|
432
431
|
}
|
|
433
432
|
}
|
|
433
|
+
}
|
|
434
434
|
});
|
|
435
435
|
});
|
|
436
436
|
|
|
@@ -447,9 +447,9 @@ describe('taskFilter', function () {
|
|
|
447
447
|
expect(filter).to.be.deep.equal({
|
|
448
448
|
range: {
|
|
449
449
|
'last_comment_data.created_at': {
|
|
450
|
-
|
|
451
|
-
}
|
|
450
|
+
gt: 1704124799999
|
|
452
451
|
}
|
|
452
|
+
}
|
|
453
453
|
});
|
|
454
454
|
});
|
|
455
455
|
|
|
@@ -466,9 +466,9 @@ describe('taskFilter', function () {
|
|
|
466
466
|
expect(filter).to.be.deep.equal({
|
|
467
467
|
range: {
|
|
468
468
|
'last_comment_data.created_at': {
|
|
469
|
-
|
|
470
|
-
}
|
|
469
|
+
lt: 1704038400000
|
|
471
470
|
}
|
|
471
|
+
}
|
|
472
472
|
});
|
|
473
473
|
});
|
|
474
474
|
|
|
@@ -485,10 +485,72 @@ describe('taskFilter', function () {
|
|
|
485
485
|
expect(filter).to.be.deep.equal({
|
|
486
486
|
range: {
|
|
487
487
|
'last_comment_data.created_at': {
|
|
488
|
-
|
|
489
|
-
|
|
488
|
+
gte: 1705593600000,
|
|
489
|
+
lte: 1709222399999
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
describe('is_starred', () => {
|
|
497
|
+
it('should handle `is_true` filter', () => {
|
|
498
|
+
const filter = taskFilter.buildTaskPipelineFilter({
|
|
499
|
+
field_id: '',
|
|
500
|
+
field_type: 'boolean',
|
|
501
|
+
type: 'is_starred',
|
|
502
|
+
condition: 'is_true',
|
|
503
|
+
value: null,
|
|
504
|
+
second_value: null
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
expect(filter).to.be.deep.equal({
|
|
508
|
+
script: {
|
|
509
|
+
script: {
|
|
510
|
+
lang: 'painless',
|
|
511
|
+
source:
|
|
512
|
+
'\n' +
|
|
513
|
+
' if (params.starredTaskIds.contains(doc._id.value)) {\n' +
|
|
514
|
+
' return true;\n' +
|
|
515
|
+
' } else {\n' +
|
|
516
|
+
' return false;\n' +
|
|
517
|
+
' }\n' +
|
|
518
|
+
' ',
|
|
519
|
+
params: {
|
|
520
|
+
starredTaskIds: []
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it('should handle `is_false` filter', () => {
|
|
528
|
+
const filter = taskFilter.buildTaskPipelineFilter({
|
|
529
|
+
field_id: '',
|
|
530
|
+
field_type: 'boolean',
|
|
531
|
+
type: 'is_starred',
|
|
532
|
+
condition: 'is_false',
|
|
533
|
+
value: null,
|
|
534
|
+
second_value: null
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
expect(filter).to.be.deep.equal({
|
|
538
|
+
script: {
|
|
539
|
+
script: {
|
|
540
|
+
lang: 'painless',
|
|
541
|
+
source:
|
|
542
|
+
'\n' +
|
|
543
|
+
' if (params.starredTaskIds.contains(doc._id.value)) {\n' +
|
|
544
|
+
' return false;\n' +
|
|
545
|
+
' } else {\n' +
|
|
546
|
+
' return true;\n' +
|
|
547
|
+
' }\n' +
|
|
548
|
+
' ',
|
|
549
|
+
params: {
|
|
550
|
+
starredTaskIds: []
|
|
490
551
|
}
|
|
491
552
|
}
|
|
553
|
+
}
|
|
492
554
|
});
|
|
493
555
|
});
|
|
494
556
|
});
|