Skip to content

Commit f69843a

Browse files
committed
fix: user access to classroom after edit, refactor, add selectors
1 parent 2affd69 commit f69843a

9 files changed

+83
-26
lines changed

src/actions/classroom.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ import {
2424
} from '../types';
2525
import {
2626
ERROR_GENERAL,
27+
ERROR_ACCESS_DENIED_CLASSROOM,
2728
ERROR_DUPLICATE_CLASSROOM_NAME,
2829
ERROR_INVALID_USERNAME,
2930
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
3031
ERROR_NO_USER_TO_DELETE,
31-
ERROR_ACCESS_DENIED_CLASSROOM,
3232
} from '../config/errors';
3333
import {
3434
ADD_CLASSROOM_CHANNEL,
@@ -90,10 +90,14 @@ export const getClassrooms = () => dispatch => {
9090
// create listener
9191
window.ipcRenderer.once(GET_CLASSROOMS_CHANNEL, (event, classrooms) => {
9292
// dispatch that the getter has succeeded
93-
dispatch({
94-
type: GET_CLASSROOMS_SUCCEEDED,
95-
payload: classrooms,
96-
});
93+
if (classrooms === ERROR_ACCESS_DENIED_CLASSROOM) {
94+
toastr.error(ERROR_MESSAGE_HEADER, ERROR_ACCESS_DENIED_CLASSROOM_MESSAGE);
95+
} else {
96+
dispatch({
97+
type: GET_CLASSROOMS_SUCCEEDED,
98+
payload: classrooms,
99+
});
100+
}
97101
dispatch(flagGettingClassrooms(false));
98102
});
99103
};
@@ -214,7 +218,8 @@ export const editClassroom = payload => dispatch => {
214218
if (response === ERROR_GENERAL) {
215219
toastr.error(ERROR_MESSAGE_HEADER, ERROR_EDITING_CLASSROOM_MESSAGE);
216220
} else {
217-
// update saved classrooms in state
221+
// update saved classrooms and current classroom in state
222+
dispatch(getClassroom(payload));
218223
dispatch(getClassrooms());
219224

220225
toastr.success(SUCCESS_MESSAGE_HEADER, SUCCESS_EDITING_CLASSROOM_MESSAGE);

src/components/classrooms/EditClassroomButton.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
EDIT_CLASSROOM_BUTTON_CLASS,
2222
EDIT_CLASSROOM_VALIDATE_BUTTON_ID,
2323
EDIT_CLASSROOM_CANCEL_BUTTON_ID,
24+
EDIT_CLASSROOM_DELETE_DATA_BUTTON_CLASS,
2425
} from '../../config/selectors';
2526
import ClassroomNameTextField from './ClassroomNameTextField';
2627
import { isClassroomNameValid } from '../../utils/classroom';
@@ -56,6 +57,7 @@ class EditClassroomButton extends Component {
5657
spaces: PropTypes.arrayOf({}).isRequired,
5758
}).isRequired,
5859
t: PropTypes.func.isRequired,
60+
userId: PropTypes.string.isRequired,
5961
};
6062

6163
state = (() => {
@@ -95,9 +97,10 @@ class EditClassroomButton extends Component {
9597
const {
9698
dispatchEditClassroom,
9799
classroom: { id },
100+
userId,
98101
} = this.props;
99102
if (isClassroomNameValid(name)) {
100-
dispatchEditClassroom({ name, id, deleteSelection });
103+
dispatchEditClassroom({ name, id, deleteSelection, userId });
101104
this.close();
102105
}
103106
};
@@ -142,6 +145,7 @@ class EditClassroomButton extends Component {
142145
) : (
143146
<Tooltip title={t(`Delete this space`)}>
144147
<IconButton
148+
className={EDIT_CLASSROOM_DELETE_DATA_BUTTON_CLASS}
145149
color="inherit"
146150
onClick={e => this.changeDeleteSelection(e, spaceId, true)}
147151
>
@@ -151,7 +155,7 @@ class EditClassroomButton extends Component {
151155
);
152156

153157
return (
154-
<>
158+
<Grid container data-space-id={spaceId} alignItems="center">
155159
<Grid item xs={2}>
156160
{button}
157161
</Grid>
@@ -166,7 +170,7 @@ class EditClassroomButton extends Component {
166170
>
167171
<Typography>{spaceName}</Typography>
168172
</Grid>
169-
</>
173+
</Grid>
170174
);
171175
})}
172176
</Grid>
@@ -231,12 +235,16 @@ class EditClassroomButton extends Component {
231235
}
232236
}
233237

238+
const mapStateToProps = ({ authentication }) => ({
239+
userId: authentication.getIn(['user', 'id']),
240+
});
241+
234242
const mapDispatchToProps = {
235243
dispatchEditClassroom: editClassroom,
236244
};
237245

238246
const ConnectedComponent = connect(
239-
null,
247+
mapStateToProps,
240248
mapDispatchToProps
241249
)(EditClassroomButton);
242250

src/components/classrooms/EditUserInClassroomButton.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
EDIT_USER_IN_CLASSROOM_BUTTON_CLASS,
2727
EDIT_USER_IN_CLASSROOM_VALIDATE_BUTTON_ID,
2828
EDIT_USER_IN_CLASSROOM_USERNAME_INPUT_ID,
29+
EDIT_USER_IN_CLASSROOM_DELETE_DATA_BUTTON_CLASS,
2930
} from '../../config/selectors';
3031
import {
3132
ERROR_MESSAGE_HEADER,
@@ -233,13 +234,17 @@ class EditUserInClassroomButton extends Component {
233234
color="inherit"
234235
onClick={e => this.changeDeleteSelection(e, spaceId, true)}
235236
>
236-
<DeleteIcon />
237+
<DeleteIcon
238+
className={
239+
EDIT_USER_IN_CLASSROOM_DELETE_DATA_BUTTON_CLASS
240+
}
241+
/>
237242
</IconButton>
238243
</Tooltip>
239244
);
240245

241246
return (
242-
<>
247+
<Grid container data-space-id={spaceId}>
243248
<Grid item xs={2} classes={{ root: classes.editSpaceRow }}>
244249
{button}
245250
</Grid>
@@ -256,7 +261,7 @@ class EditUserInClassroomButton extends Component {
256261
{hasResources && <ResourceIcon />}
257262
{hasActions && <ActionIcon />}
258263
</Grid>
259-
</>
264+
</Grid>
260265
);
261266
})}
262267
</Grid>

src/components/classrooms/ImportDataAssignUserForm.js

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { loadSpaceInClassroom, clearLoadSpaceInClassroom } from '../../actions';
1212
import StudentForm from './StudentForm';
1313
import LoadSpaceSelectors from '../space/load/LoadSpaceSelectors';
1414
import { isSpaceDifferent as isSpaceDifferentFunc } from '../../utils/syncSpace';
15+
import { IMPORT_DATA_CLASSROOM_VALIDATE_BUTTON_ID } from '../../config/selectors';
1516

1617
const styles = theme => ({
1718
...Styles(theme),
@@ -117,6 +118,7 @@ class ImportDataAssignUserForm extends Component {
117118

118119
return (
119120
<Button
121+
id={IMPORT_DATA_CLASSROOM_VALIDATE_BUTTON_ID}
120122
variant="contained"
121123
onClick={this.handleValidate}
122124
color="primary"

src/components/classrooms/StudentForm.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
22
import { connect } from 'react-redux';
33
import { withStyles } from '@material-ui/core';
44
import { withTranslation } from 'react-i18next';
5+
import clsx from 'clsx';
56
import { withRouter } from 'react-router';
67
import Typography from '@material-ui/core/Typography/Typography';
78
import PropTypes from 'prop-types';
@@ -10,6 +11,10 @@ import Toolbar from '@material-ui/core/Toolbar';
1011
import CssBaseline from '@material-ui/core/CssBaseline/CssBaseline';
1112
import AppBar from '@material-ui/core/AppBar/AppBar';
1213
import Loader from '../common/Loader';
14+
import {
15+
IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_PREFIX_CLASS,
16+
IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_CONTAINER_CLASS,
17+
} from '../../config/selectors';
1318

1419
const styles = theme => ({
1520
select: {
@@ -82,7 +87,11 @@ class StudentForm extends Component {
8287
{t('Assign data to student')}
8388
</Typography>
8489
<Creatable
85-
className={classes.select}
90+
className={clsx(
91+
classes.select,
92+
IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_CONTAINER_CLASS
93+
)}
94+
classNamePrefix={IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_PREFIX_CLASS}
8695
options={options}
8796
isClearable
8897
placeholder={t('Create new student...')}

src/components/classrooms/StudentsTable.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import {
3232
CLASSROOM_TABLE_BODY_ID,
3333
DELETE_USER_IN_CLASSROOM_BUTTON_CLASS,
3434
SELECT_USER_IN_CLASSROOM_CLASS,
35+
STUDENT_ROW_ACTIONS_CLASS,
36+
STUDENT_ROW_RESOURCES_CLASS,
3537
} from '../../config/selectors';
3638
import {
3739
getUserResourcesForSpaceInClassroom,
@@ -284,8 +286,12 @@ class StudentsTable extends Component {
284286
// display all other data depending on headcells
285287
.map(({ id }) => (
286288
<TableCell key={id}>
287-
{row[id].actions.length > 0 && <ActionIcon />}
288-
{row[id].resources.length > 0 && <ResourceIcon />}
289+
{row[id].actions.length > 0 && (
290+
<ActionIcon className={STUDENT_ROW_ACTIONS_CLASS} />
291+
)}
292+
{row[id].resources.length > 0 && (
293+
<ResourceIcon className={STUDENT_ROW_RESOURCES_CLASS} />
294+
)}
289295
</TableCell>
290296
))}
291297
{this.renderUserOperations(row)}

src/components/classrooms/TableHeader.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import TableSortLabel from '@material-ui/core/TableSortLabel';
88
import Checkbox from '@material-ui/core/Checkbox';
99
import PropTypes from 'prop-types';
1010
import { TABLE_ORDER } from '../../config/constants';
11+
import { buildTableCellSpaceId } from '../../config/selectors';
1112

1213
const styles = () => ({
1314
visuallyHidden: {
@@ -74,19 +75,20 @@ class TableHeader extends Component {
7475
inputProps={{ 'aria-label': t('Select all') }}
7576
/>
7677
</TableCell>
77-
{headCells.map(headCell => (
78+
{headCells.map(({ id, numeric, label }) => (
7879
<TableCell
79-
key={headCell.id}
80-
align={headCell.numeric ? 'right' : 'left'}
81-
sortDirection={orderBy === headCell.id ? order : false}
80+
id={buildTableCellSpaceId(id)}
81+
key={id}
82+
align={numeric ? 'right' : 'left'}
83+
sortDirection={orderBy === id ? order : false}
8284
>
8385
<TableSortLabel
84-
active={orderBy === headCell.id}
85-
direction={orderBy === headCell.id ? order : TABLE_ORDER.ASC}
86-
onClick={createSortHandler(headCell.id)}
86+
active={orderBy === id}
87+
direction={orderBy === id ? order : TABLE_ORDER.ASC}
88+
onClick={createSortHandler(id)}
8789
>
88-
{headCell.label}
89-
{orderBy === headCell.id ? (
90+
{label}
91+
{orderBy === id ? (
9092
<span className={classes.visuallyHidden}>
9193
{order === TABLE_ORDER.DESC
9294
? t('sorted descending')

src/config/selectors.js

+20
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,23 @@ export const CLASSROOM_CARD_NAME_CLASS = 'classroomCardName';
122122
export const SELECT_USER_IN_CLASSROOM_CLASS = 'selectUserInClassroom';
123123
export const DELETE_USERS_IN_CLASSROOM_BUTTON_ID =
124124
'deleteUsersInClassroomButton';
125+
export const IMPORT_DATA_IN_CLASSROOM_BUTTON_ID = 'importDataInClassroomButton';
126+
export const IMPORT_FILEPATH_IN_CLASSROOM_INPUT_ID =
127+
'importFilepathInClassroomInput';
128+
export const IMPORT_DATA_IN_CLASSROOM_SUBMIT_BUTTON_ID =
129+
'importDataInClassroomSubmitButton';
130+
export const IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_CONTAINER_CLASS =
131+
'importDataInClassroomStudentSelectContainer';
132+
export const IMPORT_DATA_IN_CLASSROOM_STUDENT_SELECT_PREFIX_CLASS =
133+
'importDataInClassroomStudentSelectPrefix';
134+
export const IMPORT_DATA_IN_CLASSROOM_BACK_BUTTON_ID =
135+
'importDataInClassroomBackButton';
136+
export const IMPORT_DATA_CLASSROOM_VALIDATE_BUTTON_ID =
137+
'importDataInClassroomValidateButton';
138+
export const STUDENT_ROW_RESOURCES_CLASS = 'studentRowResources';
139+
export const STUDENT_ROW_ACTIONS_CLASS = 'studentRowActions';
140+
export const EDIT_USER_IN_CLASSROOM_DELETE_DATA_BUTTON_CLASS =
141+
'editUserInClassroomDeleteDataButton';
142+
export const EDIT_CLASSROOM_DELETE_DATA_BUTTON_CLASS =
143+
'editClassroomDeleteDataButton';
144+
export const buildTableCellSpaceId = id => `tableCellSpace-${id}`;

test/classrooms.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ describe('Classrooms Scenarios', function() {
231231
// open and cancel modal
232232
await client.click(`#${ADD_CLASSROOM_BUTTON_ID}`);
233233
await client.pause(MODAL_OPEN_PAUSE);
234-
await client.setValue(`#${ADD_CLASSROOM_NAME_INPUT_ID}`, name);
234+
await client.setValue(`#${CLASSROOM_NAME_INPUT_ID}`, name);
235235
await client.pause(INPUT_TYPE_PAUSE);
236236
await client.click(`#${ADD_CLASSROOM_CANCEL_BUTTON_ID}`);
237237
await client.pause(MODAL_CLOSE_PAUSE);

0 commit comments

Comments
 (0)