Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assessments Tab: Surveys multiple choice overview table #23172

Merged
merged 4 commits into from Jun 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions apps/src/templates/sectionAssessments/SectionAssessments.jsx
Expand Up @@ -3,6 +3,7 @@ import { setScriptId, validScriptPropType } from '@cdo/apps/redux/scriptSelectio
import {
asyncLoadAssessments,
getCurrentScriptAssessmentList,
getMultipleChoiceSurveyResults,
setAssessmentId,
} from '@cdo/apps/templates/sectionAssessments/sectionAssessmentsRedux';
import {connect} from 'react-redux';
Expand All @@ -12,6 +13,7 @@ import ScriptSelector from '@cdo/apps/templates/sectionProgress/ScriptSelector';
import MultipleChoiceByStudentContainer from './MultipleChoiceByStudentContainer';
import StudentsMCSummaryContainer from './StudentsMCSummaryContainer';
import FreeResponseBySurveyQuestionContainer from './FreeResponseBySurveyQuestionContainer';
import MultipleChoiceSurveyOverviewTable from './MultipleChoiceSurveyOverviewTable';
import AssessmentSelector from './AssessmentSelector';

const styles = {
Expand All @@ -31,7 +33,8 @@ class SectionAssessments extends Component {
assessmentId: PropTypes.number,
setScriptId: PropTypes.func.isRequired,
setAssessmentId: PropTypes.func.isRequired,
asyncLoadAssessments: PropTypes.func.isRequired
asyncLoadAssessments: PropTypes.func.isRequired,
multipleChoiceSurveyResults: PropTypes.array,
};

onChangeScript = scriptId => {
Expand All @@ -42,7 +45,7 @@ class SectionAssessments extends Component {
};

render() {
const {validScripts, scriptId, assessmentList, assessmentId} = this.props;
const {validScripts, scriptId, assessmentList, assessmentId, multipleChoiceSurveyResults} = this.props;

return (
<div>
Expand Down Expand Up @@ -70,6 +73,11 @@ class SectionAssessments extends Component {
<StudentsMCSummaryContainer />
<MultipleChoiceByStudentContainer />
{/* Surveys */}
{multipleChoiceSurveyResults.length > 0 &&
<MultipleChoiceSurveyOverviewTable
multipleChoiceSurveyData={multipleChoiceSurveyResults}
/>
}
<FreeResponseBySurveyQuestionContainer />
</div>
);
Expand All @@ -85,6 +93,7 @@ export default connect(state => ({
assessmentList: getCurrentScriptAssessmentList(state),
scriptId: state.scriptSelection.scriptId,
assessmentId: state.sectionAssessments.assessmentId,
multipleChoiceSurveyResults: getMultipleChoiceSurveyResults(state),
}), dispatch => ({
setScriptId(scriptId) {
dispatch(setScriptId(scriptId));
Expand Down
53 changes: 53 additions & 0 deletions apps/src/templates/sectionAssessments/sectionAssessmentsRedux.js
Expand Up @@ -250,6 +250,59 @@ export const getSurveyFreeResponseQuestions = (state) => {
});
};

/**
* Returns an array of objects, each of type multipleChoiceSurveyDataPropType
* indicating a multiple choice question and the percent of responses received
* for each answer.
*/
export const getMultipleChoiceSurveyResults = (state) => {
const surveysStructure = state.sectionAssessments.surveysByScript[state.scriptSelection.scriptId] || {};
const currentSurvey = surveysStructure[state.sectionAssessments.assessmentId];
if (!currentSurvey) {
return [];
}

const questionData = currentSurvey.levelgroup_results;

// Filter to multiple choice questions.
return questionData.filter(question => question.type === 'multi').map((question, index) => {
// Calculate the total responses for each answer.

const totalAnswered = question.results.length;
// Each value of answerTotals represents the number of responses received for
// the answer in that index.
const answerTotals = [];
// Initialize each answer to 0 responses.
for (let i = 0; i< question.answer_texts.length; i++) {
answerTotals[i] = 0;
}
let notAnswered = 0;

// For each response, add 1 to the correct value in answerTotals.
for (let i = 0; i<totalAnswered; i++) {
const answerIndex = question.results[i].answer_index;
if (answerIndex >= 0) {
answerTotals[answerIndex]++;
} else {
notAnswered++;
}
}

// TODO(caleybrock): Make a better way to get letter options, here and below.
return {
id: index,
question: question.question,
answers: question.answer_texts.map((answer, index) => {
return {
multipleChoiceOption: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'][index],
percentAnswered: Math.floor((answerTotals[index]/totalAnswered) * 100),
};
}),
notAnswered: Math.floor((notAnswered/totalAnswered) * 100),
};
});
};

/** Get data for students assessments multiple choice table
* Returns an object, each of type studentOverviewDataPropType with
* the value of the key being an object that contains the number
Expand Down
Expand Up @@ -11,6 +11,7 @@ import sectionAssessments, {
getStudentMCResponsesForCurrentAssessment,
getStudentsMCSummaryForCurrentAssessment,
getSurveyFreeResponseQuestions,
getMultipleChoiceSurveyResults,
} from '@cdo/apps/templates/sectionAssessments/sectionAssessmentsRedux';
import {setSection} from '@cdo/apps/redux/sectionDataRedux';

Expand Down Expand Up @@ -251,6 +252,59 @@ describe('sectionAssessmentsRedux', () => {
});
});

describe('getMultipleChoiceSurveyResults', () => {
it('returns an empty array when no surveys in redux', () => {
const result = getMultipleChoiceSurveyResults(rootState);
assert.deepEqual(result, []);
});

it('returns an array of objects representing free response questions', () => {
const stateWithSurvey = {
...rootState,
sectionAssessments: {
...rootState.sectionAssessments,
assessmentId: 123,
surveysByScript: {
3: {
123: {
stage_name: 'name',
levelgroup_results: [
{
type: 'multi',
question: 'question1',
answer_texts: [{text: 'agree'}, {text: 'disagree'}],
results: [{answer_index: 0}]
},
{
type: 'multi',
question: 'question2',
answer_texts: [{text: 'agree'}, {text: 'disagree'}],
results: [{answer_index: 1}]
},
],
}
}
}
}
};
const result = getMultipleChoiceSurveyResults(stateWithSurvey);
assert.deepEqual(result, [
{
id: 0,
question: 'question1',
answers: [{multipleChoiceOption: 'A', percentAnswered: 100}, {multipleChoiceOption: 'B', percentAnswered: 0}],
notAnswered: 0,
},
{
id: 1,
question: 'question2',
answers: [{multipleChoiceOption: 'A', percentAnswered: 0}, {multipleChoiceOption: 'B', percentAnswered: 100}],
notAnswered: 0,
},
]);
});
});

describe('getStudentsMCSummaryForCurrentAssessment', () => {
it('returns an empty object when no assessments in redux', () => {
const result = getStudentsMCSummaryForCurrentAssessment(rootState);
Expand Down