Commit 2422d4c8 authored by Adrià Labay's avatar Adrià Labay
Browse files

use text value instead of int for ExamLayout

parent e7578c8a
......@@ -12,28 +12,28 @@ class Exams extends React.Component {
pdf: null,
previewPageCount: 0,
examName: '',
types: null,
selectedType: null
layouts: null,
selectedLayout: null
};
componentDidMount = () => {
api.get('/exams/types')
.then(types => {
this.setState({ types: types, selectedType: types[0] })
api.get('/exams/layouts')
.then(layouts => {
this.setState({ layouts: layouts, selectedLayout: layouts[0] })
})
}
onChangeType = (index) => {
const newtype = this.state.types[index]
onChangeLayout = (event) => {
const newtype = this.state.layouts[event.target.value]
if (!newtype.acceptsPDF) {
this.setState({
selectedType: newtype,
selectedLayout: newtype,
pdf: null,
previewPageCount: 0
})
} else {
this.setState({
selectedType: newtype
selectedLayout: newtype
})
}
}
......@@ -58,15 +58,15 @@ class Exams extends React.Component {
Notification.error('Please enter exam name.')
return
}
if (this.state.selectedType.acceptsPDF && !this.state.pdf) {
if (this.state.selectedLayout.acceptsPDF && !this.state.pdf) {
Notification.error('Please upload a PDF.')
return
}
const data = new window.FormData()
data.append('exam_name', this.state.examName)
data.append('layout', this.state.selectedType.value)
if (this.state.selectedType.acceptsPDF) {
data.append('layout', this.state.selectedLayout.value)
if (this.state.selectedLayout.acceptsPDF) {
data.append('pdf', this.state.pdf)
}
api.post('exams', data)
......@@ -120,9 +120,9 @@ class Exams extends React.Component {
<div className='field'>
<div className='control'>
<div className='select'>
<select onChange={(e) => this.onChangeType(e.target.value)}>
{this.state.types !== null ? this.state.types.map((type, index) => {
return <option key={`key_${index}`} value={index}>{type.name}</option>
<select onChange={this.onChangeLayout}>
{this.state.layouts !== null ? this.state.layouts.map((layout, index) => {
return <option key={`key_${index}`} value={index}>{layout.name}</option>
}) : null}
</select>
</div>
......@@ -131,21 +131,21 @@ class Exams extends React.Component {
</div>
</div>
{this.state.selectedType &&
{this.state.selectedLayout &&
<div className='field is-horizontal'>
<div className='field-label' />
<div className='field-body'>
<div className='field'>
<div className='control'>
<p>{this.state.selectedType.description}</p>
<p>{this.state.selectedLayout.description}</p>
</div>
</div>
</div>
</div>
}
{this.state.selectedType && this.state.selectedType.acceptsPDF &&
{this.state.selectedLayout && this.state.selectedLayout.acceptsPDF &&
<div className='field is-horizontal'>
<div className='field-label'>
<label className='label'>Upload PDF</label>
......@@ -195,8 +195,9 @@ class Exams extends React.Component {
className='button is-info'
onClick={this.addExam}
disabled={!this.state.examName ||
(this.state.selectedType !== null && this.state.selectedType.acceptsPDF && this.state.pdf === null)}>
Create Exam
(this.state.selectedLayout !== null && this.state.selectedLayout.acceptsPDF && this.state.pdf === null)}
>
Create Exam
</button>
</div>
</div>
......
......@@ -43,20 +43,20 @@ class Exams extends React.Component {
renderExamContent = () => {
const layout = this.state.exam.layout.value
const commonProps = {
'examID': this.state.exam.id,
'examName': this.state.exam.name,
'updateExamList': this.props.updateExamList,
'updateExam': this.loadExam
examID: this.state.exam.id,
examName: this.state.exam.name,
updateExamList: this.props.updateExamList,
updateExam: this.loadExam
}
if (layout === 1) {
if (layout === 'templated') {
// templated exam
return <ExamTemplated
exam={this.state.exam}
deleteExam={() => { this.setState({deletingExam: true}) }}
setHelpPage={this.props.setHelpPage}
{...commonProps} />
} else if (layout === 2) {
} else if (layout === 'unstructured') {
// unstructured
return <ExamUnstructured
{...commonProps} />
......
......@@ -2,7 +2,7 @@ from flask import Blueprint
from flask_restful import Api
from .graders import Graders
from .exams import Exams, ExamSource, ExamGeneratedPdfs, ExamPreview, ExamTypes
from .exams import Exams, ExamSource, ExamGeneratedPdfs, ExamPreview, ExamLayouts
from .scans import Scans
from .students import Students
from .copies import Copies, MissingPages
......@@ -28,7 +28,7 @@ api.add_resource(Exams, '/exams', '/exams/<int:exam_id>', '/exams/<int:exam_id>/
api.add_resource(ExamSource, '/exams/<int:exam_id>/source_pdf')
api.add_resource(ExamGeneratedPdfs, '/exams/<int:exam_id>/generated_pdfs')
api.add_resource(ExamPreview, '/exams/<int:exam_id>/preview')
api.add_resource(ExamTypes, '/exams/types')
api.add_resource(ExamLayouts, '/exams/layouts')
api.add_resource(Scans, '/scans/<int:exam_id>')
api.add_resource(Students, '/students', '/students/<int:student_id>')
api.add_resource(Copies,
......
......@@ -199,7 +199,8 @@ class Exams(Resource):
post_parser = reqparse.RequestParser()
post_parser.add_argument('pdf', type=FileStorage, required=False, location='files')
post_parser.add_argument('exam_name', type=str, required=True, location='form')
post_parser.add_argument('layout', type=int, required=True, location='form')
post_parser.add_argument('layout', type=str, required=True, location='form',
choices=[layout.name for layout in ExamLayout])
def post(self):
"""Add a new exam.
......@@ -226,13 +227,13 @@ class Exams(Resource):
if not exam_name:
return dict(status=400, message='Exam name is empty'), 400
if layout == ExamLayout.templated:
if layout == ExamLayout.templated.name:
pdf_data = args['pdf']
exam = self._add_templated_exam(exam_name, pdf_data)
elif layout == ExamLayout.unstructured:
elif layout == ExamLayout.unstructured.name:
exam = self._add_unstructured_exam(exam_name)
else:
return dict(status=400, message=f'Exam type {type} is not defined'), 400
return dict(status=400, message=f'Exam type {layout} is not defined'), 400
print(f"Added exam {exam.id} (name: {exam_name}, token: {exam.token}) to database")
......@@ -501,8 +502,8 @@ def layout_to_data(layout):
"""
if layout == ExamLayout.templated:
return {
'name': 'Zesje',
'value': ExamLayout.templated.value,
'name': 'Templated',
'value': ExamLayout.templated.name,
'acceptsPDF': True,
'description': 'This is the default type, specially made for presencial exams. '
'In this mode, the pdf you upload is used as a template to create unique copies '
......@@ -513,7 +514,7 @@ def layout_to_data(layout):
elif layout == ExamLayout.unstructured:
return {
'name': 'Unstructured',
'value': ExamLayout.unstructured.value,
'value': ExamLayout.unstructured.name,
'acceptsPDF': False,
'description': 'Image based exam, this is specially made for take-home or virtual exam. '
'It is not based in any PDF, the scans can be images, pdfs or zipfiles made by students. '
......@@ -522,7 +523,7 @@ def layout_to_data(layout):
}
class ExamTypes(Resource):
class ExamLayouts(Resource):
"""Resource to request all the possible layouts to create an exam."""
def get(self):
......
......@@ -48,7 +48,7 @@ class Grader(db.Model):
graded_solutions = db.relationship('Solution', backref='graded_by', lazy=True)
ExamLayout = enum.IntEnum(
ExamLayout = enum.Enum(
'ExamLayout',
'templated unstructured'
)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment