@outliant/sunrise-utils 1.0.11 → 1.1.1
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 +17 -1
- package/helpers/searchFilter.js +44 -0
- package/helpers/task.js +17 -0
- package/helpers/taskFilter/buildAgeColorFilter.js +45 -0
- package/helpers/taskFilter/index.js +22 -0
- package/index.d.ts +3 -0
- package/lib/projectPipeline.js +14 -0
- package/lib/taskPipeline.js +36 -0
- package/package.json +1 -1
- package/test/helpers/taskFilter/index.spec.js +22 -0
- package/test/lib/taskPipeline.spec.js +121 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,28 @@ 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.1](https://github.com/outliant/sunrise-utils/compare/1.1.0...1.1.1)
|
|
8
|
+
|
|
9
|
+
- chore: add search for projectIds [`#5`](https://github.com/outliant/sunrise-utils/pull/5)
|
|
10
|
+
- chore: add match_phrase_prefix search for project fields [`#6`](https://github.com/outliant/sunrise-utils/pull/6)
|
|
11
|
+
- chore: revert taskPipeline [`3fb9c24`](https://github.com/outliant/sunrise-utils/commit/3fb9c2486b1459a0b33050e6691963e8aa04cfcf)
|
|
12
|
+
- chore: update projectId filter query [`dbe2f3c`](https://github.com/outliant/sunrise-utils/commit/dbe2f3c6cc40c470d02c78911a1fc0ba30cda900)
|
|
13
|
+
|
|
14
|
+
#### [1.1.0](https://github.com/outliant/sunrise-utils/compare/1.0.11...1.1.0)
|
|
15
|
+
|
|
16
|
+
> 13 April 2023
|
|
17
|
+
|
|
18
|
+
- chore: support task age color #860q9c397 [`50d79a7`](https://github.com/outliant/sunrise-utils/commit/50d79a78e309c70d7eac0f5533686bd65c1167a7)
|
|
19
|
+
- chore(release): 1.1.0 [`73ee00e`](https://github.com/outliant/sunrise-utils/commit/73ee00e07226e06fcfbf4d8c96ba87b8970ce312)
|
|
20
|
+
|
|
7
21
|
#### [1.0.11](https://github.com/outliant/sunrise-utils/compare/1.0.10...1.0.11)
|
|
8
22
|
|
|
23
|
+
> 31 March 2023
|
|
24
|
+
|
|
9
25
|
- (task/additional date filters #860q65z6h [`#4`](https://github.com/outliant/sunrise-utils/pull/4)
|
|
10
26
|
- chore: add last n days [`bb2f94a`](https://github.com/outliant/sunrise-utils/commit/bb2f94aade4ed11845ca29cf7f9b970cac51ae42)
|
|
11
27
|
- chore: add new filters for task [`3fa42e5`](https://github.com/outliant/sunrise-utils/commit/3fa42e52bc6076dfd35272b91558d9696729cfbf)
|
|
12
|
-
- chore:
|
|
28
|
+
- chore(release): 1.0.11 [`8795194`](https://github.com/outliant/sunrise-utils/commit/879519458081a5c38786c9ba344748883a026796)
|
|
13
29
|
|
|
14
30
|
#### [1.0.10](https://github.com/outliant/sunrise-utils/compare/1.0.9...1.0.10)
|
|
15
31
|
|
package/helpers/searchFilter.js
CHANGED
|
@@ -85,6 +85,50 @@ module.exports = (query = {}, searchFields = []) => {
|
|
|
85
85
|
min_score: 15
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
|
+
|
|
89
|
+
should.push({
|
|
90
|
+
bool: {
|
|
91
|
+
must: [
|
|
92
|
+
{
|
|
93
|
+
nested: {
|
|
94
|
+
path: 'fields',
|
|
95
|
+
query: {
|
|
96
|
+
bool: {
|
|
97
|
+
must: [
|
|
98
|
+
{
|
|
99
|
+
term: {
|
|
100
|
+
'fields.id': {
|
|
101
|
+
value: projectFields[i]
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
bool: {
|
|
107
|
+
should: [
|
|
108
|
+
{
|
|
109
|
+
match: {
|
|
110
|
+
[`fields.text.analyzed`]: {
|
|
111
|
+
query: searchString,
|
|
112
|
+
operator: 'and'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
match_phrase_prefix: {
|
|
118
|
+
[`fields.text.analyzed`]: searchString
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
});
|
|
88
132
|
}
|
|
89
133
|
}
|
|
90
134
|
|
package/helpers/task.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { taskAgeColorRangeMap } = require('../task');
|
|
2
|
+
|
|
3
|
+
module.exports = (filter) => {
|
|
4
|
+
switch (filter.condition) {
|
|
5
|
+
case 'is_equal':
|
|
6
|
+
return module.exports.isEqual(filter);
|
|
7
|
+
default:
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports.isEqual = (filter) => {
|
|
13
|
+
const range = taskAgeColorRangeMap[filter.value];
|
|
14
|
+
if (!range) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
script: {
|
|
20
|
+
script: {
|
|
21
|
+
source: `
|
|
22
|
+
try {
|
|
23
|
+
def now = new Date().getTime();
|
|
24
|
+
def readyDate = doc['ready_at'].value.millis;
|
|
25
|
+
|
|
26
|
+
long elapsedDays = (now - readyDate)/(1000 * 3600 * 24);
|
|
27
|
+
boolean valid = elapsedDays >= params.min;
|
|
28
|
+
|
|
29
|
+
if (params.containsKey('max')) {
|
|
30
|
+
valid = valid && elapsedDays <= params.max;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return valid;
|
|
34
|
+
} catch(Exception err){
|
|
35
|
+
return false;
|
|
36
|
+
}`,
|
|
37
|
+
lang: 'painless',
|
|
38
|
+
params: {
|
|
39
|
+
min: range.min,
|
|
40
|
+
max: range.max
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -5,6 +5,7 @@ const buildRegionFilter = require('./regionFilter');
|
|
|
5
5
|
const buildTaskFieldFilter = require('./taskFieldFilter');
|
|
6
6
|
const buildCriticalPathFilter = require('./criticalPathFilter');
|
|
7
7
|
const buildOnHoldFilter = require('./onHoldFilter');
|
|
8
|
+
const buildAgeColorFilter = require('./buildAgeColorFilter');
|
|
8
9
|
const buildProjectFieldFilter = require('../projectFilter/projectFieldFilter');
|
|
9
10
|
|
|
10
11
|
module.exports.taskStatusOptions = [
|
|
@@ -30,6 +31,25 @@ module.exports.taskStatusOptions = [
|
|
|
30
31
|
}
|
|
31
32
|
];
|
|
32
33
|
|
|
34
|
+
module.exports.taskAgeColorOptions = [
|
|
35
|
+
{
|
|
36
|
+
label: 'Green',
|
|
37
|
+
value: 'green'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
label: 'Yellow',
|
|
41
|
+
value: 'yellow'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: 'Red',
|
|
45
|
+
value: 'red'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
label: 'Black',
|
|
49
|
+
value: 'black'
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
|
|
33
53
|
module.exports.defaultCustomColumns = [
|
|
34
54
|
{
|
|
35
55
|
name: 'Owner',
|
|
@@ -196,6 +216,8 @@ module.exports.buildTaskPipelineFilter = (filter) => {
|
|
|
196
216
|
// Always expected as is_equal condition
|
|
197
217
|
case 'path_age':
|
|
198
218
|
return buildPathAgeFilter(filter);
|
|
219
|
+
case 'task_age':
|
|
220
|
+
return buildAgeColorFilter(filter);
|
|
199
221
|
// Always expected as is_equal condition with array of task template ids
|
|
200
222
|
case 'task_templates':
|
|
201
223
|
let value = filter.value;
|
package/index.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ declare namespace Utils {
|
|
|
41
41
|
|
|
42
42
|
namespace taskPipeline {
|
|
43
43
|
export const taskStatusOptions: FilterConditionOption[];
|
|
44
|
+
export const taskAgeColorOptions: FilterConditionOption[];
|
|
44
45
|
export const defaultCustomColumns: Column[];
|
|
45
46
|
export function buildFilter(filter: Filter): any;
|
|
46
47
|
export function buildFiltersQuery(
|
|
@@ -51,6 +52,8 @@ declare namespace Utils {
|
|
|
51
52
|
searchFields?: string[]
|
|
52
53
|
): any;
|
|
53
54
|
export function buildSortScript(query?: Query, customSort?: any[]): any;
|
|
55
|
+
export function getTaskAge(task: any): any;
|
|
56
|
+
export function getTaskAgeColor(task: any): any;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
namespace projectPipeline {
|
package/lib/projectPipeline.js
CHANGED
|
@@ -45,6 +45,20 @@ class ProjectPipeline {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
if (query.projectIds && query.projectIds.length) {
|
|
49
|
+
const should = query.projectIds.map(projectId => {
|
|
50
|
+
return {
|
|
51
|
+
match: {
|
|
52
|
+
_id: projectId
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
mustQuery.push({
|
|
58
|
+
bool: { should }
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
if (!filters.length) {
|
|
49
63
|
return {
|
|
50
64
|
bool: {
|
package/lib/taskPipeline.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
const { validate: isUuid } = require('uuid');
|
|
2
|
+
const moment = require('moment');
|
|
3
|
+
|
|
2
4
|
const {
|
|
3
5
|
taskStatusOptions,
|
|
6
|
+
taskAgeColorOptions,
|
|
4
7
|
defaultCustomColumns,
|
|
5
8
|
defaultTaskFilter,
|
|
6
9
|
buildTaskPipelineFilter
|
|
7
10
|
} = require('../helpers/taskFilter');
|
|
8
11
|
const searchFilter = require('../helpers/searchFilter');
|
|
9
12
|
const sortScript = require('../helpers/sortScript');
|
|
13
|
+
const taskHelper = require('../helpers/task');
|
|
10
14
|
|
|
11
15
|
class TaskPipeline {
|
|
12
16
|
taskStatusOptions = taskStatusOptions;
|
|
13
17
|
defaultCustomColumns = defaultCustomColumns;
|
|
18
|
+
taskAgeColorOptions = taskAgeColorOptions;
|
|
14
19
|
buildFilter = buildTaskPipelineFilter;
|
|
15
20
|
|
|
16
21
|
buildFiltersQuery(
|
|
@@ -127,6 +132,37 @@ class TaskPipeline {
|
|
|
127
132
|
|
|
128
133
|
return taskPipelinesSort;
|
|
129
134
|
}
|
|
135
|
+
|
|
136
|
+
getTaskAge(task) {
|
|
137
|
+
if (!task.is_complete && task.is_ready && task.ready_at) {
|
|
138
|
+
return moment().diff(moment(task.ready_at), 'days');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getTaskAgeColor(task) {
|
|
145
|
+
const taskAge = this.getTaskAge(task);
|
|
146
|
+
|
|
147
|
+
if (taskAge === null) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let ageColor = null;
|
|
152
|
+
|
|
153
|
+
Object.keys(taskHelper.taskAgeColorRangeMap).forEach((color) => {
|
|
154
|
+
const range = taskHelper.taskAgeColorRangeMap[color];
|
|
155
|
+
const isValid =
|
|
156
|
+
taskAge >= range.min &&
|
|
157
|
+
(!range.max || (range.max && taskAge <= range.max));
|
|
158
|
+
|
|
159
|
+
if (!ageColor && isValid) {
|
|
160
|
+
ageColor = color;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return ageColor;
|
|
165
|
+
}
|
|
130
166
|
}
|
|
131
167
|
|
|
132
168
|
module.exports = new TaskPipeline();
|
package/package.json
CHANGED
|
@@ -137,6 +137,28 @@ describe('taskFilter', function () {
|
|
|
137
137
|
done();
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
it('should handle task_age filter', (done) => {
|
|
141
|
+
const filter = taskFilter.buildTaskPipelineFilter({
|
|
142
|
+
condition: 'is_equal',
|
|
143
|
+
field_id: '',
|
|
144
|
+
field_type: 'select',
|
|
145
|
+
type: 'task_age',
|
|
146
|
+
value: 'red'
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
expect(filter).to.be.deep.equal({
|
|
150
|
+
script: {
|
|
151
|
+
script: {
|
|
152
|
+
source:
|
|
153
|
+
"\n try {\n def now = new Date().getTime();\n def readyDate = doc['ready_at'].value.millis;\n\n long elapsedDays = (now - readyDate)/(1000 * 3600 * 24);\n boolean valid = elapsedDays >= params.min;\n\n if (params.containsKey('max')) {\n valid = valid && elapsedDays <= params.max;\n }\n\n return valid;\n } catch(Exception err){\n return false;\n }",
|
|
154
|
+
lang: 'painless',
|
|
155
|
+
params: { min: 11, max: 30 }
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
done();
|
|
160
|
+
});
|
|
161
|
+
|
|
140
162
|
it('should handle task_templates array filter', (done) => {
|
|
141
163
|
const filter = taskFilter.buildTaskPipelineFilter({
|
|
142
164
|
condition: 'is_equal',
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/* eslint-env node, mocha */
|
|
4
4
|
const { expect } = require('chai');
|
|
5
|
+
const moment = require('moment');
|
|
5
6
|
|
|
6
7
|
// To test
|
|
7
8
|
const taskPipeline = require('../../lib/taskPipeline');
|
|
@@ -377,4 +378,124 @@ describe('taskPipeline', function () {
|
|
|
377
378
|
done();
|
|
378
379
|
});
|
|
379
380
|
});
|
|
381
|
+
|
|
382
|
+
describe('getTaskAge', () => {
|
|
383
|
+
it('should calculate task age', (done) => {
|
|
384
|
+
const task = {
|
|
385
|
+
is_complete: false,
|
|
386
|
+
is_ready: true,
|
|
387
|
+
ready_at: moment().subtract(2, 'days').valueOf()
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
const age = taskPipeline.getTaskAge(task);
|
|
391
|
+
|
|
392
|
+
expect(age).to.equal(2);
|
|
393
|
+
done();
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('should return null if task is completed', (done) => {
|
|
397
|
+
const task = {
|
|
398
|
+
is_complete: true,
|
|
399
|
+
is_ready: true,
|
|
400
|
+
ready_at: moment().subtract(2, 'days').valueOf()
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const age = taskPipeline.getTaskAge(task);
|
|
404
|
+
|
|
405
|
+
expect(age).to.equal(null);
|
|
406
|
+
done();
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('should return null if task is blocked', (done) => {
|
|
410
|
+
const task = {
|
|
411
|
+
is_complete: false,
|
|
412
|
+
is_ready: false,
|
|
413
|
+
ready_at: null
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
const age = taskPipeline.getTaskAge(task);
|
|
417
|
+
|
|
418
|
+
expect(age).to.equal(null);
|
|
419
|
+
done();
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
describe('getTaskAgeColor', () => {
|
|
424
|
+
it('should calculate task age color green', (done) => {
|
|
425
|
+
const testNumbers = [0, 1, 2, 3, 4, 5];
|
|
426
|
+
for (let i = 0; i < testNumbers.length; i++) {
|
|
427
|
+
const testNumber = testNumbers[i];
|
|
428
|
+
const task = {
|
|
429
|
+
is_complete: false,
|
|
430
|
+
is_ready: true,
|
|
431
|
+
ready_at: moment().subtract(testNumber, 'days').valueOf()
|
|
432
|
+
};
|
|
433
|
+
const color = taskPipeline.getTaskAgeColor(task);
|
|
434
|
+
|
|
435
|
+
expect(color).to.equal('green');
|
|
436
|
+
}
|
|
437
|
+
done();
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
it('should calculate task age color yellow', (done) => {
|
|
441
|
+
const testNumbers = [6, 7, 8, 9, 10];
|
|
442
|
+
for (let i = 0; i < testNumbers.length; i++) {
|
|
443
|
+
const testNumber = testNumbers[i];
|
|
444
|
+
const task = {
|
|
445
|
+
is_complete: false,
|
|
446
|
+
is_ready: true,
|
|
447
|
+
ready_at: moment().subtract(testNumber, 'days').valueOf()
|
|
448
|
+
};
|
|
449
|
+
const color = taskPipeline.getTaskAgeColor(task);
|
|
450
|
+
|
|
451
|
+
expect(color).to.equal('yellow');
|
|
452
|
+
}
|
|
453
|
+
done();
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it('should calculate task age color red', (done) => {
|
|
457
|
+
const testNumbers = [11, 12, 15, 20, 25, 30];
|
|
458
|
+
for (let i = 0; i < testNumbers.length; i++) {
|
|
459
|
+
const testNumber = testNumbers[i];
|
|
460
|
+
const task = {
|
|
461
|
+
is_complete: false,
|
|
462
|
+
is_ready: true,
|
|
463
|
+
ready_at: moment().subtract(testNumber, 'days').valueOf()
|
|
464
|
+
};
|
|
465
|
+
const color = taskPipeline.getTaskAgeColor(task);
|
|
466
|
+
|
|
467
|
+
expect(color).to.equal('red');
|
|
468
|
+
}
|
|
469
|
+
done();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it('should calculate task age color black', (done) => {
|
|
473
|
+
const testNumbers = [31, 40, 55, 360];
|
|
474
|
+
for (let i = 0; i < testNumbers.length; i++) {
|
|
475
|
+
const testNumber = testNumbers[i];
|
|
476
|
+
const task = {
|
|
477
|
+
is_complete: false,
|
|
478
|
+
is_ready: true,
|
|
479
|
+
ready_at: moment().subtract(testNumber, 'days').valueOf()
|
|
480
|
+
};
|
|
481
|
+
const color = taskPipeline.getTaskAgeColor(task);
|
|
482
|
+
|
|
483
|
+
expect(color).to.equal('black');
|
|
484
|
+
}
|
|
485
|
+
done();
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
it('should return null if task is not ready', (done) => {
|
|
489
|
+
const task = {
|
|
490
|
+
is_complete: true,
|
|
491
|
+
is_ready: true,
|
|
492
|
+
ready_at: moment().subtract(2, 'days')
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const age = taskPipeline.getTaskAgeColor(task);
|
|
496
|
+
|
|
497
|
+
expect(age).to.equal(null);
|
|
498
|
+
done();
|
|
499
|
+
});
|
|
500
|
+
});
|
|
380
501
|
});
|