Skip to content

Commit 2affd69

Browse files
committed
feat: add spaces, actions, resources to table, add functionalities
1 parent c79e909 commit 2affd69

14 files changed

+654
-146
lines changed

public/app/listeners/editClassroom.js

+29-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
const { EDIT_CLASSROOM_CHANNEL } = require('../config/channels');
22
const { ERROR_GENERAL } = require('../config/errors');
3-
const { CLASSROOMS_COLLECTION } = require('../db');
3+
const {
4+
CLASSROOMS_COLLECTION,
5+
SPACES_COLLECTION,
6+
ACTIONS_COLLECTION,
7+
APP_INSTANCE_RESOURCES_COLLECTION,
8+
} = require('../db');
49
const logger = require('../logger');
510

6-
const editClassroom = (mainWindow, db) => async (event, { name, id }) => {
11+
const editClassroom = (mainWindow, db) => async (
12+
event,
13+
{ name, id, deleteSelection }
14+
) => {
715
logger.debug('editing classroom');
816

917
try {
@@ -15,9 +23,27 @@ const editClassroom = (mainWindow, db) => async (event, { name, id }) => {
1523
mainWindow.webContents.send(EDIT_CLASSROOM_CHANNEL, ERROR_GENERAL);
1624
}
1725

26+
// delete selected space and their resources
27+
Object.entries(deleteSelection).forEach(([spaceId, selected]) => {
28+
if (selected) {
29+
classroom
30+
.get(SPACES_COLLECTION)
31+
.remove({ id: spaceId })
32+
.write();
33+
classroom
34+
.get(ACTIONS_COLLECTION)
35+
.remove({ spaceId })
36+
.write();
37+
classroom
38+
.get(APP_INSTANCE_RESOURCES_COLLECTION)
39+
.remove({ spaceId })
40+
.write();
41+
}
42+
});
43+
1844
// update data
1945
const now = new Date();
20-
classroom.assign({ name, updatedAt: now }).write();
46+
classroom.assign({ name, lastUpdatedAt: now }).write();
2147

2248
mainWindow.webContents.send(EDIT_CLASSROOM_CHANNEL);
2349
} catch (err) {

public/app/listeners/editUserInClassroom.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
const { EDIT_USER_IN_CLASSROOM_CHANNEL } = require('../config/channels');
22
const { ERROR_GENERAL } = require('../config/errors');
3-
const { CLASSROOMS_COLLECTION, USERS_COLLECTION } = require('../db');
3+
const {
4+
CLASSROOMS_COLLECTION,
5+
USERS_COLLECTION,
6+
ACTIONS_COLLECTION,
7+
APP_INSTANCE_RESOURCES_COLLECTION,
8+
} = require('../db');
49
const logger = require('../logger');
510

11+
// @param deleteSelection : map key-value with space id as key to whether the space data should be deleted
612
const editUserInClassroom = (mainWindow, db) => async (
713
event,
8-
{ username, userId, classroomId }
14+
{ username, userId, classroomId, deleteSelection }
915
) => {
1016
logger.debug('editing user in classroom');
1117

1218
try {
13-
const user = db
14-
.get(CLASSROOMS_COLLECTION)
15-
.find({ id: classroomId })
16-
.get(USERS_COLLECTION)
17-
.find({ id: userId });
19+
const classroom = db.get(CLASSROOMS_COLLECTION).find({ id: classroomId });
20+
21+
const user = classroom.get(USERS_COLLECTION).find({ id: userId });
1822

1923
// check user exists
2024
const found = user.value();
@@ -25,6 +29,16 @@ const editUserInClassroom = (mainWindow, db) => async (
2529
);
2630
}
2731

32+
// delete space data related to user if selected
33+
const actions = classroom.get(ACTIONS_COLLECTION);
34+
const resources = classroom.get(APP_INSTANCE_RESOURCES_COLLECTION);
35+
Object.entries(deleteSelection).forEach(([spaceId, selected]) => {
36+
if (selected) {
37+
actions.remove({ spaceId, user: userId }).write();
38+
resources.remove({ spaceId, user: userId }).write();
39+
}
40+
});
41+
2842
// update data
2943
const now = new Date();
3044
user.assign({ username, lastUpdatedAt: now }).write();

src/actions/classroom.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ import {
2525
import {
2626
ERROR_GENERAL,
2727
ERROR_DUPLICATE_CLASSROOM_NAME,
28-
ERROR_LOADING_MESSAGE,
2928
ERROR_INVALID_USERNAME,
3029
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
3130
ERROR_NO_USER_TO_DELETE,
31+
ERROR_ACCESS_DENIED_CLASSROOM,
3232
} from '../config/errors';
3333
import {
3434
ADD_CLASSROOM_CHANNEL,
@@ -67,6 +67,8 @@ import {
6767
ERROR_GETTING_SPACE_IN_CLASSROOM_MESSAGE,
6868
ERROR_INVALID_USERNAME_MESSAGE,
6969
SUCCESS_SPACE_LOADED_MESSAGE,
70+
ERROR_LOADING_MESSAGE,
71+
ERROR_ACCESS_DENIED_CLASSROOM_MESSAGE,
7072
} from '../config/messages';
7173
import { createFlag } from './common';
7274
import { createExtractFile, createClearLoadSpace } from './loadSpace';
@@ -110,6 +112,12 @@ export const getClassroom = async payload => async dispatch => {
110112
}
111113

112114
switch (response) {
115+
case ERROR_ACCESS_DENIED_CLASSROOM:
116+
toastr.error(
117+
ERROR_MESSAGE_HEADER,
118+
ERROR_ACCESS_DENIED_CLASSROOM_MESSAGE
119+
);
120+
break;
113121
case ERROR_GENERAL:
114122
toastr.error(ERROR_MESSAGE_HEADER, ERROR_GETTING_CLASSROOM_MESSAGE);
115123
break;

src/components/classrooms/AddClassroomButton.js

+20-16
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@ import { connect } from 'react-redux';
66
import PropTypes from 'prop-types';
77
import Button from '@material-ui/core/Button';
88
import { withTranslation } from 'react-i18next';
9-
import TextField from '@material-ui/core/TextField';
109
import Dialog from '@material-ui/core/Dialog';
1110
import DialogActions from '@material-ui/core/DialogActions';
1211
import DialogContent from '@material-ui/core/DialogContent';
1312
import DialogTitle from '@material-ui/core/DialogTitle';
1413
import { addClassroom } from '../../actions';
1514
import {
1615
ADD_CLASSROOM_BUTTON_ID,
17-
ADD_CLASSROOM_NAME_INPUT_ID,
1816
ADD_CLASSROOM_VALIDATE_BUTTON_ID,
1917
ADD_CLASSROOM_CANCEL_BUTTON_ID,
2018
} from '../../config/selectors';
19+
import ClassroomNameTextField from './ClassroomNameTextField';
2120

2221
const styles = theme => ({
2322
fab: {
@@ -41,18 +40,25 @@ class AddClassroomButton extends Component {
4140

4241
state = (() => {
4342
const { t } = this.props;
43+
const defaultName = t('New Classroom');
4444
return {
4545
open: false,
46-
name: t('New Classroom'),
46+
name: defaultName,
4747
};
4848
})();
4949

50+
isClassroomNameValid = () => {
51+
const { name } = this.state;
52+
// todo: check for special characters
53+
return name.trim().length;
54+
};
55+
5056
handleClickOpen = () => {
5157
this.setState({ open: true });
5258
};
5359

5460
close = () => {
55-
this.setState({ name: '', open: false });
61+
this.setState({ open: false });
5662
};
5763

5864
handleCancel = () => {
@@ -62,11 +68,14 @@ class AddClassroomButton extends Component {
6268
handleValidate = () => {
6369
const { name } = this.state;
6470
const { userId, dispatchAddClassroom } = this.props;
65-
dispatchAddClassroom({ name, userId });
66-
this.close();
71+
if (this.isClassroomNameValid()) {
72+
const trimmedName = name.trim();
73+
dispatchAddClassroom({ name: trimmedName, userId });
74+
this.close();
75+
}
6776
};
6877

69-
handleChange = event => {
78+
handleNameChange = event => {
7079
const { target } = event;
7180
this.setState({ name: target.value });
7281
};
@@ -96,15 +105,9 @@ class AddClassroomButton extends Component {
96105
{t('Enter a name for your new classroom')}
97106
</DialogTitle>
98107
<DialogContent>
99-
<TextField
100-
id={ADD_CLASSROOM_NAME_INPUT_ID}
101-
autoFocus
102-
margin="dense"
103-
label={t("Classroom's Name")}
104-
type="text"
105-
fullWidth
106-
value={name}
107-
onChange={this.handleChange}
108+
<ClassroomNameTextField
109+
name={name}
110+
handleChange={this.handleNameChange}
108111
/>
109112
</DialogContent>
110113
<DialogActions>
@@ -119,6 +122,7 @@ class AddClassroomButton extends Component {
119122
onClick={this.handleValidate}
120123
color="primary"
121124
id={ADD_CLASSROOM_VALIDATE_BUTTON_ID}
125+
disabled={!this.isClassroomNameValid()}
122126
>
123127
{t('Validate')}
124128
</Button>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { withTranslation } from 'react-i18next';
4+
import TextField from '@material-ui/core/TextField';
5+
import { CLASSROOM_NAME_INPUT_ID } from '../../config/selectors';
6+
import { isClassroomNameValid } from '../../utils/classroom';
7+
8+
const ClassroomNameTextField = ({ name, t, handleChange }) => {
9+
const isValid = isClassroomNameValid(name);
10+
let errorProps = {};
11+
if (!isValid) {
12+
errorProps = {
13+
...errorProps,
14+
helperText: t(`Classroom's name is not valid`),
15+
error: true,
16+
};
17+
}
18+
19+
return (
20+
<TextField
21+
id={CLASSROOM_NAME_INPUT_ID}
22+
autoFocus
23+
margin="dense"
24+
label={t("Classroom's Name")}
25+
type="text"
26+
fullWidth
27+
value={name}
28+
onChange={handleChange}
29+
// eslint-disable-next-line react/jsx-props-no-spreading
30+
{...errorProps}
31+
/>
32+
);
33+
};
34+
35+
ClassroomNameTextField.propTypes = {
36+
name: PropTypes.string.isRequired,
37+
handleChange: PropTypes.func.isRequired,
38+
t: PropTypes.func.isRequired,
39+
};
40+
41+
const TranslatedComponent = withTranslation()(ClassroomNameTextField);
42+
43+
export default TranslatedComponent;

src/components/classrooms/ClassroomScreen.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
33
import { withStyles } from '@material-ui/core';
44
import { withTranslation } from 'react-i18next';
55
import { withRouter } from 'react-router';
6-
import { Map } from 'immutable';
6+
import { Map, List } from 'immutable';
77
import PropTypes from 'prop-types';
88
import Button from '@material-ui/core/Button';
99
import Toolbar from '@material-ui/core/Toolbar';
@@ -45,6 +45,7 @@ class ClassroomScreen extends Component {
4545
goBack: PropTypes.func.isRequired,
4646
}).isRequired,
4747
userId: PropTypes.string.isRequired,
48+
classrooms: PropTypes.instanceOf(List).isRequired,
4849
};
4950

5051
static defaultProps = {
@@ -62,6 +63,22 @@ class ClassroomScreen extends Component {
6263
dispatchGetClassroom({ id, userId });
6364
}
6465

66+
componentDidUpdate({ classrooms: prevClassrooms }) {
67+
const {
68+
dispatchGetClassroom,
69+
classrooms,
70+
match: {
71+
params: { id },
72+
},
73+
userId,
74+
} = this.props;
75+
76+
// update current classroom if classrooms change
77+
if (!prevClassrooms.equals(classrooms)) {
78+
dispatchGetClassroom({ id, userId });
79+
}
80+
}
81+
6582
renderBackButton = () => {
6683
const {
6784
t,
@@ -117,6 +134,7 @@ class ClassroomScreen extends Component {
117134
}
118135

119136
const mapStateToProps = ({ classroom, authentication }) => ({
137+
classrooms: classroom.getIn(['classrooms']),
120138
classroom: classroom.getIn(['current', 'classroom']),
121139
activity: Boolean(classroom.get('activity').size),
122140
userId: authentication.getIn(['user', 'id']),

0 commit comments

Comments
 (0)