From 5edfd485869076950a5d57fdfb0bace1e0fa7ec9 Mon Sep 17 00:00:00 2001 From: Zhongnan Su Date: Wed, 2 Mar 2022 15:47:29 -0800 Subject: [PATCH] Fix empty or multiple date values in csv (#293) Signed-off-by: Zhongnan Su --- .../__tests__/savedSearchReportHelper.test.ts | 58 ++++++++++++++++++- server/routes/utils/dataReportHelpers.ts | 22 +++++-- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/server/routes/utils/__tests__/savedSearchReportHelper.test.ts b/server/routes/utils/__tests__/savedSearchReportHelper.test.ts index ff4dcb0e..7009dda3 100644 --- a/server/routes/utils/__tests__/savedSearchReportHelper.test.ts +++ b/server/routes/utils/__tests__/savedSearchReportHelper.test.ts @@ -466,6 +466,59 @@ test('create report for data set with metadata fields', async () => { ); }, 20000); +test('create report with empty/one/multiple(list) date values', async () => { + const hits = [ + hit( + { category: 'c1', customer_gender: 'Ma', order_date: [] }, + { order_date: [] } + ), + hit( + { + category: 'c2', + customer_gender: 'le', + order_date: ['2021-12-16T14:04:55'], + }, + { order_date: ['2021-12-16T14:04:55'] } + ), + hit( + { + category: 'c3', + customer_gender: 'he', + order_date: ['2021-12-17T14:04:55', '2021-12-18T14:04:55'], + }, + { order_date: ['2021-12-17T14:04:55', '2021-12-18T14:04:55'] } + ), + hit( + { + category: 'c4', + customer_gender: 'te', + order_date: '2021-12-19T14:04:55', + }, + { order_date: ['2021-12-19T14:04:55'] } + ), + ]; + const client = mockOpenSearchClient( + hits, + '"category", "customer_gender", "order_date"' + ); + const { dataUrl } = await createSavedSearchReport( + input, + client, + mockDateFormat, + ',', + undefined, + mockLogger + ); + + expect(dataUrl).toEqual( + 'category,customer_gender,order_date\n' + + 'c1,Ma,[]\n' + + 'c2,le,"[""12/16/2021 2:04:55.000 pm""]"\n' + + 'c3,he,"[""12/17/2021 2:04:55.000 pm"",""12/18/2021 2:04:55.000 pm""]"\n' + + 'c4,te,12/19/2021 2:04:55.000 pm' + ); +}, 20000); + /** * Mock Elasticsearch client and return different mock objects based on endpoint and parameters. */ @@ -588,8 +641,9 @@ function mockIndexSettings() { `); } -function hit(kv: any) { +function hit(source_kv: any, fields_kv = {}) { return { - _source: kv, + _source: source_kv, + fields: fields_kv, }; } diff --git a/server/routes/utils/dataReportHelpers.ts b/server/routes/utils/dataReportHelpers.ts index 649f7a86..bc108832 100644 --- a/server/routes/utils/dataReportHelpers.ts +++ b/server/routes/utils/dataReportHelpers.ts @@ -118,11 +118,23 @@ export const getOpenSearchData = ( for (let data of valueRes.hits) { const fields = data.fields; // get all the fields of type date and format them to excel format - for (let dateType of report._source.dateFields) { - if (data._source[dateType]) { - data._source[dateType] = moment(fields[dateType][0]).format( - dateFormat - ); + for (let dateField of report._source.dateFields) { + const dateValue = data._source[dateField]; + if (dateValue && dateValue.length !== 0) { + if (dateValue instanceof Array) { + // loop through array + dateValue.forEach((element, index) => { + data._source[dateField][index] = moment( + fields[dateField][index] + ).format(dateFormat); + }); + } else { + // The fields response always returns an array of values for each field + // https://www.elastic.co/guide/en/elasticsearch/reference/master/search-fields.html#search-fields-response + data._source[dateField] = moment(fields[dateField][0]).format( + dateFormat + ); + } } } delete data['fields'];