@outliant/sunrise-utils 1.0.6 → 1.0.8

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 CHANGED
@@ -4,8 +4,22 @@ 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.0.8](https://github.com/outliant/sunrise-utils/compare/1.0.7...1.0.8)
8
+
9
+ - chore: use match_phrase_prefix [`#3`](https://github.com/outliant/sunrise-utils/pull/3)
10
+ - chore(#860q1ku0m): use match_phrase_prefix for fuzzy searching [`f607110`](https://github.com/outliant/sunrise-utils/commit/f607110d9071d02b0aeeb1a41dd0e8ee4b13d6f5)
11
+
12
+ #### [1.0.7](https://github.com/outliant/sunrise-utils/compare/1.0.6...1.0.7)
13
+
14
+ > 9 March 2023
15
+
16
+ - chore: support multiple sorting #860px39yc [`133144d`](https://github.com/outliant/sunrise-utils/commit/133144d805126d301543e1df50510b982ea0f130)
17
+ - chore(release): 1.0.7 [`617bf83`](https://github.com/outliant/sunrise-utils/commit/617bf83a2ac80e030b0a81e9cdce0bd719b9e27b)
18
+
7
19
  #### [1.0.6](https://github.com/outliant/sunrise-utils/compare/1.0.5...1.0.6)
8
20
 
21
+ > 7 March 2023
22
+
9
23
  - Task/string contains filters #860pq6e4d [`#2`](https://github.com/outliant/sunrise-utils/pull/2)
10
24
  - chore: string contains filters [`2d80b31`](https://github.com/outliant/sunrise-utils/commit/2d80b31ac08ff5c1710373ccaae7c641333b5557)
11
25
  - chore: add contains any/none filters [`eeec3bd`](https://github.com/outliant/sunrise-utils/commit/eeec3bdbce07ce6a9a782db3953c6926bfd24e4d)
@@ -1,11 +1,11 @@
1
1
  const moment = require('moment');
2
2
  const { escapeElasticQuery } = require('../es');
3
3
 
4
- function getContainsMappingValue (filter) {
4
+ function getContainsMappingValue(filter) {
5
5
  if (['text', 'textarea'].includes(filter.field_type)) {
6
6
  return {
7
7
  bool: {
8
- must: [
8
+ should: [
9
9
  {
10
10
  match: {
11
11
  [`fields.text.analyzed`]: {
@@ -13,6 +13,11 @@ function getContainsMappingValue (filter) {
13
13
  operator: 'and'
14
14
  }
15
15
  }
16
+ },
17
+ {
18
+ match_phrase_prefix: {
19
+ [`fields.text.analyzed`]: filter.value
20
+ }
16
21
  }
17
22
  ]
18
23
  }
@@ -85,9 +90,15 @@ module.exports.containsAny = (filter) => {
85
90
  }
86
91
  },
87
92
  {
88
- nested: {
89
- path: 'fields',
90
- query: mapping
93
+ bool: {
94
+ should: [
95
+ {
96
+ nested: {
97
+ path: 'fields',
98
+ query: mapping
99
+ }
100
+ }
101
+ ]
91
102
  }
92
103
  }
93
104
  ]
@@ -43,6 +43,12 @@ module.exports = (query = {}, searchFields = []) => {
43
43
  fields: localFields.map((x) => `${x}^5`)
44
44
  }
45
45
  });
46
+
47
+ should.push({
48
+ match_phrase_prefix: {
49
+ name: parsedQuery
50
+ }
51
+ });
46
52
  }
47
53
  }
48
54
 
@@ -65,13 +65,13 @@ class ProjectPipeline {
65
65
  }
66
66
 
67
67
  buildSortScript(query = {}, customSort = []) {
68
- const sort = query.sort || 'desc';
69
- const sortBy = query.sortBy || 'created_at';
70
- const sortByMultiple = sortBy.split(',');
68
+ const sortMultiple = (query.sort || 'desc').split(',');
69
+ const sortByMultiple = (query.sortBy || 'created_at').split(',');
71
70
  const projectPipelinesSort = [];
72
71
 
73
72
  if (sortByMultiple.length > 0) {
74
- sortByMultiple.forEach((s) => {
73
+ sortByMultiple.forEach((s, i) => {
74
+ const sort = sortMultiple[i] || 'desc';
75
75
  if (isUuid(s)) {
76
76
  projectPipelinesSort.push(sortScript.projectFieldNumeric(sort, s));
77
77
  projectPipelinesSort.push(sortScript.projectFieldText(sort, s));
@@ -81,11 +81,11 @@ class ProjectPipeline {
81
81
  projectPipelinesSort.push(sortScript.criticalPathStage(sort));
82
82
  } else if (s === 'name') {
83
83
  projectPipelinesSort.push({
84
- 'name.raw': { order: query.sort, missing: '_last' }
84
+ 'name.raw': { order: sort, missing: '_last' }
85
85
  });
86
86
  } else {
87
87
  projectPipelinesSort.push({
88
- [s]: { order: query.sort, missing: '_last' }
88
+ [s]: { order: sort, missing: '_last' }
89
89
  });
90
90
  }
91
91
  });
@@ -84,46 +84,41 @@ class TaskPipeline {
84
84
  }
85
85
 
86
86
  buildSortScript(query = {}, customSort = []) {
87
- const sort = query.sort || 'desc';
88
- const sortBy = query.sortBy || 'created_at';
89
- const sortByMultiple = sortBy.split(',');
87
+ const sortMultiple = (query.sort || 'desc').split(',');
88
+ const sortByMultiple = (query.sortBy || 'created_at').split(',');
90
89
  let taskPipelinesSort = [];
91
90
 
92
- if (sortByMultiple.length > 0) {
93
- if (sortByMultiple[0] === 'default') {
94
- taskPipelinesSort = sortScript.default;
95
- } else {
96
- sortByMultiple.forEach((s) => {
97
- if (s === 'region') {
98
- taskPipelinesSort.push(sortScript.region(sort));
99
- } else if (s === 'owner' || s === 'completed_by') {
100
- taskPipelinesSort.push(sortScript.owner(sort));
101
- } else if (s === 'status') {
102
- taskPipelinesSort.push(sortScript.status(sort));
103
- } else if (s === 'critical_path_stage') {
104
- taskPipelinesSort.push(sortScript.criticalPathStage(sort));
105
- } else if (s === 'project_id') {
106
- // Sort numeric part of the Project ID
107
- taskPipelinesSort.push(sortScript.projectId(sort));
108
- } else if (s === 'ready_at') {
109
- taskPipelinesSort.push(sortScript.readyAt(sort));
110
- } else if (s === 'was_marked_incomplete') {
111
- taskPipelinesSort.push(sortScript.wasMarkedIncomplete(sort));
112
- } else if (s === 'last_comment_date') {
113
- taskPipelinesSort.push(sortScript.lastCommentDate(sort));
114
- } else if (isUuid(s)) {
115
- taskPipelinesSort.push(sortScript.projectFieldNumeric(sort, s));
116
- taskPipelinesSort.push(sortScript.projectFieldText(sort, s));
117
- } else {
118
- taskPipelinesSort.push({
119
- [s]: { order: sort, missing: '_last' }
120
- });
121
- }
122
- });
123
- }
124
- } else {
125
- // Default sorting
91
+ if (sortByMultiple[0] === 'default') {
126
92
  taskPipelinesSort = sortScript.default;
93
+ } else {
94
+ sortByMultiple.forEach((s, i) => {
95
+ const sort = sortMultiple[i] || 'desc';
96
+ if (s === 'region') {
97
+ taskPipelinesSort.push(sortScript.region(sort));
98
+ } else if (s === 'owner' || s === 'completed_by') {
99
+ taskPipelinesSort.push(sortScript.owner(sort));
100
+ } else if (s === 'status') {
101
+ taskPipelinesSort.push(sortScript.status(sort));
102
+ } else if (s === 'critical_path_stage') {
103
+ taskPipelinesSort.push(sortScript.criticalPathStage(sort));
104
+ } else if (s === 'project_id') {
105
+ // Sort numeric part of the Project ID
106
+ taskPipelinesSort.push(sortScript.projectId(sort));
107
+ } else if (s === 'ready_at') {
108
+ taskPipelinesSort.push(sortScript.readyAt(sort));
109
+ } else if (s === 'was_marked_incomplete') {
110
+ taskPipelinesSort.push(sortScript.wasMarkedIncomplete(sort));
111
+ } else if (s === 'last_comment_date') {
112
+ taskPipelinesSort.push(sortScript.lastCommentDate(sort));
113
+ } else if (isUuid(s)) {
114
+ taskPipelinesSort.push(sortScript.projectFieldNumeric(sort, s));
115
+ taskPipelinesSort.push(sortScript.projectFieldText(sort, s));
116
+ } else {
117
+ taskPipelinesSort.push({
118
+ [s]: { order: sort, missing: '_last' }
119
+ });
120
+ }
121
+ });
127
122
  }
128
123
 
129
124
  if (customSort.length > 0) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@outliant/sunrise-utils",
3
3
  "description": "Helper functions for project Sunrise",
4
- "version": "1.0.6",
4
+ "version": "1.0.8",
5
5
  "license": "ISC",
6
6
  "author": "Outliant",
7
7
  "main": "index.js",
@@ -159,4 +159,222 @@ describe('taskPipeline', function () {
159
159
  done();
160
160
  });
161
161
  });
162
+
163
+ describe('buildSortScript', () => {
164
+ it('should format sorting with default', (done) => {
165
+ const sort = taskPipeline.buildSortScript({
166
+ sort: 'desc',
167
+ sortBy: 'default'
168
+ });
169
+ expect(sort).to.deep.equal([
170
+ {
171
+ _script: {
172
+ type: 'number',
173
+ script: {
174
+ lang: 'painless',
175
+ source:
176
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == false) {\n return 1;\n }\n\n return 0;\n } catch (Exception err) {\n return 0;\n }\n "
177
+ },
178
+ order: 'desc'
179
+ }
180
+ },
181
+ {
182
+ _script: {
183
+ type: 'string',
184
+ script: {
185
+ lang: 'painless',
186
+ source:
187
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == false) {\n return doc['name'].value.raw;\n }\n\n return 'zzzzzzzz';\n } catch (Exception err) {\n return 'zzzzzzzz';\n }\n "
188
+ },
189
+ order: 'asc'
190
+ }
191
+ },
192
+ {
193
+ _script: {
194
+ type: 'number',
195
+ script: {
196
+ lang: 'painless',
197
+ source:
198
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == true) {\n return 1;\n }\n\n return 0;\n } catch (Exception err) {\n return 0;\n }\n "
199
+ },
200
+ order: 'desc'
201
+ }
202
+ },
203
+ {
204
+ _script: {
205
+ type: 'string',
206
+ script: {
207
+ lang: 'painless',
208
+ source:
209
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == true) {\n return doc['name'].value.raw;\n }\n\n return 'zzzzzzzz';\n } catch (Exception err) {\n return 'zzzzzzzz';\n }\n "
210
+ },
211
+ order: 'asc'
212
+ }
213
+ },
214
+ {
215
+ _script: {
216
+ type: 'number',
217
+ script: {
218
+ lang: 'painless',
219
+ source:
220
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == true) {\n return doc['completed_at'].value.millis;\n }\n\n return 0;\n } catch (Exception err) {\n return 0;\n }\n "
221
+ },
222
+ order: 'desc'
223
+ }
224
+ },
225
+ { 'name.raw': { order: 'asc' } },
226
+ { id: { order: 'asc' } }
227
+ ]);
228
+ done();
229
+ });
230
+ it('should format sorting and custom sort', (done) => {
231
+ const sort = taskPipeline.buildSortScript(
232
+ {
233
+ sort: 'asc,asc,asc',
234
+ sortBy:
235
+ 'region,owner,completed_by,status,critical_path_stage,project_id,ready_at,was_marked_incomplete,last_comment_date,38d423bf-fc24-4183-b8b7-15420c89e318,id'
236
+ },
237
+ [
238
+ {
239
+ _script: {
240
+ type: 'number',
241
+ script: {
242
+ lang: 'painless',
243
+ source: `
244
+ if (params.starredTaskIds.contains(doc._id.value)) {
245
+ return 1;
246
+ } else {
247
+ return 0;
248
+ }
249
+ `,
250
+ params: {
251
+ starredTaskIds: ['task-1', 'task-2']
252
+ }
253
+ },
254
+ order: 'desc'
255
+ }
256
+ }
257
+ ]
258
+ );
259
+ expect(sort).to.deep.equal([
260
+ {
261
+ _script: {
262
+ type: 'number',
263
+ script: {
264
+ lang: 'painless',
265
+ source:
266
+ '\n if (params.starredTaskIds.contains(doc._id.value)) {\n return 1;\n } else {\n return 0;\n }\n ',
267
+ params: { starredTaskIds: ['task-1', 'task-2'] }
268
+ },
269
+ order: 'desc'
270
+ }
271
+ },
272
+ { region_name: { order: 'asc' } },
273
+ {
274
+ _script: {
275
+ type: 'string',
276
+ script: {
277
+ lang: 'painless',
278
+ source:
279
+ "\n try {\n String owner = doc['owner'].value;\n\n if (owner != '' && owner != null) {\n return owner.toLowerCase();\n }\n } catch (Exception err) {}\n\n return '';\n "
280
+ },
281
+ order: 'asc'
282
+ }
283
+ },
284
+ {
285
+ _script: {
286
+ type: 'string',
287
+ script: {
288
+ lang: 'painless',
289
+ source:
290
+ "\n try {\n String owner = doc['owner'].value;\n\n if (owner != '' && owner != null) {\n return owner.toLowerCase();\n }\n } catch (Exception err) {}\n\n return '';\n "
291
+ },
292
+ order: 'asc'
293
+ }
294
+ },
295
+ {
296
+ _script: {
297
+ type: 'string',
298
+ script: {
299
+ lang: 'painless',
300
+ source:
301
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true) {\n if (isComplete == true) {\n return 'completed';\n }\n\n return 'pending';\n }\n\n return 'new';\n } catch (Exception err) {\n return '';\n }\n "
302
+ },
303
+ order: 'desc'
304
+ }
305
+ },
306
+ {
307
+ _script: {
308
+ type: 'number',
309
+ script: {
310
+ lang: 'painless',
311
+ source:
312
+ "\n try {\n def stageIndex = doc['critical_path.stage_index'].value;\n if (stageIndex != null) {\n return stageIndex;\n }\n \n return 9999999;\n } catch (Exception err) {\n return 9999999;\n }\n "
313
+ },
314
+ order: 'desc'
315
+ }
316
+ },
317
+ {
318
+ _script: {
319
+ type: 'number',
320
+ script: {
321
+ lang: 'painless',
322
+ source:
323
+ "\n def projectNumber = params._source.project_id;\n projectNumber = /[^0-9]/.matcher(projectNumber).replaceAll('');\n return Integer.parseInt(projectNumber);\n "
324
+ },
325
+ order: 'desc'
326
+ }
327
+ },
328
+ {
329
+ _script: {
330
+ type: 'number',
331
+ script: {
332
+ lang: 'painless',
333
+ source:
334
+ "\n try {\n boolean isReady = doc['is_ready'].value;\n boolean isComplete = doc['is_complete'].value;\n\n if (isReady == true && isComplete == true && doc.containsKey('completed_at') && !doc['completed_at'].empty) {\n return doc['completed_at'].value.millis;\n } else if (isReady == true && doc.containsKey('ready_at') && !doc['ready_at'].empty) {\n return doc['ready_at'].value.millis;\n }\n\n return doc['created_at'].value.millis;\n } catch (Exception err) {\n return 0;\n }\n "
335
+ },
336
+ order: 'desc'
337
+ }
338
+ },
339
+ {
340
+ _script: {
341
+ type: 'number',
342
+ script: {
343
+ lang: 'painless',
344
+ source:
345
+ "\n return doc['was_marked_incomplete'].empty\n ? 0\n : doc['was_marked_incomplete'].value ? 1 : 0;\n "
346
+ },
347
+ order: 'desc'
348
+ }
349
+ },
350
+ { 'last_comment_data.created_at': { order: 'desc' } },
351
+ {
352
+ _script: {
353
+ type: 'number',
354
+ script: {
355
+ lang: 'painless',
356
+ source:
357
+ '\n try {\n def fields = params._source.fields;\n\n for (int i=0; i<fields.size(); i++) {\n if (fields[i].id.equals(params.value)) {\n if (fields[i].number != null) {\n return fields[i].number;\n } else {\n return -999999;\n }\n }\n }\n\n return -999999;\n } catch (Exception err) {\n return -999999;\n }\n ',
358
+ params: { value: '38d423bf-fc24-4183-b8b7-15420c89e318' }
359
+ },
360
+ order: 'desc'
361
+ }
362
+ },
363
+ {
364
+ _script: {
365
+ type: 'string',
366
+ script: {
367
+ lang: 'painless',
368
+ source:
369
+ "\n try {\n String textInfo = '';\n def fields = params._source.fields;\n\n for (int i=0; i<fields.size(); i++) {\n if (fields[i].id.equals(params.value)) {\n\n if (fields[i].number != null) {\n return '';\n }\n \n textInfo = fields[i].text == null ? '' : fields[i].text;\n }\n\n }\n\n return textInfo;\n } catch (Exception err) {\n return '';\n }\n ",
370
+ params: { value: '38d423bf-fc24-4183-b8b7-15420c89e318' }
371
+ },
372
+ order: 'desc'
373
+ }
374
+ },
375
+ { id: { order: 'desc', missing: '_last' } }
376
+ ]);
377
+ done();
378
+ });
379
+ });
162
380
  });