- {this.textareaContent(deploymentPath.concat(['external', 'symbols', i]))} |
+
+ {this.textareaContent(deploymentPath.concat(['external', 'symbols', i]))}
+ |
{controlButton('Delete', IconNames.MINUS, this.handleSymbolDelete(i))} |
));
+
const globals = deployment.globals.map((symbol, i) => (
-
- {this.textareaContent(deploymentPath.concat(['globals', i, 0]))}
+ |
+
+ {this.textareaContent(deploymentPath.concat(['globals', i, 0]))}
+
+ |
+
+
+ {this.globalValueTextareaContent(i)}
+
|
- {this.globalValueTextareaContent(i)} |
{controlButton('Delete', IconNames.MINUS, this.handleGlobalDelete(i))}
|
));
- const resetLibrary = controlButton('Reload Library', IconNames.REFRESH, () =>
+ const resetLibrary = controlButton('Refresh Library', IconNames.REFRESH, () =>
this.props.handleRefreshLibrary(deployment)
);
- return (
-
- {deploymentDisp} {resetLibrary}
-
-
- Interpreter:
-
- {chapterSelect(deployment.chapter, this.handleChapterSelect)}
-
-
+ const symbolsFragment = (
+
External Library:
{externalSelect(deployment.external.name, this.handleExternalSelect!)}
@@ -100,16 +106,55 @@ export class DeploymentTab extends React.Component
{controlButton('New Symbol', IconNames.PLUS, this.handleNewSymbol)}
-
-
+
+ );
+
+ const globalsFragment = (
+
Globals:
{controlButton('New Global', IconNames.PLUS, this.handleNewGlobal)}
+
+ );
+
+ const tabs = [
+ {
+ label: `Library`,
+ icon: IconNames.BOOK,
+ body: symbolsFragment
+ },
+ {
+ label: `Globals`,
+ icon: IconNames.GLOBE,
+ body: globalsFragment
+ }
+ ];
+
+ return (
+
+ {/* {deploymentDisp}
+
*/}
+ {resetLibrary}
+
+ Interpreter:
+
+ {chapterSelect(deployment.chapter, this.handleChapterSelect)}
+
);
};
+ private handleChangeActiveTab = (tab: number) => {
+ this.setState({
+ activeTab: tab
+ });
+ };
+
private textareaContent = (path: Array
) => {
return (
void;
}
-export class ManageQuestionTab extends React.Component {
+interface IState {
+ showSaveOverlay: boolean;
+ modifyAssessment: () => void;
+}
+
+export class ManageQuestionTab extends React.Component {
public constructor(props: IProps) {
super(props);
+ this.state = {
+ showSaveOverlay: false,
+ modifyAssessment: () => {}
+ };
}
public render() {
- return this.manageQuestionTab();
+ return (
+
+ {this.confirmSaveOverlay()}
+ {this.manageQuestionTab()}
+
+ );
}
private manageQuestionTab = () => {
return (
{controlButton(
- 'Make Programming Question',
+ 'Insert Programming Question',
IconNames.FONT,
- this.makeQuestion(programmingTemplate)
+ this.confirmSave(this.makeQuestion(programmingTemplate))
+ )}
+ {controlButton(
+ 'Insert MCQ Question',
+ IconNames.CONFIRM,
+ this.confirmSave(this.makeQuestion(mcqTemplate))
+ )}
+ {controlButton(
+ 'Delete Current Question',
+ IconNames.REMOVE,
+ this.confirmSave(this.deleteQn)
)}
- {controlButton('Make MCQ Question', IconNames.CONFIRM, this.makeQuestion(mcqTemplate))}
- {controlButton('Delete Question', IconNames.REMOVE, this.deleteQn)}
);
};
@@ -56,6 +81,52 @@ export class ManageQuestionTab extends React.Component {
assessment.questions = questions;
this.props.updateAssessment(assessment);
};
+
+ private confirmSave = (modifyAssessment: () => void) => () => {
+ if (this.props.hasUnsavedChanges) {
+ this.setState({
+ showSaveOverlay: true,
+ modifyAssessment
+ });
+ } else {
+ modifyAssessment();
+ }
+ };
+
+ /**
+ * Asks to save work.
+ */
+ private confirmSaveOverlay = () => (
+
+ );
}
export default ManageQuestionTab;
diff --git a/src/components/incubator/editingWorkspaceSideContent/QuestionTemplateTab.tsx b/src/components/incubator/editingWorkspaceSideContent/QuestionTemplateTab.tsx
index cb3bae3f11..5dbef15fa7 100644
--- a/src/components/incubator/editingWorkspaceSideContent/QuestionTemplateTab.tsx
+++ b/src/components/incubator/editingWorkspaceSideContent/QuestionTemplateTab.tsx
@@ -1,8 +1,10 @@
import { Card } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
import * as React from 'react';
import AceEditor from 'react-ace';
import { IAssessment, IMCQQuestion } from '../../assessment/assessmentShape';
+import { controlButton } from '../../commons';
import { assignToPath, getValueFromPath, limitNumberRange } from './';
import TextareaContent from './TextareaContent';
@@ -117,12 +119,39 @@ export class QuestionTemplateTab extends React.Component {
{mcqButton}
Solution:
{this.textareaContent(['questions', questionId, 'solution'], true, [0, 3])}
+ {controlButton('Add Option', IconNames.CONFIRM, this.addOption)}
+ {controlButton('Delete Option', IconNames.REMOVE, this.delOption)}
);
};
+ private addOption = () => {
+ const assessment = this.props.assessment;
+ const questionId = this.props.questionId;
+ const question = assessment!.questions[questionId] as IMCQQuestion;
+ const choices = question.choices.concat([
+ {
+ content: 'A',
+ hint: null
+ }
+ ]);
+ question.choices = choices;
+ assessment!.questions[questionId] = question;
+ this.props.updateAssessment(assessment);
+ };
+
+ private delOption = () => {
+ const assessment = this.props.assessment;
+ const questionId = this.props.questionId;
+ const question = assessment!.questions[questionId] as IMCQQuestion;
+ const choices = question.choices.slice(0, question.choices.length - 1);
+ question.choices = choices;
+ assessment!.questions[questionId] = question;
+ this.props.updateAssessment(assessment);
+ };
+
private textareaContent = (
path: Array