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

Swik 2488 enable selection of questions for exam mode #1034

Merged
merged 22 commits into from
Oct 27, 2018
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a57da57
SWIK-2488 Initial changes taken from exam prototype branch
dpaun Oct 4, 2018
ae1b2be
SWIK-2488 added select exam questions option
dpaun Oct 12, 2018
4b2cf1d
SWIK-2488 fixing indentation
dpaun Oct 12, 2018
f311a41
SWIK-2488 using non_exam_questions_only
dpaun Oct 15, 2018
87d9b1d
SWIK-2488 small label change
dpaun Oct 15, 2018
9463d39
SWIK-2488 changed icon
dpaun Oct 15, 2018
d7868f8
SWIK-2488 using nonExamQuestionsOnly
dpaun Oct 15, 2018
4f2b46b
SWIK-2488 fixing nonExamQuestionsOnly param passing
dpaun Oct 15, 2018
c78c7ec
SWIK-2488 corrected makeNodeUrl location
dpaun Oct 16, 2018
c6d2191
SWIK-2488 Corrected exam questions selection
dpaun Oct 16, 2018
f8c996b
SWIK-2488 fixing questions for exam scoring
dpaun Oct 16, 2018
01c7752
Merge branch 'master' into SWIK-2488-Enable_selection_of_questions_fo…
abijames Oct 19, 2018
4fa0577
Made exam mode accessible
abijames Oct 19, 2018
536e8da
SWIK-2488 Exam-disable submit, readonly checkboxes, reset answers
dpaun Oct 22, 2018
5a9fa3c
SWIK-2488 fix showing exam questions for users without edit permissions
dpaun Oct 25, 2018
30f09eb
SWIK-2488 missing ;
dpaun Oct 25, 2018
e9637c3
Added extra exam question index
Oct 25, 2018
99a0cbe
SWIK-2488 show back button when there are no exam questions
dpaun Oct 26, 2018
85368af
Merge branch 'SWIK-2488-Enable_selection_of_questions_for_exam_mode' …
dpaun Oct 26, 2018
e84a820
SWIK-2488 fixing a typo
dpaun Oct 26, 2018
9f211b4
Merge branch 'master' into SWIK-2488-Enable_selection_of_questions_fo…
kprist Oct 26, 2018
c94e863
Merge branch 'master' into SWIK-2488-Enable_selection_of_questions_fo…
kprist Oct 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions actions/loadContentModules.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import deckContentTypeError from './error/deckContentTypeError';
import slideIdTypeError from './error/slideIdTypeError';
import { AllowedPattern } from './error/util/allowedPattern';
import serviceUnavailable from './error/serviceUnavailable';
import PermissionsStore from '../stores/PermissionsStore';
const log = require('./log/clog');


Expand All @@ -35,6 +36,9 @@ export default function loadContentModules(context, payload, done) {
// },

(callback) => {
let editPermission = (context.getStore(PermissionsStore) && context.getStore(PermissionsStore).permissions && (context.getStore(PermissionsStore).permissions.admin || context.getStore(PermissionsStore).permissions.edit));

payload.params.nonExamQuestionsOnly = !editPermission;
context.executeAction(loadQuestionsCount, payload, callback);
},
(callback) => {
Expand Down
5 changes: 1 addition & 4 deletions actions/loadContentQuestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,12 @@ export default function loadContentQuestions(context, payload, done) {
if (err) {
log.error(context, {filepath: __filename});
context.executeAction(serviceUnavailable, payload, done);
//context.dispatch('LOAD_CONTENT_QUESTIONS_FAILURE', err);
} else {
context.dispatch('LOAD_CONTENT_QUESTIONS_SUCCESS', res);
context.dispatch('UPDATE_MODULE_TYPE_SUCCESS', {moduleType: 'questions'});
}
let pageTitle = shortTitle + ' | Content Questions | ' + payload.params.stype + ' | ' + payload.params.sid;
//context.dispatch('UPDATE_PAGE_TITLE', {
// pageTitle: pageTitle
//});

done();
});
}
7 changes: 7 additions & 0 deletions actions/questions/invertExamListFlag.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const log = require('../log/clog');

export default function invertExamListFlag(context, payload, done) {
log.info(context);
context.dispatch('INVERT_EXAM_LIST_FLAG', payload);
done();
}
37 changes: 37 additions & 0 deletions actions/questions/loadExamQuestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const log = require('../log/clog');
import ContentQuestionsStore from '../../stores/ContentQuestionsStore';
import deckContentTypeError from '../error/deckContentTypeError';
import serviceUnavailable from '../error/serviceUnavailable';
import slideIdTypeError from '../error/slideIdTypeError';
import { AllowedPattern } from '../error/util/allowedPattern';
export default function loadExamQuestions(context, payload, done) {
log.info(context);
const selector = context.getStore(ContentQuestionsStore).selector;
const sid = (selector.sid) ? selector.sid.split('-')[0] : '';
if (payload.params.sid.split('-')[0] !== sid || payload.params.stype !== selector.stype) {

if (!(['deck', 'slide', 'question'].indexOf(payload.params.stype) > -1 || payload.params.stype === undefined)){
context.executeAction(deckContentTypeError, payload, done);
return;
}

if (!(AllowedPattern.SLIDE_ID.test(payload.params.sid) || payload.params.sid === undefined)) {
context.executeAction(slideIdTypeError, payload, done);
return;
}

context.service.read('questions.examlist', payload, {timeout: 20 * 1000}, (err, res) => {
if (err) {
log.error(context, {filepath: __filename});
context.executeAction(serviceUnavailable, payload, done);
} else {
context.dispatch('LOAD_CONTENT_QUESTIONS_SUCCESS', res);
context.dispatch('UPDATE_MODULE_TYPE_SUCCESS', {moduleType: 'questions'});
}

done();
});
} else {
done();
}
}
6 changes: 6 additions & 0 deletions actions/questions/resetExamAnswers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import log from '../log/clog';
export default function resetExamAnswers(context, payload, done) {
log.info(context);
context.dispatch('RESET_ANSWERS', payload);
done();
}
6 changes: 6 additions & 0 deletions actions/questions/selectExamAnswer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import log from '../log/clog';
export default function selectExamAnswer(context, payload, done) {
log.info(context);
context.dispatch('QUESTION_ANSWER_SELECTED', payload);
done();
}
6 changes: 6 additions & 0 deletions actions/questions/showCorrectExamAnswers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import log from '../log/clog';
export default function showCorrectExamAnswers(context, payload, done) {
log.info(context);
context.dispatch('SHOW_CORRECT_EXAM_ANSWERS', payload);
done();
}
17 changes: 17 additions & 0 deletions actions/questions/updateExamList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const log = require('../log/clog');
import serviceUnavailable from '../error/serviceUnavailable';
import ContentQuestionsStore from '../../stores/ContentQuestionsStore';

export default function updateExamList(context, payload, done) {
log.info(context, payload);

context.service.update('questions.updateExamList', {modifiedSelections: payload.modifiedSelections}, {timeout: 20 * 1000}, (err, res) => {
if (err) {
log.error(context, {filepath: __filename});
context.executeAction(serviceUnavailable, payload, done);
} else {
context.dispatch('UPDATE_QUESTIONS', payload);
}
done();
});
}
11 changes: 8 additions & 3 deletions components/Deck/ContentModulesPanel/ContentModulesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import DataSourcePanel from './DataSourcePanel/DataSourcePanel';
import TagsPanel from './TagsPanel/TagsPanel';
//import ContributorsPanel from './ContributorsPanel/ContributorsPanel';
import ContentModulesStore from '../../../stores/ContentModulesStore';
import PermissionsStore from '../../../stores/PermissionsStore';
import { isLocalStorageOn } from '../../../common.js';
import loadCollectionsTab from '../../../actions/collections/loadCollectionsTab';
import CollectionsPanel from './CollectionsPanel/CollectionsPanel';
Expand Down Expand Up @@ -50,7 +51,10 @@ class ContentModulesPanel extends React.Component {
handleTabClick(type, e) {
switch (type) {
case 'questions':
this.context.executeAction(loadContentQuestions, {params: this.props.ContentModulesStore.selector});
let editPermission = (this.props.PermissionsStore && this.props.PermissionsStore.permissions && (this.props.PermissionsStore.permissions.admin || this.props.PermissionsStore.permissions.edit));
let params = this.props.ContentModulesStore.selector;
this.context.executeAction(loadContentQuestions, {params: params});

break;
case 'datasource':
this.context.executeAction(loadDataSources, {params: this.props.ContentModulesStore.selector});
Expand Down Expand Up @@ -196,9 +200,10 @@ class ContentModulesPanel extends React.Component {
ContentModulesPanel.contextTypes = {
executeAction: PropTypes.func.isRequired
};
ContentModulesPanel = connectToStores(ContentModulesPanel, [ContentModulesStore], (context, props) => {
ContentModulesPanel = connectToStores(ContentModulesPanel, [ContentModulesStore, PermissionsStore], (context, props) => {
return {
ContentModulesStore: context.getStore(ContentModulesStore).getState()
ContentModulesStore: context.getStore(ContentModulesStore).getState(),
PermissionsStore: context.getStore(PermissionsStore).getState()
};
});
export default ContentModulesPanel;
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ContentQuestionAdd extends React.Component {
userId: this.props.userId,
relatedObjectId: this.props.selector.sid,
relatedObject: this.props.selector.stype,
isExamQuestion: false
};
this.updateQuestionTitle = this.updateQuestionTitle.bind(this);
this.updateQuestionDifficulty = this.updateQuestionDifficulty.bind(this);
Expand All @@ -39,6 +40,7 @@ class ContentQuestionAdd extends React.Component {
this.updateCorrect4 = this.updateCorrect4.bind(this);

this.updateExplanation = this.updateExplanation.bind(this);
this.updateIsExamQuestion = this.updateIsExamQuestion.bind(this);
this.saveButtonClick = this.saveButtonClick.bind(this);
this.cancelButtonClick = this.cancelButtonClick.bind(this);
}
Expand Down Expand Up @@ -132,6 +134,10 @@ class ContentQuestionAdd extends React.Component {
updateQuestionDifficulty(e) {
this.setState({difficulty: e.target.value});
}

updateIsExamQuestion(e) {
this.setState({isExamQuestion: e.target.checked});
}

render() {
//const numAnswers = this.props.question.answers.length;
Expand Down Expand Up @@ -213,6 +219,12 @@ class ContentQuestionAdd extends React.Component {
<label htmlFor="explanation">Explanation (optional)</label>
<textarea rows="2" id="explanation" onChange={this.updateExplanation}></textarea>
</div>
<div className="field">
<div className="ui checkbox">
<input type="checkbox" name="exam" id="exam" tabIndex="0" className="hidden" defaultChecked={this.state.isExamQuestion} onChange={this.updateIsExamQuestion}/>
<label htmlFor="exam">This is an exam question</label>
</div>
</div>
<div className="field">
<div className="ui container">
<div >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,12 @@ class ContentQuestionAnswersItem extends React.Component {

render() {
const answer = this.props.answer;
const name = this.props.name;

// let rightIcon = (<i className="icon"></i>);
// switch (answer.correct) {
// case true:
// rightIcon = (<i className="checkmark icon teal"></i>);
// break;
// }


return (
//<div className="item"> {rightIcon}
// <div className="content"> {answer.answer} </div>
// </div>

<div className="field">
<div className="ui checkbox">
<input type="checkbox" name={name} id={name} /> {/* defaultChecked={answer.correct} */}
<label htmlFor={name}>
<div className="ui ">
<i className="ui small circle outline icon" />
<label >
{answer.answer}
</label>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class ContentQuestionAnswersList extends React.Component {
constructor(props){
super(props);
this.state = {
// isEditButtonClicked: false,
showCorrect: false,
};
this.handleButtonClick = this.handleButtonClick.bind(this);
Expand All @@ -26,16 +25,10 @@ class ContentQuestionAnswersList extends React.Component {
}

handleEditButtonClick() {
// this.setState({
// isEditButtonClicked: true
// });

this.context.executeAction(loadQuestion, {qstid: this.props.qstid});
}

render() {
const creatorId = this.props.DeckViewStore.creatorData._id;
const userId = this.props.UserProfileStore.userid;
const editButton = (
<button className="ui compact button primary" onClick={this.handleEditButtonClick}>
<i className="edit icon" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class ContentQuestionEdit extends React.Component {
explanation: this.props.question.explanation,
userId: this.props.userId,
relatedObjectId: this.props.question.relatedObjectId,
relatedObject: this.props.question.relatedObject
relatedObject: this.props.question.relatedObject,
isExamQuestion: this.props.question.isExamQuestion
};
this.updateQuestionTitle = this.updateQuestionTitle.bind(this);
this.updateQuestionDifficulty = this.updateQuestionDifficulty.bind(this);
Expand All @@ -41,6 +42,7 @@ class ContentQuestionEdit extends React.Component {
this.updateCorrect4 = this.updateCorrect4.bind(this);

this.updateExplanation = this.updateExplanation.bind(this);
this.updateIsExamQuestion = this.updateIsExamQuestion.bind(this);
this.saveButtonClick = this.saveButtonClick.bind(this);
this.cancelButtonClick = this.cancelButtonClick.bind(this);
this.deleteButtonClick = this.deleteButtonClick.bind(this);
Expand Down Expand Up @@ -148,7 +150,11 @@ class ContentQuestionEdit extends React.Component {
updateQuestionDifficulty(e) {
this.setState({difficulty: e.target.value});
}


updateIsExamQuestion(e) {
this.setState({isExamQuestion: e.target.checked});
}

render() {
// const numAnswers = this.props.question.answers.length;
const answerChoiceWidth = {
Expand Down Expand Up @@ -238,6 +244,12 @@ class ContentQuestionEdit extends React.Component {
<label htmlFor="explanation">Explanation (optional)</label>
<textarea rows="2" id="explanation" defaultValue={this.state.explanation} onChange={this.updateExplanation}></textarea>
</div>
<div className="field">
<div className="ui checkbox">
<input type="checkbox" name="exam" id="exam" tabIndex="0" className="hidden" defaultChecked={this.state.isExamQuestion} onChange={this.updateIsExamQuestion}/>
<label htmlFor="exam">This is an exam question</label>
</div>
</div>
<div className="field">
<div className="ui container">
<div >
Expand Down
Loading