Skip to content

Commit

Permalink
feat: add spaces, actions, resources to table, add functionalities
Browse files Browse the repository at this point in the history
  • Loading branch information
pyphilia committed Jun 3, 2020
1 parent c79e909 commit 2affd69
Show file tree
Hide file tree
Showing 14 changed files with 654 additions and 146 deletions.
32 changes: 29 additions & 3 deletions public/app/listeners/editClassroom.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
const { EDIT_CLASSROOM_CHANNEL } = require('../config/channels');
const { ERROR_GENERAL } = require('../config/errors');
const { CLASSROOMS_COLLECTION } = require('../db');
const {
CLASSROOMS_COLLECTION,
SPACES_COLLECTION,
ACTIONS_COLLECTION,
APP_INSTANCE_RESOURCES_COLLECTION,
} = require('../db');
const logger = require('../logger');

const editClassroom = (mainWindow, db) => async (event, { name, id }) => {
const editClassroom = (mainWindow, db) => async (
event,
{ name, id, deleteSelection }
) => {
logger.debug('editing classroom');

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

// delete selected space and their resources
Object.entries(deleteSelection).forEach(([spaceId, selected]) => {
if (selected) {
classroom
.get(SPACES_COLLECTION)
.remove({ id: spaceId })
.write();
classroom
.get(ACTIONS_COLLECTION)
.remove({ spaceId })
.write();
classroom
.get(APP_INSTANCE_RESOURCES_COLLECTION)
.remove({ spaceId })
.write();
}
});

// update data
const now = new Date();
classroom.assign({ name, updatedAt: now }).write();
classroom.assign({ name, lastUpdatedAt: now }).write();

mainWindow.webContents.send(EDIT_CLASSROOM_CHANNEL);
} catch (err) {
Expand Down
28 changes: 21 additions & 7 deletions public/app/listeners/editUserInClassroom.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
const { EDIT_USER_IN_CLASSROOM_CHANNEL } = require('../config/channels');
const { ERROR_GENERAL } = require('../config/errors');
const { CLASSROOMS_COLLECTION, USERS_COLLECTION } = require('../db');
const {
CLASSROOMS_COLLECTION,
USERS_COLLECTION,
ACTIONS_COLLECTION,
APP_INSTANCE_RESOURCES_COLLECTION,
} = require('../db');
const logger = require('../logger');

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

try {
const user = db
.get(CLASSROOMS_COLLECTION)
.find({ id: classroomId })
.get(USERS_COLLECTION)
.find({ id: userId });
const classroom = db.get(CLASSROOMS_COLLECTION).find({ id: classroomId });

const user = classroom.get(USERS_COLLECTION).find({ id: userId });

// check user exists
const found = user.value();
Expand All @@ -25,6 +29,16 @@ const editUserInClassroom = (mainWindow, db) => async (
);
}

// delete space data related to user if selected
const actions = classroom.get(ACTIONS_COLLECTION);
const resources = classroom.get(APP_INSTANCE_RESOURCES_COLLECTION);
Object.entries(deleteSelection).forEach(([spaceId, selected]) => {
if (selected) {
actions.remove({ spaceId, user: userId }).write();
resources.remove({ spaceId, user: userId }).write();
}
});

// update data
const now = new Date();
user.assign({ username, lastUpdatedAt: now }).write();
Expand Down
10 changes: 9 additions & 1 deletion src/actions/classroom.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ import {
import {
ERROR_GENERAL,
ERROR_DUPLICATE_CLASSROOM_NAME,
ERROR_LOADING_MESSAGE,
ERROR_INVALID_USERNAME,
ERROR_DUPLICATE_USERNAME_IN_CLASSROOM,
ERROR_NO_USER_TO_DELETE,
ERROR_ACCESS_DENIED_CLASSROOM,
} from '../config/errors';
import {
ADD_CLASSROOM_CHANNEL,
Expand Down Expand Up @@ -67,6 +67,8 @@ import {
ERROR_GETTING_SPACE_IN_CLASSROOM_MESSAGE,
ERROR_INVALID_USERNAME_MESSAGE,
SUCCESS_SPACE_LOADED_MESSAGE,
ERROR_LOADING_MESSAGE,
ERROR_ACCESS_DENIED_CLASSROOM_MESSAGE,
} from '../config/messages';
import { createFlag } from './common';
import { createExtractFile, createClearLoadSpace } from './loadSpace';
Expand Down Expand Up @@ -110,6 +112,12 @@ export const getClassroom = async payload => async dispatch => {
}

switch (response) {
case ERROR_ACCESS_DENIED_CLASSROOM:
toastr.error(
ERROR_MESSAGE_HEADER,
ERROR_ACCESS_DENIED_CLASSROOM_MESSAGE
);
break;
case ERROR_GENERAL:
toastr.error(ERROR_MESSAGE_HEADER, ERROR_GETTING_CLASSROOM_MESSAGE);
break;
Expand Down
36 changes: 20 additions & 16 deletions src/components/classrooms/AddClassroomButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import { withTranslation } from 'react-i18next';
import TextField from '@material-ui/core/TextField';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import { addClassroom } from '../../actions';
import {
ADD_CLASSROOM_BUTTON_ID,
ADD_CLASSROOM_NAME_INPUT_ID,
ADD_CLASSROOM_VALIDATE_BUTTON_ID,
ADD_CLASSROOM_CANCEL_BUTTON_ID,
} from '../../config/selectors';
import ClassroomNameTextField from './ClassroomNameTextField';

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

state = (() => {
const { t } = this.props;
const defaultName = t('New Classroom');
return {
open: false,
name: t('New Classroom'),
name: defaultName,
};
})();

isClassroomNameValid = () => {
const { name } = this.state;
// todo: check for special characters
return name.trim().length;
};

handleClickOpen = () => {
this.setState({ open: true });
};

close = () => {
this.setState({ name: '', open: false });
this.setState({ open: false });
};

handleCancel = () => {
Expand All @@ -62,11 +68,14 @@ class AddClassroomButton extends Component {
handleValidate = () => {
const { name } = this.state;
const { userId, dispatchAddClassroom } = this.props;
dispatchAddClassroom({ name, userId });
this.close();
if (this.isClassroomNameValid()) {
const trimmedName = name.trim();
dispatchAddClassroom({ name: trimmedName, userId });
this.close();
}
};

handleChange = event => {
handleNameChange = event => {
const { target } = event;
this.setState({ name: target.value });
};
Expand Down Expand Up @@ -96,15 +105,9 @@ class AddClassroomButton extends Component {
{t('Enter a name for your new classroom')}
</DialogTitle>
<DialogContent>
<TextField
id={ADD_CLASSROOM_NAME_INPUT_ID}
autoFocus
margin="dense"
label={t("Classroom's Name")}
type="text"
fullWidth
value={name}
onChange={this.handleChange}
<ClassroomNameTextField
name={name}
handleChange={this.handleNameChange}
/>
</DialogContent>
<DialogActions>
Expand All @@ -119,6 +122,7 @@ class AddClassroomButton extends Component {
onClick={this.handleValidate}
color="primary"
id={ADD_CLASSROOM_VALIDATE_BUTTON_ID}
disabled={!this.isClassroomNameValid()}
>
{t('Validate')}
</Button>
Expand Down
43 changes: 43 additions & 0 deletions src/components/classrooms/ClassroomNameTextField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withTranslation } from 'react-i18next';
import TextField from '@material-ui/core/TextField';
import { CLASSROOM_NAME_INPUT_ID } from '../../config/selectors';
import { isClassroomNameValid } from '../../utils/classroom';

const ClassroomNameTextField = ({ name, t, handleChange }) => {
const isValid = isClassroomNameValid(name);
let errorProps = {};
if (!isValid) {
errorProps = {
...errorProps,
helperText: t(`Classroom's name is not valid`),
error: true,
};
}

return (
<TextField
id={CLASSROOM_NAME_INPUT_ID}
autoFocus
margin="dense"
label={t("Classroom's Name")}
type="text"
fullWidth
value={name}
onChange={handleChange}
// eslint-disable-next-line react/jsx-props-no-spreading
{...errorProps}
/>
);
};

ClassroomNameTextField.propTypes = {
name: PropTypes.string.isRequired,
handleChange: PropTypes.func.isRequired,
t: PropTypes.func.isRequired,
};

const TranslatedComponent = withTranslation()(ClassroomNameTextField);

export default TranslatedComponent;
20 changes: 19 additions & 1 deletion src/components/classrooms/ClassroomScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import { withStyles } from '@material-ui/core';
import { withTranslation } from 'react-i18next';
import { withRouter } from 'react-router';
import { Map } from 'immutable';
import { Map, List } from 'immutable';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import Toolbar from '@material-ui/core/Toolbar';
Expand Down Expand Up @@ -45,6 +45,7 @@ class ClassroomScreen extends Component {
goBack: PropTypes.func.isRequired,
}).isRequired,
userId: PropTypes.string.isRequired,
classrooms: PropTypes.instanceOf(List).isRequired,
};

static defaultProps = {
Expand All @@ -62,6 +63,22 @@ class ClassroomScreen extends Component {
dispatchGetClassroom({ id, userId });
}

componentDidUpdate({ classrooms: prevClassrooms }) {
const {
dispatchGetClassroom,
classrooms,
match: {
params: { id },
},
userId,
} = this.props;

// update current classroom if classrooms change
if (!prevClassrooms.equals(classrooms)) {
dispatchGetClassroom({ id, userId });
}
}

renderBackButton = () => {
const {
t,
Expand Down Expand Up @@ -117,6 +134,7 @@ class ClassroomScreen extends Component {
}

const mapStateToProps = ({ classroom, authentication }) => ({
classrooms: classroom.getIn(['classrooms']),
classroom: classroom.getIn(['current', 'classroom']),
activity: Boolean(classroom.get('activity').size),
userId: authentication.getIn(['user', 'id']),
Expand Down
Loading

0 comments on commit 2affd69

Please sign in to comment.