Commit a2fa8377 authored by Thomas Roos's avatar Thomas Roos

Minimal working version of student addition and editing

parent 15872471
......@@ -11,10 +11,13 @@ import * as api from '../api';
import ProgressBar from './students/ProgressBar.jsx';
import SearchPanel from './students/SearchPanel.jsx';
import ExamSelector from './students/ExamSelector.jsx';
import EditPanel from './students/EditPanel.jsx';
class CheckStudents extends React.Component {
state = {
editActive: false,
editStud: null,
exam: {
id: 0,
name: "Loading...",
......@@ -47,7 +50,7 @@ class CheckStudents extends React.Component {
Mousetrap.unbind(["right", "l"]);
Mousetrap.unbind(["up", "k"]);
Mousetrap.unbind(["down", "j"]);
}
};
componentDidMount = () => {
......@@ -201,7 +204,7 @@ class CheckStudents extends React.Component {
validated: sub.validated,
list: newList
}
}, this.search.listMatchedStudent)
}, this.listMatchedStudent)
})
.catch(err => {
alert('failed to get submission (see javascript console for details)')
......@@ -223,7 +226,7 @@ class CheckStudents extends React.Component {
imagePath: 'api/images/signature/' + this.state.exam.id + '/' + subs[0].id,
list: subs
}
}, this.search.listMatchedStudent)
}, this.listMatchedStudent)
})
.catch(err => {
alert('failed to get submissions (see javascript console for details)')
......@@ -232,6 +235,10 @@ class CheckStudents extends React.Component {
})
}
listMatchedStudent = () => {
if (this.search) this.search.listMatchedStudent();
};
matchStudent = (studID) => {
let newList = this.state.submission.list;
......@@ -262,6 +269,20 @@ class CheckStudents extends React.Component {
})
}
toggleEdit = (student) => {
if (student.id) {
this.setState({
editActive: true,
editStud: student
})
} else {
this.setState({
editActive: !this.state.editActive,
editStud: null
})
}
}
render() {
const inputStyle = {
width: '5em'
......@@ -286,12 +307,13 @@ class CheckStudents extends React.Component {
<div className="is-hidden-desktop">
<ExamSelector exam={this.state.exam} selectExam={this.selectExam} />
</div>
<SearchPanel ref={(search) => { this.search = search; }}
matchStudent={this.matchStudent}
studentID={this.state.submission.studentID} validated={this.state.submission.validated} />
{this.state.editActive ?
<EditPanel toggleEdit={this.toggleEdit} editStud={this.state.editStud} />
:
<SearchPanel ref={(search) => { this.search = search; }}
matchStudent={this.matchStudent} toggleEdit={this.toggleEdit}
studentID={this.state.submission.studentID} validated={this.state.submission.validated} />
}
</div>
<div className="column">
......
import React from 'react';
import * as api from '../../api';
import IDBlock from './IDBlock.jsx';
const BackButton = (props) => (
<button className="button is-light is-fullwidth" onClick={props.onClick}>
<span className="icon is-small">
<i className="fa fa-chevron-left"></i>
</span>
<span>search</span>
</button>
)
const SaveButton = (props) => (
<button className="button is-primary is-fullwidth" disabled={props.disabled} onClick={props.onClick}>
<span className="icon is-small">
<i className="fa fa-floppy-o"></i>
</span>
<span>save</span>
</button>
)
const UploadButton = (props) => (
<button className="button is-link is-fullwidth" onClick={props.onClick}>
<span className="icon is-small">
<i className="fa fa-upload"></i>
</span>
<span>upload</span>
</button>
)
class EditPanel extends React.Component {
state = {
id: "",
firstName: "",
lastName: "",
email: ""
}
componentWillMount = () => {
if (this.props.editStud){
const stud = this.props.editStud;
this.setState({
id: stud.id,
firstName: stud.firstName,
lastName: stud.lastName,
email: stud.email
})
}
}
changeFirstName = (event) => {
this.setState({
firstName: event.target.value
})
}
changeLastName = (event) => {
this.setState({
lastName: event.target.value
})
}
changeMail = (event) => {
this.setState({
email: event.target.value
})
}
setID = (id, student) => {
this.setState({
id: id
})
if (student) {
this.setState({
firstName: student.firstName,
lastName: student.lastName,
email: student.email
})
}
}
saveStudent = () => {
api.put('students', {
studentID: this.state.id,
firstName: this.state.firstName,
lastName: this.state.lastName,
email: this.state.email
})
.then((stud) => {
this.setState({
id: "",
firstName: "",
lastName: "",
email: ""
})
this.idblock.clear();
})
}
render() {
const empty = !(this.state.id + this.state.firstName + this.state.lastName + this.state.email);
const full = this.state.id && this.state.firstName && this.state.lastName;
return (
<nav className="panel">
<p className="panel-heading">
Manage students
</p>
<IDBlock setID={this.setID} editStud={this.state.id} ref={(id) => { this.idblock = id; }}/>
<div className="panel-block">
<div className="field">
<label className="label">Name</label>
<div className="control has-icons-left">
<input className="input" type="email" placeholder="First name"
value={this.state.firstName} onChange={this.changeFirstName} />
<span className="icon is-small is-left">
<i className="fa fa-quote-left"></i>
</span>
</div>
</div>
</div>
<div className="panel-block">
<div className="field">
<div className="control has-icons-left">
<input className="input" type="email" placeholder="Second name"
value={this.state.lastName} onChange={this.changeLastName} />
<span className="icon is-small is-left">
<i className="fa fa-quote-right"></i>
</span>
</div>
</div>
</div>
<div className="panel-block">
<div className="field">
<label className="label">Email</label>
<div className="control has-icons-left has-icons-right">
<input className="input" type="email" placeholder="Email input"
value={this.state.email} onChange={this.changeMail} />
<span className="icon is-small is-left">
<i className="fa fa-envelope"></i>
</span>
</div>
</div>
</div>
<div className="panel-block">
<BackButton onClick={this.props.toggleEdit} />
{empty ?
<UploadButton />
:
<SaveButton disabled={!full} onClick={this.saveStudent} />
}
</div>
</nav>
)
}
}
export default EditPanel;
import React from 'react';
import * as api from '../../api';
class IDBlock extends React.Component {
state = {
input: "",
editing: true,
short: true,
new: true,
}
componentDidMount = () => {
if (this.props.editStud) {
this.setState({
input: this.props.editStud,
editing: false,
short: false,
new: false
})
}
}
clear = () => {
this.setState({
input: "",
editing: true,
short: false,
new: false
})
}
statusIcon = () => {
if (this.state.editing) {
return null
} else {
const icon = this.state.short ? "exclamation-triangle" : "check";
return (
<span className="icon is-small is-right">
<i className={"fa fa-" + icon}></i>
</span>
)
}
}
helpText = () => {
if (this.state.editing) {
return null
}
let text;
let boldText = null;
if (this.state.short) {
text = "This entered number is ";
boldText = "too short"
} else {
text = "This student will be "
boldText = this.state.new ? "added" : "updated"
}
return (
<p className={"help" + this.color()}>{text}<b>{boldText}</b></p>
)
}
color = () => {
if (this.state.editing) {
return ""
} else {
return this.state.short ? " is-danger" : " is-success"
}
}
changeID = (event) => {
const patt = new RegExp(/^[1-9]\d*$|^()$/);
if (patt.test(event.target.value)) {
this.setState({
input: event.target.value
})
}
}
blur = (event) => {
const id = parseInt(event.target.value);
if (id >= 1000000) {
api.get('students/' + id)
.then(stud => {
this.setState({
editing: false,
short: false,
new: false
})
this.props.setID(id, stud);
})
.catch(res => {
console.log('If your browser just gave a 404 error, that is normal - do not worry!');
this.setState({
editing: false,
short: false,
new: true
})
this.props.setID(id);
})
} else {
this.setState({
editing: false,
short: true,
})
}
}
focus = () => {
this.setState({
editing: true
})
}
render() {
return (
<div className="panel-block">
<div className="field">
<label className="label">Student number</label>
<div className="control has-icons-left has-icons-right">
<input className={"input" + this.color()} type="text" maxLength="7" placeholder="Student number"
value={this.state.input} onChange={this.changeID}
onBlur={this.blur} onFocus={this.focus} />
<span className="icon is-small is-left">
<i className="fa fa-user"></i>
</span>
{this.statusIcon()}
</div>
{this.helpText()}
</div>
</div>
)
}
}
export default IDBlock;
\ No newline at end of file
......@@ -26,6 +26,7 @@ class SearchPanel extends React.Component {
api.get('students')
.then(students => {
this.students = students;
this.listMatchedStudent();
})
.catch(err => {
alert('failed to get students (see javascript console for details)')
......@@ -113,9 +114,9 @@ class SearchPanel extends React.Component {
render() {
return (
<div>
<nav className="panel">
<p className="panel-heading">
Students
Search students
</p>
<div className="panel-block">
<p className="control has-icons-left">
......@@ -132,10 +133,17 @@ class SearchPanel extends React.Component {
<StudentPanelBlock key={student.id} student={student}
selected={index === this.state.selected}
matched={student.id === this.props.studentID && this.props.validated}
selectStudent={this.selectStudent} />
selectStudent={this.selectStudent} editStudent={this.props.toggleEdit}/>
)}
</div>
<div className="panel-block is-hidden-mobile">
<button className="button is-link is-outlined is-fullwidth" onClick={this.props.toggleEdit}>
<span className="icon is-small">
<i className="fa fa-user-plus"></i>
</span>
<span>add students</span>
</button>
</div>
</nav>
)
}
......
......@@ -23,9 +23,9 @@ const StudentPanelBlock = (props) => {
<div className={"panel-block" + (props.selected ? " is-info" : " is-hidden")}
key="info" style={{ backgroundColor: '#dbdbdb' }}>
<span className="panel-icon">
<a className="panel-icon" onClick={() => props.editStudent(props.student)}>
<i className="fa fa-database"></i>
</span>
</a>
{props.student.id}&emsp;
<span className="panel-icon">
<i className="fa fa-check"></i>
......
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