Skip to content

Commit 74874f7

Browse files
authored
Merge pull request #2980 from kobotoolbox/master-fix-submission-modal-choices-bug
Fix submission modal displaying wrong labels for choices
2 parents 5343e60 + 08d9499 commit 74874f7

File tree

5 files changed

+412
-335
lines changed

5 files changed

+412
-335
lines changed

jsapp/js/components/submissionDataTable.es6

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ import React from 'react';
22
import autoBind from 'react-autobind';
33
import {
44
formatTimeDate,
5-
formatDate
5+
formatDate,
66
} from 'utils';
77
import {bem} from 'js/bem';
88
import {renderTypeIcon} from 'js/assetUtils';
99
import {
1010
DISPLAY_GROUP_TYPES,
11-
getSubmissionDisplayData
11+
getSubmissionDisplayData,
1212
} from 'js/submissionUtils';
1313
import {
1414
META_QUESTION_TYPES,
1515
QUESTION_TYPES,
1616
SCORE_ROW_TYPE,
17-
RANK_LEVEL_TYPE
17+
RANK_LEVEL_TYPE,
1818
} from 'js/constants';
1919

2020
/**
@@ -103,7 +103,7 @@ class SubmissionDataTable extends React.Component {
103103
</bem.SubmissionDataTable__column>
104104

105105
<bem.SubmissionDataTable__column m='data'>
106-
{this.renderResponseData(item.type, item.data)}
106+
{this.renderResponseData(item.type, item.data, item.listName)}
107107
</bem.SubmissionDataTable__column>
108108
</bem.SubmissionDataTable__row>
109109
);
@@ -112,8 +112,9 @@ class SubmissionDataTable extends React.Component {
112112
/**
113113
* @prop {string} type
114114
* @prop {string|null} data
115+
* @prop {string|undefined} listName
115116
*/
116-
renderResponseData(type, data) {
117+
renderResponseData(type, data, listName) {
117118
if (data === null) {
118119
return null;
119120
}
@@ -124,24 +125,36 @@ class SubmissionDataTable extends React.Component {
124125
case QUESTION_TYPES.get('select_one').id:
125126
case SCORE_ROW_TYPE:
126127
case RANK_LEVEL_TYPE:
127-
choice = this.findChoice(data);
128-
return (
129-
<bem.SubmissionDataTable__value>
130-
{choice.label[this.props.translationIndex]}
131-
</bem.SubmissionDataTable__value>
132-
);
128+
choice = this.findChoice(listName, data);
129+
if (!choice) {
130+
console.error(`Choice not found for "${listName}" and "${data}".`);
131+
// fallback to raw data to display anything meaningful
132+
return data;
133+
} else {
134+
return (
135+
<bem.SubmissionDataTable__value>
136+
{choice.label[this.props.translationIndex] || choice.name}
137+
</bem.SubmissionDataTable__value>
138+
);
139+
}
133140
case QUESTION_TYPES.get('select_multiple').id:
134141
return (
135142
<ul>
136143
{data.split(' ').map((answer, answerIndex) => {
137-
choice = this.findChoice(answer);
138-
return (
139-
<li key={answerIndex}>
140-
<bem.SubmissionDataTable__value>
141-
{choice.label[this.props.translationIndex]}
142-
</bem.SubmissionDataTable__value>
143-
</li>
144-
);
144+
choice = this.findChoice(listName, answer);
145+
if (!choice) {
146+
console.error(`Choice not found for "${listName}" and "${answer}".`);
147+
// fallback to raw data to display anything meaningful
148+
return answer;
149+
} else {
150+
return (
151+
<li key={answerIndex}>
152+
<bem.SubmissionDataTable__value>
153+
{choice.label[this.props.translationIndex] || choice.name}
154+
</bem.SubmissionDataTable__value>
155+
</li>
156+
);
157+
}
145158
})}
146159
</ul>
147160
);
@@ -179,12 +192,13 @@ class SubmissionDataTable extends React.Component {
179192
}
180193

181194
/**
182-
* @prop {string} name
195+
* @prop {string} listName
196+
* @prop {string} choiceName
183197
* @returns {object|undefined}
184198
*/
185-
findChoice(name) {
199+
findChoice(listName, choiceName) {
186200
return this.props.asset.content.choices.find((choice) => {
187-
return choice.name === name;
201+
return choice.name === choiceName && choice.list_name === listName;
188202
});
189203
}
190204

jsapp/js/constants.es6

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,16 @@ export const SCORE_ROW_TYPE = 'score__row';
380380
// a custom question type for rank
381381
export const RANK_LEVEL_TYPE = 'rank__level';
382382

383+
export const CHOICE_LISTS = Object.freeze({
384+
SELECT: 'select_from_list_name',
385+
MATRIX: 'kobo--matrix_list',
386+
SCORE: 'kobo--score-choices',
387+
RANK: 'kobo--rank-items',
388+
});
389+
383390
export const MATRIX_PAIR_PROPS = {
384-
inSurvey: 'kobo--matrix_list',
385-
inChoices: 'list_name'
391+
inSurvey: CHOICE_LISTS.MATRIX,
392+
inChoices: 'list_name',
386393
};
387394

388395
export const NAME_MAX_LENGTH = 255;
@@ -417,6 +424,7 @@ const constants = {
417424
RANK_LEVEL_TYPE,
418425
NAME_MAX_LENGTH,
419426
CATEGORY_LABELS,
427+
CHOICE_LISTS,
420428
};
421429

422430
export default constants;

jsapp/js/submissionUtils.es6

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ import {
22
getRowName,
33
getTranslatedRowLabel,
44
getSurveyFlatPaths,
5-
isRowSpecialLabelHolder
5+
isRowSpecialLabelHolder,
66
} from 'js/assetUtils';
77
import {
88
FORM_VERSION_NAME,
99
SCORE_ROW_TYPE,
1010
RANK_LEVEL_TYPE,
1111
MATRIX_PAIR_PROPS,
1212
GROUP_TYPES_BEGIN,
13-
QUESTION_TYPES
13+
QUESTION_TYPES,
14+
CHOICE_LISTS,
1415
} from 'js/constants';
1516

1617
export const DISPLAY_GROUP_TYPES = new Map();
@@ -19,7 +20,7 @@ new Set([
1920
'group_repeat',
2021
'group_regular',
2122
'group_matrix',
22-
'group_matrix_row'
23+
'group_matrix_row',
2324
]).forEach((codename) => {DISPLAY_GROUP_TYPES.set(codename, codename);});
2425

2526
/**
@@ -50,14 +51,20 @@ class DisplayGroup {
5051
* @property {string} type - One of QUESTION_TYPES
5152
* @property {string} label - Localized display label
5253
* @property {string} name - Unique identifier
54+
* @property {string|undefined} listName - Unique identifier of a choices list,
55+
* only applicable for question types
56+
* that uses choices lists
5357
* @property {string|null} data - User response, `null` for no response
5458
*/
5559
class DisplayResponse {
56-
constructor(type, label, name, data = null) {
60+
constructor(type, label, name, listName, data = null) {
5761
this.type = type;
5862
this.label = label;
5963
this.name = name;
6064
this.data = data;
65+
if (listName) {
66+
this.listName = listName;
67+
}
6168
}
6269
}
6370

@@ -85,6 +92,7 @@ export function getSubmissionDisplayData(survey, choices, translationIndex, subm
8592
const row = survey[rowIndex];
8693

8794
const rowName = getRowName(row);
95+
let rowListName = getRowListName(row);
8896
const rowLabel = getTranslatedRowLabel(rowName, survey, translationIndex);
8997

9098
let parentGroupPath = null;
@@ -194,10 +202,20 @@ export function getSubmissionDisplayData(survey, choices, translationIndex, subm
194202
rowData = rowData[repeatIndex];
195203
}
196204

205+
// score and rank don't have list name on them and they need to use
206+
// the one of their parent
207+
if (row.type === SCORE_ROW_TYPE || row.type === RANK_LEVEL_TYPE) {
208+
const parentGroupRow = survey.find((row) => {
209+
return getRowName(row) === parentGroup.name;
210+
});
211+
rowListName = getRowListName(parentGroupRow);
212+
}
213+
197214
let rowObj = new DisplayResponse(
198215
row.type,
199216
rowLabel,
200217
rowName,
218+
rowListName,
201219
rowData
202220
);
203221
parentGroup.addChild(rowObj);
@@ -276,6 +294,7 @@ function populateMatrixData(
276294
questionSurveyObj.type,
277295
getTranslatedRowLabel(questionName, survey, translationIndex),
278296
questionName,
297+
getRowListName(questionSurveyObj),
279298
questionData
280299
);
281300
matrixRowGroupObj.addChild(questionObj);
@@ -379,8 +398,21 @@ function getRegularGroupAnswers(data, targetKey) {
379398
return answers;
380399
}
381400

401+
/**
402+
* @param {object} row
403+
* @returns {string|undefiend}
404+
*/
405+
function getRowListName(row) {
406+
return (
407+
row[CHOICE_LISTS.SELECT] ||
408+
row[CHOICE_LISTS.MATRIX] ||
409+
row[CHOICE_LISTS.SCORE] ||
410+
row[CHOICE_LISTS.RANK]
411+
);
412+
}
413+
382414
export default {
383415
DISPLAY_GROUP_TYPES,
384416
getSubmissionDisplayData,
385-
getRepeatGroupAnswers
417+
getRepeatGroupAnswers,
386418
};

0 commit comments

Comments
 (0)