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

Grader view #105

Merged
merged 7 commits into from
Jul 4, 2016
38 changes: 36 additions & 2 deletions browser/js/actions/assessmentActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@ export const LOAD_ASSESSMENTS_FAILURE = 'LOAD_ASSESSMENTS_FAILURE'
export const CREATE_ASSESSMENT_REQUEST = 'CREATE_ASSESSMENT_REQUEST'
export const CREATE_ASSESSMENT_SUCCESS = 'CREATE_ASSESSMENT_SUCCESS'
export const CREATE_ASSESSMENT_FAILURE = 'CREATE_ASSESSMENT_FAILURE'
export const UPDATE_ASSESSMENT_REQUEST = 'UPDATE_ASSESSMENT_REQUEST'
export const UPDATE_ASSESSMENT_SUCCESS = 'UPDATE_ASSESSMENT_SUCCESS'
export const UPDATE_ASSESSMENT_FAILURE = 'UPDATE_ASSESSMENT_FAILURE'
export const SWITCH_ASSESSMENT_REQUEST = 'SWITCH_ASSESSMENT_REQUEST'
export const SWITCH_ASSESSMENT_SUCCESS = 'SWITCH_ASSESSMENT_SUCCESS'
export const SWITCH_ASSESSMENT_FAILURE = 'SWITCH_ASSESSMENT_FAILURE'
import { getAssessment } from '../reducers/assessments'

const API_URL = '/api/v1'
const USER_URL = `${API_URL}/users`
const ASSESSMENT_URL = `${API_URL}/assessments`

export const getUserAssessments = (id) => (dispatch) => {
export const getUserAssessments = () => (dispatch) => {
dispatch({ type: LOAD_ASSESSMENTS_REQUEST })

return axios.get(`${USER_URL}/${id}/assessments`).then(res => res.data)
return axios.get(`${USER_URL}/assessments`).then(res => res.data)
.then(resData => dispatch({
type: LOAD_ASSESSMENTS_SUCCESS,
assessments: resData
Expand All @@ -36,3 +43,30 @@ export const createAssessment = (assessment) => (dispatch, getState) => {
}))
.catch(error => dispatch({ type: CREATE_ASSESSMENT_FAILURE, error }))
}

export const updateAssessment = (assessment) => (dispatch) => {
dispatch({ type: UPDATE_ASSESSMENT_REQUEST })

return axios.put(`${ASSESSMENT_URL}/${assessment.id}` , assessment).then(res => res.data)
.then(resData => dispatch({
type: UPDATE_ASSESSMENT_SUCCESS,
assessment: resData
}))
.catch(error => dispatch({ type: UPDATE_ASSESSMENT_FAILURE, error }))
}
export const switchAssessment = (id) => (dispatch, getState) => {
dispatch({ type: SWITCH_ASSESSMENT_REQUEST })

const assessment = getAssessment(getState().assessments, id)

if (assessment) {
dispatch({ type: SWITCH_ASSESSMENT_SUCCESS, assessment })
} else {
return axios.get(`${ASSESSMENT_URL}/${id}`)
.then(resData => dispatch({
type: SWITCH_ASSESSMENT_SUCCESS, assessment: resData
})
.catch(error => dispatch({ type: SWITCH_ASSESSMENT_FAILURE, error })))
}

}
42 changes: 42 additions & 0 deletions browser/js/components/AssessmentCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict'

import React, { Component, PropTypes } from 'react'
import Paper from 'material-ui/Paper'
import IconButton from 'material-ui/IconButton'
import AssessmentForm from './AssessmentForm'
import styles from './graderStyles'

class AssessmentCard extends Component {

render () {
const { assessment, onSelect, onEdit } = this.props

return (
<Paper style={Object.assign({}, styles.assessmentInfo, styles.skinny)}>
<div>
<div onTouchTap={() => onSelect(assessment.id)}
style={Object.assign({}, styles.editAssessment, styles.gradingTitle)}>
{assessment.name}
</div>
<IconButton
style={{ float: 'right' }}
iconStyle={{ color: '#fff' }}
iconClassName={'fa fa-pencil'}
tooltip='Edit Assessment'
onTouchTap={() => onEdit(assessment)}
/>
</div>
<div style={styles.gradingSubtitle}>{`Team: ${assessment.team.name}`}</div>
<a href="#" style={styles.gradingSubtitle}>{assessment.repoUrl}</a>
</Paper>
)
}
}

AssessmentCard.propTypes = {
assessment: PropTypes.object.isRequired,
onSelect: PropTypes.func,
onEdit: PropTypes.func
}

export default AssessmentCard
158 changes: 87 additions & 71 deletions browser/js/components/AssessmentForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,7 @@ import AutoComplete from 'material-ui/AutoComplete'
import { Step, Stepper, StepLabel, StepContent } from 'material-ui/Stepper'
import { getUserOrgs, getOrgTeams } from '../actions/githubActions'
import { getOrgs, getTeams } from '../reducers/github'

const styles = {
blueBg: {
backgroundColor: blue600
},
form: {
marginTop: 50
},
skinny: {
margin: 0,
marginBottom: 15
},
paperStyle: {
margin: 'auto',
padding: 20
},
button: {
marginTop: 15
},
fullWidth: {
width: '100%'
},
center: {
textAlign: 'center'
},
stepLabel: {
fontSize: 24
},
addBtn: {
marginLeft: 20,
backgroundColor: '#000',
borderRadius: '2px',
padding: 8,
height: 38,
width: 38
}
}
import styles from './graderStyles'

// const validate = (values) => {
// const errors = {}
Expand All @@ -72,20 +36,24 @@ const styles = {
class AssessmentForm extends Component {
constructor(props) {
super(props)

const { assessment } = props

this.state = {
finished: false,
stepIndex: 0,
form: {
name: '',
description: '',
repoUrl: '',
org: '',
teamName: '',
teamId: '',
id: assessment ? assessment.id : '',
name: assessment ? assessment.name : '',
description: assessment ? assessment.description : '',
repoUrl: assessment ? assessment.repoUrl : '',
org: assessment ? assessment.org : '',
teamName: assessment ? assessment.team.name : '',
teamId: assessment ? assessment.teamId : '',
},
errors: {},
path: '',
paths: []
paths: assessment ? assessment.solutionFiles : [],
}
}

Expand All @@ -109,7 +77,7 @@ class AssessmentForm extends Component {
checkAndAddPath () {
const { path, paths, repo } = this.state
axios.get(`/api/v1/github/${repo}/contents?path=${path}`)
.then(resData => {
.then(() => {
this.setState({
paths: paths.concat(path),
path: '',
Expand Down Expand Up @@ -179,13 +147,80 @@ class AssessmentForm extends Component {
this.setState({ form: nextForm })
}

renderOrgInput () {
const { form } = this.state
const { orgs, assessment } = this.props

if (!assessment) {
return (
<AutoComplete
floatingLabelText='Organization'
filter={AutoComplete.fuzzyFilter}
dataSource={orgs.map(org => org.login)}
maxSearchResults={4}
searchText={form.org}
fullWidth={true}
onNewRequest={this.handleOrgSelect}
/>
)
} else {
return (
<TextField
floatingLabelText='Organization'
value={form.org}
fullWidth={true}
disabled={true}
/>
)
}
}

renderTeamInput () {
const { form } = this.state
const { assessment, isFetchingTeams, teams } = this.props

if (!isFetchingTeams && teams.length && !assessment) {
return (
<AutoComplete
floatingLabelText='Team'
filter={AutoComplete.fuzzyFilter}
dataSource={teams}
dataSourceConfig={{text: 'name', value: 'name'}}
maxSearchResults={4}
searchText={form.teamName}
fullWidth={true}
onNewRequest={this.handleTeamSelect}
/>
)
} else if (assessment) {
return (
<TextField
floatingLabelText='Team'
value={form.teamName}
fullWidth={true}
disabled={true}
/>
)
}
}

renderStepActions(step) {
const { stepIndex } = this.state
const { assessment } = this.props
let buttonLabel

if (stepIndex === 1 && assessment) {
buttonLabel = 'Save'
} else if (stepIndex === 1) {
buttonLabel = 'Create'
} else {
buttonLabel = 'Next'
}

return (
<div style={{margin: '12px 0'}}>
<RaisedButton
label={stepIndex === 1 ? 'Create' : 'Next'}
label={buttonLabel}
primary={stepIndex !== 1}
secondary={stepIndex === 1}
onTouchTap={stepIndex === 1
Expand All @@ -209,7 +244,7 @@ class AssessmentForm extends Component {
const { form, error } = this.state

return (
<Paper zDepth={0} style={styles.paperStyle}>
<Paper zDepth={0} style={styles.formPaperStyle}>
<form>
<TextField
floatingLabelText="Name"
Expand All @@ -220,33 +255,14 @@ class AssessmentForm extends Component {
<TextField
floatingLabelText="Description"
multiLine={true}
rows={2}
rows={1}
rowsMax={Infinity}
value={form.description}
fullWidth={true}
onChange={(e) => this.handleChange(e, 'description')}
/>
<AutoComplete
floatingLabelText='Organization'
filter={AutoComplete.fuzzyFilter}
dataSource={orgs.map(org => org.login)}
maxSearchResults={4}
searchText={form.org}
fullWidth={true}
onNewRequest={this.handleOrgSelect}
/>
{ !isFetchingTeams && teams.length
? <AutoComplete
floatingLabelText='Team'
filter={AutoComplete.fuzzyFilter}
dataSource={teams}
dataSourceConfig={{text: 'name', value: 'name'}}
maxSearchResults={4}
searchText={form.teamName}
fullWidth={true}
onNewRequest={this.handleTeamSelect}
/>
: null }
{this.renderOrgInput()}
{this.renderTeamInput()}
{ form.teamId === ''
? null
: <TextField
Expand All @@ -266,7 +282,7 @@ class AssessmentForm extends Component {
const { path, error } = this.state

return (
<Paper zDepth={0} style={styles.paperStyle}>
<Paper zDepth={0} style={styles.formPaperStyle}>
<TextField
floatingLabelText="Solution Path"
value={path}
Expand Down Expand Up @@ -309,7 +325,7 @@ class AssessmentForm extends Component {
if (isFetchingOrgs && !orgs.length) return <h1>Is Loading...</h1>
else {
return (
<Paper style={styles.paperStyle}>
<Paper style={styles.formPaperStyle}>
<Stepper activeStep={stepIndex} orientation="vertical">
<Step>
<StepLabel style={styles.stepLabel}>Enter Assessment Information</StepLabel>
Expand Down
Loading