Commit 1e4cc30a by Pablo Molina

Merge branch 'issue/389' into 'develop'

Solved #389
parents 77f385d1 7c0d395e
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
"angular-timer": "~1.3.3", "angular-timer": "~1.3.3",
"humanize-duration": "~3.0.0", "humanize-duration": "~3.0.0",
"momentjs": "~2.10.3", "momentjs": "~2.10.3",
"ng-context-menu": "~1.0.1",
"ngtoast": "~1.5.4", "ngtoast": "~1.5.4",
"angular-animate": "~1.4.1", "angular-animate": "~1.4.1",
"angular-sanitize": "~1.4.1", "angular-sanitize": "~1.4.1",
......
'use strict'; /* global angular */
/* App Module */ 'use strict';
var dashboardApp = angular.module('dashboardApp', [ var dashboardApp = angular.module('dashboardApp', [
'ui.router', // This module enables PAC pattern 'ui.router',
'dashboardControllers', // PAC controllers (they are, actually, implemented under directives thanks to ui-router) 'dashboardControllers',
'dashboardServices', // HTTP interceptor for authentication tokens attachment and checking 'dashboardServices',
'dashboardDirectives', // simple directives to dragable elements and other stuff 'dashboardDirectives',
'pascalprecht.translate', 'pascalprecht.translate',
'reCAPTCHA', 'reCAPTCHA',
'ui.bootstrap', 'ui.bootstrap',
...@@ -15,52 +15,34 @@ var dashboardApp = angular.module('dashboardApp', [ ...@@ -15,52 +15,34 @@ var dashboardApp = angular.module('dashboardApp', [
'timer', 'timer',
'ngAnimate', 'ngAnimate',
'ngSanitize', 'ngSanitize',
'ngToast', // This is for pop-up notifications 'ngToast',
'ng-context-menu', 'chart.js',
'chart.js', // Interactive charts!
'ngLodash' 'ngLodash'
//'ngWebsocket'
//'ngImgCrop'
// angular-translate as a module load dependency for dashboardApp
]); ]);
/* Toast (notification) configuration */ /* Toast (notification) configuration */
dashboardApp.config(['ngToastProvider', function(ngToast) { dashboardApp.config(['ngToastProvider', function (ngToast) {
ngToast.configure({ ngToast.configure({
verticalPosition: 'top', verticalPosition: 'top',
horizontalPosition: 'center', horizontalPosition: 'center',
maxNumber: 3, maxNumber: 3,
animation: 'slide' animation: 'slide'
}); });
}]); }]);
dashboardApp.config(function($translateProvider) { dashboardApp.config(function ($translateProvider) {
/* i18n */
$translateProvider.useStaticFilesLoader({ $translateProvider.useStaticFilesLoader({
'prefix': '/app/i18n/', prefix: '/app/i18n/',
'suffix': '.json' suffix: '.json'
}); });
/* $translateProvider.preferredLanguage('es-es');
// Set preferred language to browser language
var lang = $window.navigator.language || $window.navigator.userLanguage;
if (lang === 'en-US')
lang = 'en-gb';
if (lang === 'es-ES')
lang = 'es-es';
*/$translateProvider.preferredLanguage('es-es');
//$translateProvider.determinePreferredLanguage();
}); });
/* /*
* ui-routes is used to implement a PAC pattern so views and related controllers are * ui-routes is used to implement a PAC pattern so views and related controllers are
* hierarchically arranged. * hierarchically arranged.
*
*/ */
dashboardApp.config(function ($stateProvider, $urlRouterProvider) {
dashboardApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider $stateProvider
.state('login', { .state('login', {
url: '/login', url: '/login',
...@@ -110,7 +92,7 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) { ...@@ -110,7 +92,7 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) {
templateUrl: 'modules/student/views/student.html', templateUrl: 'modules/student/views/student.html',
parent: 'supervisor', parent: 'supervisor',
controller: 'StudentCtrl', controller: 'StudentCtrl',
data: {studentData1: "tomate"}, data: { studentData1: 'tomate' },
abstract: true, abstract: true,
}) })
.state('student_collections', { .state('student_collections', {
...@@ -164,19 +146,13 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) { ...@@ -164,19 +146,13 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) {
; ;
$urlRouterProvider.otherwise('/login'); $urlRouterProvider.otherwise('/login');
}); });
/* reCAPTCHA */ /* reCAPTCHA */
dashboardApp.config(function (reCAPTCHAProvider) { dashboardApp.config(function (reCAPTCHAProvider) {
// required: please use your own key :)
reCAPTCHAProvider.setPublicKey('6LdkZwMTAAAAANDR_7_y9_ifEve1gLPcgneM_50o'); reCAPTCHAProvider.setPublicKey('6LdkZwMTAAAAANDR_7_y9_ifEve1gLPcgneM_50o');
// optional: gets passed into the Recaptcha.create call
reCAPTCHAProvider.setOptions({ reCAPTCHAProvider.setOptions({
theme: 'clean' theme: 'clean'
}); });
}); });
...@@ -184,24 +160,17 @@ dashboardApp.config(function (reCAPTCHAProvider) { ...@@ -184,24 +160,17 @@ dashboardApp.config(function (reCAPTCHAProvider) {
// New confirm service to avoid Firefox buggy confirm dialog window (which // New confirm service to avoid Firefox buggy confirm dialog window (which
// results in rootScope.inprog errors) // results in rootScope.inprog errors)
// //
dashboardApp.factory('newconfirm', function ($window, $q, $timeout) {
dashboardApp.factory("newconfirm", function ($window, $q, $timeout) { function newconfirm(message) {
var defer = $q.defer();
// Define promise-based confirm() method. $timeout(function () {
function newconfirm(message) { if ($window.confirm(message)) {
var defer = $q.defer(); defer.resolve(true);
} else {
$timeout(function () { defer.reject(false);
if ($window.confirm(message)) { }
defer.resolve(true); }, 0, false);
} return defer.promise;
else { }
defer.reject(false); return newconfirm;
}
}, 0, false);
return defer.promise;
}
return newconfirm;
}); });
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
// Student Session Controller // Student Session Controller
//----------------------- //-----------------------
dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtrl($scope, $stateParams, $http, config, $window) { dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtrl($scope, $stateParams, $http, config, $window) {
console.log("dashboardControllers reload:"+$scope.$id);
// For tab navigation (here too, if the user refresh the page...) // For tab navigation (here too, if the user refresh the page...)
$scope.nav.tab = 'session'; $scope.nav.tab = 'session';
...@@ -14,12 +14,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -14,12 +14,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// Prepare session recording information // Prepare session recording information
// //
// //
// Actual WS // Actual WS
$scope.ws = $scope.ws || {}; $scope.ws = $scope.ws || {};
$scope.actual_try = $scope.actual_try || {}; $scope.actual_try = $scope.actual_try || {};
// pause flag // pause flag
$scope.paused = false; $scope.paused = false;
// Read the last working session to show the last tries when session tab is opened // Read the last working session to show the last tries when session tab is opened
...@@ -29,18 +29,17 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -29,18 +29,17 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// Array with student methods (with instructions) // Array with student methods (with instructions)
// //
$scope.methods = []; $scope.methods = [];
// Query to obtain an array of student methods // Query to obtain an array of student methods
$http $http
.get(config.backend+'/stu/'+ $scope.studentData.id +'/methods') .get(config.backend+'/stu/'+ $scope.studentData.id +'/methods')
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
// Add to list // Add to list
$scope.methods = data; $scope.methods = data;
console.log(JSON.stringify($scope.methods));
console.log("Methods recovered");
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
// Query to obtain an array of only one working session (the last) with its tries/actions // Query to obtain an array of only one working session (the last) with its tries/actions
...@@ -49,28 +48,24 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -49,28 +48,24 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
// Add to list // Add to list
$scope.wsessions = data; $scope.wsessions = data;
console.log(JSON.stringify($scope.wsessions));
console.log("Tries of last working session recovered");
$scope.currentPage = 1; $scope.currentPage = 1;
$scope.numPerPage = 5; $scope.numPerPage = 5;
$scope.totalPages = Math.ceil($scope.wsessions.length / $scope.numPerPage); $scope.totalPages = Math.ceil($scope.wsessions.length / $scope.numPerPage);
$scope.ws_recover = $scope.wsessions[0]!=null && $scope.wsessions[0].end==null; $scope.ws_recover = $scope.wsessions[0]!=null && $scope.wsessions[0].end==null;
console.log("sessions: " + $scope.wsessions.length);
console.log("numPerPage: " + $scope.numPerPage);
console.log("pages: " + $scope.totalPages);
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
// Initially, show the last try // Initially, show the last try
$scope.showLastTry = true; $scope.showLastTry = true;
// VER SI BORRAR --> SÓLO NECESARIO PARA DEJAR EN BLANCO LOS ENSAYOS CARGADOS // VER SI BORRAR --> SÓLO NECESARIO PARA DEJAR EN BLANCO LOS ENSAYOS CARGADOS
// Cargar instrucciones en select del método seleccionado arriba // Cargar instrucciones en select del método seleccionado arriba
$scope.load_instructions = function (method){ $scope.load_instructions = function (method){
console.log(JSON.stringify(method));
// Empty ws/tries/actions // Empty ws/tries/actions
$scope.wsessions=[]; $scope.wsessions=[];
// Update the number of pages // Update the number of pages
...@@ -92,27 +87,23 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -92,27 +87,23 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// If to avoid the default select option "-- select one instruction --" // If to avoid the default select option "-- select one instruction --"
if(instruction){ if(instruction){
console.log(JSON.stringify(instruction));
$http $http
.get(config.backend+'/instruction/'+ instruction.id +'/ws') .get(config.backend+'/instruction/'+ instruction.id +'/ws')
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
// Add to list // Add to list
$scope.wsessions = data; $scope.wsessions = data;
console.log(JSON.stringify($scope.wsessions));
console.log("#WS for instruction "+ instruction.id +" recovered: "+$scope.wsessions.length);
// Refresh navigation vars // Refresh navigation vars
$scope.currentPage = 1; $scope.currentPage = 1;
$scope.numPerPage = 5; $scope.numPerPage = 5;
$scope.totalPages = Math.ceil($scope.wsessions.length / $scope.numPerPage); $scope.totalPages = Math.ceil($scope.wsessions.length / $scope.numPerPage);
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data);
}); });
} }
}; };
// Tries pagination - previous tries // Tries pagination - previous tries
$scope.before = function(){ $scope.before = function(){
...@@ -135,10 +126,10 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -135,10 +126,10 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
$http $http
.put(config.backend+'/try/' + t.id, update_data) .put(config.backend+'/try/' + t.id, update_data)
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
console.log("Try - updated: " + $scope.studentData.id+" try:"+t.id);
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
}; };
...@@ -148,35 +139,34 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -148,35 +139,34 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
.put(config.backend+'/try/' + $scope.actual_try.id, { result: $scope.actual_try.result, end: new Date() }) .put(config.backend+'/try/' + $scope.actual_try.id, { result: $scope.actual_try.result, end: new Date() })
.then( .then(
function(data, status, headers, config) { function(data, status, headers, config) {
console.log("Current try - updated. Student: " + $scope.studentData.id+" try:"+$scope.actual_try.id);
} }
, function(data, status, headers, config) { , function(data, status, headers, config) {
console.log("Error from API: " + data.error+ "when updating try "+$scope.actual_try);
} }
); );
}; };
$scope.send_show_action = function(){ $scope.send_show_action = function(){
console.log("ACTION!" + $scope.studentData.id+" try:"+$scope.actual_try.id);
$http $http
.post(config.backend+'/action', { .post(config.backend+'/action', {
student: $scope.studentData.id, student: $scope.studentData.id,
type: 'Show', type: 'Show',
timestamp: new Date(), timestamp: new Date(),
_try: $scope.actual_try.id _try: $scope.actual_try.id
}) })
.then( .then(
function(data, status, headers, config) { function(data, status, headers, config) {
$scope.load_tries($scope.selectedIns); $scope.load_tries($scope.selectedIns);
// Empty actual try and push the first action of next try // Empty actual try and push the first action of next try
$scope.actual_try.actions = []; $scope.actual_try.actions = [];
$scope.actual_try.actions.push({ action: 'tryinit' }); $scope.actual_try.actions.push({ action: 'tryinit' });
$scope.actual_try.id = data.data.open_try; $scope.actual_try.id = data.data.open_try;
console.log("New try: " + $scope.actual_try.id+"="+ data.data.open_try+": "+JSON.stringify(data));
} }
, function(data, status, headers, config) { , function(data, status, headers, config) {
console.log("Error from API: " + data.error);
} }
); );
}; };
...@@ -188,20 +178,19 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -188,20 +178,19 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// Close a working session // Close a working session
// //
$scope.close_ws = function (){ $scope.close_ws = function (){
$http $http
.post(config.backend+ '/workingsession/'+$scope.wsessions[0].id+'/close') .post(config.backend+ '/workingsession/'+$scope.wsessions[0].id+'/close')
.then( .then(
function(data, status, headers, config) { function(data, status, headers, config) {
$scope.wsessions[0].end=data.data.end; $scope.wsessions[0].end=data.data.end;
$scope.ws_recover=false; $scope.ws_recover=false;
console.log("WS " + $scope.wsessions[0].id + "closed at "+ JSON.stringify(data.data.end));
} }
, function(data, status, headers, config) { , function(data, status, headers, config) {
console.log("Error from API: " + data.error);
} }
); );
} }
...@@ -220,47 +209,46 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -220,47 +209,46 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
"id_ins": $scope.selectedIns "id_ins": $scope.selectedIns
}) })
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
// Actual WS // Actual WS
$scope.ws = { $scope.ws = {
id: data.id id: data.id
}; };
// List of tries --> empty // List of tries --> empty
// BORRAR después lo que no sirva // BORRAR después lo que no sirva
$scope.actual_try = { $scope.actual_try = {
actions: [], actions: [],
id: data.first_try_id, id: data.first_try_id,
result: null result: null
}; };
// Adding initial action to the list of actions // Adding initial action to the list of actions
$scope.actual_try.actions.push({ action: 'tryinit' }); $scope.actual_try.actions.push({ action: 'tryinit' });
console.log("WS created for method "+$scope.selectedMethod.name+" Ins:"+$scope.selectedIns.name+": "+JSON.stringify(data));
$scope.studentData.current_method=$scope.selectedMethod.name; $scope.studentData.current_method=$scope.selectedMethod.name;
$scope.studentData.current_instruction=$scope.selectedIns.name; $scope.studentData.current_instruction=$scope.selectedIns.name;
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
}; };
// //
// update the description of a given working session // update the description of a given working session
// //
$scope.update_ws = function (ws){ $scope.update_ws = function (ws){
console.log("WS description - updating: " + ws.id+":"+ws.description);
$http $http
.put(config.backend+'/workingsession/' + ws.id, { "description" : ws.description }) .put(config.backend+'/workingsession/' + ws.id, { "description" : ws.description })
.then(function(data, status, headers, config) { .then(function(data, status, headers, config) {
console.log("WS description - updated: " + ws.description);
}) })
,function(data, status, headers, config) { ,function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}; };
} }
// //
// Finish a working session updating its end time // Finish a working session updating its end time
// //
...@@ -271,45 +259,27 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -271,45 +259,27 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
$scope.ws.end = new Date(); $scope.ws.end = new Date();
$http $http
.put(config.backend+'/workingsession/' + $scope.ws.id, { "end": $scope.ws.end, .put(config.backend+'/workingsession/' + $scope.ws.id, { "end": $scope.ws.end,
"id_stu": $scope.studentData.id "id_stu": $scope.studentData.id
}) })
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
console.log("WS stopped - updated: " + JSON.stringify(data));
// Empty actual WS and actual try // Empty actual WS and actual try
$scope.ws = {}; $scope.ws = {};
$scope.actual_try = {}; $scope.actual_try = {};
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
// Cancel the mark of the device connected (with a new session will be connected again) // Cancel the mark of the device connected (with a new session will be connected again)
//$scope.active_device = null; //$scope.active_device = null;
}; };
// //
// Pause the actual working session // Pause the actual working session
// //
$scope.pause_ws = function (){ $scope.pause_ws = function (){
/*
// /////////////////////////////////////////////////////////////
// Websocket: Emit action PauseSession action (dashboard --> PCB)
var data = {
action: 'pausesession',
attributes: {
id_stu: $scope.studentData.id,
id_ws: $scope.ws.id
}
};
io.socket.post('/stu/action', data, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
*/
$http $http
.post(config.backend+'/action', { .post(config.backend+'/action', {
"type": "pausesession", "type": "pausesession",
...@@ -317,14 +287,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -317,14 +287,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
"supervisor": $scope.user.id "supervisor": $scope.user.id
}) })
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
console.log("Action created: " + JSON.stringify(data));
// Adding pause action to the list of actions // Adding pause action to the list of actions
$scope.actual_try.actions.push({ action: 'pausesession'} ); $scope.actual_try.actions.push({ action: 'pausesession'} );
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
}; };
...@@ -332,23 +300,6 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -332,23 +300,6 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// Resume the actual working session // Resume the actual working session
// //
$scope.resume_ws = function (){ $scope.resume_ws = function (){
/*
// /////////////////////////////////////////////////////////////
// Websocket: Emit action ResumeSession action (dashboard --> PCB)
var data = {
action: 'resumesession',
attributes: {
id_stu: $scope.studentData.id,
id_ws: $scope.ws.id
}
};
io.socket.post('/stu/action', data, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
*/
$http $http
.post(config.backend+'/action', { .post(config.backend+'/action', {
"type": "resumesession", "type": "resumesession",
...@@ -356,14 +307,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -356,14 +307,12 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
"supervisor": $scope.user.id "supervisor": $scope.user.id
}) })
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
console.log("Action created: " + JSON.stringify(data));
// Adding pause action to the list of actions // Adding pause action to the list of actions
$scope.actual_try.actions.push({ action: 'resumesession'} ); $scope.actual_try.actions.push({ action: 'resumesession'} );
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
}); });
}; };
...@@ -395,9 +344,9 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -395,9 +344,9 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
}; };
$scope.$on('timer-stopped', function (event, data){ $scope.$on('timer-stopped', function (event, data){
console.log('Timer Stopped WS - data = ', data);
}); });
/* /*
* Set current try (the one that is not closed and it's part of current working session ) * Set current try (the one that is not closed and it's part of current working session )
* this is required because current open try is not showed into the list of tries of the current ws * this is required because current open try is not showed into the list of tries of the current ws
...@@ -410,335 +359,10 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -410,335 +359,10 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
} }
return false; return false;
} }
/********************************************************************/
/* Student actions simulation */
/* DELETE AND IMPLEMENT ON TABLET PCB */
/********************************************************************/
/*
// The same picto for simulating the add, select and delete actions
$scope.pic = {
"id": 1470,
"picto": {
"id": 2718,
"uri": "/symbolstx/color/png/descriptives/hot_spicy.png",
"category": 9,
"source": 1,
"owner": null
},
"expression": {
"id": 7878,
"lang": "es-es",
"text": "condimentado",
"picto": 2718
},
"attributes": {
"id_cat": 609,
"coord_x": 3,
"coord_y": 3,
"status": "invisible",
"magnify": false,
"highlight": false
}
};
// For simulating the managing of the try in the pcb
// if($scope.ws) $scope.pcb_try = {};
$scope.pcb_actions = [];
// Always the first action is tryinit
var data = {
action: 'tryinit',
attributes: {
id_stu: $scope.studentData.id,
timestamp: new Date()
}
};
$scope.pcb_actions.push(data);
//
// PCB add picto simulation - Notify it to dashboard
//
$scope.add_picto = function(){
// /////////////////////////////////////////////////////////////
// Websocket: Emit action add action
var data = {
action: 'add',
attributes: {
id_stu: $scope.studentData.id,
picto: $scope.pic,
timestamp: new Date()
}
};
io.socket.post('/stu/action', data, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
// Save locally
$scope.pcb_actions.push(data);
};
//
// PCB delete picto simulation - Notify it to dashboard
//
$scope.del_picto = function(){
// /////////////////////////////////////////////////////////////
// Websocket: Emit action delete action
var data = {
action: 'delete',
attributes: {
id_stu: $scope.studentData.id,
picto: $scope.pic,
timestamp: new Date()
}
};
io.socket.post('/stu/action', data, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
// Save locally
$scope.pcb_actions.push(data);
};
//
// PCB select picto simulation - Notify it to dashboard
//
$scope.select_picto = function(){
// /////////////////////////////////////////////////////////////
// Websocket: Emit action select action
var data = {
action: 'select',
attributes: {
id_stu: $scope.studentData.id,
picto: $scope.pic,
timestamp: new Date()
}
};
io.socket.post('/stu/action', data, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
// Save locally
$scope.pcb_actions.push(data);
};
//
// PCB show sentence simulation - Notify it to dashboard
// For this simulation, it is supposed that the phrase stripe has 3 pictos
//
$scope.show_sentence = function(){
var endDate = new Date();
// This var will be needed later for websockets show action
var datashow = {
action: 'show',
attributes: {
id_stu: $scope.studentData.id,
pictos: [ $scope.pic, $scope.pic, $scope.pic ], // The actual state of the phrase stripe
timestamp: endDate
}
};
// Save locally
$scope.pcb_actions.push(datashow);
var data = {
action: 'tryend',
attributes: {
id_stu: $scope.studentData.id,
timestamp: endDate
}
};
// Save locally
$scope.pcb_actions.push(data);
console.log("PCB actions: " + JSON.stringify($scope.pcb_actions));
// Save in server the actions associated with a try or not associated with it
// It depends on the working session created
// Here is controlled by a scope var, but in PCB it will be created
// a flag var to this purpouse when it gets an "WSInit" action
if($scope.ws){
// End the try with actual time
$scope.pcb_try.end = endDate;
// Save actions with a try (working session is running)
$http
.post(config.backend+'/try', {
"ws": $scope.ws.id,
"begin": $scope.pcb_try.begin,
"end": $scope.pcb_try.end,
"actions": $scope.pcb_actions,
"student": $scope.studentData.id,
"supervisor": $scope.user.id,
"device": 58
})
.success(function(data, status, headers, config) {
console.log("Try and actions created: " + JSON.stringify(data));
// /////////////////////////////////////////////////////////////
// Websocket: Emit action show action
io.socket.post('/stu/action', datashow, function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
})
.error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
});
}else{
// Save actions without a try (not working session)
$http
.post(config.backend+'/actions', {
"actions": $scope.pcb_actions,
"student": $scope.studentData.id,
"supervisor": $scope.user.id,
"device": 58
})
.success(function(data, status, headers, config) {
console.log("Actions created: " + JSON.stringify(data));
})
.error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
});
}
};
//
// PCB unshow sentence simulation - Notify it to dashboard and prepare the phrase stripe to next try
//
$scope.unshow_sentence = function(){
// Begin a new try if there is a session initiated
if($scope.ws){
$scope.pcb_try = {};
$scope.pcb_try.begin = new Date();
}
// Empty PCB Actions
$scope.pcb_actions = [];
// Empty stripe on PCB
// The first action
var data = {
action: 'unshow',
attributes: {
id_stu: $scope.studentData.id,
timestamp: new Date()
}
};
// Save locally
$scope.pcb_actions.push(data);
data = {
action: 'tryinit',
attributes: {
id_stu: $scope.studentData.id,
timestamp: new Date()
}
};
// Save locally
$scope.pcb_actions.push(data);
// /////////////////////////////////////////////////////////////
// Websocket: Emit action unshow action
io.socket.post('/stu/action', {
action: 'unshow',
attributes: {
id_stu: $scope.studentData.id,
timestamp: new Date()
}
},
function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
};
//
// websockets events handling (In PCB)
//
io.socket.on('action', function(data) {
console.log('Action '+ data.action +' event received with the following data:');
console.log(JSON.stringify(data.attributes));
switch(data.action){
case 'initsession':
console.log("PCB: InitSession action!!!!!!!!!!!!!");
$scope.unshow_sentence();
// /////////////////////////////////////////////////////////////
// Websocket: Emit action show_device from pcb to dashboard
io.socket.post('/stu/action', {
action: 'show_device',
attributes: {
id_stu: $scope.studentData.id,
id_dev: 58,
timestamp: new Date()
}
},
function(res) {
console.log("Action emited: " + JSON.stringify(res.msg));
});
///////////////////////////////////////////////////////////////
break;
case 'endsession':
console.log("PCB: EndSession action!!!!!!!!!!!!!");
// In PCB use other var to control the session (it is important to save the actions with or without the id_try field)
$scope.ws = null;
break;
case 'pausesession':
console.log("PCB: blocked");
$scope.pcb_actions.push(data);
break;
case 'resumesession':
console.log("PCB: unblocked");
$scope.pcb_actions.push(data);
break;
case 'changeinstruction':
console.log("Changed instruction during the session");
// Change in PCB the var controlling the actual instruction
break;
}
// Socket.io does not live inside the angular lifecycle, and thus Angular
// doesn't know new data has come in. Inside the socket.io callback,
// as the last action, added $scope.apply() that lets angular know
// what data has updated, and refresh what needs to be refreshed.
$scope.$apply();
});
*/
/**********************************************************************/
/* Here ends de PCB simulation */
/* DELETE THIS WHEN PCB WILL BE READY */
/**********************************************************************/
// //
// websockets events handling (Dashboard) // websockets events handling (Dashboard)
// //
// Remove all listeners to this event // Remove all listeners to this event
io.socket.off('action'); io.socket.off('action');
...@@ -749,75 +373,33 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr ...@@ -749,75 +373,33 @@ dashboardControllers.controller('StudentSessionCtrl', function StudentSessionCtr
// Socket.io does not live inside the angular lifecycle, and thus Angular // Socket.io does not live inside the angular lifecycle, and thus Angular
// doesn't know new data has come in. Inside the socket.io callback, // doesn't know new data has come in. Inside the socket.io callback,
// as the last action, added $scope.apply() that lets angular know // as the last action, added $scope.apply() that lets angular know
// what data has updated, and refresh what needs to be refreshed. // what data has updated, and refresh what needs to be refreshed.
console.log('Action '+ data.action +' event received with the following data:');
console.log(JSON.stringify(data.attributes));
if($scope.ws){ if($scope.ws){
switch(data.action){ switch(data.action){
case 'Add': case 'Add':
console.log("ADD action to ws "+$scope.ws.id+":"+$scope.actual_try.id+" Scope:"+$scope.$id);
$scope.actual_try.actions.push(data); $scope.actual_try.actions.push(data);
break; break;
case 'Delete': case 'Delete':
console.log("delete action!!!!!!!!!!!!!");
$scope.actual_try.actions.push(data); $scope.actual_try.actions.push(data);
break; break;
case 'Select': case 'Select':
console.log("select action!!!!!!!!!!!!");
$scope.actual_try.actions.push(data); $scope.actual_try.actions.push(data);
break; break;
case 'Show': case 'Show':
console.log("show action!!!!!!!!!!!!");
// If a session is initiated, show the try in the list
// Stop the timer
//$scope.stopTimer();
// Load tries with actions or add more info in the PCB websocket action
// to build the try in the list of tries properly
$scope.load_tries($scope.selectedIns); $scope.load_tries($scope.selectedIns);
/*
// Add the last show action to the list of try actions
$scope.actual_try.actions.push(data);
// Put it in the list
$scope.wsessions.push($scope.actual_try);
// Update total pages for navigation
$scope.totalPages = Math.ceil($scope.wsessions.length / $scope.numPerPage);
*/
// Empty actual try and push the first action of next try // Empty actual try and push the first action of next try
$scope.actual_try.actions = []; $scope.actual_try.actions = [];
$scope.actual_try.actions.push({ action: 'tryinit' }); $scope.actual_try.actions.push({ action: 'tryinit' });
break;
/*
case 'unshow':
console.log("unshow action!!!!!!!!!!!!");
$scope.actual_try.actions = [];
$scope.actual_try.actions.push(data);
// If a session is initiated
if($scope.ws){
// Start the timer for the new try
$scope.startTimer();
}
break; break;
case 'show_device':
console.log("show_device action!!!!!!!!!!!!!");
$scope.active_device = data.attributes.id_dev;
break;
*/
} }
} }
$scope.$apply();
// Socket.io does not live inside the angular lifecycle, and thus Angular
// doesn't know new data has come in. Inside the socket.io callback,
// as the last action, added $scope.apply() that lets angular know
// what data has updated, and refresh what needs to be refreshed.
$scope.$apply();
}); });
}); });
\ No newline at end of file
<!-- Session tab -->
<div class="panel panel-default student_tab_panel"> <div class="panel panel-default student_tab_panel">
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<!-- Select con Instrucciones --> <div class="col-md-6">
<div class="col-md-6"> <form role="form" action="#">
<!-- Select para seleccionar Instrucción --> <select class="form-control" name="met_select" id="met_select" ng-model="selectedMethod" ng-options="m.name for m in methods" ng-change="load_instructions(selectedMethod)">
<form role="form" action="#"> <option value="" translate>select_a_method</option>
<select class="form-control" name="met_select" id="met_select" ng-model="selectedMethod" ng-options="m.name for m in methods" ng-change="load_instructions(selectedMethod)"> </select>
<option value="" translate>select_a_method</option> <select ng-hide="!selectedMethod" class="form-control" name="instruction_select" id="instruction_select" ng-model="selectedIns" ng-options="ins.name for ins in selectedMethod.instructions" ng-change="load_tries(selectedIns)">
</select> <option value="" translate>select_instruction</option>
</select>
<select ng-hide="!selectedMethod" class="form-control" name="instruction_select" id="instruction_select" ng-model="selectedIns" ng-options="ins.name for ins in selectedMethod.instructions" ng-change="load_tries(selectedIns)"> </form>
<option value="" translate>select_instruction</option> </div>
</select> </div>
</form> <div class="row" ng-hide="!selectedIns">
<p class="session_controls">
<div class="col-md-4">
<a ng-click="startTimer(); new_ws()" ng-disabled="!selectedIns" ng-hide="sessionRunning" class="btn btn-success btn-sm" role="button" id="session_new" translate>new_session</a>
<a class="text_large" ng-click="pause_ws(); pauseTimer();" ng-hide="!sessionRunning || paused" id="session_pause" popover="{{ 'pause_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-pause" aria-hidden="true" title="{{ 'pause_session' | translate }}"></span>
</a>
<a class="text_large" ng-click="resume_ws(); resumeTimer();" ng-hide="!sessionRunning || !paused" id="session_continue" popover="{{ 'continue_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-play" aria-hidden="true" title="{{ 'continue_session' | translate }}"></span>
</a>
<a class="text_large" ng-click="stopTimer(); stop_ws()" ng-hide="!sessionRunning" id="session_stop" popover="{{ 'finish_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-stop color_black" aria-hidden="true" title="{{ 'finish_session' | translate }}"></span>
</a>
</div> </div>
</div> <!--row --> <div class="col-md-2" style="text-align: right">
<!-- wsessions navigation info --> <span class="label label-success" style="font-size: 10pt">{{ 'sessions' | translate}} <span class="badge" style="font-size: 10pt">{{wsessions.length}}</span></span>
<div class="row" ng-hide="!selectedIns">
<!-- Fin de select con Instrucciones -->
<!-- Temporizador Sesión de trabajo -->
<p/><p class="session_controls">
<div class="col-md-4">
<a ng-click="startTimer(); new_ws()" ng-disabled="!selectedIns" ng-hide="sessionRunning" class="btn btn-success btn-sm" role="button" id="session_new" translate>new_session</a>
<a class="text_large" ng-click="pause_ws(); pauseTimer();" ng-hide="!sessionRunning || paused" id="session_pause" popover="{{ 'pause_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-pause" aria-hidden="true" title="{{ 'pause_session' | translate }}"></span>
</a>
<a class="text_large" ng-click="resume_ws(); resumeTimer();" ng-hide="!sessionRunning || !paused" id="session_continue" popover="{{ 'continue_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-play" aria-hidden="true" title="{{ 'continue_session' | translate }}"></span>
</a>
<a class="text_large" ng-click="stopTimer(); stop_ws()" ng-hide="!sessionRunning" id="session_stop" popover="{{ 'finish_session' | translate}}" popover-trigger="mouseenter">
<span class="glyphicon glyphicon-stop color_black" aria-hidden="true" title="{{ 'finish_session' | translate }}"></span>
</a>
</div>
<div class="col-md-2" style="text-align: right">
<span class="label label-success" style="font-size: 10pt">{{ 'sessions' | translate}} <span class="badge" style="font-size: 10pt">{{wsessions.length}}</span></span>
</div>
</div> </div>
<!-- Title for list of sessions FERNANDO: No necesario, ya aparece en la lista
<div class="page-header" ng-show="selectedIns"><h2 id="try_title">{{ 'sessions_of' | translate}} {{ selectedIns.name }}</h2></div>
-->
<!-- Tries panel with actual try and wsessions list -->
<div id="tries">
<!--
<p>Simular acciones alumno:
<a ng-click="select_picto()" class="btn btn-default btn-sm" role="button" id="" ng-disabled="showed">Seleccionar Picto</a>
<a ng-click="add_picto()" class="btn btn-primary btn-sm" role="button" id="" ng-disabled="showed">Añadir Picto</a>
<a ng-click="del_picto()" class="btn btn-danger btn-sm" role="button" id="" ng-disabled="showed">Eliminar Picto</a>
<a ng-click="show_sentence(); showed = true" class="btn btn-success btn-sm" role="button" id="" ng-disabled="showed">Entregar frase</a>
<a ng-click="unshow_sentence(); showed = false" class="btn btn-warning btn-sm" role="button" id="" ng-disabled="!showed">Volver a escritura tras entregar</a>
</p> </p>
--> </div>
<!-- PCB actions--> <div id="tries">
<!-- BORRAR!!! -->
<!--
<h3>PCB (BORRAR!!!)</h3>
<p>Sesión: {{ ws }}</p>
<div id="pcb_actions" class="try">
<div ng-repeat="pcb_a in pcb_actions track by $index" class="picto pull-left">
<img ng-src="{{pcb_a.attributes.picto.picto.uri}}">
<br />
<span>{{ pcb_a.action }}</span>
<br />
<span>{{ pcb_a.attributes.timestamp | date:'HH:mm:ss' }}</span>
</div>
<div class="clean"></div>
</div>
-->
<!-- BORRAR hasta aquí -->
<!-- Actual try -->
<div id="actual_try" ng-model="actual_try" ng-show="tryRunning"> <div id="actual_try" ng-model="actual_try" ng-show="tryRunning">
<div class="try_time"> <div class="try_time">
<timer id="time_try" class="color_blue" interval="1000" auto-start="false"> <timer id="time_try" class="color_blue" interval="1000" auto-start="false">
{{mminutes}}:{{sseconds}} {{mminutes}}:{{sseconds}}
</timer> </timer>
</div> </div>
<div class="try"> <div class="try">
<div class="pull-left" ng-repeat="a in actual_try.actions track by $index"> <div class="pull-left" ng-repeat="a in actual_try.actions track by $index">
<div class="picto" popover="{{ 'action-' + a.action | translate }}" popover-trigger="mouseenter"> <div class="picto" popover="{{ 'action-' + a.action | translate }}" popover-trigger="mouseenter">
...@@ -102,241 +55,207 @@ ...@@ -102,241 +55,207 @@
</div> </div>
</div> </div>
</div> </div>
<div class="try_result dropdown">
<div class="try_result" context-menu data-target="menu-new"> <span
<span class="glyphicon glyphicon-question-sign" ng-model="actual_try.result" aria-hidden="true"></span> class="glyphicon glyphicon-question-sign"
</div> ng-model="actual_try.result"
<div class="dropdown position-fixed" id="menu-new" style="z-index:10"> aria-hidden="true"
<ul class="dropdown-menu" role="menu"> data-toggle="dropdown"
data-target="#">
</span>
<ul class="dropdown-menu dropdown-menu-right" role="menu" style="z-index:10">
<li> <li>
<a class="pointer" role="menuitem" tabindex="0" ng-click="actual_try.result = null; update_current_try();send_show_action() "> <a class="pointer" role="menuitem" tabindex="0" ng-click="actual_try.result = null; update_current_try();send_show_action() ">
<span class="glyphicon glyphicon-question-sign color_blue" aria-hidden="true"></span> {{ 'state_not_evaluated' | translate }} <span class="glyphicon glyphicon-question-sign color_blue" aria-hidden="true"></span> {{ 'state_not_evaluated' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="1" ng-click="actual_try.result = 'SUCCESS'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="1" ng-click="actual_try.result = 'SUCCESS'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-ok color_green" aria-hidden="true"></span> {{ 'state_correct' | translate }} <span class="glyphicon glyphicon-ok color_green" aria-hidden="true"></span> {{ 'state_correct' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="2" ng-click="actual_try.result = 'SUPERVISED SUCCESS'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="2" ng-click="actual_try.result = 'SUPERVISED SUCCESS'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-ok-circle color_blue" aria-hidden="true"></span> {{ 'state_supervised' | translate }} <span class="glyphicon glyphicon-ok-circle color_blue" aria-hidden="true"></span> {{ 'state_supervised' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="3" ng-click="actual_try.result = 'SPONTANEOUS SUCCESS';update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="3" ng-click="actual_try.result = 'SPONTANEOUS SUCCESS';update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-user color_blue" aria-hidden="true"></span> {{ 'state_spontaneous' | translate }} <span class="glyphicon glyphicon-user color_blue" aria-hidden="true"></span> {{ 'state_spontaneous' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="4" ng-click="actual_try.result = 'FAIL'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="4" ng-click="actual_try.result = 'FAIL'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span> {{ 'state_fail' | translate }} <span class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span> {{ 'state_fail' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="5" ng-click="actual_try.result = 'DISCARDED'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="5" ng-click="actual_try.result = 'DISCARDED'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-trash color_red" aria-hidden="true"></span> {{ 'state_discarded' | translate }} <span class="glyphicon glyphicon-trash color_red" aria-hidden="true"></span> {{ 'state_discarded' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="6" ng-click="actual_try.result = 'MODEL'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="6" ng-click="actual_try.result = 'MODEL'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-edit color_orange" aria-hidden="true"></span> {{ 'state_demonstration' | translate }} <span class="glyphicon glyphicon-edit color_orange" aria-hidden="true"></span> {{ 'state_demonstration' | translate }}
</a> </a>
</li> </li>
<li> <li>
<a class="pointer" role="menuitem" tabindex="7" ng-click="actual_try.result = 'BROKEN'; update_current_try(); send_show_action() "> <a class="pointer" role="menuitem" tabindex="7" ng-click="actual_try.result = 'BROKEN'; update_current_try(); send_show_action() ">
<span class="glyphicon glyphicon-flash color_black" aria-hidden="true"></span> {{ 'state_broken' | translate }} <span class="glyphicon glyphicon-flash color_black" aria-hidden="true"></span> {{ 'state_broken' | translate }}
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="clean"></div> <div class="clean"></div>
</div> <!-- .try --> </div>
</div> <!-- #actual_try --> </div>
<!-- Next sessions -->
<div class="tries_nav" ng-show="!showLastTry && wsessions.length > 0"> <div class="tries_nav" ng-show="!showLastTry && wsessions.length > 0">
<a ng-click="before()" class="btn btn-sm" role="button" id="" ng-disabled="currentPage == 1" ng-hide="wsessions.length == 0"> <a ng-click="before()" class="btn btn-sm" role="button" id="" ng-disabled="currentPage == 1" ng-hide="wsessions.length == 0">
<span class="glyphicon glyphicon-chevron-up" aria-hidden="true" popover="{{ 'next_sessions' | translate}}" popover-trigger="mouseenter"></span> <span class="glyphicon glyphicon-chevron-up" aria-hidden="true" popover="{{ 'next_sessions' | translate}}" popover-trigger="mouseenter"></span>
</a> </a>
</div> </div>
<!-- wsessions -->
<div class="list-group"> <div class="list-group">
<div class="list-group-item" ng-repeat="s in wsessions | orderBy: '-begin' | limitTo: numPerPage:(currentPage-1)*numPerPage"> <div class="list-group-item" ng-repeat="s in wsessions | orderBy: '-begin' | limitTo: numPerPage:(currentPage-1)*numPerPage">
<!-- <span class="badge">{{ s.tries.length }}</span> --> <div ng-show="showLastTry && wsessions.length > 0">
<div ng-show="showLastTry && wsessions.length > 0"> <h4><strong>{{ 'last_session' | translate}}</strong>: {{ studentData.current_method }}, {{ studentData.current_instruction }}</h4>
<h4> <div ng-show="ws_recover" >
<strong>{{ 'last_session' | translate}}</strong>: {{ studentData.current_method }}, {{ studentData.current_instruction }} <table style="border: 1px solid #666666; padding:5px; background-color:#f5f5f5;" width="100%">
</h4> <tr>
<div ng-show="ws_recover" > <td><h4 translate>warning_last_session_bad</h4></td>
<table style="border: 1px solid #666666; padding:5px; background-color:#f5f5f5;" width="100%"> <td>
<td><h4 translate>warning_last_session_bad</h4></td> <button class="btn btn-success btn-sm" type="button" ng-click="close_ws()" translate>close_session</button>
<td> </td>
<button class="btn btn-success btn-sm" type="button" ng-click="close_ws()" translate> </tr>
close_session </table>
</div>
</div>
<button class="btn btn-primary pull-right" type="button" ng-click="showTries = !showTries">
{{ 'tries' | translate }}
<span class="badge">{{ s.tries.length }}</span>
</button> </button>
</td> <span ng-show="!showLastTry" class="list-group-item-heading color_green">{{$index+1}}&nbsp;&nbsp;&nbsp;</span>
</table> <p style="text-align: left ; margin-bottom: 5px" class="list-group-item-text color_green">
<b>{{ 'tpl_day' | translate:{'day':s.begin} }}</b>
{{ 'tpl_hours_frame' | translate:{'begin':s.begin, 'end':s.end} }}
</p> </p>
</div> <textarea type="editable title" rows="2" id="ins_desc_ws" placeholder=" {{ 'session_notes' | translate }}" ng-model="s.description"
</div> <!--showLasTry --> ng-model-options="{ updateOn: 'blur' }" ng-change="update_ws(s)" cols="80"></textarea>
<a class="session_details" ng-click="showTries = !showTries">
<button class="btn btn-primary pull-right" type="button" ng-click="showTries = !showTries"> <span ng-if="!showTries" class="glyphicon glyphicon-collapse-down color_green" aria-hidden="true"></span>
{{ 'tries' | translate }} <span class="badge">{{ s.tries.length }}</span> <span ng-if="showTries" class="glyphicon glyphicon-collapse-up color_green" aria-hidden="true"></span>
</button> </a>
<div class="sessionTries" ng-class="{ 'hidden': !showTries && ws.id!=s.id }">
<span ng-show="!showLastTry" class="list-group-item-heading color_green">{{$index+1}}&nbsp;&nbsp;&nbsp;</span> <div class="try" ng-repeat="t in s.tries">
<p style="text-align: left ; margin-bottom: 5px" class="list-group-item-text color_green"> <div ng-show="!is_currentOpenTry(t)">
<b>{{ 'tpl_day' | translate:{'day':s.begin} }}</b> <table width="100%">
{{ 'tpl_hours_frame' | translate:{'begin':s.begin, 'end':s.end} }} <tr>
</p> <td class="dropdown">
<textarea type="editable title" rows="2" id="ins_desc_ws" placeholder=" {{ 'session_notes' | translate }}" ng-model="s.description" <div class="pull-left" ng-repeat="p in t.actions">
ng-model-options="{ updateOn: 'blur' }" ng-change="update_ws(s)" cols="80"></textarea> <div class="picto" popover="{{ 'action-' + p.type | translate }}" popover-trigger="mouseenter">
<!-- Collapse tries --> <img ng-src="{{ p.description.picto.uri }}">
<a class="session_details" ng-click="showTries = !showTries"> <div class="action-type">
<span ng-if="!showTries" class="glyphicon glyphicon-collapse-down color_green" aria-hidden="true"></span> <span ng-if="p.type == 'Select'" class="glyphicon glyphicon-hand-up color_blue" aria-hidden="true"></span>
<span ng-if="showTries" class="glyphicon glyphicon-collapse-up color_green" aria-hidden="true"></span> <span ng-if="p.type == 'Delete'" class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span>
</a> <span ng-if="p.type == 'Show'" class="glyphicon glyphicon-eye-open color_blue" aria-hidden="true"></span>
<span ng-if="p.type == 'Unshow'" class="glyphicon glyphicon-edit color_blue" aria-hidden="true"></span>
<div class="sessionTries" ng-class="{ 'hidden': !showTries && ws.id!=s.id }"> <!--current working session is always showed --> <span ng-if="p.type == 'tryinit'" class="glyphicon glyphicon-log-in" aria-hidden="true"></span>
<div class="try" ng-repeat="t in s.tries"> <span ng-if="p.type == 'tryend'" class="glyphicon glyphicon-log-out" aria-hidden="true"></span>
<div ng-show="!is_currentOpenTry(t)"> <!--the current try is not showed--> <span ng-if="p.type == 'pausesession'" class="glyphicon glyphicon-pause" aria-hidden="true"></span>
<!-- Pictos submitted by the student --> <span ng-if="p.type == 'resumesession'" class="glyphicon glyphicon-play" aria-hidden="true"></span>
<table width="100%"> </div>
<tr><td> </div>
</div>
<div class="pull-left" ng-repeat="p in t.actions"> <div class="try_result pull-right" data-toggle="dropdown" data-target="#">
<div class="picto" popover="{{ 'action-' + p.type | translate }}" popover-trigger="mouseenter"> <span class="glyphicon" ng-class="{
<img ng-src="{{ p.description.picto.uri }}"> 'glyphicon-question-sign': t.result == null,
<div class="action-type"> 'glyphicon-ok': t.result == 'SUCCESS',
<span ng-if="p.type == 'Select'" class="glyphicon glyphicon-hand-up color_blue" aria-hidden="true"></span> 'glyphicon-ok-circle': t.result == 'SUPERVISED SUCCESS',
<span ng-if="p.type == 'Delete'" class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span> 'glyphicon-user': t.result == 'SPONTANEOUS SUCCESS',
<span ng-if="p.type == 'Show'" class="glyphicon glyphicon-eye-open color_blue" aria-hidden="true"></span> 'glyphicon-remove': t.result == 'FAIL',
<span ng-if="p.type == 'Unshow'" class="glyphicon glyphicon-edit color_blue" aria-hidden="true"></span> 'glyphicon-trash': t.result == 'DISCARDED',
<span ng-if="p.type == 'tryinit'" class="glyphicon glyphicon-log-in" aria-hidden="true"></span> 'glyphicon-edit': t.result == 'MODEL',
<span ng-if="p.type == 'tryend'" class="glyphicon glyphicon-log-out" aria-hidden="true"></span> 'glyphicon-flash': t.result == 'BROKEN',
<span ng-if="p.type == 'pausesession'" class="glyphicon glyphicon-pause" aria-hidden="true"></span> 'color_green': t.result == 'SUCCESS',
<span ng-if="p.type == 'resumesession'" class="glyphicon glyphicon-play" aria-hidden="true"></span> 'color_blue': t.result == 'SUPERVISED SUCCESS' || t.result == 'SPONTANEOUS SUCCESS' || t.result == null,
</div> 'color_red': t.result == 'FAIL' || t.result == 'DISCARDED',
'color_black': t.result == 'BROKEN',
'color_orange': t.result == 'MODEL'
}" aria-hidden="true" title="{{t.result | translate}}">
</span>
</div>
<ul class="dropdown-menu dropdown-menu-right" role="menu" style="z-index:10">
<li>
<a class="pointer" role="menuitem" tabindex="0" ng-click="t.result = null; update_try(t)">
<span class="glyphicon glyphicon-question-sign color_blue" aria-hidden="true"></span>
{{ 'state_not_evaluated' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="1" ng-click="t.result = 'SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-ok color_green" aria-hidden="true"></span> {{ 'state_correct' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="2" ng-click="t.result = 'SUPERVISED SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-ok-circle color_blue" aria-hidden="true"></span> {{ 'state_supervised' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="3" ng-click="t.result = 'SPONTANEOUS SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-user color_blue" aria-hidden="true"></span> {{ 'state_spontaneous' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="4" ng-click="t.result = 'FAIL'; update_try(t)">
<span class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span> {{ 'state_fail' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="5" ng-click="t.result = 'DISCARDED'; update_try(t)">
<span class="glyphicon glyphicon-trash color_red" aria-hidden="true"></span> {{ 'state_discarded' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="6" ng-click="t.result = 'MODEL'; update_try(t)">
<span class="glyphicon glyphicon-edit color_orange" aria-hidden="true"></span> {{ 'state_demonstration' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="7" ng-click="t.result = 'BROKEN'; update_try(t)">
<span class="glyphicon glyphicon-flash color_black" aria-hidden="true"></span> {{ 'state_broken' | translate }}
</a>
</li>
</ul>
</td>
</tr>
<tr>
<td>
<div class="try_time pull-left">
<div class="color_blue">
<strong>({{$index+1}}) {{ 'tpl_day' | translate:{'day':t.begin} }}</strong>
{{ 'tpl_hours_frame' | translate:{'begin':t.begin, 'end':t.end} }}
</div>
</div>
<a class="try_details" ng-click="showTryNotes = !showTryNotes">
<span ng-if="!showActions" class="glyphicon glyphicon-collapse-down" aria-hidden="true"></span>
<span ng-if="showActions" class="glyphicon glyphicon-collapse-up" aria-hidden="true"></span>
</a>
<div class="tryNotes pull-left" ng-class="{ 'hidden': !showTryNotes }">
<textarea type="editable title" rows="2" id="ins_desc_try" placeholder=" {{ 'notes' | translate }}" ng-model="t.description" ng-model-options="{ updateOn: 'blur' }" ng-change="update_try(t)" cols="80"></textarea>
</div>
</td>
</tr>
</table>
</div> </div>
</div>
<div class="try_result pull-right" context-menu data-target="menu-{{ t.id }}" >
<span class="glyphicon" ng-class="{
'glyphicon-question-sign': t.result == null,
'glyphicon-ok': t.result == 'SUCCESS',
'glyphicon-ok-circle': t.result == 'SUPERVISED SUCCESS',
'glyphicon-user': t.result == 'SPONTANEOUS SUCCESS',
'glyphicon-remove': t.result == 'FAIL',
'glyphicon-trash': t.result == 'DISCARDED',
'glyphicon-edit': t.result == 'MODEL',
'glyphicon-flash': t.result == 'BROKEN',
'color_green': t.result == 'SUCCESS',
'color_blue': t.result == 'SUPERVISED SUCCESS' || t.result == 'SPONTANEOUS SUCCESS' || t.result == null,
'color_red': t.result == 'FAIL' || t.result == 'DISCARDED',
'color_black': t.result == 'BROKEN',
'color_orange': t.result == 'MODEL'
}" aria-hidden="true" title="{{t.result | translate}}">
</span>
</div>
</td></tr>
<tr><td>
<div class="try_time pull-left">
<div class="color_blue">
<strong> ({{$index+1}}) {{ 'tpl_day' | translate:{'day':t.begin} }}</strong>
{{ 'tpl_hours_frame' | translate:{'begin':t.begin, 'end':t.end} }}
</div> </div>
</div> </div>
</div>
<!-- Collapse try notes --> <div class="tries_nav" ng-show="!showLastTry ">
<a class="try_details" ng-click="showTryNotes = !showTryNotes"> <a ng-click="after()" class="btn btn-sm" role="button" id="" ng-disabled="currentPage == totalPages || totalPages == 0" ng-hide="wsessions.length == 0">
<span ng-if="!showActions" class="glyphicon glyphicon-collapse-down" aria-hidden="true"></span> <span class="glyphicon glyphicon-chevron-down" aria-hidden="true" popover="{{ 'previous_sessions' | translate}}" popover-trigger="mouseenter"></span>
<span ng-if="showActions" class="glyphicon glyphicon-collapse-up" aria-hidden="true"></span> </a>
</a>
<!-- List of try actions -->
<div class="tryNotes pull-left" ng-class="{ 'hidden': !showTryNotes }">
<textarea type="editable title" rows="2" id="ins_desc_try" placeholder=" {{ 'notes' | translate }}" ng-model="t.description"
ng-model-options="{ updateOn: 'blur' }" ng-change="update_try(t)" cols="80"></textarea>
</div>
</td></tr>
</table>
<!-- Context Menu -->
<div class="dropdown position-fixed" id="menu-{{ t.id }}" style="z-index:10">
<ul class="dropdown-menu" role="menu">
<li>
<a class="pointer" role="menuitem" tabindex="0" ng-click="t.result = null; update_try(t)">
<span class="glyphicon glyphicon-question-sign color_blue" aria-hidden="true"></span> {{ 'state_not_evaluated' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="1" ng-click="t.result = 'SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-ok color_green" aria-hidden="true"></span> {{ 'state_correct' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="2" ng-click="t.result = 'SUPERVISED SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-ok-circle color_blue" aria-hidden="true"></span> {{ 'state_supervised' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="3" ng-click="t.result = 'SPONTANEOUS SUCCESS'; update_try(t)">
<span class="glyphicon glyphicon-user color_blue" aria-hidden="true"></span> {{ 'state_spontaneous' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="4" ng-click="t.result = 'FAIL'; update_try(t)">
<span class="glyphicon glyphicon-remove color_red" aria-hidden="true"></span> {{ 'state_fail' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="5" ng-click="t.result = 'DISCARDED'; update_try(t)">
<span class="glyphicon glyphicon-trash color_red" aria-hidden="true"></span> {{ 'state_discarded' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="6" ng-click="t.result = 'MODEL'; update_try(t)">
<span class="glyphicon glyphicon-edit color_orange" aria-hidden="true"></span> {{ 'state_demonstration' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="7" ng-click="t.result = 'BROKEN'; update_try(t)">
<span class="glyphicon glyphicon-flash color_black" aria-hidden="true"></span> {{ 'state_broken' | translate }}
</a>
</li>
</ul>
</div>
<!-- End Context Menu -->
</div> <!-ng-show-->
<!-- End .try -->
</div> </div>
<!-- .sessionTries -->
</div>
<!-- End .session -->
</div>
<!-- list-group -->
<!-- Previous sessions -->
<div class="tries_nav" ng-show="!showLastTry ">
<a ng-click="after()" class="btn btn-sm" role="button" id="" ng-disabled="currentPage == totalPages || totalPages == 0" ng-hide="wsessions.length == 0">
<span class="glyphicon glyphicon-chevron-down" aria-hidden="true" popover="{{ 'previous_sessions' | translate}}" popover-trigger="mouseenter"></span>
</a>
</div> </div>
</div> </div>
<!-- End #tries -->
</div> </div>
<!-- Fin de panel body -->
</div> </div>
<!-- Fin de panel -->
<nav id="supervisor_header"class="navbar navbar-default" role="navigation"> <nav
<div class="container-fluid"> class="topbar navbar navbar-default"
<!-- Lo que se muestra en dispositivos móviles --> role="navigation">
<div class="container-fluid">
<div class="navbar-header"> <div class="navbar-header">
<button class="navbar-toggle" data-target=".navbar-ex6-collapse" data-toggle="collapse" type="button"> <a
<span class="sr-only">{{ 'expand_navigation' | translate }}</span> class="topbar__logo navbar-brand"
<!-- Un span por línea del icono de abrir menú --> href="/app/#/students">
<span class="icon-bar"></span> <img
<span class="icon-bar"></span> class="topbar__logo__image"
<span class="icon-bar"></span> src="img/logo_pictogram.png"
</button> alt="Pictogram"
<a class="navbar-brand" href="/app/#/students"><img src="img/logo_pictogram.png" alt="Pictogram" title="Pictogram" style="height: 50px;" /></a> title="Pictogram" />
</a>
</div> </div>
<div class="topbar__supervisor nav navbar-nav navbar-right">
<div class="dropdown">
<!-- Agrupar los enlaces de navegación, los formularios y cualquier otro elemento que se pueda ocultar al minimizar la barra --> <div class="topbar__supervisor__name">
<div class="collapse navbar-collapse navbar-ex6-collapse"> <div class="topbar__supervisor__name__fullname">{{user.getFullName()}}</div>
<div class="topbar__supervisor__name__office">{{user.office.name}}</div>
<div class="nav navbar-nav navbar-right thumbnail img_profile" context-menu data-target="menu-sup">
<img id="supervisor_profile" ng-src="{{user.pic}}" alt="Supervisor" title="Supervisor" />
</div> </div>
<div class="dropdown position-fixed" id="menu-sup" style="z-index:10"> <div
<ul class="dropdown-menu" role="menu"> class="topbar__supervisor__avatar thumbnail"
<li> data-toggle="dropdown"
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/setup"> data-target="#">
<span class="glyphicon glyphicon-cog" aria-hidden="true"></span> {{ 'setup' | translate }} <img id="supervisor_profile" ng-src="{{user.pic}}" alt="Supervisor" title="Supervisor" />
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="0" ng-click="logout()">
<span class="glyphicon glyphicon-log-out" aria-hidden="true"></span> {{ 'logout' | translate }}
</a>
</li>
</ul>
</div>
<div class="nav navbar-nav navbar-right navbar-text">
<div class="text-right">{{user.getFullName()}}</div>
<div class="text-right">{{user.office.name}}</div>
</div> </div>
<ul class="dropdown-menu" role="menu">
<li>
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/setup">
<i class="glyphicon glyphicon-cog" aria-hidden="true"></i>
{{ 'setup' | translate }}
</a>
</li>
<li>
<a class="pointer" role="menuitem" tabindex="0" ng-click="logout()">
<span class="glyphicon glyphicon-log-out" aria-hidden="true"></span>
{{ 'logout' | translate }}
</a>
</li>
</ul>
</div>
</div> </div>
</div> </div>
</nav> </nav>
\ No newline at end of file
...@@ -43,20 +43,6 @@ ...@@ -43,20 +43,6 @@
font-size: 30px; font-size: 30px;
} }
.img_profile{
width: 80px;
height: 80px;
}
.img_profile img{
width: 100%;
height: 100%;
}
.position-fixed {
position: fixed;
}
.padding8{ .padding8{
padding: 8px; padding: 8px;
} }
...@@ -181,20 +167,6 @@ tr:hover .ops a{ ...@@ -181,20 +167,6 @@ tr:hover .ops a{
margin-bottom: 70px; margin-bottom: 70px;
} }
/* Estilos para la cabecera del supervisor */
#supervisor_header{
margin-bottom: 5px;
}
#supervisor_header .img_profile{
margin-top: 10px;
margin-left: 10px;
margin-bottom: 0;
width: 50px;
height: 50px;
overflow: hidden;
}
/* Estilos para la cabecera del alumno */ /* Estilos para la cabecera del alumno */
#student_header{ #student_header{
background: #F5F5F3; background: #F5F5F3;
...@@ -514,11 +486,6 @@ textarea.editable{ ...@@ -514,11 +486,6 @@ textarea.editable{
margin-top: 10px; margin-top: 10px;
} }
/* Para que la altura de los li de la lista se adapte al tamaño automáticamente */
.list-group-item{
overflow:hidden;
}
/* Etiquetas dentro de las ventanas modales de info y etiquetas de los pictos */ /* Etiquetas dentro de las ventanas modales de info y etiquetas de los pictos */
#picto_tags .label, #picto_info .label{ #picto_tags .label, #picto_info .label{
margin: 4px; margin: 4px;
...@@ -677,9 +644,7 @@ textarea.editable{ ...@@ -677,9 +644,7 @@ textarea.editable{
float: right; float: right;
font-size: 36px; font-size: 36px;
margin: 10px 10px 0 0; margin: 10px 10px 0 0;
cursor: pointer; cursor: hand; cursor: pointer;
text-shadow: 1px 1px 1px #222;
} }
/* Para que se vea el menú contextual por encima del resto de paneles */ /* Para que se vea el menú contextual por encima del resto de paneles */
......
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
@import (less) '../app/bower_components/angular-chart.js/dist/angular-chart.css'; @import (less) '../app/bower_components/angular-chart.js/dist/angular-chart.css';
@import (less) 'cropper.css'; @import (less) 'cropper.css';
@import (less) 'main.css'; @import (less) 'main.css';
@import 'topbar.less';
/**
* This navigation element will be shown accross the whole interface when
* a supervisor has logged in.
*/
.topbar {
padding: 0.5em;
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
&__logo {
width: 5rem;
height: 5rem;
padding: 0;
margin-left: 0;
border-radius: 2px;
&__image {
width: 100%;
height: 100%;
border-radius: 2px;
}
}
&__supervisor {
&__name {
display: inline-block;
vertical-align: top;
padding: 0.5em;
&__fullname,
&__office {
text-align: right;
}
&__office {
opacity: 0.75;
}
}
&__avatar {
width: 5rem;
height: 5rem;
border-radius: 2px;
display: inline-block;
margin-bottom: 0;
cursor: pointer;
& img {
width: 100%;
height: 100%;
border-radius: 2px;
}
}
}
}
...@@ -120,6 +120,8 @@ module.exports.policies = { ...@@ -120,6 +120,8 @@ module.exports.policies = {
per_year: ['tokenAuth'], per_year: ['tokenAuth'],
per_month: ['tokenAuth'], per_month: ['tokenAuth'],
tries: ['tokenAuth'], tries: ['tokenAuth'],
create: ['tokenAuth'],
update: ['tokenAuth'],
close: ['tokenAuth'] close: ['tokenAuth']
} }
}; };
...@@ -103,5 +103,7 @@ module.exports.routes = { ...@@ -103,5 +103,7 @@ module.exports.routes = {
'GET /ws/:id_stu/year/:year': 'WorkingSessionController.per_year', 'GET /ws/:id_stu/year/:year': 'WorkingSessionController.per_year',
'GET /ws/:id_stu/month/:month': 'WorkingSessionController.per_month', 'GET /ws/:id_stu/month/:month': 'WorkingSessionController.per_month',
'GET /ws/:id_ws/tries': 'WorkingSessionController.tries', 'GET /ws/:id_ws/tries': 'WorkingSessionController.tries',
'PUT /workingsession/:id': 'WorkingSessionController.update',
'POST /workingsession': 'WorkingSessionController.create',
'POST /workingsession/:id_ws/close': 'WorkingSessionController.close' 'POST /workingsession/:id_ws/close': 'WorkingSessionController.close'
}; };
...@@ -22,7 +22,6 @@ module.exports = function (grunt) { ...@@ -22,7 +22,6 @@ module.exports = function (grunt) {
'assets/app/bower_components/angular-sanitize/angular-sanitize.js', 'assets/app/bower_components/angular-sanitize/angular-sanitize.js',
'assets/app/bower_components/ngtoast/dist/ngToast.js', 'assets/app/bower_components/ngtoast/dist/ngToast.js',
'assets/app/bower_components/ng-context-menu/dist/ng-context-menu.js',
'assets/app/bower_components/Chart.js/Chart.js', 'assets/app/bower_components/Chart.js/Chart.js',
'assets/app/bower_components/angular-chart.js/dist/angular-chart.js', 'assets/app/bower_components/angular-chart.js/dist/angular-chart.js',
'assets/app/bower_components/ng-lodash/build/ng-lodash.js', 'assets/app/bower_components/ng-lodash/build/ng-lodash.js',
......
...@@ -2,5 +2,7 @@ describe('Working Session API', function () { ...@@ -2,5 +2,7 @@ describe('Working Session API', function () {
it('GET /ws/:id_stu/year/:year'); it('GET /ws/:id_stu/year/:year');
it('GET /ws/:id_stu/month/:month'); it('GET /ws/:id_stu/month/:month');
it('GET /ws/:id_ws/tries'); it('GET /ws/:id_ws/tries');
it('POST /workingsession');
it('PUT /workingsession/:id');
it('POST /workingsession/:id_ws/close'); it('POST /workingsession/:id_ws/close');
}); });
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