@awell-health/awell-extensions 2.0.211 → 2.0.213
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/dist/extensions/awell/v1/actions/updatePatient/config/getTimezones.js +37 -4
- package/dist/extensions/awell/v1/actions/updatePatient/config/getTimezones.js.map +1 -1
- package/dist/extensions/mailgun/settings.d.ts +2 -2
- package/dist/extensions/math/v1/actions/generateRandomNumber/config/fields.d.ts +2 -2
- package/dist/extensions/shelly/actions/summarizeForm/summarizeForm.js +13 -17
- package/dist/extensions/shelly/actions/summarizeForm/summarizeForm.js.map +1 -1
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/prompt.d.ts +1 -1
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/prompt.js +98 -48
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/prompt.js.map +1 -1
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/summarizeTrackOutcomeWithLLM.evaluate.d.ts +1 -0
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/summarizeTrackOutcomeWithLLM.evaluate.js +151 -0
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/lib/summarizeTrackOutcomeWithLLM/summarizeTrackOutcomeWithLLM.evaluate.js.map +1 -0
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/summarizeTrackOutcome.js +14 -19
- package/dist/extensions/shelly/actions/summarizeTrackOutcome/summarizeTrackOutcome.js.map +1 -1
- package/dist/extensions/shelly/lib/getCareFlowDetails/getCareFlowDetails.d.ts +15 -0
- package/dist/extensions/shelly/lib/getCareFlowDetails/getCareFlowDetails.js +98 -0
- package/dist/extensions/shelly/lib/getCareFlowDetails/getCareFlowDetails.js.map +1 -0
- package/dist/extensions/shelly/lib/getCareFlowDetails/index.d.ts +1 -0
- package/dist/extensions/shelly/lib/getCareFlowDetails/index.js +18 -0
- package/dist/extensions/shelly/lib/getCareFlowDetails/index.js.map +1 -0
- package/dist/extensions/shelly/lib/getTrackData/getTrackData.d.ts +6 -53
- package/dist/extensions/shelly/lib/getTrackData/getTrackData.js +557 -372
- package/dist/extensions/shelly/lib/getTrackData/getTrackData.js.map +1 -1
- package/dist/extensions/shelly/lib/getTrackData/index.d.ts +1 -1
- package/dist/extensions/shelly/lib/getTrackData/index.js +15 -3
- package/dist/extensions/shelly/lib/getTrackData/index.js.map +1 -1
- package/dist/extensions/shelly/lib/getTrackData/types.d.ts +193 -0
- package/dist/extensions/shelly/lib/getTrackData/types.js +3 -0
- package/dist/extensions/shelly/lib/getTrackData/types.js.map +1 -0
- package/dist/extensions/talkDesk/settings.d.ts +2 -2
- package/package.json +2 -1
@@ -1,408 +1,593 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.getTrackData = void 0;
|
4
|
-
const
|
5
|
-
|
4
|
+
const lodash_1 = require("lodash");
|
5
|
+
/**
|
6
|
+
* Fetch and process track data from Awell SDK
|
7
|
+
* @param params Input parameters for fetching track data
|
8
|
+
* @returns Processed track data with steps and activities
|
9
|
+
*/
|
10
|
+
const getTrackData = async ({ awellSdk, pathwayId, trackId, currentActivityId, }) => {
|
11
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
12
|
+
// Validate input parameters
|
13
|
+
if ((0, lodash_1.isNil)(awellSdk))
|
14
|
+
throw new Error('AwellSdk is required');
|
15
|
+
if ((0, lodash_1.isEmpty)(pathwayId))
|
16
|
+
throw new Error('PathwayId is required');
|
17
|
+
if ((0, lodash_1.isEmpty)(trackId))
|
18
|
+
throw new Error('TrackId is required');
|
19
|
+
if ((0, lodash_1.isEmpty)(currentActivityId))
|
20
|
+
throw new Error('CurrentActivityId is required');
|
21
|
+
// 1. Make a single combined query for all data
|
22
|
+
const combinedQuery = await fetchAllTrackData(awellSdk, pathwayId);
|
23
|
+
// 2. Find current activity cutoff date
|
24
|
+
const activities = (_b = (_a = combinedQuery.pathwayActivities) === null || _a === void 0 ? void 0 : _a.activities) !== null && _b !== void 0 ? _b : [];
|
25
|
+
const currentActivity = activities.find(activity => activity.id === currentActivityId);
|
26
|
+
const currentActivityDate = (_c = currentActivity === null || currentActivity === void 0 ? void 0 : currentActivity.date) !== null && _c !== void 0 ? _c : '';
|
27
|
+
// 3. Filter activities for this track
|
28
|
+
const trackActivities = filterTrackActivities(activities, trackId, currentActivityDate);
|
29
|
+
// 4. Get and process steps for this track
|
30
|
+
const elements = (_e = (_d = combinedQuery.pathwayElements) === null || _d === void 0 ? void 0 : _d.elements) !== null && _e !== void 0 ? _e : [];
|
31
|
+
const trackSteps = filterTrackSteps(elements, trackId);
|
32
|
+
// 5. Process data points for activities
|
33
|
+
const dataPoints = (_g = (_f = combinedQuery.pathwayDataPoints) === null || _f === void 0 ? void 0 : _f.dataPoints) !== null && _g !== void 0 ? _g : [];
|
34
|
+
const activityDataPointsMap = createDataPointsMap(dataPoints);
|
35
|
+
// 6. Extract activities with forms for processing
|
36
|
+
const activitiesWithForms = extractActivitiesWithForms(trackActivities);
|
37
|
+
// 7. Process form definitions and responses
|
38
|
+
const { formDefinitionsMap, formResponsesMap } = await processFormDefinitionsAndResponses(awellSdk, pathwayId, activitiesWithForms);
|
39
|
+
// 8. Try to extract message activities and fetch message content, but continue if it fails
|
40
|
+
let messageContentsMap = new Map();
|
41
|
+
try {
|
42
|
+
const messageActivities = extractMessageActivities(trackActivities);
|
43
|
+
messageContentsMap = await fetchMessageContents(awellSdk, messageActivities);
|
44
|
+
}
|
45
|
+
catch (error) {
|
46
|
+
// Continue without message data
|
47
|
+
}
|
48
|
+
// 9. Process steps with activities
|
49
|
+
const processedSteps = trackSteps.map(step => processStep(step, trackActivities, activityDataPointsMap, formDefinitionsMap, formResponsesMap, messageContentsMap));
|
6
50
|
return {
|
7
|
-
|
8
|
-
title: (_a = data.track.title) !== null && _a !== void 0 ? _a : 'Untitled Track',
|
9
|
-
},
|
10
|
-
steps: await Promise.all(data.steps.map(async (step) => {
|
11
|
-
var _a;
|
12
|
-
const stepActivities = data.activities.filter(activity => { var _a; return ((_a = activity.context) === null || _a === void 0 ? void 0 : _a.step_id) === step.id; });
|
13
|
-
return {
|
14
|
-
name: step.name,
|
15
|
-
label: step.label,
|
16
|
-
status: step.status,
|
17
|
-
start_date: step.start_date,
|
18
|
-
end_date: step.end_date,
|
19
|
-
stakeholders: (_a = step.stakeholders) === null || _a === void 0 ? void 0 : _a.map(s => ({
|
20
|
-
name: s.name
|
21
|
-
})),
|
22
|
-
activities: await Promise.all(stepActivities.map(async (activity) => {
|
23
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
24
|
-
const baseActivity = {
|
25
|
-
date: activity.date,
|
26
|
-
action: activity.action,
|
27
|
-
status: activity.status,
|
28
|
-
subject: {
|
29
|
-
type: activity.subject.type,
|
30
|
-
name: activity.subject.name
|
31
|
-
},
|
32
|
-
object: {
|
33
|
-
type: activity.object.type,
|
34
|
-
name: activity.object.name
|
35
|
-
}
|
36
|
-
};
|
37
|
-
if (((_a = activity.indirect_object) === null || _a === void 0 ? void 0 : _a.type) !== undefined && ((_b = activity.indirect_object) === null || _b === void 0 ? void 0 : _b.name) !== undefined) {
|
38
|
-
baseActivity.indirect_object = {
|
39
|
-
type: activity.indirect_object.type,
|
40
|
-
name: activity.indirect_object.name
|
41
|
-
};
|
42
|
-
}
|
43
|
-
// Process form data if available
|
44
|
-
const formId = (_c = activity.form) === null || _c === void 0 ? void 0 : _c.id;
|
45
|
-
const formTitle = (_d = activity.form) === null || _d === void 0 ? void 0 : _d.title;
|
46
|
-
if (formId !== undefined &&
|
47
|
-
formId !== '' &&
|
48
|
-
formTitle !== undefined &&
|
49
|
-
formTitle !== '') {
|
50
|
-
try {
|
51
|
-
// Get form definition using SDK
|
52
|
-
const formDefinitionResponse = await awellSdk.orchestration.query({
|
53
|
-
form: {
|
54
|
-
__args: {
|
55
|
-
id: formId,
|
56
|
-
pathway_id: pathwayId,
|
57
|
-
},
|
58
|
-
form: {
|
59
|
-
id: true,
|
60
|
-
title: true,
|
61
|
-
key: true,
|
62
|
-
definition_id: true,
|
63
|
-
release_id: true,
|
64
|
-
questions: {
|
65
|
-
id: true,
|
66
|
-
key: true,
|
67
|
-
title: true,
|
68
|
-
userQuestionType: true,
|
69
|
-
options: {
|
70
|
-
label: true,
|
71
|
-
value: true,
|
72
|
-
value_string: true,
|
73
|
-
},
|
74
|
-
},
|
75
|
-
},
|
76
|
-
},
|
77
|
-
});
|
78
|
-
// Get form response using SDK
|
79
|
-
const formResponseData = await awellSdk.orchestration.query({
|
80
|
-
formResponse: {
|
81
|
-
__args: {
|
82
|
-
pathway_id: pathwayId,
|
83
|
-
activity_id: activity.id,
|
84
|
-
},
|
85
|
-
response: {
|
86
|
-
answers: {
|
87
|
-
question_id: true,
|
88
|
-
value: true,
|
89
|
-
label: true,
|
90
|
-
value_type: true,
|
91
|
-
},
|
92
|
-
},
|
93
|
-
},
|
94
|
-
});
|
95
|
-
const formDefinition = (_e = formDefinitionResponse.form) === null || _e === void 0 ? void 0 : _e.form;
|
96
|
-
const formResponse = (_f = formResponseData.formResponse) === null || _f === void 0 ? void 0 : _f.response;
|
97
|
-
if (formDefinition !== null && formResponse !== null) {
|
98
|
-
// Map questions to their answers
|
99
|
-
const formattedResponses = formDefinition.questions.map(question => {
|
100
|
-
var _a, _b, _c;
|
101
|
-
const answer = formResponse.answers.find(a => a.question_id === question.id);
|
102
|
-
let responseText = (_a = answer === null || answer === void 0 ? void 0 : answer.value) !== null && _a !== void 0 ? _a : 'No response';
|
103
|
-
// Handle different question types
|
104
|
-
if (question.userQuestionType === 'YES_NO') {
|
105
|
-
responseText = responseText === '1' ? 'Yes' : responseText === '0' ? 'No' : 'No response';
|
106
|
-
}
|
107
|
-
else if (question.userQuestionType === 'MULTIPLE_CHOICE' && answer !== null) {
|
108
|
-
const option = (_b = question.options) === null || _b === void 0 ? void 0 : _b.find(opt => opt.value_string === (answer === null || answer === void 0 ? void 0 : answer.value));
|
109
|
-
responseText = (_c = option === null || option === void 0 ? void 0 : option.label) !== null && _c !== void 0 ? _c : responseText;
|
110
|
-
}
|
111
|
-
return {
|
112
|
-
title: question.title,
|
113
|
-
response: responseText
|
114
|
-
};
|
115
|
-
});
|
116
|
-
baseActivity.form = {
|
117
|
-
title: formTitle,
|
118
|
-
questions: formattedResponses
|
119
|
-
};
|
120
|
-
}
|
121
|
-
}
|
122
|
-
catch (error) {
|
123
|
-
// Fallback to basic form data if form questions exist
|
124
|
-
const questions = (_g = activity.form) === null || _g === void 0 ? void 0 : _g.questions;
|
125
|
-
if (Array.isArray(questions)) {
|
126
|
-
baseActivity.form = {
|
127
|
-
title: formTitle,
|
128
|
-
questions: questions.map(q => ({
|
129
|
-
title: q.title,
|
130
|
-
response: 'No response'
|
131
|
-
}))
|
132
|
-
};
|
133
|
-
}
|
134
|
-
}
|
135
|
-
}
|
136
|
-
// Handle standalone data points
|
137
|
-
else if (Array.isArray(activity.dataPoints) && activity.dataPoints.length > 0) {
|
138
|
-
baseActivity.data_points = activity.dataPoints.map(dp => ({
|
139
|
-
value: dp.serialized_value,
|
140
|
-
date: dp.date,
|
141
|
-
title: dp.definitionTitle
|
142
|
-
}));
|
143
|
-
}
|
144
|
-
return baseActivity;
|
145
|
-
}))
|
146
|
-
};
|
147
|
-
}))
|
51
|
+
steps: processedSteps
|
148
52
|
};
|
149
53
|
};
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
},
|
158
|
-
code: true,
|
159
|
-
success: true,
|
54
|
+
exports.getTrackData = getTrackData;
|
55
|
+
/**
|
56
|
+
* Fetch all track data in a single combined query
|
57
|
+
*/
|
58
|
+
async function fetchAllTrackData(awellSdk, pathwayId) {
|
59
|
+
try {
|
60
|
+
return await awellSdk.orchestration.query({
|
160
61
|
pathway: {
|
161
|
-
id:
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
release_id: true,
|
168
|
-
can_trigger_manually: true,
|
169
|
-
},
|
170
|
-
},
|
171
|
-
},
|
172
|
-
});
|
173
|
-
// 2. Get pathway elements (steps)
|
174
|
-
const elementsQuery = (await awellSdk.orchestration.query({
|
175
|
-
pathwayElements: {
|
176
|
-
__args: {
|
177
|
-
pathway_id: pathwayId,
|
178
|
-
},
|
179
|
-
code: true,
|
180
|
-
success: true,
|
181
|
-
elements: {
|
182
|
-
id: true,
|
183
|
-
parent_id: true,
|
184
|
-
name: true,
|
185
|
-
label: {
|
186
|
-
text: true,
|
187
|
-
color: true,
|
188
|
-
id: true,
|
189
|
-
},
|
190
|
-
start_date: true,
|
191
|
-
end_date: true,
|
192
|
-
status: true,
|
193
|
-
type: true,
|
194
|
-
activity_type: true,
|
195
|
-
stakeholders: {
|
196
|
-
id: true,
|
197
|
-
name: true,
|
198
|
-
},
|
199
|
-
context: {
|
200
|
-
instance_id: true,
|
201
|
-
pathway_id: true,
|
202
|
-
step_id: true,
|
203
|
-
track_id: true,
|
204
|
-
},
|
205
|
-
},
|
206
|
-
},
|
207
|
-
}));
|
208
|
-
// 3. Get all activities in the track up to current activity
|
209
|
-
const activitiesQuery = (await awellSdk.orchestration.query({
|
210
|
-
pathwayActivities: {
|
211
|
-
__args: {
|
212
|
-
pathway_id: pathwayId,
|
213
|
-
pagination: {
|
214
|
-
offset: 0,
|
215
|
-
count: 500
|
62
|
+
__args: { id: pathwayId },
|
63
|
+
pathway: {
|
64
|
+
tracks: {
|
65
|
+
id: true,
|
66
|
+
title: true
|
67
|
+
}
|
216
68
|
}
|
217
69
|
},
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
date: true,
|
222
|
-
action: true,
|
223
|
-
status: true,
|
224
|
-
subject: {
|
225
|
-
type: true,
|
226
|
-
name: true
|
227
|
-
},
|
228
|
-
object: {
|
229
|
-
id: true,
|
230
|
-
type: true,
|
231
|
-
name: true
|
232
|
-
},
|
233
|
-
indirect_object: {
|
70
|
+
pathwayElements: {
|
71
|
+
__args: { pathway_id: pathwayId },
|
72
|
+
elements: {
|
234
73
|
id: true,
|
74
|
+
name: true,
|
75
|
+
label: {
|
76
|
+
text: true
|
77
|
+
},
|
78
|
+
start_date: true,
|
79
|
+
end_date: true,
|
80
|
+
status: true,
|
235
81
|
type: true,
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
key: true,
|
243
|
-
title: true,
|
244
|
-
questionConfig: {
|
245
|
-
mandatory: true
|
246
|
-
}
|
82
|
+
stakeholders: {
|
83
|
+
name: true
|
84
|
+
},
|
85
|
+
context: {
|
86
|
+
step_id: true,
|
87
|
+
track_id: true
|
247
88
|
}
|
89
|
+
}
|
90
|
+
},
|
91
|
+
pathwayActivities: {
|
92
|
+
__args: {
|
93
|
+
pathway_id: pathwayId,
|
94
|
+
pagination: { offset: 0, count: 500 } // TODO: we might need to handle this differently later but it is ok for now
|
248
95
|
},
|
249
|
-
|
96
|
+
activities: {
|
250
97
|
id: true,
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
98
|
+
date: true,
|
99
|
+
action: true,
|
100
|
+
status: true,
|
101
|
+
resolution: true,
|
102
|
+
subject: { type: true, name: true },
|
103
|
+
object: {
|
104
|
+
type: true,
|
105
|
+
name: true,
|
106
|
+
id: true // id field to get message ID
|
107
|
+
},
|
108
|
+
indirect_object: { type: true, name: true },
|
109
|
+
form: {
|
110
|
+
id: true,
|
111
|
+
title: true
|
112
|
+
},
|
113
|
+
track: { id: true, title: true },
|
114
|
+
context: { track_id: true, step_id: true }
|
115
|
+
}
|
116
|
+
},
|
117
|
+
pathwayDataPoints: {
|
118
|
+
__args: {
|
119
|
+
pathway_id: pathwayId,
|
259
120
|
},
|
260
|
-
|
261
|
-
stakeholders: {
|
262
|
-
type: true,
|
121
|
+
dataPoints: {
|
263
122
|
id: true,
|
264
|
-
|
265
|
-
|
266
|
-
|
123
|
+
data_set_id: true,
|
124
|
+
key: true,
|
125
|
+
serialized_value: true,
|
126
|
+
data_point_definition_id: true,
|
127
|
+
date: true,
|
128
|
+
valueType: true,
|
129
|
+
activity_id: true,
|
267
130
|
},
|
268
|
-
resolution: true,
|
269
|
-
stream_id: true
|
270
131
|
}
|
271
|
-
}
|
272
|
-
}
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
132
|
+
});
|
133
|
+
}
|
134
|
+
catch (error) {
|
135
|
+
throw new Error(`Failed to fetch track data: ${error instanceof Error ? error.message : String(error)}`);
|
136
|
+
}
|
137
|
+
}
|
138
|
+
/**
|
139
|
+
* Filter activities that belong to the specified track
|
140
|
+
*/
|
141
|
+
function filterTrackActivities(activities, trackId, currentActivityDate) {
|
142
|
+
return activities
|
282
143
|
.filter(activity => {
|
283
|
-
var _a;
|
284
|
-
const isInTrack = ((_a = activity.context) === null || _a === void 0 ? void 0 : _a.track_id)
|
285
|
-
|
144
|
+
var _a, _b;
|
145
|
+
const isInTrack = !(0, lodash_1.isNil)((_a = activity.context) === null || _a === void 0 ? void 0 : _a.track_id) &&
|
146
|
+
!(0, lodash_1.isEmpty)((_b = activity.context) === null || _b === void 0 ? void 0 : _b.track_id) &&
|
147
|
+
activity.context.track_id === trackId;
|
148
|
+
const hasNoCurrentActivityDate = (0, lodash_1.isEmpty)(currentActivityDate);
|
149
|
+
const isBeforeOrEqualToCurrentDate = !hasNoCurrentActivityDate && activity.date <= currentActivityDate;
|
150
|
+
const isBeforeOrEqualDate = hasNoCurrentActivityDate || isBeforeOrEqualToCurrentDate;
|
286
151
|
return isInTrack && isBeforeOrEqualDate;
|
287
152
|
})
|
288
153
|
.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
// 6. Enhance activities with data points
|
310
|
-
const activitiesWithDataPoints = trackActivities.map(activity => {
|
154
|
+
}
|
155
|
+
/**
|
156
|
+
* Filter steps that belong to the specified track
|
157
|
+
*/
|
158
|
+
function filterTrackSteps(elements, trackId) {
|
159
|
+
return elements.filter(element => {
|
160
|
+
var _a, _b;
|
161
|
+
if ((0, lodash_1.isNil)((_a = element.context) === null || _a === void 0 ? void 0 : _a.track_id) || (0, lodash_1.isEmpty)((_b = element.context) === null || _b === void 0 ? void 0 : _b.track_id))
|
162
|
+
return false;
|
163
|
+
if ((0, lodash_1.isNil)(element.type) || (0, lodash_1.isEmpty)(element.type))
|
164
|
+
return false;
|
165
|
+
return element.context.track_id === trackId && element.type === 'STEP';
|
166
|
+
});
|
167
|
+
}
|
168
|
+
/**
|
169
|
+
* Create a map of activity ID to data points for faster lookup
|
170
|
+
*/
|
171
|
+
function createDataPointsMap(dataPoints) {
|
172
|
+
const activityDataPointsMap = new Map();
|
173
|
+
dataPoints.forEach(dataPoint => {
|
311
174
|
var _a;
|
312
|
-
|
313
|
-
.
|
314
|
-
|
315
|
-
if (dp.data_point_definition_id.endsWith('-ACTIVATION')) {
|
316
|
-
return {
|
317
|
-
...dp,
|
318
|
-
definitionKey: 'activation_date',
|
319
|
-
definitionTitle: 'Activation Date',
|
320
|
-
};
|
175
|
+
if (typeof dataPoint.activity_id === 'string' && dataPoint.activity_id !== '') {
|
176
|
+
if (!activityDataPointsMap.has(dataPoint.activity_id)) {
|
177
|
+
activityDataPointsMap.set(dataPoint.activity_id, []);
|
321
178
|
}
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
data_point_definition_id: question.key,
|
335
|
-
date: (_d = dataPoint === null || dataPoint === void 0 ? void 0 : dataPoint.date) !== null && _d !== void 0 ? _d : activity.date,
|
336
|
-
valueType: (_e = dataPoint === null || dataPoint === void 0 ? void 0 : dataPoint.valueType) !== null && _e !== void 0 ? _e : 'STRING',
|
337
|
-
activity_id: activity.id,
|
338
|
-
definitionKey: question.key,
|
339
|
-
definitionTitle: question.title,
|
340
|
-
};
|
341
|
-
});
|
342
|
-
activityDataPoints.push(...formResponses);
|
179
|
+
// Add enhanced data point with improved title detection
|
180
|
+
const enhancedDataPoint = { ...dataPoint };
|
181
|
+
// Apply pattern-based mappings for titles
|
182
|
+
if (typeof dataPoint.data_point_definition_id === 'string' && dataPoint.data_point_definition_id !== '') {
|
183
|
+
if (dataPoint.data_point_definition_id.endsWith('-ACTIVATION')) {
|
184
|
+
enhancedDataPoint.definitionTitle = 'Activation Date';
|
185
|
+
}
|
186
|
+
else if (dataPoint.data_point_definition_id.endsWith('-COMPLETION')) {
|
187
|
+
enhancedDataPoint.definitionTitle = 'Completion Date';
|
188
|
+
}
|
189
|
+
}
|
190
|
+
(_a = activityDataPointsMap.get(dataPoint.activity_id)) === null || _a === void 0 ? void 0 : _a.push(enhancedDataPoint);
|
343
191
|
}
|
344
|
-
return {
|
345
|
-
...activity,
|
346
|
-
dataPoints: activityDataPoints
|
347
|
-
};
|
348
192
|
});
|
349
|
-
|
350
|
-
|
351
|
-
|
193
|
+
return activityDataPointsMap;
|
194
|
+
}
|
195
|
+
/**
|
196
|
+
* Extract activities with forms for processing
|
197
|
+
*/
|
198
|
+
function extractActivitiesWithForms(activities) {
|
199
|
+
return activities
|
200
|
+
.filter(activity => { var _a; return typeof ((_a = activity.form) === null || _a === void 0 ? void 0 : _a.id) === 'string' && activity.form.id !== ''; })
|
201
|
+
.map(activity => {
|
352
202
|
var _a;
|
353
|
-
const elementTrackId = (_a = element.context) === null || _a === void 0 ? void 0 : _a.track_id;
|
354
|
-
const isInTrack = elementTrackId === trackId;
|
355
|
-
const isStep = element.type === 'STEP';
|
356
|
-
return isInTrack && isStep;
|
357
|
-
})
|
358
|
-
.map(element => {
|
359
|
-
var _a, _b;
|
360
203
|
return ({
|
361
|
-
|
362
|
-
|
363
|
-
name: element.name,
|
364
|
-
label: (_b = (_a = element.label) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '',
|
365
|
-
start_date: element.start_date,
|
366
|
-
end_date: element.end_date,
|
367
|
-
status: element.status,
|
368
|
-
activity_type: element.activity_type,
|
369
|
-
stakeholders: element.stakeholders.map(stakeholder => {
|
370
|
-
var _a;
|
371
|
-
return ({
|
372
|
-
id: stakeholder.id,
|
373
|
-
name: (_a = stakeholder.name) !== null && _a !== void 0 ? _a : '',
|
374
|
-
});
|
375
|
-
}),
|
376
|
-
activities: [],
|
204
|
+
activityId: activity.id,
|
205
|
+
formId: (_a = activity.form) === null || _a === void 0 ? void 0 : _a.id
|
377
206
|
});
|
378
207
|
});
|
379
|
-
|
380
|
-
|
381
|
-
|
208
|
+
}
|
209
|
+
/**
|
210
|
+
* Process form definitions and responses in batches
|
211
|
+
*/
|
212
|
+
async function processFormDefinitionsAndResponses(awellSdk, pathwayId, activitiesWithForms) {
|
213
|
+
const formDefinitionsMap = new Map();
|
214
|
+
const formResponsesMap = {};
|
215
|
+
if (activitiesWithForms.length === 0) {
|
216
|
+
return { formDefinitionsMap, formResponsesMap };
|
217
|
+
}
|
218
|
+
// Prepare queries in batches to avoid overloading
|
219
|
+
const batchSize = 10;
|
220
|
+
const batches = [];
|
221
|
+
for (let i = 0; i < activitiesWithForms.length; i += batchSize) {
|
222
|
+
batches.push(activitiesWithForms.slice(i, i + batchSize));
|
223
|
+
}
|
224
|
+
for (const batch of batches) {
|
225
|
+
await processBatch(awellSdk, pathwayId, batch, formDefinitionsMap, formResponsesMap);
|
226
|
+
}
|
227
|
+
return { formDefinitionsMap, formResponsesMap };
|
228
|
+
}
|
229
|
+
/**
|
230
|
+
* Process a batch of form definitions and responses
|
231
|
+
*/
|
232
|
+
async function processBatch(awellSdk, pathwayId, batch, formDefinitionsMap, formResponsesMap) {
|
233
|
+
try {
|
234
|
+
// Create an array of promises for form definitions and responses
|
235
|
+
const formDefinitionPromises = batch.map(async ({ formId }) => {
|
236
|
+
try {
|
237
|
+
// Only fetch form definition if we haven't already
|
238
|
+
if (!formDefinitionsMap.has(formId)) {
|
239
|
+
return await awellSdk.orchestration.query({
|
240
|
+
form: {
|
241
|
+
__args: {
|
242
|
+
id: formId,
|
243
|
+
pathway_id: pathwayId,
|
244
|
+
},
|
245
|
+
form: {
|
246
|
+
id: true,
|
247
|
+
title: true,
|
248
|
+
key: true,
|
249
|
+
definition_id: true,
|
250
|
+
release_id: true,
|
251
|
+
questions: {
|
252
|
+
id: true,
|
253
|
+
key: true,
|
254
|
+
title: true,
|
255
|
+
userQuestionType: true,
|
256
|
+
options: {
|
257
|
+
label: true,
|
258
|
+
value: true,
|
259
|
+
value_string: true,
|
260
|
+
},
|
261
|
+
},
|
262
|
+
},
|
263
|
+
},
|
264
|
+
});
|
265
|
+
}
|
266
|
+
return null;
|
267
|
+
}
|
268
|
+
catch (error) {
|
269
|
+
return null;
|
270
|
+
}
|
271
|
+
});
|
272
|
+
const formResponsePromises = batch.map(async ({ activityId }) => {
|
273
|
+
try {
|
274
|
+
return await awellSdk.orchestration.query({
|
275
|
+
formResponse: {
|
276
|
+
__args: {
|
277
|
+
pathway_id: pathwayId,
|
278
|
+
activity_id: activityId
|
279
|
+
},
|
280
|
+
response: {
|
281
|
+
answers: {
|
282
|
+
question_id: true,
|
283
|
+
value: true,
|
284
|
+
label: true,
|
285
|
+
value_type: true
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
});
|
290
|
+
}
|
291
|
+
catch (error) {
|
292
|
+
return null;
|
293
|
+
}
|
294
|
+
});
|
295
|
+
// Await all promises in the batch
|
296
|
+
const formDefinitionResults = await Promise.all(formDefinitionPromises);
|
297
|
+
const formResponseResults = await Promise.all(formResponsePromises);
|
298
|
+
// Process form definitions
|
299
|
+
formDefinitionResults.forEach((result, index) => {
|
300
|
+
if (!(0, lodash_1.isNil)(result) && !(0, lodash_1.isNil)((0, lodash_1.get)(result, 'form.form'))) {
|
301
|
+
const { formId } = batch[index];
|
302
|
+
formDefinitionsMap.set(formId, (0, lodash_1.get)(result, 'form.form'));
|
303
|
+
}
|
304
|
+
});
|
305
|
+
// Process form responses
|
306
|
+
batch.forEach(({ activityId, formId }, index) => {
|
307
|
+
const result = formResponseResults[index];
|
308
|
+
if (!(0, lodash_1.isNil)(result) && !(0, lodash_1.isNil)((0, lodash_1.get)(result, 'formResponse.response'))) {
|
309
|
+
const responseData = result.formResponse.response;
|
310
|
+
// Create the map entry if it doesn't exist
|
311
|
+
if (!Object.prototype.hasOwnProperty.call(formResponsesMap, formId)) {
|
312
|
+
formResponsesMap[formId] = {};
|
313
|
+
}
|
314
|
+
const answers = Array.isArray(responseData.answers) ? responseData.answers : [];
|
315
|
+
formResponsesMap[formId][activityId] = {
|
316
|
+
activity_id: activityId,
|
317
|
+
form_id: formId,
|
318
|
+
answers: answers
|
319
|
+
};
|
320
|
+
}
|
321
|
+
});
|
322
|
+
}
|
323
|
+
catch (error) {
|
324
|
+
// Continue with partial data rather than failing completely
|
325
|
+
}
|
326
|
+
}
|
327
|
+
/**
|
328
|
+
* Extract activities that are messages
|
329
|
+
*/
|
330
|
+
function extractMessageActivities(activities) {
|
331
|
+
const messageActivities = activities
|
332
|
+
.filter(activity => {
|
333
|
+
return !(0, lodash_1.isNil)(activity.object) &&
|
334
|
+
typeof activity.object.type === 'string' &&
|
335
|
+
activity.object.type === 'MESSAGE' &&
|
336
|
+
!(0, lodash_1.isNil)(activity.object.id) &&
|
337
|
+
!(0, lodash_1.isEmpty)(activity.object.id);
|
338
|
+
})
|
339
|
+
.map(activity => {
|
340
|
+
// Use object.id as the message ID
|
341
|
+
const messageId = activity.object.id;
|
342
|
+
// Extract fallback content from activity if available
|
343
|
+
let fallbackSubject = '';
|
344
|
+
if (!(0, lodash_1.isNil)(activity.object.name) && !(0, lodash_1.isEmpty)(activity.object.name)) {
|
345
|
+
fallbackSubject = activity.object.name;
|
346
|
+
}
|
382
347
|
return {
|
383
|
-
|
384
|
-
|
348
|
+
activityId: activity.id,
|
349
|
+
messageId,
|
350
|
+
fallbackSubject,
|
351
|
+
fallbackBody: ''
|
385
352
|
};
|
386
353
|
});
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
const
|
394
|
-
|
395
|
-
|
396
|
-
|
354
|
+
return messageActivities;
|
355
|
+
}
|
356
|
+
/**
|
357
|
+
* Fetch message contents for message activities
|
358
|
+
*/
|
359
|
+
async function fetchMessageContents(awellSdk, messageActivities) {
|
360
|
+
const messageContentsMap = new Map();
|
361
|
+
if (messageActivities.length === 0) {
|
362
|
+
return messageContentsMap;
|
363
|
+
}
|
364
|
+
// Process in batches to avoid overloading
|
365
|
+
const batchSize = 10;
|
366
|
+
const batches = [];
|
367
|
+
for (let i = 0; i < messageActivities.length; i += batchSize) {
|
368
|
+
batches.push(messageActivities.slice(i, i + batchSize));
|
369
|
+
}
|
370
|
+
for (const batch of batches) {
|
371
|
+
await Promise.all(batch.map(async ({ activityId, messageId, fallbackSubject, fallbackBody }) => {
|
372
|
+
try {
|
373
|
+
// Try to fetch message content with the query structure from documentation
|
374
|
+
const response = await awellSdk.orchestration.query({
|
375
|
+
message: {
|
376
|
+
__args: {
|
377
|
+
id: messageId
|
378
|
+
},
|
379
|
+
message: {
|
380
|
+
id: true,
|
381
|
+
subject: true,
|
382
|
+
body: true,
|
383
|
+
format: true,
|
384
|
+
attachments: {
|
385
|
+
id: true,
|
386
|
+
name: true,
|
387
|
+
type: true,
|
388
|
+
url: true
|
389
|
+
}
|
390
|
+
}
|
391
|
+
}
|
392
|
+
});
|
393
|
+
// Use lodash to check for null/undefined values
|
394
|
+
if (!(0, lodash_1.isNil)(response) &&
|
395
|
+
!(0, lodash_1.isNil)(response.message) &&
|
396
|
+
!(0, lodash_1.isNil)(response.message.message)) {
|
397
|
+
messageContentsMap.set(activityId, {
|
398
|
+
subject: response.message.message.subject,
|
399
|
+
body: response.message.message.body
|
400
|
+
});
|
401
|
+
}
|
402
|
+
else {
|
403
|
+
// Use fallback content if available
|
404
|
+
const hasFallbackSubject = !(0, lodash_1.isNil)(fallbackSubject) && !(0, lodash_1.isEmpty)(fallbackSubject);
|
405
|
+
const hasFallbackBody = !(0, lodash_1.isNil)(fallbackBody) && !(0, lodash_1.isEmpty)(fallbackBody);
|
406
|
+
if (hasFallbackSubject || hasFallbackBody) {
|
407
|
+
messageContentsMap.set(activityId, {
|
408
|
+
subject: fallbackSubject,
|
409
|
+
body: fallbackBody
|
410
|
+
});
|
411
|
+
}
|
412
|
+
}
|
413
|
+
}
|
414
|
+
catch (error) {
|
415
|
+
// Use fallback content if available after error
|
416
|
+
const hasFallbackSubject = !(0, lodash_1.isNil)(fallbackSubject) && !(0, lodash_1.isEmpty)(fallbackSubject);
|
417
|
+
const hasFallbackBody = !(0, lodash_1.isNil)(fallbackBody) && !(0, lodash_1.isEmpty)(fallbackBody);
|
418
|
+
if (hasFallbackSubject || hasFallbackBody) {
|
419
|
+
messageContentsMap.set(activityId, {
|
420
|
+
subject: fallbackSubject,
|
421
|
+
body: fallbackBody
|
422
|
+
});
|
423
|
+
}
|
424
|
+
}
|
425
|
+
}));
|
426
|
+
}
|
427
|
+
return messageContentsMap;
|
428
|
+
}
|
429
|
+
/**
|
430
|
+
* Process a step with its activities
|
431
|
+
*/
|
432
|
+
function processStep(step, trackActivities, activityDataPointsMap, formDefinitionsMap, formResponsesMap, messageContentsMap) {
|
433
|
+
var _a, _b;
|
434
|
+
const stepActivities = trackActivities
|
435
|
+
.filter(activity => { var _a; return ((_a = activity.context) === null || _a === void 0 ? void 0 : _a.step_id) === step.id; })
|
436
|
+
.map(activity => processActivity(activity, activityDataPointsMap, formDefinitionsMap, formResponsesMap, messageContentsMap));
|
437
|
+
return {
|
438
|
+
name: step.name,
|
439
|
+
label: typeof ((_a = step.label) === null || _a === void 0 ? void 0 : _a.text) === 'string' ? step.label.text : '',
|
440
|
+
status: step.status,
|
441
|
+
start_date: step.start_date,
|
442
|
+
end_date: step.end_date,
|
443
|
+
stakeholders: (_b = step.stakeholders) === null || _b === void 0 ? void 0 : _b.map(s => ({
|
444
|
+
name: typeof s.name === 'string' ? s.name : ''
|
445
|
+
})),
|
446
|
+
activities: stepActivities
|
397
447
|
};
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
448
|
+
}
|
449
|
+
/**
|
450
|
+
* Process an activity with its form and data points
|
451
|
+
*/
|
452
|
+
function processActivity(activity, activityDataPointsMap, formDefinitionsMap, formResponsesMap, messageContentsMap) {
|
453
|
+
var _a, _b, _c, _d;
|
454
|
+
const baseActivity = {
|
455
|
+
date: activity.date,
|
456
|
+
action: activity.action,
|
457
|
+
status: activity.status,
|
458
|
+
resolution: activity.resolution,
|
459
|
+
subject: {
|
460
|
+
type: activity.subject.type,
|
461
|
+
name: activity.subject.name
|
462
|
+
},
|
463
|
+
object: {
|
464
|
+
type: activity.object.type,
|
465
|
+
name: activity.object.name
|
466
|
+
}
|
402
467
|
};
|
403
|
-
//
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
468
|
+
// Add indirect object if it exists
|
469
|
+
if (!(0, lodash_1.isNil)((_a = activity.indirect_object) === null || _a === void 0 ? void 0 : _a.type) &&
|
470
|
+
!(0, lodash_1.isEmpty)((_b = activity.indirect_object) === null || _b === void 0 ? void 0 : _b.type) &&
|
471
|
+
!(0, lodash_1.isNil)((_c = activity.indirect_object) === null || _c === void 0 ? void 0 : _c.name) &&
|
472
|
+
!(0, lodash_1.isEmpty)((_d = activity.indirect_object) === null || _d === void 0 ? void 0 : _d.name)) {
|
473
|
+
baseActivity.indirect_object = {
|
474
|
+
type: activity.indirect_object.type,
|
475
|
+
name: activity.indirect_object.name
|
476
|
+
};
|
477
|
+
}
|
478
|
+
// Process message if exists
|
479
|
+
processActivityMessage(baseActivity, activity, messageContentsMap);
|
480
|
+
// Process form if exists
|
481
|
+
processActivityForm(baseActivity, activity, formDefinitionsMap, formResponsesMap);
|
482
|
+
// Process data points
|
483
|
+
processActivityDataPoints(baseActivity, activity, activityDataPointsMap);
|
484
|
+
return baseActivity;
|
485
|
+
}
|
486
|
+
/**
|
487
|
+
* Process message for an activity
|
488
|
+
*/
|
489
|
+
function processActivityMessage(baseActivity, activity, messageContentsMap) {
|
490
|
+
if (messageContentsMap.has(activity.id)) {
|
491
|
+
const messageContent = messageContentsMap.get(activity.id);
|
492
|
+
if (!(0, lodash_1.isNil)(messageContent)) {
|
493
|
+
baseActivity.message = {
|
494
|
+
subject: messageContent.subject,
|
495
|
+
body: messageContent.body
|
496
|
+
};
|
497
|
+
}
|
498
|
+
}
|
499
|
+
}
|
500
|
+
/**
|
501
|
+
* Process form for an activity
|
502
|
+
*/
|
503
|
+
function processActivityForm(baseActivity, activity, formDefinitionsMap, formResponsesMap) {
|
504
|
+
if ((0, lodash_1.isNil)(activity.form) || (0, lodash_1.isNil)(activity.form.id) || activity.form.id === '') {
|
505
|
+
return;
|
506
|
+
}
|
507
|
+
const formId = activity.form.id;
|
508
|
+
const formTitle = typeof activity.form.title === 'string' && !(0, lodash_1.isEmpty)(activity.form.title)
|
509
|
+
? activity.form.title
|
510
|
+
: 'Untitled Form';
|
511
|
+
// Check if we have form responses for this activity
|
512
|
+
const hasFormResponses = Object.prototype.hasOwnProperty.call(formResponsesMap, formId) &&
|
513
|
+
Object.prototype.hasOwnProperty.call(formResponsesMap[formId], activity.id);
|
514
|
+
if (hasFormResponses) {
|
515
|
+
const formResponseData = formResponsesMap[formId][activity.id];
|
516
|
+
const formDefinition = formDefinitionsMap.get(formId);
|
517
|
+
// Create form with responses
|
518
|
+
if (!(0, lodash_1.isNil)(formDefinition)) {
|
519
|
+
// Map questions to their answers with proper formatting
|
520
|
+
baseActivity.form = {
|
521
|
+
title: formTitle,
|
522
|
+
questions: formResponseData.answers.map(answer => {
|
523
|
+
var _a, _b, _c, _d;
|
524
|
+
const question = formDefinition.questions.find((q) => q.id === answer.question_id);
|
525
|
+
let responseText = (_a = answer.value) !== null && _a !== void 0 ? _a : 'No response';
|
526
|
+
// Handle different question types
|
527
|
+
if (!(0, lodash_1.isNil)(question)) {
|
528
|
+
if (question.userQuestionType === 'YES_NO') {
|
529
|
+
responseText = responseText === '1' ? 'Yes' : responseText === '0' ? 'No' : 'No response';
|
530
|
+
}
|
531
|
+
else if (question.userQuestionType === 'MULTIPLE_CHOICE' &&
|
532
|
+
typeof answer.value === 'string' && !(0, lodash_1.isEmpty)(answer.value)) {
|
533
|
+
const option = (_b = question.options) === null || _b === void 0 ? void 0 : _b.find((opt) => opt.value_string === answer.value);
|
534
|
+
responseText = (_c = option === null || option === void 0 ? void 0 : option.label) !== null && _c !== void 0 ? _c : responseText;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
return {
|
538
|
+
title: (_d = question === null || question === void 0 ? void 0 : question.title) !== null && _d !== void 0 ? _d : answer.question_id,
|
539
|
+
response: responseText
|
540
|
+
};
|
541
|
+
})
|
542
|
+
};
|
543
|
+
}
|
544
|
+
else {
|
545
|
+
// Fallback if form definition not available
|
546
|
+
baseActivity.form = {
|
547
|
+
title: formTitle,
|
548
|
+
questions: formResponseData.answers.map(answer => {
|
549
|
+
var _a;
|
550
|
+
return ({
|
551
|
+
title: answer.question_id,
|
552
|
+
response: (_a = answer.value) !== null && _a !== void 0 ? _a : 'No response'
|
553
|
+
});
|
554
|
+
})
|
555
|
+
};
|
556
|
+
}
|
557
|
+
}
|
558
|
+
else {
|
559
|
+
// Just include the form title if no responses
|
560
|
+
baseActivity.form = {
|
561
|
+
title: formTitle
|
562
|
+
};
|
563
|
+
}
|
564
|
+
}
|
565
|
+
/**
|
566
|
+
* Process data points for an activity
|
567
|
+
*/
|
568
|
+
function processActivityDataPoints(baseActivity, activity, activityDataPointsMap) {
|
569
|
+
const activityDataPoints = activityDataPointsMap.get(activity.id);
|
570
|
+
if ((0, lodash_1.isNil)(activityDataPoints) || activityDataPoints.length === 0) {
|
571
|
+
return;
|
572
|
+
}
|
573
|
+
// Determine which data points to include
|
574
|
+
let dataPointsToInclude = [];
|
575
|
+
const hasForm = !(0, lodash_1.isNil)(activity.form) && !(0, lodash_1.isEmpty)((0, lodash_1.get)(activity.form, 'id'));
|
576
|
+
if (hasForm) {
|
577
|
+
// If this activity has a form, only include activation data points
|
578
|
+
dataPointsToInclude = activityDataPoints.filter(dp => !(0, lodash_1.isNil)(dp) && !(0, lodash_1.isNil)(dp.data_point_definition_id) &&
|
579
|
+
dp.data_point_definition_id.endsWith('-ACTIVATION'));
|
580
|
+
}
|
581
|
+
else {
|
582
|
+
// If this activity doesn't have a form, include all data points
|
583
|
+
dataPointsToInclude = activityDataPoints;
|
584
|
+
}
|
585
|
+
if (dataPointsToInclude.length > 0) {
|
586
|
+
baseActivity.data_points = dataPointsToInclude.map(dp => ({
|
587
|
+
value: dp.serialized_value,
|
588
|
+
title: !(0, lodash_1.isNil)(dp.definitionTitle) ? dp.definitionTitle : (!(0, lodash_1.isNil)(dp.key) ? dp.key : dp.data_point_definition_id),
|
589
|
+
date: dp.date
|
590
|
+
}));
|
591
|
+
}
|
592
|
+
}
|
408
593
|
//# sourceMappingURL=getTrackData.js.map
|