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: Add Multiple Choice Answer Table Component #22054

Merged
merged 11 commits into from
Apr 26, 2018
2 changes: 2 additions & 0 deletions apps/i18n/common/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"anotherHoCDesc": "Keep it up! Try your next Hour of Code activity.",
"anotherHoCTitle": "Try another Hour of Code",
"answersVisible": "Answers visible (read-only)",
"answerOptionOne": "A",
"answerOptionTwo": "B",
"archiveSection": "Archive Section",
"applabMarketingButton": "Learn more",
"applabMarketingDesc": "See sample projects, watch demos, and learn more about what you can do with App Lab.",
Expand Down
140 changes: 140 additions & 0 deletions apps/src/templates/sectionAssessments/MultipleChoiceAnswerTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React, {Component, PropTypes} from 'react';
import {Table, sort} from 'reactabular';
import {tableLayoutStyles, sortableOptions} from "../tables/tableConstants";
import commonMsg from '@cdo/locale';
import wrappedSortable from '../tables/wrapped_sortable';
import orderBy from 'lodash/orderBy';

export const COLUMNS = {
QUESTION: 0,
A: 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make more sense to call these answerOptionOne and answerOptionTwo since that's how you refer to them in code. A and B seem to be more of display strings.

B: 2,
};

const questionAnswerDataPropType = PropTypes.shape({
id: PropTypes.number.isRequired,
question: PropTypes.string,
answerOptionOne: PropTypes.string,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this name it seems like this will be A. The best answer.
Can this be someone that makes it more obvious that it's a percent, like percentAnsweredOption1?

answerOptionTwo: PropTypes.string,
});

class MultipleChoiceAnswerTable extends Component {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of this is a bit confusing. It'd expect it to be a table that shows me the answers, but really it shows me an overview of my students results. Maybe MultipleChoiceOverviewTable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion.

static propTypes= {
questionAnswerData: PropTypes.arrayOf(questionAnswerDataPropType),
};

state = {
[COLUMNS.NAME]: {
direction: 'desc',
position: 0
}
};

getSortingColumns = () => {
return this.state.sortingColumns || {};
};

onSort = (selectedColumn) => {
this.setState({
sortingColumns: sort.byColumn({
sortingColumns: this.state.sortingColumns,
// Custom sortingOrder removes 'no-sort' from the cycle
sortingOrder: {
FIRST: 'asc',
asc: 'desc',
desc: 'asc'
},
selectedColumn
})
});
};

getColumns = (sortable) => {
let dataColumns = [
{
property: 'question',
header: {
label: commonMsg.question(),
props: {
style: {
...tableLayoutStyles.headerCell,
}},
transforms: [sortable],
},
cell: {
format: this.nameFormatter,
props: {
style: {
...tableLayoutStyles.cell,
}}
}
},
{
property: 'answerOptionOne',
header: {
label: commonMsg.answerOptionOne(),
props: {
style: {
...tableLayoutStyles.headerCell,
width: 90,
}},
transforms: [sortable],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't actually show any of the columns as sortable. Did Poorva ask for a change? I'm guessing we might only want the question column sortable for now?

},
cell: {
format: this.ageFormatter,
props: {
style: {
...tableLayoutStyles.cell,
width: 90,
}}
}
},
{
property: 'answerOptionTwo',
header: {
label: commonMsg.answerOptionTwo(),
props: {
style: {
...tableLayoutStyles.headerCell,
width: 120,
}},
transforms: [sortable],
},
cell: {
format: this.genderFormatter,
props: {
style: {
...tableLayoutStyles.cell,
width: 120,
}}
}
},
];
return dataColumns;
};

render() {
// Define a sorting transform that can be applied to each column
const sortable = wrappedSortable(this.getSortingColumns, this.onSort, sortableOptions);
const columns = this.getColumns(sortable);
const sortingColumns = this.getSortingColumns();

const sortedRows = sort.sorter({
columns,
sortingColumns,
sort: orderBy,
})(this.props.questionAnswerData);

return (
<Table.Provider
columns={columns}
style={tableLayoutStyles.table}
>
<Table.Header />
<Table.Body rows={sortedRows} rowKey="id" />
</Table.Provider>
);
}
}

export default MultipleChoiceAnswerTable;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import MultipleChoiceAnswerTable from './MultipleChoiceAnswerTable';

const multipleChoiceData = [
{
id: 1,
question: 'What is a variable?',
answerOptionOne: '40%',
answerOptionTwo: '20%',
},
{
id: 2,
question: 'What is a 4-bit number for the decimal number Ten(10)',
answerOptionOne: '40%',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: It'd be nice to have different percent breakdowns for each to show that the table works with all different values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

answerOptionTwo: '20%',
},
{
id: 3,
question: 'What is the minimum number of bits you will need to encode the 26 letters of the alphabet',
answerOptionOne: '40%',
answerOptionTwo: '20%',
}
];

export default storybook => {
return storybook
.storiesOf('SectionAssessments/MultipleChoiceAnswerTable', module)
.addStoryTable([
{
name: 'Table for assessments',
description: 'Ability to see assessment overview for the entire class',
story: () => (
<MultipleChoiceAnswerTable
questionAnswerData={multipleChoiceData}
/>
)
},
]);
};