| Dependency | Description |
|---|---|
| vuejs | Vue.js is a JavaScript framework |
| vue-router | Single-page application routing |
| vuex | Large-scale state management |
| express | Fast, minimalist web framework for node |
| mongoDB | NoSQL Database |
| mongoose | MongoDB ODM designed to work in an asynchronous environment |
| socket.io | Realtime application framework |
| JsonWebToken | Authentification for node.js API |
git clone git@github.com:Hashs7/mascarade.git
npm install
cd client && npm install
Create MongoDB database with Mongo Atlas
Rename .env.example by .env with correct field and start server
npm start
In client folder
npm run serve
Site is alive at : http://localhost:8080
In client folder
npm run build
To deploy client, you only need to push on upstream repository or create new pull request
git remote add upstream git@github.com:Hashs7/mascarade.git
git add yourcommitfiles
git commit -m "Your commit message"
git push upstream master
To deploy API, you need to push on heroku repository
git remote add heroku https://git.heroku.com/mascarade.git
git add yourcommitfiles
git commit -m "Your commit message"
git push heroku master
This project is using MVC pattern
A model represents a set of structured data, called records. Models usually correspond to a collection in a database, attributes correspond to fields, and records correspond to documents. In this project, there is 4 models : Flash, Session, Student, Teacher they're represent each "collections" in database
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const mySchema = new Schema({
student: {
type: Schema.Types.ObjectId,
ref: 'Student',
required: true
},
total: {
type: Number,
required: true
}
});
module.exports = mongoose.model('MySchema', mySchema);
Controllers are the principal objects in our application that are responsible for responding to requests from a web browser. They often act as a middleman between your models and views. Controllers will orchestrate the bulk of the project’s business logic. To simplify communicate with MongoDB, we're using mongoose as ODM.
exports.myController = (req, res, next) => {
//Get all data in request body
const {studentId, sessionId, total} = req.body;
//Find current student in DB with ID
Student.findById(studentId)
.populate()
.then(student => {
//Update his value
student.total = total;
return student.save()
})
.then(result => {
//Payload datas for response
const payload = {
studentId,
sessionId,
total
};
//Emit socket event to update admin view
io.getIO().emit('updateCharity', payload);
//Send API response
res.status(201).json({
message: 'myController a été mis à jour',
payload
});
})
.catch(err => {
//Catch if an error occured
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
});
};
To access to theses controllers, we expose differents routes for the REST API.
For each models, we have routes which can be called.
Call getSessionById controller with the route GET "/student/:sessionId"
router.get('/student/:sessionId', sessionController.getSessionById);
We have single middlewares to check Token on restricted routes.
To manage dynamic and interactive views, we choose vue.js framework in client folder
In this folder, there are all icons, images and fonts which are loaded in the website
In order to modularize the code, we created different type of reusable components. They are in respective folders according to their type.
We are using Vuetify, wich is Material Design Component Framework. They are mainly use in admin dashboard.
In this SPA, we need to manage differents url to access to different views. We are using default vue-router. For dashboard page, we had to check if the user is authenticated to show view. There is method "redirectIfNotAuth" to validate token.
Vue-router This folder contains all the views connected to the router. We separate the dashboard and student parts.
We're using Vuex to have global store which contains all application datas. The components are connected to this store and are refreshed when data change.
State : is the main object with datas
Actions : are methods call async to perform API action
Mutations : change the current state after actions is done.
Getters : are usefull when you need to compute derived state based on store state.
We defined global style for the entire of application. Mainly for layout, variables, buttons and scenes.
On the landing page, we needed to translate all the content. We're using vuex-i18n to create 2 files for each languages and swap the content instantly.
Teacher's routes
GET /teacher/is-auth
Headers : Token
POST /teacher/signup
Body : email, firstname, surname, password
PUT /teacher/login
Body : email, password
Student's routes
PUT /student/signup
Body : email, firstname, surname, password
POST /student/login
Body : email, password
PUT /student/achievement
Body : studentId, sessionId, achievType, amount
PUT /student/charity
Body : studentId, sessionId, charityType, title, description
PUT /student/dialog
Body : studentId, sessionId, dialogType, response, state
PUT /student/scene
Body : studentId, sessionId, sceneType, action
PUT /student/slider
Body : studentId, sessionId, amount
PUT /student/quizz
Body : studentId, sessionId, responses
Session's routes
GET /session/all
GET /session/:sessionId
PUT /session/new
Body : className
Flash's routes
PUT /flash/send
Body : studentFromId, studentToId
Simple request to update student achievements
//Base url for API
export const api = axios.create({ baseURL: BASE_API_URL });
// Define method in utils/API.js
export const updateAchievement = async (studentId, sessionId, achievType, amount) => {
const options = {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
url: '/student/achievement',
data: {
studentId,
sessionId,
achievType,
amount
}
};
return api(options)
};
// Should be use in vuex action
updateAchievement(rootState.studentId, rootState.sessionId, type, amount)
.then(res => {
// Call mutation to update state
commit('updateAchievement', {type, amount})
})
.catch(err => console.log(err))
Request restricted routes with token
// Define method in utils/API.js
export const getSessions = async () => {
const token = await getTokenState();
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + token
},
url: ROUTE_TEACHER_ALL_SESSION
};
return api(options)
};
// Should be use in vuex action
getSessions()
.then(res => {
// Call mutation to update state
commit('initSessions', res.data.sessions);
})
.catch(err => console.log(err))