diff --git a/src/ducks/classrooms.js b/src/ducks/classrooms.js
index 2ef9ebf7..97d69c35 100644
--- a/src/ducks/classrooms.js
+++ b/src/ducks/classrooms.js
@@ -171,7 +171,7 @@ Effect('createClassroom', (data) => {
// Hmm.... Effects can only take one argument?
Effect('updateClassroom', (data) => {
Actions.classrooms.setStatus(CLASSROOMS_STATUS.UPDATING);
- return put(`/teachers/classrooms/${data.id}`, data.payload)
+ return put(`/teachers/classrooms/${data.id}`, { data: { attributes: data.payload } } )
.then((response) => {
if (!response) { throw 'ERROR (ducks/classrooms/updateClassroom): No response'; }
if (response.ok) {
diff --git a/src/ducks/programs.js b/src/ducks/programs.js
index e22d7b6a..6bd3cbcf 100644
--- a/src/ducks/programs.js
+++ b/src/ducks/programs.js
@@ -274,7 +274,7 @@ Effect('createProgram', (data) => {
Effect('updateProgram', (data) => {
Actions.programs.setStatus(PROGRAMS_STATUS.UPDATING);
- return put(`/programs/${data.id}`, data.payload)
+ return put(`/programs/${data.id}`, { data: { attributes: data.payload } })
.then((response) => {
if (!response) { throw 'ERROR (ducks/programs/updateProgram): No response'; }
if (response.ok) {
diff --git a/src/lib/edu-api.js b/src/lib/edu-api.js
index 32b14630..c4318e0c 100644
--- a/src/lib/edu-api.js
+++ b/src/lib/edu-api.js
@@ -29,7 +29,7 @@ export function put(endpoint, data) {
return superagent.put(`${config.root}${endpoint}`)
.set('Content-Type', 'application/json')
.set('Authorization', apiClient.headers.Authorization)
- .send({ data: { attributes: data } })
+ .send(data)
.then(response => response);
}
diff --git a/src/modules/wildcam-classrooms/components/AssignmentForm.jsx b/src/modules/wildcam-classrooms/components/AssignmentForm.jsx
index 8c00facd..57c4ff1e 100644
--- a/src/modules/wildcam-classrooms/components/AssignmentForm.jsx
+++ b/src/modules/wildcam-classrooms/components/AssignmentForm.jsx
@@ -31,6 +31,7 @@ import Label from 'grommet/components/Label';
import List from 'grommet/components/List';
import ListItem from 'grommet/components/ListItem';
import TextInput from 'grommet/components/TextInput';
+import NumberInput from 'grommet/components/NumberInput';
import LinkPreviousIcon from 'grommet/components/icons/base/LinkPrevious';
import LinkNextIcon from 'grommet/components/icons/base/LinkNext';
@@ -76,7 +77,12 @@ const TEXT = {
},
ASSIGNMENT_FORM: {
NAME: 'Assignment name',
- DESCRIPTION: 'Instructions for Students',
+ DESCRIPTION: 'Instructions for students',
+ CLASSIFICATIONS_TARGET: 'Number of subjects each student needs to classify',
+ DUEDATE: 'Due date',
+ },
+ ASSIGNMENT_FORM_PLACEHOLDERS: {
+ DUEDATE: 'e.g. 2020-12-31',
},
ERROR: {
GENERAL: 'Something went wrong',
@@ -91,6 +97,8 @@ const TEXT = {
const INITIAL_FORM_DATA = {
name: '',
description: '',
+ classifications_target: '',
+ duedate: '',
};
/*
@@ -103,6 +111,7 @@ class AssignmentForm extends React.Component {
this.state = {
view: VIEWS.CREATE_NEW,
form: INITIAL_FORM_DATA, //Contains basic Assignment data: name, description, etc.
+ formInitialised: false, //Has initialiseForm() already been run?
filters: {},
subjects: [],
students: [],
@@ -127,7 +136,6 @@ class AssignmentForm extends React.Component {
.../classrooms/123/assignments/456 - edit assignment 456 (i.e. assignment_id=456 supplied.)
*/
initialise(props = this.props) {
- console.log('+++ initialise: ');
const state = this.state;
const classroom_id = (props.match && props.match.params)
@@ -145,6 +153,7 @@ class AssignmentForm extends React.Component {
//Data store update + Redundancy Check (prevent infinite loop, only trigger once)
if (props.selectedClassroom !== selectedClassroom) {
+ //this.setState({ formInitialised: false });
Actions.wildcamClassrooms.setSelectedClassroom(selectedClassroom);
}
@@ -155,24 +164,13 @@ class AssignmentForm extends React.Component {
} else {
this.initialise_partTwo(props, classroom_id, assignment_id, props.assignmentsList);
}
-
- //Check the connection to WildCam Maps: if the user recently selected
- //Subjects for the Assignment, respect it.
- console.log('+++ props.wccwcmSelectedSubjects: ', props.wccwcmSelectedSubjects);
- if (props.wccwcmSelectedSubjects) {
- this.setState({
- subjects: props.wccwcmSelectedSubjects,
- filters: props.wccwcmSelectedFilters,
- });
- Actions.wildcamMap.resetWccWcmAssignmentData();
- }
}
initialise_partTwo(props, classroom_id, assignment_id, assignmentsList) {
//Create a new assignment
if (!assignment_id) { //Note: there should never be assignment_id === 0 or ''
this.setState({ view: VIEWS.CREATE_NEW });
- this.initialiseForm(null);
+ this.initialiseForm(props, null);
//Edit an existing assignment... if we can find it.
} else {
@@ -188,7 +186,6 @@ class AssignmentForm extends React.Component {
//Also extract initial subjects and filters used by the Assignment
if (!this.state.subjects || this.state.subjects.length === 0) {
- console.log('+++ selectedAssignment: ', selectedAssignment);
const newSubjects = (selectedAssignment.metadata && selectedAssignment.metadata.subjects)
? selectedAssignment.metadata.subjects.map((subject) => {
return {
@@ -208,7 +205,7 @@ class AssignmentForm extends React.Component {
//View update
this.setState({ view: VIEWS.EDIT_EXISTING });
- this.initialiseForm(selectedAssignment);
+ this.initialiseForm(props, selectedAssignment);
//Otherwise, uh oh.
} else {
@@ -223,28 +220,65 @@ class AssignmentForm extends React.Component {
/* Initialises the classroom form.
*/
- initialiseForm(selectedAssignment) {
+ initialiseForm(props, selectedAssignment) {
+ //Only run this once per page load, thank you.
+ if (this.state.formInitialised) return;
+ this.setState({ formInitialised: true });
+
if (!selectedAssignment) {
this.setState({ form: INITIAL_FORM_DATA });
} else {
const originalForm = INITIAL_FORM_DATA;
const updatedForm = {};
Object.keys(originalForm).map((key) => {
- updatedForm[key] = (selectedAssignment && selectedAssignment[key])
- ? selectedAssignment[key]
- : originalForm[key];
+ //The structure for Assignments is weird.
+ if (selectedAssignment && selectedAssignment.metadata && selectedAssignment.metadata[key]) {
+ updatedForm[key] = selectedAssignment.metadata[key];
+ } else if (selectedAssignment && selectedAssignment.attributes && selectedAssignment.attributes[key]) {
+ updatedForm[key] = selectedAssignment.attributes[key];
+ } else {
+ updatedForm[key] = originalForm[key];
+ }
});
this.setState({ form: updatedForm });
}
+
+ //WildCam Map Selected Subjects:
+ //Check the connection to WildCam Maps to see if the user recently selected
+ //Subjects for the Assignment.
+ if (props.wccwcmSelectedSubjects && props.wccwcmSavedAssignmentState) {
+ this.setState({
+ subjects: props.wccwcmSelectedSubjects,
+ filters: props.wccwcmSelectedFilters,
+ form: {
+ ...this.state.form,
+ ...props.wccwcmSavedAssignmentState,
+ classifications_target: props.wccwcmSelectedSubjects.length,
+ }
+ });
+ Actions.wildcamMap.resetWccWcmAssignmentData();
+ }
}
// ----------------------------------------------------------------
updateForm(e) {
+ let val = e.target.value;
+
+ //Special case: classificatons_target
+ //The number of Classfications a Student needs to do cannot exceed the amount of Subjects selected.
+ if (e.target.id === 'classifications_target') {
+ let maxVal = (this.state.subjects) ? this.state.subjects.length : 0;
+ val = parseInt(val);
+ if (isNaN(val)) val = 0;
+ val = Math.min(maxVal, val);
+ val = Math.max(0, val);
+ }
+
this.setState({
form: {
...this.state.form,
- [e.target.id]: e.target.value
+ [e.target.id]: val,
}
});
@@ -305,7 +339,7 @@ class AssignmentForm extends React.Component {
assignmentData: state.form,
filters,
subjects,
- students: state.students,
+ students: state.students,
}).then(() => {
//Message
Actions.wildcamClassrooms.setToast({ message: TEXT.SUCCESS.ASSIGNMENT_EDITED, status: 'ok' });
@@ -428,6 +462,21 @@ class AssignmentForm extends React.Component {
+
+
+ {
+ //TODO: add (optional) Assignment link for students?
+ }
+
+ {(state.subjects && state.subjects.length > 0) && (
+
+ )}
+
{TEXT.HEADINGS.STUDENTS}
diff --git a/src/modules/wildcam-classrooms/components/SubjectsList.jsx b/src/modules/wildcam-classrooms/components/SubjectsList.jsx
index 2c1f407c..9942ab6a 100644
--- a/src/modules/wildcam-classrooms/components/SubjectsList.jsx
+++ b/src/modules/wildcam-classrooms/components/SubjectsList.jsx
@@ -105,7 +105,7 @@ class SubjectsList extends React.Component {
return (
{TEXT.HEADINGS.SUBJECTS}
@@ -124,8 +124,10 @@ class SubjectsList extends React.Component {
className="button"
label={TEXT.ACTIONS.SELECT_SUBJECTS}
onClick={() => {
- //Save the return path
+ //Save the return path, assignment state, and the initial filters to be used by the map.
Actions.wildcamMap.setWccWcmAssignmentPath(props.location.pathname);
+ Actions.wildcamMap.setWccWcmSavedAssignmentState(props.assignmentStateForSaving);
+ if (props.filters) Actions.wildcamMap.setFilters(props.filters);
//Transition to: WildCam Map
props.history.push(props.wccwcmMapPath);
@@ -152,7 +154,17 @@ class SubjectsList extends React.Component {
return Object.keys(props.filters).map((key, index) => {
const val = props.filters[key];
return (
- {key} : {val}
+ {key} : {(()=>{
+ if (Array.isArray(val, index)) {
+ let output = '';
+ val.map((v) => {
+ output += ((output !== '') ? ', ' : '' ) + v;
+ });
+ return output;
+ } else {
+ return val;
+ }
+ })()}
);
});
})()}
@@ -198,6 +210,7 @@ class SubjectsList extends React.Component {
SubjectsList.defaultProps = {
filters: null,
subjects: [],
+ assignmentStateForSaving: null,
// ----------------
...WILDCAMCLASSROOMS_INITIAL_STATE,
...WILDCAMMAP_INITIAL_STATE,
@@ -206,6 +219,7 @@ SubjectsList.defaultProps = {
SubjectsList.propTypes = {
filters: PropTypes.object,
subjects: PropTypes.array,
+ assignmentStateForSaving: PropTypes.object,
// ----------------
...WILDCAMCLASSROOMS_PROPTYPES,
...WILDCAMMAP_PROPTYPES,
diff --git a/src/modules/wildcam-classrooms/containers/WildCamClassrooms.jsx b/src/modules/wildcam-classrooms/containers/WildCamClassrooms.jsx
index 3738bf28..151a1583 100644
--- a/src/modules/wildcam-classrooms/containers/WildCamClassrooms.jsx
+++ b/src/modules/wildcam-classrooms/containers/WildCamClassrooms.jsx
@@ -106,16 +106,6 @@ class WildCamClassroom extends React.Component {
/>
-
-
- Debug Panel
-
- Classrooms Status: [{props.classroomsStatus}]
- Classrooms Count: [{props.classroomsList && props.classroomsList.length}]
- Assignments Status: [{props.assignmentsStatus}]
- Assignments Count: [{props.assignmentsList && props.assignmentsList.length}]
-
-
);
diff --git a/src/modules/wildcam-classrooms/ducks/index.js b/src/modules/wildcam-classrooms/ducks/index.js
index ac96d45c..c0014d21 100644
--- a/src/modules/wildcam-classrooms/ducks/index.js
+++ b/src/modules/wildcam-classrooms/ducks/index.js
@@ -357,7 +357,7 @@ Effect('wcc_teachers_editClassroom', ({ selectedClassroom, classroomData }) => {
Actions.wildcamClassrooms.setClassroomsStatus(WILDCAMCLASSROOMS_DATA_STATUS.SENDING);
- return put(`/teachers/classrooms/${selectedClassroom.id}`, classroomData) //NOTE: the put() function requires a different argument format than post().
+ return put(`/teachers/classrooms/${selectedClassroom.id}`, { data: { attributes: classroomData } })
.then((response) => {
if (!response) { throw 'ERROR (ducks/wildcam-classrooms/ducks/wcc_teachers_editClassrooms): No response'; }
if (response.ok) {
@@ -676,7 +676,7 @@ Effect('wcc_editAssignment', ({ selectedAssignment, assignmentData, students = [
}
};
- return put(`/assignments/${selectedAssignment.id}`, assignmentData) //NOTE: the put() function requires a different argument format than post().
+ return put(`/assignments/${selectedAssignment.id}`, requestBody)
.then((response) => {
if (!response) { throw 'ERROR (ducks/wildcam-classrooms/ducks/wcc_teachers_editClassrooms): No response'; }
if (response.ok) {
diff --git a/src/modules/wildcam-map/containers/MapControls.jsx b/src/modules/wildcam-map/containers/MapControls.jsx
index 2ea0802a..42350f8d 100644
--- a/src/modules/wildcam-map/containers/MapControls.jsx
+++ b/src/modules/wildcam-map/containers/MapControls.jsx
@@ -74,7 +74,10 @@ class MapControls extends React.Component {
return (
-
+
diff --git a/src/modules/wildcam-map/ducks/index.js b/src/modules/wildcam-map/ducks/index.js
index 5c93cba4..a381298b 100644
--- a/src/modules/wildcam-map/ducks/index.js
+++ b/src/modules/wildcam-map/ducks/index.js
@@ -70,6 +70,7 @@ const WILDCAMMAP_INITIAL_STATE = {
//Connection between WildCam Classroom and WildCam Map
wccwcmMapPath: '', //The URL/path that the Teacher is taken to when they click on "Select subject" in the WildCam Classroom - Create Assignment stage. Must be registered early on in the Program.
wccwcmAssignmentPath: '', //The URL/path that the Teacher is returned to when they finally finish selecting subjects on the WildCam Map.
+ wccwcmSavedAssignmentState: null,
wccwcmSelectedSubjects: null,
wccwcmSelectedFilters: null,
};
@@ -105,6 +106,7 @@ const WILDCAMMAP_PROPTYPES = {
wccwcmMapPath: PropTypes.string,
wccwcmAssignmentPath: PropTypes.string,
+ wccwcmSavedAssignmentState: PropTypes.object,
wccwcmSelectedSubjects: PropTypes.array,
wccwcmSelectedFilters: PropTypes.object,
};
@@ -183,6 +185,10 @@ const setActiveCameraDataStatus = (state, activeCameraDataStatus) => {
return { ...state, activeCameraDataStatus };
};
+const setFilters = (state, filters) => {
+ return { ...state, filters };
+};
+
/* Adds to a multi-choice filter selection.
*/
const addFilterSelectionItem = (state, item) => {
@@ -229,6 +235,7 @@ const resetWccWcmAssignmentData = (state) => {
...state,
//Maintain the Map Path, however
wccwcmAssignmentPath: WILDCAMMAP_INITIAL_STATE.wccwcmAssignmentPath,
+ wccwcmSavedAssignmentState: WILDCAMMAP_INITIAL_STATE.wccwcmSavedAssignmentState,
wccwcmSelectedSubjects: WILDCAMMAP_INITIAL_STATE.wccwcmSelectedSubjects,
wccwcmSelectedFilters: WILDCAMMAP_INITIAL_STATE.wccwcmSelectedFilters,
}
@@ -239,6 +246,9 @@ const setWccWcmMapPath = (state, wccwcmMapPath) => {
const setWccWcmAssignmentPath = (state, wccwcmAssignmentPath) => {
return { ...state, wccwcmAssignmentPath };
}
+const setWccWcmSavedAssignmentState = (state, wccwcmSavedAssignmentState) => {
+ return { ...state, wccwcmSavedAssignmentState };
+}
const setWccWcmSelectedSubjects = (state, wccwcmSelectedSubjects) => {
return { ...state, wccwcmSelectedSubjects };
}
@@ -386,12 +396,14 @@ const wildcamMap = State('wildcamMap', {
setActiveCameraMetadataStatus,
setActiveCameraData,
setActiveCameraDataStatus,
+ setFilters,
addFilterSelectionItem,
removeFilterSelectionItem,
setFilterSelectionItem,
resetWccWcmAssignmentData,
setWccWcmMapPath,
setWccWcmAssignmentPath,
+ setWccWcmSavedAssignmentState,
setWccWcmSelectedSubjects,
setWccWcmSelectedFilters,
});
diff --git a/src/programs/darien/DarienProgram.jsx b/src/programs/darien/DarienProgram.jsx
index f433a0c1..07c01f37 100644
--- a/src/programs/darien/DarienProgram.jsx
+++ b/src/programs/darien/DarienProgram.jsx
@@ -22,35 +22,44 @@ import Status401 from '../../components/common/Status401';
import Status404 from '../../components/common/Status404';
import GenericStatusPage from '../../components/common/GenericStatusPage';
-function DarienProgram(props) {
- if (!props.initialised) { //User status unknown: wait.
- return ();
- } else if (!props.selectedProgram) { //Anomaly: program status not set.
- //Users should _not_ see this, but might due to weird lifecycle/timing issues.
- return ();
- } else {
-
+class DarienProgram extends React.Component {
+ constructor() {
+ super();
+ }
+
+ componentWillReceiveProps(props = this.props) {
//Register the connection between the WildCam Classrooms and the WildCam Maps.
Actions.wildcamMap.setWccWcmMapPath(`${props.match.url}/map`);
+ }
- if (props.user) { //User logged in: give access to all locations.
- return (
-
-
-
-
-
-
- );
- } else { //User not logged in: give limited access.
- return (
-
-
-
-
-
-
- );
+ render() {
+ const props = this.props;
+
+ if (!props.initialised) { //User status unknown: wait.
+ return ();
+ } else if (!props.selectedProgram) { //Anomaly: program status not set.
+ //Users should _not_ see this, but might due to weird lifecycle/timing issues.
+ return ();
+ } else {
+ if (props.user) { //User logged in: give access to all locations.
+ return (
+
+
+
+
+
+
+ );
+ } else { //User not logged in: give limited access.
+ return (
+
+
+
+
+
+
+ );
+ }
}
}
}
diff --git a/src/styles/components/wildcam-map.styl b/src/styles/components/wildcam-map.styl
index a498960c..47f5e53e 100644
--- a/src/styles/components/wildcam-map.styl
+++ b/src/styles/components/wildcam-map.styl
@@ -40,6 +40,9 @@
&.selected
background: TEAL_LIGHT
+ .wccwcm-connector
+ border: 1px solid GREY_5
+
.zooniversal-translator
.selected
background: TEAL_LIGHT