tango-app-api-trax 3.8.14 → 3.8.16
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/package.json
CHANGED
|
@@ -3412,7 +3412,16 @@ export async function getStoreTaskDetails( req, res ) {
|
|
|
3412
3412
|
|
|
3413
3413
|
export async function runAIFlag( req, res ) {
|
|
3414
3414
|
try {
|
|
3415
|
-
let checklistDetails = await CLconfig.find( {
|
|
3415
|
+
let checklistDetails = await CLconfig.find( {
|
|
3416
|
+
publish: true,
|
|
3417
|
+
runAIQuestionCount: { $ne: 0 },
|
|
3418
|
+
$expr: {
|
|
3419
|
+
$gt: [
|
|
3420
|
+
{ $size: { $cond: [ { $isArray: '$notifyFlags.notifyType' }, '$notifyFlags.notifyType', [] ] } },
|
|
3421
|
+
0,
|
|
3422
|
+
],
|
|
3423
|
+
},
|
|
3424
|
+
}, { _id: 1, notifyFlags: 1, approver: 1 } );
|
|
3416
3425
|
let date = dayjs().subtract( 1, 'day' ).format( 'YYYY-MM-DD' );
|
|
3417
3426
|
if ( checklistDetails.length ) {
|
|
3418
3427
|
await Promise.all( checklistDetails.map( async ( ele ) => {
|
|
@@ -3422,7 +3431,7 @@ export async function runAIFlag( req, res ) {
|
|
|
3422
3431
|
let runAIFlag = 0;
|
|
3423
3432
|
store.questionAnswers.forEach( ( section ) => {
|
|
3424
3433
|
section.questions.forEach( ( question ) => {
|
|
3425
|
-
if ( question.answerType == 'image' && ( question?.userAnswer?.[0]?.runAIData
|
|
3434
|
+
if ( question.answerType == 'image' && ( question?.userAnswer?.[0]?.runAIData?.value == 'False' || !question?.userAnswer?.[0]?.runAIData?.value ) ) {
|
|
3426
3435
|
runAIFlag++;
|
|
3427
3436
|
}
|
|
3428
3437
|
} );
|
package/src/hbs/template.hbs
CHANGED
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
.q-answer-text{font-size:12px;color:#1a1a1a;line-height:1.5}
|
|
70
70
|
.q-answer-text.flagged{color:#a32d2d}
|
|
71
71
|
.q-answer-media{margin-top:8px}
|
|
72
|
-
.q-answer-media img,.q-answer-media video{display:block;
|
|
72
|
+
.q-answer-media img,.q-answer-media video,.q-answer-item td img{display:block;width:200px;height:180px;object-fit:cover;border-radius:6px;margin-bottom:6px}
|
|
73
73
|
.q-answer-link{font-size:12px;color:#0085D2;text-decoration:underline;word-break:break-all}
|
|
74
74
|
.q-answer-caption{font-size:11px;color:#666;margin-bottom:4px}
|
|
75
|
-
.q-answer-remarks{font-size:11px;color:#666;margin-top:6px}
|
|
75
|
+
.q-answer-remarks{font-size:11px;color:#666;margin-top:6px;white-space:pre-line}
|
|
76
76
|
/* Footer */
|
|
77
77
|
.page-footer{position:absolute;bottom:20px;left:40px;right:40px;display:flex;justify-content:space-between;align-items:center;font-size:11px;color:#999;border-top:1px solid #d9d9d9;padding-top:10px}
|
|
78
78
|
.footer-brand{display:flex;align-items:center;gap:8px;font-weight:600;color:#0066CC;font-size:11px}
|
|
@@ -179,60 +179,101 @@
|
|
|
179
179
|
<div>Score:{{this.score}}</div>
|
|
180
180
|
{{/if}}
|
|
181
181
|
</div>
|
|
182
|
+
{{#if this.questionReferenceImage}}
|
|
183
|
+
<div class="q-answer-media">
|
|
184
|
+
<div class="q-answer-caption">Reference Image</div>
|
|
185
|
+
<img src="{{this.questionReferenceImage}}" alt="Reference Image" />
|
|
186
|
+
</div>
|
|
187
|
+
{{/if}}
|
|
188
|
+
{{#if this.multiQuestionReferenceImage.length}}
|
|
189
|
+
<div class="q-answer-media">
|
|
190
|
+
<div class="q-answer-caption">Reference Images</div>
|
|
191
|
+
{{#each this.multiQuestionReferenceImage}}
|
|
192
|
+
<img src="{{this}}" alt="Reference Image" />
|
|
193
|
+
{{/each}}
|
|
194
|
+
</div>
|
|
195
|
+
{{/if}}
|
|
182
196
|
{{!-- <span class="q-ans {{#if this.isYes}}ans-yes{{else}}{{#if this.isNo}}ans-no{{/if}}{{/if}}">{{#if this.isYes}}✓ Yes{{else}}{{#if this.isNo}}✗ No{{else}}{{this.answerDisplay}}{{/if}}{{/if}}</span> --}}
|
|
183
197
|
{{#if this.userAnswer.length}}
|
|
184
198
|
<div class="q-answer-list">
|
|
199
|
+
{{!-- text/video answers render per userAnswer above the table --}}
|
|
185
200
|
{{#each this.userAnswer}}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
{{#
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
{{/if}}
|
|
194
|
-
<div class="q-answer-caption">Uploaded Image</div>
|
|
195
|
-
<img src="{{this.answer}}" alt="Uploaded Image" />
|
|
196
|
-
</div>
|
|
197
|
-
{{/eq}}
|
|
198
|
-
{{#eq this.answerType 'video'}}
|
|
201
|
+
{{#eq this.answerType 'text'}}
|
|
202
|
+
{{#if this.answer}}
|
|
203
|
+
<div class="q-answer-text {{#if this.sopFlag}}flagged{{/if}}">{{this.answer}}</div>
|
|
204
|
+
{{/if}}
|
|
205
|
+
{{/eq}}
|
|
206
|
+
{{#eq this.answerType 'video'}}
|
|
207
|
+
{{#if this.answer}}
|
|
199
208
|
<div class="q-answer-media">
|
|
200
209
|
<div class="q-answer-caption">Uploaded Video</div>
|
|
201
210
|
<a class="q-answer-link" href="{{this.answer}}" target="_blank">{{this.answer}}</a>
|
|
202
211
|
</div>
|
|
203
|
-
{{/
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{{/eq}}
|
|
207
|
-
{{/if}}
|
|
212
|
+
{{/if}}
|
|
213
|
+
{{/eq}}
|
|
214
|
+
{{/each}}
|
|
208
215
|
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
{{!-- Single 50/50 table per question: references rendered once on the left,
|
|
217
|
+
all uploaded/validation images stacked on the right --}}
|
|
218
|
+
<table style="width:100%;margin-top:8px"><tr>
|
|
219
|
+
{{#if this.userAnswer.[0].multiReferenceImage.length}}
|
|
220
|
+
<td style="width:50%;vertical-align:top;padding-right:8px">
|
|
221
|
+
<div class="q-answer-caption">Reference Image</div>
|
|
222
|
+
{{#each this.userAnswer.[0].multiReferenceImage}}
|
|
223
|
+
<img src="{{this}}" alt="Reference Image" />
|
|
224
|
+
{{/each}}
|
|
225
|
+
</td>
|
|
226
|
+
{{else}}
|
|
227
|
+
{{#if this.userAnswer.[0].referenceImage}}
|
|
228
|
+
<td style="width:50%;vertical-align:top;padding-right:8px">
|
|
229
|
+
<div class="q-answer-caption">Reference Image</div>
|
|
230
|
+
<img src="{{this.userAnswer.[0].referenceImage}}" alt="Reference Image" />
|
|
231
|
+
</td>
|
|
232
|
+
{{/if}}
|
|
233
|
+
{{/if}}
|
|
234
|
+
<td style="vertical-align:top">
|
|
235
|
+
{{#each this.userAnswer}}
|
|
236
|
+
{{#eq this.answerType 'image'}}
|
|
237
|
+
{{#if this.answer}}
|
|
238
|
+
<div class="q-answer-caption">Uploaded Image</div>
|
|
239
|
+
<img src="{{this.answer}}" alt="Uploaded Image" />
|
|
240
|
+
{{/if}}
|
|
241
|
+
{{/eq}}
|
|
242
|
+
{{#if this.validation}}
|
|
211
243
|
{{#eq this.validationDisplayType 'image'}}
|
|
212
|
-
|
|
244
|
+
{{#if this.validationAnswer}}
|
|
213
245
|
<div class="q-answer-caption">Validation Image</div>
|
|
214
246
|
<img src="{{this.validationAnswer}}" alt="Validation Image" />
|
|
215
|
-
|
|
247
|
+
{{/if}}
|
|
216
248
|
{{/eq}}
|
|
217
249
|
{{#eq this.validationDisplayType 'video'}}
|
|
218
|
-
|
|
250
|
+
{{#if this.validationAnswer}}
|
|
219
251
|
<div class="q-answer-caption">Validation Video</div>
|
|
220
252
|
<a class="q-answer-link" href="{{this.validationAnswer}}" target="_blank">{{this.validationAnswer}}</a>
|
|
221
|
-
|
|
253
|
+
{{/if}}
|
|
222
254
|
{{/eq}}
|
|
223
255
|
{{#eq this.validationDisplayType 'text'}}
|
|
224
|
-
|
|
256
|
+
{{#if this.validationAnswer}}
|
|
257
|
+
<div class="q-answer-text">{{this.validationAnswer}}</div>
|
|
258
|
+
{{/if}}
|
|
259
|
+
{{/eq}}
|
|
260
|
+
{{#eq this.validationDisplayType 'multiImage'}}
|
|
261
|
+
{{#if this.validationImage.length}}
|
|
262
|
+
<div class="q-answer-caption">Validation Image</div>
|
|
263
|
+
{{#each this.validationImage}}
|
|
264
|
+
<img src="{{this}}" alt="Validation Image" />
|
|
265
|
+
{{/each}}
|
|
266
|
+
{{/if}}
|
|
225
267
|
{{/eq}}
|
|
226
268
|
{{/if}}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
<div class="q-answer-remarks">Remarks: {{this.remarks}}</div>
|
|
231
|
-
{{/if}}
|
|
232
|
-
</div>
|
|
233
|
-
{{/each}}
|
|
269
|
+
{{/each}}
|
|
270
|
+
</td>
|
|
271
|
+
</tr></table>
|
|
234
272
|
</div>
|
|
235
273
|
{{/if}}
|
|
274
|
+
{{#if this.remarks}}
|
|
275
|
+
<div class="q-answer-remarks">Remarks: {{this.remarks}}</div>
|
|
276
|
+
{{/if}}
|
|
236
277
|
</div>
|
|
237
278
|
</div>
|
|
238
279
|
{{/each}}
|
|
@@ -129,9 +129,23 @@ function getMediaDisplayType( questionAnswerType, userAnswer = {} ) {
|
|
|
129
129
|
function getValidationDisplayType( validationType ) {
|
|
130
130
|
if ( validationType === 'Capture Image' ) return 'image';
|
|
131
131
|
if ( validationType === 'Capture Video' ) return 'video';
|
|
132
|
+
if ( validationType === 'Capture Multiple Image with description' ) return 'multiImage';
|
|
132
133
|
return 'text';
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
function flattenImageRefs( arr ) {
|
|
137
|
+
if ( !Array.isArray( arr ) ) return [];
|
|
138
|
+
return arr
|
|
139
|
+
.map( ( ele ) => {
|
|
140
|
+
if ( typeof ele === 'string' ) return ele;
|
|
141
|
+
if ( ele && typeof ele === 'object' ) {
|
|
142
|
+
return ele.imageURL || ele.imageUrl || ele.url || ele.image || ele.path || '';
|
|
143
|
+
}
|
|
144
|
+
return '';
|
|
145
|
+
} )
|
|
146
|
+
.filter( Boolean );
|
|
147
|
+
}
|
|
148
|
+
|
|
135
149
|
function buildQuestionAnswerEntries( question ) {
|
|
136
150
|
const rawUserAnswers = getSourceUserAnswers( question );
|
|
137
151
|
const uniqueUserAnswers = [];
|
|
@@ -153,15 +167,29 @@ function buildQuestionAnswerEntries( question ) {
|
|
|
153
167
|
const validationType = matchedAnswer?.validationType || userAnswer?.validationType || '';
|
|
154
168
|
const validationAnswer = matchedAnswer?.validationAnswer || userAnswer?.validationAnswer || '';
|
|
155
169
|
|
|
170
|
+
const rawMultiRefSources = [
|
|
171
|
+
userAnswer?.multiReferenceImage,
|
|
172
|
+
matchedAnswer?.multiReferenceImage,
|
|
173
|
+
question?.answers?.[0]?.multiReferenceImage,
|
|
174
|
+
];
|
|
175
|
+
let multiReferenceImage = [];
|
|
176
|
+
for ( const src of rawMultiRefSources ) {
|
|
177
|
+
const flat = flattenImageRefs( src );
|
|
178
|
+
if ( flat.length ) { multiReferenceImage = flat; break; }
|
|
179
|
+
}
|
|
180
|
+
const validationImage = flattenImageRefs( userAnswer?.validationImage );
|
|
181
|
+
|
|
156
182
|
return {
|
|
157
183
|
answer: userAnswer?.answer || '',
|
|
158
184
|
answerType: getMediaDisplayType( question?.answerType, userAnswer ),
|
|
159
185
|
referenceImage: userAnswer?.referenceImage || matchedAnswer?.referenceImage || '',
|
|
186
|
+
multiReferenceImage,
|
|
160
187
|
remarks: userAnswer?.remarks || '',
|
|
161
188
|
sopFlag: userAnswer?.sopFlag ?? matchedAnswer?.sopFlag ?? false,
|
|
162
189
|
validation,
|
|
163
190
|
validationType,
|
|
164
191
|
validationAnswer,
|
|
192
|
+
validationImage,
|
|
165
193
|
validationDisplayType: getValidationDisplayType( validationType ),
|
|
166
194
|
};
|
|
167
195
|
} );
|
|
@@ -276,6 +304,10 @@ function mapSectionsFromQuestionAnswer( questionAnswer ) {
|
|
|
276
304
|
|
|
277
305
|
compliance: Boolean( q.compliance ),
|
|
278
306
|
|
|
307
|
+
questionReferenceImage: q.questionReferenceImage || '',
|
|
308
|
+
|
|
309
|
+
multiQuestionReferenceImage: flattenImageRefs( q.multiQuestionReferenceImage ),
|
|
310
|
+
|
|
279
311
|
isYes: isYes || ( !isNo && score >= 10 ),
|
|
280
312
|
|
|
281
313
|
isNo,
|
|
@@ -750,14 +782,27 @@ export function createImageCache() {
|
|
|
750
782
|
|
|
751
783
|
const collectFromSection = ( section ) => {
|
|
752
784
|
section.questions?.forEach( ( q ) => {
|
|
785
|
+
if ( q.questionReferenceImage && q.questionReferenceImage.startsWith( 'http' ) ) urls.add( q.questionReferenceImage );
|
|
786
|
+
q.multiQuestionReferenceImage?.forEach( ( u ) => {
|
|
787
|
+
if ( typeof u === 'string' && u.startsWith( 'http' ) ) urls.add( u );
|
|
788
|
+
} );
|
|
753
789
|
q.userAnswer?.forEach( ( ua ) => {
|
|
754
790
|
if ( ua.referenceImage && ua.referenceImage.startsWith( 'http' ) ) urls.add( ua.referenceImage );
|
|
755
791
|
|
|
792
|
+
ua.multiReferenceImage?.forEach( ( u ) => {
|
|
793
|
+
if ( typeof u === 'string' && u.startsWith( 'http' ) ) urls.add( u );
|
|
794
|
+
} );
|
|
756
795
|
|
|
757
796
|
if ( ua.answer && ua.answerType === 'image' && ua.answer.startsWith( 'http' ) ) urls.add( ua.answer );
|
|
758
797
|
|
|
759
798
|
|
|
760
799
|
if ( ua.validationAnswer && ua.validationDisplayType === 'image' && ua.validationAnswer.startsWith( 'http' ) ) urls.add( ua.validationAnswer );
|
|
800
|
+
|
|
801
|
+
if ( ua.validationDisplayType === 'multiImage' ) {
|
|
802
|
+
ua.validationImage?.forEach( ( u ) => {
|
|
803
|
+
if ( typeof u === 'string' && u.startsWith( 'http' ) ) urls.add( u );
|
|
804
|
+
} );
|
|
805
|
+
}
|
|
761
806
|
} );
|
|
762
807
|
} );
|
|
763
808
|
};
|
|
@@ -797,14 +842,25 @@ export function createImageCache() {
|
|
|
797
842
|
|
|
798
843
|
const replaceInSection = ( section ) => {
|
|
799
844
|
section.questions?.forEach( ( q ) => {
|
|
845
|
+
if ( q.questionReferenceImage && cache.has( q.questionReferenceImage ) ) q.questionReferenceImage = cache.get( q.questionReferenceImage );
|
|
846
|
+
if ( q.multiQuestionReferenceImage?.length ) {
|
|
847
|
+
q.multiQuestionReferenceImage = q.multiQuestionReferenceImage.map( ( u ) => ( cache.has( u ) ? cache.get( u ) : u ) );
|
|
848
|
+
}
|
|
800
849
|
q.userAnswer?.forEach( ( ua ) => {
|
|
801
850
|
if ( ua.referenceImage && cache.has( ua.referenceImage ) ) ua.referenceImage = cache.get( ua.referenceImage );
|
|
802
851
|
|
|
852
|
+
if ( ua.multiReferenceImage?.length ) {
|
|
853
|
+
ua.multiReferenceImage = ua.multiReferenceImage.map( ( u ) => ( cache.has( u ) ? cache.get( u ) : u ) );
|
|
854
|
+
}
|
|
803
855
|
|
|
804
856
|
if ( ua.answer && ua.answerType === 'image' && cache.has( ua.answer ) ) ua.answer = cache.get( ua.answer );
|
|
805
857
|
|
|
806
858
|
|
|
807
859
|
if ( ua.validationAnswer && ua.validationDisplayType === 'image' && cache.has( ua.validationAnswer ) ) ua.validationAnswer = cache.get( ua.validationAnswer );
|
|
860
|
+
|
|
861
|
+
if ( ua.validationDisplayType === 'multiImage' && ua.validationImage?.length ) {
|
|
862
|
+
ua.validationImage = ua.validationImage.map( ( u ) => ( cache.has( u ) ? cache.get( u ) : u ) );
|
|
863
|
+
}
|
|
808
864
|
} );
|
|
809
865
|
} );
|
|
810
866
|
};
|
|
@@ -859,7 +915,15 @@ export function resolveTemplateUrls( templateData, baseUrl = 'https://d1r0hc2ssk
|
|
|
859
915
|
|
|
860
916
|
const resolveQuestionMedia = ( section ) => {
|
|
861
917
|
section.questions?.forEach( ( q ) => {
|
|
918
|
+
if ( q.questionReferenceImage ) q.questionReferenceImage = resolveUrl( q.questionReferenceImage );
|
|
919
|
+
if ( q.multiQuestionReferenceImage?.length ) {
|
|
920
|
+
q.multiQuestionReferenceImage = q.multiQuestionReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
921
|
+
}
|
|
862
922
|
q.userAnswer?.forEach( ( ua ) => {
|
|
923
|
+
|
|
924
|
+
if ( ua.multiReferenceImage?.length ) {
|
|
925
|
+
ua.multiReferenceImage = ua.multiReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
926
|
+
}
|
|
863
927
|
if ( ua.referenceImage ) ua.referenceImage = resolveUrl( ua.referenceImage );
|
|
864
928
|
|
|
865
929
|
|
|
@@ -867,6 +931,10 @@ export function resolveTemplateUrls( templateData, baseUrl = 'https://d1r0hc2ssk
|
|
|
867
931
|
ua.validationAnswer = resolveUrl( ua.validationAnswer );
|
|
868
932
|
}
|
|
869
933
|
|
|
934
|
+
if ( ua?.validationImage?.length ) {
|
|
935
|
+
ua.validationImage = ua.validationImage.map( ( ele ) => resolveUrl( ele ) );
|
|
936
|
+
}
|
|
937
|
+
|
|
870
938
|
|
|
871
939
|
if ( ua.answer && ua.answerType !== 'text' ) {
|
|
872
940
|
ua.answer = resolveUrl( ua.answer );
|
|
@@ -982,13 +1050,25 @@ export async function generateVisitChecklistPDF( templateData, baseUrl = 'https:
|
|
|
982
1050
|
|
|
983
1051
|
const resolveQuestionMedia = ( section ) => {
|
|
984
1052
|
section.questions?.forEach( ( q ) => {
|
|
1053
|
+
if ( q.questionReferenceImage ) q.questionReferenceImage = resolveUrl( q.questionReferenceImage );
|
|
1054
|
+
if ( q.multiQuestionReferenceImage?.length ) {
|
|
1055
|
+
q.multiQuestionReferenceImage = q.multiQuestionReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
1056
|
+
}
|
|
985
1057
|
q.userAnswer?.forEach( ( ua ) => {
|
|
986
1058
|
if ( ua.referenceImage ) ua.referenceImage = resolveUrl( ua.referenceImage );
|
|
987
1059
|
|
|
1060
|
+
if ( ua.multiReferenceImage?.length ) {
|
|
1061
|
+
ua.multiReferenceImage = ua.multiReferenceImage.map( ( ele ) => resolveUrl( ele ) );
|
|
1062
|
+
}
|
|
1063
|
+
|
|
988
1064
|
if ( ua.validationAnswer && ua.validationDisplayType !== 'text' ) {
|
|
989
1065
|
ua.validationAnswer = resolveUrl( ua.validationAnswer );
|
|
990
1066
|
}
|
|
991
1067
|
|
|
1068
|
+
if ( ua.validationImage?.length ) {
|
|
1069
|
+
ua.validationImage = ua.validationImage.map( ( ele ) => resolveUrl( ele ) );
|
|
1070
|
+
}
|
|
1071
|
+
|
|
992
1072
|
if ( ua.answer && ua.answerType !== 'text' ) {
|
|
993
1073
|
ua.answer = resolveUrl( ua.answer );
|
|
994
1074
|
}
|