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

Fix classroom form state #75

Merged
merged 11 commits into from
Oct 26, 2017
6 changes: 3 additions & 3 deletions src/components/classrooms/ClassroomForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const ClassroomForm = (props) => {
placeHolder="Class subject"
onDOMChange={props.onChange}
required={!optional}
value={props.fields.subject}
value={props.fields.subject || ''}
/>
</FormField>
<FormField htmlFor="school" label="Institution">
Expand All @@ -44,7 +44,7 @@ const ClassroomForm = (props) => {
placeHolder="Name of institution or school"
onDOMChange={props.onChange}
required={!optional}
value={props.fields.school}
value={props.fields.school || ''}
/>
</FormField>
<FormField htmlFor="description" label="Description">
Expand All @@ -53,7 +53,7 @@ const ClassroomForm = (props) => {
placeholder="Description of class"
onChange={props.onChange}
required={!optional}
value={props.fields.description}
value={props.fields.description || ''}
/>
</FormField>
</fieldset>
Expand Down
40 changes: 25 additions & 15 deletions src/containers/classrooms/ClassroomFormContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Actions } from 'jumpstate';

import ClassroomForm from '../../components/classrooms/ClassroomForm';
import {
CLASSROOMS_STATUS, CLASSROOMS_INITIAL_STATE, CLASSROOMS_PROPTYPES
CLASSROOMS_INITIAL_STATE, CLASSROOMS_PROPTYPES
} from '../../ducks/classrooms';
import {
PROGRAMS_INITIAL_STATE, PROGRAMS_PROPTYPES
Expand All @@ -19,9 +18,14 @@ export class ClassroomFormContainer extends React.Component {
this.createClassroom = this.createClassroom.bind(this);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.closeForm = this.closeForm.bind(this);
this.updateClassroom = this.updateClassroom.bind(this);
}

componentWillUnmount() {
this.resetFormFields();
}

onChange(event) {
const fields = { ...this.props.formFields, [event.target.id]: event.target.value };
Actions.classrooms.updateFormFields(fields);
Expand All @@ -30,12 +34,26 @@ export class ClassroomFormContainer extends React.Component {
onSubmit(event) {
event.preventDefault();
if (this.props.selectedClassroom) {
this.updateClassroom();
this.updateClassroom().then(() => {
Actions.getClassroom(this.props.selectedClassroom.id);
this.closeForm();
});
} else {
this.createClassroom();
this.createClassroom().then(() => {
Actions.getClassroomsAndAssignments(this.props.selectedProgram);
this.closeForm();
});
}
}

resetFormFields() {
Actions.classrooms.updateFormFields(CLASSROOMS_INITIAL_STATE.formFields);
}

closeForm() {
Actions.classrooms.toggleFormVisibility();
}

createClassroom() {
const classroomData = {
attributes: this.props.formFields,
Expand All @@ -49,25 +67,17 @@ export class ClassroomFormContainer extends React.Component {
}
};

Actions.createClassroom(classroomData)
return Actions.createClassroom(classroomData)
.then((classroom) => {
if (!this.props.selectedProgram.custom) {
const assignments = this.props.selectedProgram.metadata.assignments;
if (classroom) this.autoCreateAssignments(assignments, classroom);
}
}).then(() => {
Actions.classrooms.toggleFormVisibility();
Actions.getClassroomsAndAssignments(this.props.selectedProgram);
});
}

updateClassroom() {
Actions.updateClassroom({ id: this.props.selectedClassroom.id, payload: this.props.formFields })
.then(() => {
Actions.classrooms.toggleFormVisibility();
}).then(() => {
Actions.getClassroom(this.props.selectedClassroom.id);
});
return Actions.updateClassroom({ id: this.props.selectedClassroom.id, payload: this.props.formFields });
}

autoCreateAssignments(assignments, classroom) {
Expand All @@ -83,7 +93,7 @@ export class ClassroomFormContainer extends React.Component {
metadata: {
classification_target: assignments[workflowId].classification_target
},
workflow_id: workflowId,
workflow_id: workflowId
},
relationships: {
classroom: {
Expand Down
1 change: 1 addition & 0 deletions src/containers/classrooms/ClassroomsTableContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Paragraph from 'grommet/components/Paragraph';
import ConfirmationDialog from '../../components/common/ConfirmationDialog';
import DarienClassroomsTable from '../../components/darien/DarienClassroomsTable';
import AstroClassroomsTableContainer from '../astro/AstroClassroomsTableContainer';

import {
CLASSROOMS_INITIAL_STATE, CLASSROOMS_PROPTYPES
} from '../../ducks/classrooms';
Expand Down
21 changes: 17 additions & 4 deletions src/ducks/assignments.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { State, Effect, Actions } from 'jumpstate';
import PropTypes from 'prop-types';
import { get, post } from '../lib/edu-api';
import { i2aAssignmentNames } from './programs';

// Constants
const ASSIGNMENTS_STATUS = {
Expand Down Expand Up @@ -46,9 +47,9 @@ const setError = (state, error) => {
};

// Effects are for async actions and get automatically to the global Actions list
Effect('getAssignments', (classroomId) => {
Effect('getAssignments', (data) => {
Actions.assignments.setStatus(ASSIGNMENTS_STATUS.FETCHING);
return get('/assignments', [{ classroom_id: classroomId }])
return get('/assignments', [{ classroom_id: data.classroomId }])
.then((response) => {
if (!response) { throw 'ERROR (ducks/classrooms/getClassrooms): No response'; }
if (response.ok &&
Expand All @@ -57,9 +58,21 @@ Effect('getAssignments', (classroomId) => {
}
throw 'ERROR (ducks/classrooms/getClassrooms): Invalid response';
})
.then((data) => {
const assignmentsForClassroom = { [classroomId]: data };
.then((assignments) => {
const assignmentsForClassroom = {};
Actions.assignments.setStatus(ASSIGNMENTS_STATUS.SUCCESS);

// If I2A style program, then sort the assignments before setting them to the app state
if (!data.selectedProgram.custom) {
const firstAssignment = assignments.find(assignment => assignment.name === i2aAssignmentNames.first);
const secondAssignment = assignments.find(assignment => assignment.name === i2aAssignmentNames.second);
const thirdAssignment = assignments.find(assignment => assignment.name === i2aAssignmentNames.third);

assignmentsForClassroom[data.classroomId] = [firstAssignment, secondAssignment, thirdAssignment];
} else {
assignmentsForClassroom[data.classroomId] = assignments;
}

Actions.assignments.setAssignments(assignmentsForClassroom);
}).catch((error) => {
handleError(error);
Expand Down
2 changes: 1 addition & 1 deletion src/ducks/classrooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Effect('getClassroomsAndAssignments', (selectedProgram) => {
// loop through the number of pages to request all of the data
// and concatenate the response data together for the app state
// Neither Pagination nor infinite scroll would be good UX for current table design.
Actions.getAssignments(classroom.id);
Actions.getAssignments({ classroomId: classroom.id, selectedProgram });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, is there any reason the function getAssignments() is structured like getAssignments(data) where data = {classroomId, selectedProgram} instead of getAssignments(classroomId, selectedProgram)?

It's functionally the same, but from a readability standpoint, it's not very clear what arguments/values getAssignments() is expecting.

The only advantages that I can see for using a single 'compound variable' instead of spelling out the different variables are if:

  • the compound variable (data) supports different kinds of key-values (e.g. an advanced search query, data = {color:'red', species:'dragon', optionalAge: null } ), or
  • the data is structured in a specific way that doesn't matter to the function(), but matters to the API (e.g. createAssignnments())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jumpstate's Effect either wasn't designed to work or had a bug when I tried to pass it two separate arguments! 😢

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh gods, that's right! I totally forgot about Jumpstate's "one Effect, one argument" rule. 🤦‍♂️

});
}
});
Expand Down
18 changes: 12 additions & 6 deletions src/ducks/programs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import { get, post, put, httpDelete } from '../lib/edu-api';
import { env } from '../lib/config';

// testing mocks
export const i2aAssignmentNames = {
first: "Introduction",
second: "Galaxy Zoo 101",
third: "Hubble's Law"
}

const i2a = {
staging: {
id: '1',
Expand All @@ -24,17 +30,17 @@ const i2a = {
// to then build the URL to the project in the UI.
// These are just test projects on staging...
"2218": {
name: "Hubble's Law",
name: i2aAssignmentNames.third,
classification_target: 10,
slug: 'srallen086/intro2astro-hubble-testing'
},
"3037": {
name: 'Galaxy Zoo 101',
name: i2aAssignmentNames.second,
classification_target: 22,
slug: 'srallen086/galaxy-zoo-in-astronomy-101'
},
"3038": {
name: 'Introduction',
name: i2aAssignmentNames.first,
classification_target: 1,
slug: 'srallen086/introduction-to-platform'
}
Expand All @@ -58,17 +64,17 @@ const i2a = {
// to then build the URL to the project in the UI.
// TODO: replace the workflow ids here with the production ids
"1315": {
name: "Hubble's Law",
name: i2aAssignmentNames.third,
classification_target: 10,
slug: 'srallen086/intro2astro-hubble-testing'
},
"1771": {
name: 'Galaxy Zoo 101',
name: i2aAssignmentNames.second,
classification_target: 22,
slug: 'srallen086/galaxy-zoo-in-astronomy-101'
},
"3038": {
name: 'Introduction',
name: i2aAssignmentNames.first,
classification_target: 1,
slug: 'srallen086/introduction-to-platform'
}
Expand Down