Commit 9675647e by Pablo Molina

Merge branch 'issue/386' into develop

Conflicts:
	sails/src/assets/app/modules/supervisor/controllers/students.js
parents d0f6aea1 e39c1c30
/**
* Functions defining the events sent inside the sockets.
* In order to create a new event you have to call the corresponding
* function with the necesary parameters, and you will receive an Object:
*
* {
* name: 'eventName',
* data: 'eventData'
* }
*
* Where 'name' is the name of the event and 'data' is the block of
* information to send.
* @type {Object}
*/
module.exports = function eventsHook (sails) {
return {
/**
* Speacial Function wrapping sails.sockets.broadcast that uses a room
* from sails.hooks.rooms and an event from sails.hooks.events in
* order to broadcast information. This also logs the event as debug
* level information with the message:
*
* "websocketEvent": {
* "room",
* "name",
* "data": { ... }
* }
*
* @param {RoomId} rooms RoomID or IDs where the event will be sent
* @param {Object} event A tuple {name, data} returned by a
* function inside sails.sockets.events
* @param {socket} socketToOmit If specified, this socket will not receive
* the event
*/
broadcastEvent: function (rooms, event, socketToOmit) {
// Ensure rooms is an Array
if (!(rooms instanceof Array)) {
rooms = [rooms];
}
sails.log.debug('"websocketEvent":', JSON.stringify({
rooms: rooms,
name: event.name,
data: event.data,
socketToOmit: socketToOmit ? socketToOmit.id : undefined
}));
sails.sockets.broadcast(
rooms,
event.name,
event.data,
socketToOmit || undefined
);
},
/**
* A supervisor has been linked to a student.
* @param {ID} supId ID of the supervisor
* @param {ID} stu_id ID of the student
* @return {Object} {name, data}
*/
linkSupervisorToStudent: function (supId, stuId) {
return {
name: 'linkSupervisorToStudent',
data: {
sup_id: supId,
stu_id: stuId
}
};
},
/**
* Someone has subscribed/unsubscribed to/from a room. The number
* of subscribes is sent
* @param {number} subscriberCount Number of subscribers
* @return {Object} {name, data}
*/
roomSubscribersChange: function (subscriberCount) {
return {
name: 'update_peers',
data: {
count: subscriberCount
}
};
}
};
};
/**
* This hook is used for managing the rooms IDs.
* Every room created should call one of this functions in order
* to obtain an ID.
* @type {Object}
*/
module.exports = function roomsHook (sails) {
return {
/**
* Special function that subscribes a socket to a given room.
* This creates the connection and logs to debug with this format:
*
* {
* websocketSubscribe: {
* room,
* socket
* }
* }
*
* @param {RoomID} room Room to subscribe
* @param {Socket} socket Socket added to the subscription
*/
subscribeToRoom: function (room, socket) {
sails.log.debug('"websocketSubscribe":', JSON.stringify({
room: room,
socket: socket.id
}));
sails.sockets.join(socket, room, function () {
sails.io.sockets.in(room).clients(function(error, ids) {
if (!error) {
sails.hooks.events.broadcastEvent(
room,
sails.hooks.events.roomSubscribersChange(ids.length)
);
}
});
});
},
/**
* Special function that unsubscribes a socket from a given room.
* This remotes the connection and logs to debug with this format:
*
* {
* websocketUnsubscribe: {
* room,
* socket
* }
* }
*
* @param {RoomID} room Room to unsubscribe from
* @param {Socket} socket Socket removed from the subscription
*/
unsubscribeFromRoom: function (room, socket) {
sails.log.debug('"websocketUnsubscribe":', JSON.stringify({
room: room,
socket: socket.id
}));
sails.sockets.leave(socket, room, function () {
sails.io.sockets.in(room).clients(function(error, ids) {
if (!error) {
sails.hooks.events.broadcastEvent(
room,
sails.hooks.events.roomSubscribersChange(ids.length)
);
}
});
});
},
/**
* Student related rooms
* @param {ID} studentId Student's ID used for creating a room.
* @return {RoomID} RoomID generated
*/
student: function (studentId) {
return 'studentRoom' + studentId;
},
/**
* Supervisor related rooms
* @param {ID} supervisorId Supervisor's ID used for creating a room.
* @return {RoomID} RoomID generated
*/
supervisor: function (supervisorId) {
return 'supervisorRoom' + supervisorId;
}
};
};
'use strict';
/* Services */
/* global io */
//
// This defines an interceptor service in every HTTP request to add session
// token in the header and in every HTTP response to handle non authorized
// connections
//
'use strict';
var module = angular.module('dashboardServices', []);
angular.module('dashboardServices', [])
.service('authInterceptor', function ($rootScope, $q, $window) {
/**
* This defines an interceptor service in every HTTP request to add session
* token in the header and in every HTTP response to handle non authorized
* connections.
*/
module.factory('AuthInterceptorService', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
......@@ -30,7 +29,68 @@ angular.module('dashboardServices', [])
return $q.reject(rejection);
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
\ No newline at end of file
});
// Add AuthInterceptorService to $httpProvider.interceptors
module.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptorService');
});
/**
* IOService that must be used as communication with the server.
* It allows to subscribe/unsubscribe to/from rooms and listen/stop listening
* to events.
*/
module.factory('IOService', function ($window) {
return {
/**
* Send a get request to the server via websocket
* @param {String} url Url of the request
* @param {Function} callback Function to be called on response
*/
get: function(url, callback) {
io.socket.get(url, { token: $window.sessionStorage.token }, callback);
},
/**
* Send a post request to the server via websocket
* @param {String} url Url of the request
* @param {Object} data If this parameter is not an object, it will
* be wrapped inside an object:
* { data, token }, otherwise the token will be
* appended to the parameters
* @param {Function} callback Function to be called on response
*/
post: function (url, data, callback) {
// Create the request data and convert it to an object if necesary
// Then append the token
var requestData = data;
if (typeof requestData !== 'object') {
requestData = { data: data };
}
requestData.token = $window.sessionStorage.token;
io.socket.post(url, requestData, callback);
},
/**
* Subscribes to an event with the given function using websockets
* @param {String} event Event to subscribe to
* @param {Function} callback Function to be executed when the event occurs
*/
on: function (event, callback) {
io.socket.on(event, callback);
},
/**
* Unsubscribe from an event
* @param {String} event Event to unsubscribe from
* @param {Function} callback If specified, only this funcion will be
* unsuscribed from the event, otherwise all
* functions subscribed to this event will be
* removed
*/
off: function (event, callback) {
io.socket.off(event, callback);
}
};
});
......@@ -12,7 +12,8 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
config,
$window,
$translate,
ngToast) {
ngToast,
IOService) {
$scope.formdatastudent = {
username: '',
password: '',
......@@ -148,6 +149,10 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
$translate('student_deleted').then(function (translation) {
ngToast.success({ content: translation });
});
IOService.post('/stu/unsubscribe', {
action: 'unsubscribe'
});
})
.error(function () {
$translate('student_not_deleted').then(function (translation) {
......@@ -157,7 +162,30 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
}
};
io.socket.post('/stu/unsubscribe', { action: 'unsubscribe' });
// When a new student is added to the supervisor, we should update
// the student list if necesary
IOService.on('linkSupervisorToStudent', function (eventData) {
eventData.sup_id = parseInt(eventData.sup_id, 10);
eventData.stu_id = parseInt(eventData.stu_id, 10);
if (eventData.sup_id === $scope.user.id) {
IOService.get('/stu/' + eventData.stu_id, function (studentData) {
var i;
var studentAlreadyAdded = false;
for (i = 0; i < $scope.students.length; i++) {
if ($scope.students[i].id === eventData.stu_id) {
studentAlreadyAdded = true;
break;
}
}
if (!studentAlreadyAdded) {
$scope.students.push(studentData);
$scope.$apply();
}
});
}
});
});
/**
......
/* global io */
'use strict';
//-----------------------
// Supervisor Controller
//-----------------------
dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope, $window, $location) {
dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope, $window, $location, IOService) {
// Restore user data from session
var user = JSON.parse($window.sessionStorage.user);
// Assign values this way (like an object) to ensure it's the parent scope
$scope.user.id = user.id;
$scope.user.name = user.name;
......@@ -22,4 +24,11 @@ dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope
$location.path('/setup');
};
});
\ No newline at end of file
// Subscribe to the supervisor's room
IOService.post('/sup/subscribe', {
action: 'subscribe',
attributes: {
id_sup: $scope.user.id
}
});
});
......@@ -45,7 +45,9 @@ module.exports.policies = {
destroy: ['tokenAuth', 'isAdmin'],
students: ['tokenAuth'],
pictos: ['tokenAuth'],
upload: ['tokenAuth']
upload: ['tokenAuth'],
subscribe: ['tokenAuth'],
unsubscribe: ['tokenAuth']
},
DeviceController: {
register: true,
......
/**
* Route Mappings
* (sails.config.routes)
*
*
* Your routes map URLs to views and controllers.
*
* If Sails receives a URL that doesn't match any of the routes below,
......@@ -22,16 +22,7 @@
module.exports.routes = {
/***************************************************************************
* *
* Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
* etc. depending on your default view engine) your home page. *
* *
* (Alternatively, remove this and add an `index.html` file in your *
* `assets` directory) *
* *
***************************************************************************/
// Supervisor
'post /sup/login': 'SupervisorController.login',
'post /sup': 'SupervisorController.create',
'put /sup': 'SupervisorController.update',
......@@ -40,13 +31,15 @@ module.exports.routes = {
'get /sup/get/:id': 'SupervisorController.findOne',
'post /sup/activate': 'SupervisorController.activate',
'get /sup/:id/students': 'SupervisorController.students',
'post /sup/subscribe': 'SupervisorController.subscribe',
'post /sup/unsubscribe': 'SupervisorController.unsubscribe',
'post /sup/upload': 'SupervisorController.upload', // upload profile img file
// Pictos
'get /sup/:id/pictos': 'SupervisorController.pictos',
'get /sup/:id/pic_categories/:id_cat': 'Picto.categories',
'get /sup/:id/pic_fromcategory/:id_cat': 'Picto.fromcategory',
'post /sup/upload': 'SupervisorController.upload', // upload profile img file
// Pictogram administration
'post /admin/login': 'AdminController.login',
......@@ -65,7 +58,7 @@ module.exports.routes = {
'get /office/get/:id': 'OfficeController.get',
'get /office/get_all': 'OfficeController.getAll',
'get /office/get/:id/supervisors': 'OfficeController.supervisors',
/////////////////////////////////////////////////////////////////////////
// STUDENTS /////////////////////////////////////////////////////////////
// get /student --> List all students
......@@ -127,16 +120,16 @@ module.exports.routes = {
// (check them by inspecting the policies.js file)
// Reports
'get /ws/:id_stu/year/:year': 'WorkingSessionController.per_year',
'get /ws/:id_stu/month/:month': 'WorkingSessionController.per_month',
// Working Sessions > Tries
'get /ws/:id_ws/tries': 'WorkingSession.tries',
'post /workingsession/:id_ws/close': 'WorkingSession.close',
'get /ws/:id_ws/tries': 'WorkingSession.tries',
'post /workingsession/:id_ws/close': 'WorkingSession.close',
'put /try/:id': 'Try.update',
'post /try': 'Try.create',
// Instructions > Working Sessions
'get /instruction/:id_ins/ws': 'Instruction.ws',
//'get /instruction/:id_ins/tries': 'Instruction.tries', // BORRAR aquí y en wiki
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment