Skip to content

Commit 30bfa7d

Browse files
committed
feat: load user data in classroom
1 parent 9d5cc83 commit 30bfa7d

35 files changed

+1192
-303
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"react-redux-toastr": "7.6.4",
121121
"react-router": "5.1.2",
122122
"react-router-dom": "5.1.2",
123+
"react-select": "3.1.0",
123124
"react-split-pane": "0.1.89",
124125
"recharts": "1.8.5",
125126
"redux": "4.0.5",

public/app/config/channels.js

+2
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,6 @@ module.exports = {
6767
'prompt:classroom:user:delete:respond',
6868
EDIT_USER_IN_CLASSROOM_CHANNEL: 'classroom:user:edit',
6969
GET_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:get',
70+
LOAD_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:load',
71+
GET_SPACE_TO_LOAD_IN_CLASSROOM_CHANNEL: 'classroom:space:load:get-space',
7072
};

public/app/config/errors.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ERROR_ACCESS_DENIED_CLASSROOM = 'ERROR_ACCESS_DENIED_CLASSROOM';
1111
const ERROR_DUPLICATE_USERNAME_IN_CLASSROOM =
1212
'ERROR_DUPLICATE_USERNAME_IN_CLASSROOM';
1313
const ERROR_NO_USER_TO_DELETE = 'ERROR_NO_USER_TO_DELETE';
14+
const ERROR_INVALID_USERNAME = 'ERROR_INVALID_USERNAME';
1415

1516
module.exports = {
1617
ERROR_ZIP_CORRUPTED,
@@ -22,4 +23,5 @@ module.exports = {
2223
ERROR_ACCESS_DENIED_CLASSROOM,
2324
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
2425
ERROR_NO_USER_TO_DELETE,
26+
ERROR_INVALID_USERNAME,
2527
};

public/app/config/messages.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ module.exports = {
164164
ERROR_EDITING_USER_IN_CLASSROOM_MESSAGE,
165165
SUCCESS_DELETING_USERS_IN_CLASSROOM_MESSAGE,
166166
SUCCESS_EDITING_USER_IN_CLASSROOM_MESSAGE,
167-
ERROR_INVALID_USERNAME_MESSAGE,
168167
ERROR_NO_USER_TO_DELETE_MESSAGE,
169168
ERROR_GETTING_SPACE_IN_CLASSROOM_MESSAGE,
169+
ERROR_INVALID_USERNAME_MESSAGE,
170170
};

public/app/listeners/addClassroom.js

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const {
1313
USERS_COLLECTION,
1414
} = require('../db');
1515
const logger = require('../logger');
16+
const { createClassroomDirectory } = require('../utilities');
1617

1718
const DEFAULT_CLASSROOM = {
1819
[SPACES_COLLECTION]: [],
@@ -39,6 +40,10 @@ const addClassroom = (mainWindow, db) => async (event, { name, userId }) => {
3940

4041
// create new classroom
4142
const id = ObjectId().str;
43+
44+
// create directory where resources will be stored
45+
createClassroomDirectory({ id });
46+
4247
const now = new Date();
4348
const newClassroom = {
4449
..._.cloneDeep(DEFAULT_CLASSROOM),

public/app/listeners/addUserInClassroom.js

+46-25
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,67 @@ const { ADD_USER_IN_CLASSROOM_CHANNEL } = require('../config/channels');
33
const { createNewUser } = require('./signIn');
44
const {
55
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
6+
ERROR_INVALID_USERNAME,
67
ERROR_GENERAL,
78
} = require('../config/errors');
89

910
const logger = require('../logger');
1011

12+
const addUserInClassroomDatabase = (db, { username, id }) => {
13+
// check username validity
14+
if (!username || !username.length) {
15+
throw new Error(ERROR_INVALID_USERNAME);
16+
}
17+
18+
const users = db
19+
.get(CLASSROOMS_COLLECTION)
20+
.find({ id })
21+
.get(USERS_COLLECTION);
22+
23+
const now = new Date();
24+
25+
// check in db if username exists
26+
const found = users.find({ username }).value();
27+
28+
if (found) {
29+
throw new Error(ERROR_DUPLICATE_USERNAME_IN_CLASSROOM);
30+
}
31+
32+
const user = createNewUser(username, now);
33+
users.push(user).write();
34+
return user;
35+
};
36+
1137
const addUserInClassroom = (mainWindow, db) => async (
1238
event,
1339
{ username, classroomId: id }
1440
) => {
1541
logger.debug('adding a user in a classroom');
1642

1743
try {
18-
const users = db
19-
.get(CLASSROOMS_COLLECTION)
20-
.find({ id })
21-
.get(USERS_COLLECTION);
22-
23-
const now = new Date();
24-
25-
// check in db if username exists
26-
const found = users.find({ username }).value();
27-
28-
if (found) {
29-
return mainWindow.webContents.send(
30-
ADD_USER_IN_CLASSROOM_CHANNEL,
31-
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM
32-
);
33-
}
34-
35-
const user = createNewUser(username, now);
36-
users.push(user).write();
44+
const user = addUserInClassroomDatabase(db, { username, id });
3745

3846
return mainWindow.webContents.send(ADD_USER_IN_CLASSROOM_CHANNEL, user);
3947
} catch (err) {
40-
logger.error(err);
41-
return mainWindow.webContents.send(
42-
ADD_USER_IN_CLASSROOM_CHANNEL,
43-
ERROR_GENERAL
44-
);
48+
switch (err) {
49+
case ERROR_DUPLICATE_USERNAME_IN_CLASSROOM:
50+
return mainWindow.webContents.send(
51+
ADD_USER_IN_CLASSROOM_CHANNEL,
52+
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM
53+
);
54+
case ERROR_INVALID_USERNAME:
55+
return mainWindow.webContents.send(
56+
ADD_USER_IN_CLASSROOM_CHANNEL,
57+
ERROR_INVALID_USERNAME
58+
);
59+
default:
60+
logger.error(err);
61+
return mainWindow.webContents.send(
62+
ADD_USER_IN_CLASSROOM_CHANNEL,
63+
ERROR_GENERAL
64+
);
65+
}
4566
}
4667
};
4768

48-
module.exports = addUserInClassroom;
69+
module.exports = { addUserInClassroom, addUserInClassroomDatabase };

public/app/listeners/deleteClassroom.js

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const deleteClassroomAndResources = (db, id) => {
99
.write();
1010

1111
// todo: remove containing spaces
12+
13+
// todo: remove folder
1214
};
1315

1416
const deleteClassroom = (mainWindow, db) => async (event, { id }) => {

public/app/listeners/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ const editClassroom = require('./editClassroom');
4242
const showDeleteClassroomPrompt = require('./showDeleteClassroomPrompt');
4343
const showDeleteUsersInClassroomPrompt = require('./showDeleteUsersInClassroomPrompt');
4444
const getClassroom = require('./getClassroom');
45-
const addUserInClassroom = require('./addUserInClassroom');
45+
const { addUserInClassroom } = require('./addUserInClassroom');
4646
const deleteUsersInClassroom = require('./deleteUsersInClassroom');
4747
const editUserInClassroom = require('./editUserInClassroom');
4848
const getSpaceInClassroom = require('./getSpaceInClassroom');
49+
const loadSpaceInClassroom = require('./loadSpaceInClassroom');
4950

5051
module.exports = {
5152
loadSpace,
@@ -95,4 +96,5 @@ module.exports = {
9596
showDeleteUsersInClassroomPrompt,
9697
editUserInClassroom,
9798
getSpaceInClassroom,
99+
loadSpaceInClassroom,
98100
};

public/app/listeners/loadSpace.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ const loadSpace = (mainWindow, db) => async (
161161
db.get(SPACES_COLLECTION)
162162
.push(space)
163163
.write();
164+
} else {
165+
// clean temp space folder
166+
clean(extractPath);
164167
}
165168

166169
const userId = db.get('user.id').value();
@@ -214,4 +217,9 @@ const loadSpace = (mainWindow, db) => async (
214217
}
215218
};
216219

217-
module.exports = { clearLoadSpace, extractFileToLoadSpace, loadSpace };
220+
module.exports = {
221+
clearLoadSpace,
222+
extractFileToLoadSpace,
223+
loadSpace,
224+
renameSpaceFolder,
225+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
const _ = require('lodash');
2+
const { VAR_FOLDER } = require('../config/config');
3+
const { LOAD_SPACE_IN_CLASSROOM_CHANNEL } = require('../config/channels');
4+
const {
5+
ERROR_GENERAL,
6+
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
7+
ERROR_INVALID_USERNAME,
8+
} = require('../config/errors');
9+
const logger = require('../logger');
10+
const { isFileAvailable, clean } = require('../utilities');
11+
const {
12+
SPACES_COLLECTION,
13+
APP_INSTANCE_RESOURCES_COLLECTION,
14+
ACTIONS_COLLECTION,
15+
CLASSROOMS_COLLECTION,
16+
USERS_COLLECTION,
17+
} = require('../db');
18+
const { renameSpaceFolder } = require('./loadSpace');
19+
const { deleteSpaceAndResources } = require('./deleteSpace');
20+
const { addUserInClassroomDatabase } = require('./addUserInClassroom');
21+
22+
const loadSpaceInClassroom = (mainWindow, db) => async (
23+
event,
24+
{
25+
extractPath,
26+
classroomId,
27+
username,
28+
elements: { space, actions, appInstanceResources },
29+
selection: {
30+
space: isSpaceSelected,
31+
appInstanceResources: isResourcesSelected,
32+
actions: isActionsSelected,
33+
},
34+
}
35+
) => {
36+
logger.debug('loading a space in a classroom');
37+
38+
try {
39+
const classroom = db.get(CLASSROOMS_COLLECTION).find({ id: classroomId });
40+
41+
// add user if doesn't exist
42+
let user = classroom
43+
.get(USERS_COLLECTION)
44+
.find({ username })
45+
.value();
46+
if (!user) {
47+
user = addUserInClassroomDatabase(db, { username, id: classroomId });
48+
}
49+
50+
// todo: check teacher can write in classroom
51+
52+
// space should always be defined
53+
if (_.isEmpty(space)) {
54+
logger.debug('try to load undefined space');
55+
return mainWindow.webContents.send(
56+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
57+
ERROR_GENERAL
58+
);
59+
}
60+
61+
// write space to database if selected
62+
if (isSpaceSelected) {
63+
const { id } = space;
64+
const finalPath = `${VAR_FOLDER}/${classroomId}/${id}`;
65+
const tmpPath = `${VAR_FOLDER}/${classroomId}/.previousSpace-${id}`;
66+
67+
// temporary rename previous space if exists
68+
if (await isFileAvailable(finalPath)) {
69+
const wasRenamed = await renameSpaceFolder(finalPath, tmpPath);
70+
if (!wasRenamed) {
71+
logger.error('unable to rename previous space folder');
72+
clean(extractPath);
73+
return mainWindow.webContents.send(
74+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
75+
ERROR_GENERAL
76+
);
77+
}
78+
}
79+
80+
// we need to wrap this operation to avoid errors in windows
81+
const wasRenamed = await renameSpaceFolder(extractPath, finalPath);
82+
if (!wasRenamed) {
83+
logger.error('unable to rename previous temporary new space folder');
84+
clean(extractPath);
85+
return mainWindow.webContents.send(
86+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
87+
ERROR_GENERAL
88+
);
89+
}
90+
91+
// remove previous space
92+
deleteSpaceAndResources(db, id, tmpPath);
93+
94+
// add new space in database
95+
classroom
96+
.get(SPACES_COLLECTION)
97+
.push(space)
98+
.write();
99+
} else {
100+
// clean temp space folder
101+
clean(extractPath);
102+
}
103+
104+
const { id: userId } = user;
105+
106+
// write resources to database if selected
107+
if (isResourcesSelected) {
108+
if (_.isEmpty(appInstanceResources)) {
109+
logger.debug('try to load empty resources');
110+
return mainWindow.webContents.send(
111+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
112+
ERROR_GENERAL
113+
);
114+
}
115+
116+
const savedResources = classroom.get(APP_INSTANCE_RESOURCES_COLLECTION);
117+
118+
// todo: replace resources
119+
120+
const newResources = appInstanceResources
121+
// keep only non-duplicate resources
122+
.filter(({ id }) => !savedResources.find({ id }).value())
123+
// change user id with given user
124+
.map(action => ({ ...action, user: userId }));
125+
126+
savedResources.push(...newResources).write();
127+
}
128+
129+
// write actions to database if selected
130+
if (isActionsSelected) {
131+
if (_.isEmpty(actions)) {
132+
logger.debug('try to load empty actions');
133+
return mainWindow.webContents.send(
134+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
135+
ERROR_GENERAL
136+
);
137+
}
138+
139+
const savedActions = classroom.get(ACTIONS_COLLECTION);
140+
141+
// todo: replace actions
142+
143+
const newActions = actions
144+
// keep only non-duplicate actions
145+
.filter(({ id }) => !savedActions.find({ id }).value())
146+
// change user id with given user
147+
.map(action => ({ ...action, user: userId }));
148+
149+
savedActions.push(...newActions).write();
150+
}
151+
152+
return mainWindow.webContents.send(LOAD_SPACE_IN_CLASSROOM_CHANNEL, {
153+
spaceId: space.id,
154+
});
155+
} catch (err) {
156+
switch (err) {
157+
case ERROR_DUPLICATE_USERNAME_IN_CLASSROOM:
158+
return mainWindow.webContents.send(
159+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
160+
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM
161+
);
162+
case ERROR_INVALID_USERNAME:
163+
return mainWindow.webContents.send(
164+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
165+
ERROR_INVALID_USERNAME
166+
);
167+
default:
168+
logger.error(err);
169+
return mainWindow.webContents.send(
170+
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
171+
ERROR_GENERAL
172+
);
173+
}
174+
}
175+
};
176+
177+
module.exports = loadSpaceInClassroom;

0 commit comments

Comments
 (0)