Skip to content

Commit

Permalink
Preview for Question Builder
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan-CTL committed Jan 24, 2024
1 parent 556d1de commit 2e2fed1
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 115 deletions.
2 changes: 1 addition & 1 deletion econplayground/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ class Meta:

class QuestionSerializer(serializers.ModelSerializer):
assessmentrule_set = AssessmentRuleSerializer(many=True)
graph = GraphTypeSerializer(read_only=True)
graph = GraphSerializer(read_only=True)

class Meta:
model = Question
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
{% block js %}
<script src="{% static 'js/build/rubric.js' %}"></script>
<script src="{% static 'js/build/multipleChoice.js' %}"></script>
<script src="{% static 'js/build/graphPreview.js' %}"></script>
<script>
if (!window.EconPlayground) {
window.EconPlayground = {};
Expand Down
39 changes: 39 additions & 0 deletions econplayground/templates/assignment/assignment_questions.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ <h4>{{question.title}}</h4>
{% endfor %}
</select>
</div>

<div class="container mb-2 accordion">
<div class="accordion-item">
<div class="accordion-header"
id="heading-{{question.pk}}">
<button class="accordion-button py-2 collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapse-graph"
aria-expanded="false"
aria-controls="collapse-graph">
Graph Preview
</button>
</div>
<div id="collapse-graph"
class="accordion-collapse collapse"
aria-labelledby="heading-{{question.pk}}"
data-bs-parent="#accordionExample">
<div class="accordion-body">
<!-- Graph Preview React Component -->
<div id="graph-preview-{{question.pk}}"></div>
</div>
</div>
</div>
</div>

<!-- Rubric React component -->
<div id="question-rubric-{{question.pk}}"></div>
Expand Down Expand Up @@ -126,6 +151,20 @@ <h4>{{question.title}}</h4>
console.error(
'Multiple Choice could not be initialized for question ' + questionId);
}

if (window.initGraphPreview) {
const containerId = `graph-preview-${questionId}`;
const container = document.getElementById(containerId);
$('#questionGraph-' + questionId).on('select2:select', function (e) {
const gId = $('#questionGraph-' + questionId).find(':selected').val();
window.initGraphPreview(container, parseInt(gId));
});
const gId = $('#questionGraph-' + questionId).val();
window.initGraphPreview(container, parseInt(gId));
} else {
console.error(
'Graph Preview could not be initialized for question ' + questionId);
}

if (window.initRubric) {
const containerId = `question-rubric-${questionId}`;
Expand Down
1 change: 1 addition & 0 deletions econplayground/templates/assignment/questions_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ <h1>Question Editor</h1>
{% block js %}
<script src="{% static 'js/build/rubric.js' %}"></script>
<script src="{% static 'js/build/multipleChoice.js' %}"></script>
<script src="{% static 'js/build/graphPreview.js' %}"></script>
{% endblock %}
1 change: 1 addition & 0 deletions media/js/config/paths.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ module.exports = {
appRubricJs: resolveApp(JS_PATH + 'src/rubric-main.js'),
appQuestionJs: resolveApp(JS_PATH + 'src/question-main.js'),
appMultipleChoiceJs: resolveApp(JS_PATH + 'src/multiple-choice-main.js'),
appGraphPreviewJs: resolveApp(JS_PATH + 'src/graph-preview-main.js'),
appAssignmentJs: resolveApp(JS_PATH + 'src/assignment-main.js'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp(JS_PATH + 'src'),
Expand Down
1 change: 1 addition & 0 deletions media/js/config/webpack.config.dev.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
editor: [paths.appEditorJs],
question: [paths.appQuestionJs],
multipleChoice: [paths.appMultipleChoiceJs],
graphPreview: [paths.appGraphPreviewJs],
stepGraphViewer: [paths.appStepGraphViewerJs],
rubric: [paths.appRubricJs],
viewer: [paths.appViewerJs]
Expand Down
1 change: 1 addition & 0 deletions media/js/config/webpack.config.prod.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module.exports = {
editor: [paths.appEditorJs],
question: [paths.appQuestionJs],
multipleChoice: [paths.appMultipleChoiceJs],
graphPreview: [paths.appGraphPreviewJs],
stepGraphViewer: [paths.appStepGraphViewerJs],
rubric: [paths.appRubricJs],
viewer: [paths.appViewerJs]
Expand Down
146 changes: 32 additions & 114 deletions media/js/src/GraphPreview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
import JXGBoard from './JXGBoard.jsx';
import ResetGraphButton from './buttons/ResetGraphButton.jsx';
import {
BOARD_WIDTH, BOARD_HEIGHT
BOARD_WIDTH, BOARD_HEIGHT, getGraph
} from './utils';
import { defaultGraph, convertGraph } from './GraphMapping.js';


/**
* This component is used to view an econgraph object.
Expand All @@ -15,10 +17,30 @@ export default class GraphPreview extends React.Component {

this.initialState = {
currentFeedback: [],
score: 0
gId: null,
graph: defaultGraph,
score: 0,
};
this.state = this.initialState;
this.updateGraph = this.updateGraph.bind(this);
const me = this;
getGraph(props.gId).then(data => {
if (data) {
me.setState({graph: convertGraph(data)});
}
});
}

componentDidUpdate(prevProps) {
console.log('GraphPreview.componentDidUpdate');
if (this.props.gId !== prevProps.gId) {
const me = this;
getGraph(this.props.gId).then(data => {
if (data) {
me.setState({graph: convertGraph(data)});
}
});
}
}

render() {
Expand All @@ -37,27 +59,28 @@ export default class GraphPreview extends React.Component {
}

let graph = (
<p>Loading...</p>
<p>No Graph Found.</p>
);

if (
typeof this.props.gType !== 'undefined' &&
this.props.gType !== null
this.state.graph.gId
) {
graph = (
<JXGBoard
id={'editing-graph'}
width={BOARD_WIDTH}
height={BOARD_HEIGHT}
shadow={!isInstructor}
{...this.props}
{...this.state.graph}
/>
);
}
return (
<div className="GraphPreview p-2">
<h4><strong>{this.props.gTitle}</strong></h4>
<p>{this.props.gInstructions}</p>
<div className="row bg-white mb-2">
<h4><strong>{this.state.graph ? this.state.graph.gTitle :
'No graph selected'}</strong></h4>
<p>{this.state.graph && this.state.graph.gInstructions}</p>
<div className="row bg-white mb-2 overflow-hidden">
{graph}
</div>
<div className="row justify-content-end">
Expand All @@ -78,109 +101,4 @@ export default class GraphPreview extends React.Component {

GraphPreview.propTypes = {
gId: PropTypes.number,
gType: PropTypes.number,
gTitle: PropTypes.string,
gInstructions: PropTypes.string,
gNeedsSubmit: PropTypes.bool,
// gAssignmentType: PropTypes.number.isRequired,

// gShowIntersection: PropTypes.bool.isRequired,
// gDisplayIntersection1: PropTypes.bool.isRequired,
gDisplayIntersection1Initial: PropTypes.bool,
// gIntersectionLabel: PropTypes.string.isRequired,
// gDisplayIntersection2: PropTypes.bool.isRequired,
gDisplayIntersection2Initial: PropTypes.bool,
// gIntersection2Label: PropTypes.string.isRequired,
// gDisplayIntersection3: PropTypes.bool.isRequired,
gDisplayIntersection3Initial: PropTypes.bool,
// gIntersection3Label: PropTypes.string.isRequired,
// gDisplayShadow: PropTypes.bool.isRequired,

gIntersectionHorizLineLabel: PropTypes.string,
gIntersectionVertLineLabel: PropTypes.string,
gIntersection2HorizLineLabel: PropTypes.string,
gIntersection2VertLineLabel: PropTypes.string,
gIntersection3HorizLineLabel: PropTypes.string,
gIntersection3VertLineLabel: PropTypes.string,

gDisplayFeedback: PropTypes.bool,

// gLine1Label: PropTypes.string.isRequired,
// gLine2Label: PropTypes.string.isRequired,
// gLine3Label: PropTypes.string.isRequired,
gLine4Label: PropTypes.string,

gXAxisLabel: PropTypes.string,
gYAxisLabel: PropTypes.string,
gXAxis2Label: PropTypes.string,
gYAxis2Label: PropTypes.string,
// gLine1Slope: PropTypes.number.isRequired,
gLine1SlopeInitial: PropTypes.number,
gLine2Slope: PropTypes.number,
gLine2SlopeInitial: PropTypes.number,
gLine3Slope: PropTypes.number,
gLine3SlopeInitial: PropTypes.number,
gLine4Slope: PropTypes.number,
gLine4SlopeInitial: PropTypes.number,

// gLine1OffsetX: PropTypes.number.isRequired,
// gLine1OffsetY: PropTypes.number.isRequired,
gLine1OffsetXInitial: PropTypes.number,
gLine1OffsetYInitial: PropTypes.number,
// gLine2OffsetX: PropTypes.number.isRequired,
// gLine2OffsetY: PropTypes.number.isRequired,
gLine2OffsetXInitial: PropTypes.number,
gLine2OffsetYInitial: PropTypes.number,
// gLine3OffsetX: PropTypes.number.isRequired,
// gLine3OffsetY: PropTypes.number.isRequired,
gLine3OffsetXInitial: PropTypes.number,
gLine3OffsetYInitial: PropTypes.number,
// gLine4OffsetX: PropTypes.number.isRequired,
// gLine4OffsetY: PropTypes.number.isRequired,
gLine4OffsetXInitial: PropTypes.number,
gLine4OffsetYInitial: PropTypes.number,

// gLine1Dashed: PropTypes.bool.isRequired,
// gLine2Dashed: PropTypes.bool.isRequired,
// gLine3Dashed: PropTypes.bool.isRequired,

gAlpha: PropTypes.number,

gA1: PropTypes.number,
gA1Initial: PropTypes.number,
gA2: PropTypes.number,
gA2Initial: PropTypes.number,
gA3: PropTypes.number,
gA3Initial: PropTypes.number,
gA4: PropTypes.number,
gA4Initial: PropTypes.number,
gA5: PropTypes.number,
gA5Initial: PropTypes.number,

gA: PropTypes.number,
gK: PropTypes.number,
gR: PropTypes.number,
gY1: PropTypes.number,
gY2: PropTypes.number,

gCobbDouglasA: PropTypes.number,
gCobbDouglasAInitial: PropTypes.number,
gCobbDouglasAName: PropTypes.string,
gCobbDouglasL: PropTypes.number,
gCobbDouglasLInitial: PropTypes.number,
gCobbDouglasLName: PropTypes.string,
gCobbDouglasK: PropTypes.number,
gCobbDouglasKInitial: PropTypes.number,
gCobbDouglasKName: PropTypes.string,
gCobbDouglasAlpha: PropTypes.number,
gCobbDouglasAlphaInitial: PropTypes.number,
gCobbDouglasYName: PropTypes.string,

gNName: PropTypes.string,

gFunctionChoice: PropTypes.number,

assessment: PropTypes.array,
submission: PropTypes.object,
// updateGraph: PropTypes.func.isRequired
};
2 changes: 2 additions & 0 deletions media/js/src/JXGBoard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ export default class JXGBoard extends React.Component {
return;
}

console.log('this:', this);

if (this.board) {
// Remove all the current objects from the board so we can
// re-render.
Expand Down
19 changes: 19 additions & 0 deletions media/js/src/graph-preview-main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import GraphPreview from './GraphPreview.jsx';

const rootMC = {};

function initGraphPreview(domElement, gId= null) {
const container = domElement;
if (container) {
if (!(container.id in rootMC)) {
rootMC[domElement.id] = createRoot(domElement);
}
}
if (gId) {
rootMC[domElement.id].render(<GraphPreview gId={gId} />);
}
}

window.initGraphPreview = initGraphPreview;

0 comments on commit 2e2fed1

Please sign in to comment.