gestion de terapeutas tutores y altas/bajas operativo

parent dc1fad4c
......@@ -146,7 +146,7 @@ CREATE TABLE IF NOT EXISTS `office` (
`phone1` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`phone2` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`admin` int(11) DEFAULT NULL COMMENT 'Teacher administrator, able to associate students to teachers',
`max_students` int(4) DEFAULT 2 COMMENT 'Maximun number of enrolments for a given office',
`max_students` int(4) DEFAULT 10 COMMENT 'Maximun number of enrolments for a given office',
`current_students` int(4) DEFAULT 0 COMMENT 'calculable attr: current number of enrolments',
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
......
......@@ -90,38 +90,57 @@ module.exports = {
* exp: 1231292,
* attributes: { @see Student.getValidAttributes() },
* current_method: 'Do Things', // May be null
* current_instruction: 'Do Stuff' // May be null
* current_instruction: 'Do Stuff', // May be null
* supervision: 0|1|2, // supervision level according to requester 0 -> office admin, 1 -> tutor, 2 -> therapist
* }
*/
getInfo: function (req, res) {
Student.findOne({
id: req.params.id_stu
})
.then(function (student) {
if (student) {
student.current_method = null;
student.current_instruction = null;
VStuLastInstruction
.findOne({
student: student.id
})
.then(function (studentLastInstruction) {
if (studentLastInstruction) {
student.current_method = studentLastInstruction.met_name;
student.current_instruction = studentLastInstruction.ins_name;
}
res.ok(student);
})
.catch(function (error) {
res.serverError();
});
} else {
res.notFound();
}
})
.catch(function () {
res.serverError();
});
Student.findOne({id: req.params.id_stu})
.then(function (student) {
if (!student)
throw new Error("student not found");
student.current_method = null;
student.current_instruction = null;
// recover last instruction to complete student info
var stu_last_inst = VStuLastInstruction.findOne({student: student.id})
.then(function (stu_last_inst) {
return stu_last_inst;
});
// determine supervision level of the requester on the student
var stu_sup = StuSup.findOne({id_stu: student.id, id_sup: req.token.id})
.then(function (stu_sup) {
return stu_sup
});
return [student, stu_last_inst, stu_sup];
})
.spread(function (student, stu_last_inst, stu_sup) {
if (stu_last_inst) {
student.current_method = stu_last_inst.met_name;
student.current_instruction = stu_last_inst.ins_name;
}
// requester has no relation
student.supervision = -1;
if (!stu_sup && req.token.office && student.office == req.token.office.id)
student.supervision = 0; // requester is admin of the office
else if (stu_sup && !req.token.office)
student.supervision = 1; // requester is tutor of the studend
else if (stu_sup && req.token.office && student.office == req.token.office.id)
student.supervision = 2; // requester is supervisor of student
if (student.supervision == -1) // should not hace access!!!
return res.forbidden("Access to this student should not be granted to you");
return res.ok(student);
})
.catch(function (err) {
return res.notFound(err);
});
},
//
......@@ -353,7 +372,9 @@ module.exports = {
* Creates a relation between the student and a given supervisor.
* It broadcasts the even linkSupervisorToStudent to both the student room
* and the supervisor room.
* @param {request} {} (with studentId and supervisorId as url parameters)
* @param {request} { (with id_stu and id_sup as url parameters)
* asTherapist: true/false (optional) // assigns supervisor to student's office is true, set id_off to null otherwise
* }
* @param {response} {}
*/
link_supervisor: function (req, res) {
......@@ -362,9 +383,8 @@ module.exports = {
supervisor: req.param('id_sup')
})
.then(function (stuSup) {
if (!stuSup) {
if (!stuSup)
throw new Error('stusup not created');
}
const socketToOmit = (req.isSocket) ? req.socket : undefined;
const linkSupervisorToStudentEvent = sails.hooks.events.linkSupervisorToStudent(
......@@ -383,18 +403,40 @@ module.exports = {
socketToOmit
);
res.ok();
return stuSup;
})
.catch(() => {
.catch((err) => {
StuSup.findOne({ student: req.param('id_stu'), supervisor: req.param('id_sup') })
.then((stuSup) => {
if (stuSup) {
res.ok();
} else {
res.badRequest();
// It was already there!
if (stuSup)
return stuSup;
else
throw err;
});
})
.then((stuSup) => {
// update supervisor office if it is linked as therapist
Supervisor.findOne({id: req.param('id_sup')})
.then((sup) => {
if (sup) {
Student.findOne({id: req.param('id_stu')})
.then((stu) => {
if (stu) {
if (req.body.asTherapist)
sup.office = stu.office;
else
sup.office = NULL;
delete sup.password;
sup.save();
}
});
}
})
.catch(() => res.serverError());
});
return res.ok();
})
.catch((err) => {
return res.serverError("Error: " + err);
});
},
......@@ -412,15 +454,9 @@ module.exports = {
})
.then((stuSup) => {
if (!stuSup)
res.badRequest();
throw new Error("student and supervisor are not linked");
stuSup.destroy({
student: req.param('id_stu'),
supervisor: req.param('id_sup')
}).then(function(err){
if (err)
throw err;
});
stuSup.destroy();
const socketToOmit = req.isSocket ? req.socket : undefined;
const unlinkSupervisorFromStudentEvent = sails.hooks.events.unlinkSupervisorFromStudent(
......@@ -440,10 +476,10 @@ module.exports = {
socketToOmit
);
res.ok();
return res.ok();
})
.catch(() => {
res.serverError();
.catch((err) => {
res.serverError("Error unliking student: " + err);
});
},
......
......@@ -58,43 +58,53 @@ module.exports = {
var email = req.body.email;
var password = req.body.password;
if (email && password) {
Supervisor.findOneByEmail(email).then(function (supervisor) {
if (supervisor) {
if (bcrypt.compareSync(password, supervisor.password)) {
Office.findOne(supervisor.office).then(function (office) {
if (office) {
supervisor.office = office;
supervisor.isSupAdmin = (office.admin === supervisor.id);
res.ok({
user: supervisor,
server_time: (new Date()).getTime(),
token: sailsTokenAuth.issueToken(supervisor, sails.config.jwt.expiresInMinutes)
});
} else {
res.ok({
user: supervisor,
server_time: (new Date()).getTime(),
token: sailsTokenAuth.issueToken(supervisor, sails.config.jwt.expiresInMinutes)
});
}
})
.catch(function () {
res.serverError();
});
} else {
res.badRequest('Invalid password');
}
} else {
res.badRequest('Invalid user');
}
})
.catch(function () {
res.badRequest('Invalid user or password');
if (!email || !password)
return res.badRequest('No email or or password');
Supervisor.findOneByEmail(email).then(function (supervisor) {
if (!supervisor)
throw new Error('Invalid user');
if (!bcrypt.compareSync(password, supervisor.password))
throw new Error('Invalid password');
return (supervisor);
}).then(function (supervisor) {
var stuSup = StuSup.findOne({id_sup: supervisor.id})
.then(function (stuSup) {
if (!stuSup)
throw new Error("User without students linked to");
return stuSup;
});
var office = Office.findOne({id: supervisor.office})
.then(function (office) {
return office;
});
return [office, stuSup, supervisor];
}).spread(function(office, stuSup, supervisor) {
supervisor.office = office;
if (office)
supervisor.isSupAdmin = (office.admin === supervisor.id);
return res.ok({
user: supervisor,
server_time: (new Date()).getTime(),
token: sailsTokenAuth.issueToken(supervisor, sails.config.jwt.expiresInMinutes)
});
} else {
res.badRequest('No email or or password');
}
})
.catch(function (err) {
return res.badRequest("Error in login: " + err);
});
},
/**
......@@ -115,29 +125,23 @@ module.exports = {
* }
*/
activate: function (req, res) {
if (req.body.code && req.body.email) {
Supervisor.findOne({ email: req.body.email }).then(function (supervisor) {
if (supervisor) {
/* @TODO check user validation code */
supervisor.active = true;
supervisor.save(function (error) {
if (error) {
res.serverError();
} else {
res.ok();
}
});
res.ok(supervisor);
} else {
res.badRequest();
}
if (!req.params.token)
return res.badRequest("Invalid activation URL");
sailsTokenAuth.verifyToken(req.params.token, function(err, token) {
if (err)
return res.badRequest("Invalid token");
Supervisor.findOne(token).then(function (supervisor) {
if (!supervisor)
throw new Error("Error when looking for user");
supervisor.active = true;
delete supervisor.password;
supervisor.save();
return res.view('accountActivated', {sup: supervisor, login_url: req.protocol + '://' + req.headers.host + '/app'});
})
.catch(function () {
res.serverError();
.catch(function (err) {
return res.serverError("Error when activating account " + err);
});
} else {
req.badRequest();
}
});
},
/**
......@@ -202,6 +206,8 @@ module.exports = {
create: function (req, res) {
var params = req.params.all();
sails.log.debug("Creating supervisor with params " + JSON.stringify(params));
if (params.name &&
params.surname &&
params.gender &&
......@@ -220,20 +226,39 @@ module.exports = {
lang: params.lang || null,
ttsEngine: params.ttsEngine || null
}).then(function (supervisor) {
if (supervisor) {
/* @TODO send email confirmation */
if (!supervisor)
res.serverError("Supervisor created but returned null");
sails.log.debug("SUPERVISOR: " + JSON.stringify(supervisor));
/* Send email confirmation */
var message = sails.__({
phrase: 'signin_mail',
locale: params.lang || 'es-es'
}) + req.protocol + '://' + req.headers.host + '/sup/activate/' + sailsTokenAuth.issueToken(supervisor.id, 60*24*7); // expires in 1 week
sails.log.debug("Sending activation email: \n" + message);
mailService.mailer()
.send({
to: params.email,
text: message
})
.then(() => {
res.ok({
user: supervisor,
token: sailsTokenAuth.issueToken(supervisor.id)
});
} else {
res.serverError();
}
}).catch(function () {
res.serverError();
})
.catch((err) => {
res.serverError("Mail could not be sent " + err);
});
}).catch(function (err) {
res.serverError("Supervisor could not be created: " + err);
});
} else {
res.badRequest();
res.badRequest("Invalid params");
}
},
......
......@@ -274,6 +274,7 @@ module.exports = {
//
// Class method for getting the list of therapists associated to a given
// student
// NOTE: A therapist is a supervisor assigned to an office
therapists: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
var l = [];
......@@ -300,6 +301,7 @@ module.exports = {
//
// Class method for getting the list of tutors associated to a given
// student
// NOTE: A tutor is a supervisor not assigned to any office
tutors: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
var l = [];
......
......@@ -125,49 +125,6 @@ module.exports = {
return supervisor;
},
//
// sendMail
// adds a new entry into pending_registration
// and send an email confirmation to the user
sendMail: function() {
var hash_code = (this.name + this.email + this.phone);
// Send email confirmation
var nodemailer = require('nodemailer');
// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'noreply@yottacode.com',
pass: ''
}
});
var textBody = '';
// Diferents links for tutor (set password too) and parents
if(this.office) textBody = '<p>You must to click in the following link to validate your account and set your password</p><p><a href="http://localhost:1337/app/#/logintutor/'+ hash_code +'/'+ this.email +'">Click here</a></p>';
else textBody = '<p>You must to click in the following link to validate your account: </p><p><a href="http://localhost:1337/app/#/login/'+ hash_code +'/'+ this.email +'">Click here</a></p>';
// setup e-mail data with unicode symbols
var mailOptions = {
from: 'Pictogram <noreply@yottacode.com>', // sender address
to: this.email, // list of receivers
subject: 'Account activation', // Subject line
//text: 'plain text', // plaintext body
html: textBody // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
console.log(error);
}else{
console.log('Message sent: ' + info.response);
}
});
/* End email confirmation */
}
},
//
......
......@@ -26,13 +26,13 @@ module.exports = function(req, res, next) {
} else { // No token provided
return res.json(401, {err: 'No Authorization header was found'});
}
//
// We have a token, let's verify it
// We have a token, let's verify and decode it
//
sailsTokenAuth.verifyToken(token, function(err, token) {
if (err) return res.json(401, {err: 'Invalid token ' + token});
req.token = token;
next();
});
};
\ No newline at end of file
};
var mailerService = require('sails-service-mailer');
module.exports.mailer = function() {
return mailerService('sendmail', {
from: 'no-replay@yottacode.com',
subject: sails.__('notification_from_pictogram'),
provider: {
path: '/usr/sbin/sendmail'
}
});
};
......@@ -3,7 +3,7 @@ var jwt = require('jsonwebtoken');
module.exports.issueToken = function(payload, minutes) {
var token;
if (minutes)
token = jwt.sign(payload, sails.config.jwt.secret, {'expiresInMinutes': 120});
token = jwt.sign(payload, sails.config.jwt.secret, {'expiresInMinutes': minutes});
else
token = jwt.sign(payload, sails.config.jwt.secret);
return token;
......@@ -11,4 +11,4 @@ module.exports.issueToken = function(payload, minutes) {
module.exports.verifyToken = function(token, verified) {
return jwt.verify(token, sails.config.jwt.secret, {}, verified);
};
\ No newline at end of file
};
......@@ -148,6 +148,7 @@
"nobegin": "No started",
"no_method": "No method defined",
"no_instruction": "No instruction defined",
"no_students_for_user": "You are not associated to any students. Please ask your office to link your account to a Pictogram student.",
"no_space_in_category": "No space left in category",
"normal": "Normal",
"notes": "Notes",
......@@ -288,7 +289,7 @@
"use_categories": "Use categories",
"username": "Name of account (no spaces)",
"username_exists": "There is already an account with name '{{username}}'",
"user_created": "User {{name}} {{surname}} created. Please, contact your therapist office to validate the account.",
"user_created": "User {{name}} {{surname}} created. An email with instructions to activate the account has been sent.",
"user_exists": "User with email {{email}} already exists",
"validate_fail": "The user account couldn't be validated",
"validate_success": "The user account has been validated. Now, you can login from the link below",
......
......@@ -147,6 +147,7 @@
"no": "No",
"no_method": "Método sin definir",
"no_instruction": "Instrucción sin definir",
"no_students_for_user": "Su cuenta no está asociada a ningún estudiante. Por favor, contacto con su gabinete para enlazar su cuenta a un estudiante.",
"no_space_in_category": "No queda espacio en la categoría",
"nobegin": "Sin iniciar",
"normal": "Normal",
......@@ -289,7 +290,7 @@
"use_categories": "Usar categorías",
"username": "Nombre cuenta (sin espacios)",
"username_exists": "Ya existe un usuario con nombre de cuenta '{{username}}'",
"user_created": "Usuario {{name}} {{surname}} creado. Contacte con su gabinete para validar la cuenta.",
"user_created": "Usuario {{name}} {{surname}} creado. Se ha enviado un email de confirmación para activar su cuenta.",
"user_exists": "Ya existe el usuario con email '{{email}}'",
"validate_fail": "La cuenta no se ha podido validar",
"validate_success": "Cuenta validada. Puede iniciar sesión desde el enlace inferior",
......
......@@ -68,11 +68,17 @@ function LoginCtrl(
// Redirección
$location.path('/students');
})
.error(function () {
.error(function (err) {
delete $window.sessionStorage.token;
$translate('login_fail').then(function (translation) {
ngToast.danger({ content: translation });
});
if (err.search("without students") > 0) {
$translate('no_students_for_user').then(function (translation) {
ngToast.warning({ content: translation });
});
} else {
$translate('login_fail').then(function (translation) {
ngToast.danger({ content: translation });
});
}
});
};
});
......@@ -22,7 +22,7 @@ function SignInCtrl($scope,
email_confirm: '',
password: '',
password_confirm: '',
lang: 'es'
lang: 'es-es'
};
reCAPTCHA.setPublicKey('6LdLjh0TAAAAANblo_KUGNnmRZuIetOkdjdhj1b6');
......@@ -47,11 +47,10 @@ function SignInCtrl($scope,
$scope.captcha = '';
if ($scope.signInForm.$valid) {
$scope.showdialog = true;
} else {
if (!$scope.signInForm.$valid)
return;
}
$scope.showdialog = true;
$http
.post(config.backend + '/sup', $scope.formdata)
......@@ -61,7 +60,7 @@ function SignInCtrl($scope,
});
})
.error(function () {
$translate('user_exists').then(function (translation) {
$translate('user_exists', {email: $scope.formdata.email}).then(function (translation) {
ngToast.danger({ content: translation });
});
});
......
......@@ -5,17 +5,17 @@
<!-- Rejilla 3 elementos de igual ancho -->
<div class="col-lg-2">&nbsp;</div>
<div class="col-lg-8">
<div class="col-lg-8">
<p class="text-center">
<img src="img/logo_pictogram.png" alt="Pictogram" title="Pictogram" />
</p>
</p>
<div class="page-header">
<h2 translate>register</h2>
</div>
<div id="signin">
<!-- Logo Pictogram -->
<!-- Formulario -->
<form name="signInForm" role="form" ng-submit="signin()">
<fieldset>
......@@ -27,10 +27,10 @@
<input type="text" class="form-control" id="signin_surname" placeholder="{{ 'surname' | translate }}" required ng-model="formdata.surname"/>
</div>
<div class="form-group">
<input type="text" class="form-control" id="signin_address" placeholder="{{ 'address' | translate }}" required ng-model="formdata.address"/>
<input type="text" class="form-control" id="signin_address" placeholder="{{ 'address' | translate }}" ng-model="formdata.address"/>
</div>
<div class="form-group">
<input type="text" class="form-control" id="signin_phone" placeholder="{{ 'phone' | translate }}" required ng-model="formdata.phone"/>
<input type="text" class="form-control" id="signin_phone" placeholder="{{ 'phone' | translate }}" ng-model="formdata.phone"/>
</div>
<div class="form-group">
<select class="form-control" name="signin_gender" id="signin_gender" ng-model="formdata.gender">
......@@ -41,9 +41,9 @@
</fieldset>
<fieldset>
<fieldset>
<legend>
{{ 'email' | translate }}
{{ 'email' | translate }}
<span class="color_red text_sm pull-right" ng-show="formdata.email != formdata.email_confirm" translate>email_match</span>
</legend>
<div class="form-group">
......@@ -71,8 +71,8 @@
<legend translate>language</legend>
<div class="form-group">
<select class="form-control" name="signin_language" id="signin_language" ng-model="formdata.lang">
<option value="es" selected>Español</option>
<option value="en">English</option>
<option value="es-es" selected>Español</option>
<option value="en-gb">English</option>
</select>
</div>
</fieldset>
......
......@@ -131,7 +131,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
* Get a supervisor by their email and updates the $scope.supToAdd element.
* The email used for search is fetched from $scope.email_sup.
*/
$scope.getSupervisorByEmail = function () {
$scope.search_sup = function () {
// Find tutor by email
$http.get(config.backend + '/sup/email/' + $scope.email_sup)
.success(function (data) {
......@@ -154,14 +154,14 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
});
};
// Add supervisor (father or mother)
// Links supervisor with student
$scope.add_sup = function () {
var stusup = {
student: $scope.studentData.id,
supervisor: $scope.supToAdd.id
};
$http.get(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.supToAdd.id)
$http.post(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.supToAdd.id, {asTherapist: true})
.success(function (data) {
// Assign the info of supervisor to add
stusup.supervisor = $scope.supToAdd;
......@@ -240,7 +240,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
supervisor: $scope.tutorToAdd.id
};
$http.get(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.tutorToAdd.id)
$http.post(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.tutorToAdd.id)
.success(function (data) {
// Assign the info of supervisor to add
stusup.supervisor = $scope.tutorToAdd;
......
......@@ -93,6 +93,7 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
$scope.studentData.attributes = data.attributes;
$scope.studentData.current_method = data.current_method;
$scope.studentData.current_instruction = data.current_instruction;
$scope.studentData.supervision = data.supervision; // supervision level on student: 0->admin, 1->tutor, 2->therapist
// Setup section: Fill formUser (data able to be modified) from studentData parent object
// It must go here to assign the values when studentData is recovered
......
......@@ -13,8 +13,8 @@
</div>
<!-- Agrupar los enlaces de navegación, los formularios y cualquier otro elemento que se pueda ocultar al minimizar la barra -->
<div class="row">
<div class="col-md-1">
<div class="row">
<div class="col-md-1">
<div class="thumbnail img_profile">
<img ng-src="{{studentData.pic}}" alt="" title="" />
</div>
......@@ -29,19 +29,19 @@
<div class="row">
<div class="col-md-12">
<ul class="nav nav-tabs tabs_student">
<li role="presentation" ng-class="{'active' : nav.tab == 'collections'}">
<li role="presentation" ng-class="{'active' : nav.tab == 'collections'}" ng-if="studentData.supervision != 0">
<a href="/app/#/student/{{studentData.id}}/collections" ng-click="nav.tab = ''"><span class="glyphicon glyphicon-th" aria-hidden="true"></span> {{ 'collections' | translate }}</a>
</li>
<li role="presentation" ng-class="{'active' : nav.tab == 'instructions'}">
<li role="presentation" ng-class="{'active' : nav.tab == 'instructions'}" ng-if="studentData.supervision == 2">
<a href="/app/#/student/{{studentData.id}}/instructions" ng-click="nav.tab = 'instructions'"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> {{ 'instructions' | translate }}</a>
</li>
<li role="presentation" ng-class="{'active' : nav.tab == 'session'}">
<li role="presentation" ng-class="{'active' : nav.tab == 'session'}" ng-if="studentData.supervision == 2">
<a href="/app/#/student/{{studentData.id}}/session" ng-click="nav.tab = 'session'"><span class="glyphicon glyphicon-transfer" aria-hidden="true"></span> {{ 'session' | translate }}</a>
</li>
<li role="presentation" ng-class="{'active' : nav.tab == 'reports'}">
<li role="presentation" ng-class="{'active' : nav.tab == 'reports'}" ng-if="studentData.supervision != 1">
<a href="/app/#/student/{{studentData.id}}/reports" ng-click="nav.tab = 'reports'"><span class="glyphicon glyphicon-file" aria-hidden="true"></span> {{ 'reports' | translate }}</a>
</li>
<li role="presentation" ng-class="{'active' : nav.tab == 'setup'}">
<li role="presentation" ng-class="{'active' : nav.tab == 'setup'}" ng-if="studentData.supervision != 1">
<a href="/app/#/student/{{studentData.id}}/setup" ng-click="nav.tab = 'setup'"
><span class="glyphicon glyphicon-cog" aria-hidden="true"></span> {{ 'setup' | translate }}</a>
</li>
......
......@@ -90,7 +90,7 @@
<h3 translate>supervisors</h3>
<!-- Buscador de supervisores -->
<p>
<form role="search" ng-submit="getSupervisorByEmail()">
<form role="search" ng-submit="search_sup()">
<div class="input-group">
<input type="email" class="form-control" placeholder="{{ 'search_sup_email' | translate }}" name="email_sup" id="email_sup" ng-model="email_sup" required>
<div class="input-group-btn">
......
<!-- StudentsCtrl controls here, see app.js -->
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading"><h3 class="panel-title" translate>students</h3>
<div class="panel-heading"><h3 class="panel-title" translate>students</h3>
<span ng-if="user.isAdmin">({{user.office.currentStudents}}/{{user.office.maxStudents}} - <span translate="licenses_left" translate-values="{number: num_licenses_left}"></span>)</span>
</divuser.office.currentStudents}}/ivuser.office.maxStudents}} <div class="panel-body">
......@@ -12,7 +12,7 @@
<div class="row">
<div class="col-xs-3">
<button type="button" class="btn btn-success btn-circle btn-lg" ng-click="resetForm(); hidestudentadd = false" title="{{'add'|translate}}" ng-hide="!user.isSupAdmin || !num_licenses_left"><i class="glyphicon glyphicon-plus"></i></button>
</div>
<div class="col-xs-6 input-group">
<input type="text" ng-model="search_students" id="search_students" placeholder="{{ 'filter' | translate }}" class="form-control" aria-describedby="basic-addon2">
......@@ -44,7 +44,7 @@
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/collections" alt="{{ 'collections' | translate}}" popover="{{ 'collections' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision != 0"><span class="glyphicon glyphicon-th" aria-hidden="true"></span></a>
<span class="btn btn-default btn-lg" role="button" alt="{{ 'collections' | translate}}" popover="{{ 'collections' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 0"><span class="glyphicon glyphicon-th" style="color: #bbb" aria-hidden="true"></span></span>
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/instructions" alt="{{ 'instructions' | translate}}" popover="{{ 'instructions' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 2"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span></a>
<span class="btn btn-default btn-lg" role="button" alt="{{ 'instructions' | translate}}" popover="{{ 'instructions' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision != 2"><span class="glyphicon glyphicon-tasks" aria-hidden="true" style="color: #bbb" ></span></span>
......@@ -57,7 +57,9 @@
<span class="btn btn-default btn-lg" role="button" alt="{{ 'reports' | translate}}" popover="{{ 'reports' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 1"><span class="glyphicon glyphicon-file" aria-hidden="true" style="color: #bbb"></span></span>
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/setup" alt="{{ 'setup' | translate}}" popover="{{ 'setup' | translate}}" popover-trigger="mouseenter"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span></a>
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/setup" alt="{{ 'setup' | translate}}" popover="{{ 'setup' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision != 1"><span class="glyphicon glyphicon-cog" aria-hidden="true"></span></a>
<span class="btn btn-default btn-lg" role="button" alt="{{ 'setup' | translate}}" popover="{{ 'setup' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 1"><span class="glyphicon glyphicon-file" aria-hidden="true" style="color: #bbb"></span></span>
</td> <!-- /BUTTONS -->
<td>
......@@ -69,4 +71,3 @@
</table>
</div>
<!-- Fin de row -->
......@@ -25,9 +25,9 @@ module.exports.connections = {
adapter: 'sails-mysql',
host: 'localhost',
port: 3306,
user: 'pictodbuser',
user: 'pictodbu',
password: 'p1KT0!15.',
database: 'pictodbu',
database: 'pictodb',
charset : 'utf8',
collation : 'utf8_unicode_ci'
}
......
......@@ -23,7 +23,7 @@ module.exports.i18n = {
* *
***************************************************************************/
// locales: ['en', 'es', 'fr', 'de']
locales: ['en-gb', 'es-es'],
/****************************************************************************
* *
......@@ -34,7 +34,7 @@ module.exports.i18n = {
* *
****************************************************************************/
// defaultLocale: 'en',
defaultLocale: 'es-es',
/****************************************************************************
* *
......
{
"Welcome": "Welcome",
"A brand new app.": "A brand new app."
"A brand new app.": "A brand new app.",
"notification_from_pictogram": "Notification from Pictogram",
"signin_mail": "To activate your Pictogram account, click on this link:\n"
}
{
"Welcome": "Bienvenido",
"A brand new app.": "Una aplicación de la nueva marca."
"A brand new app.": "Una aplicación de la nueva marca.",
"notification_from_pictogram": "Notificación desde Pictogram",
"signin_mail": "Para activar su cuenta en Pictogram, haga click en el siguiente enlace:\n"
}
......@@ -59,7 +59,7 @@ module.exports.routes = {
'GET /stu/:id_stu/supervisors': 'StudentController.supervisors',
'GET /stu/:id_stu/therapists': 'StudentController.therapists',
'GET /stu/:id_stu/tutors': 'StudentController.tutors',
'GET /stu/:id_stu/sup/:id_sup': 'StudentController.link_supervisor',
'POST /stu/:id_stu/sup/:id_sup': 'StudentController.link_supervisor',
'GET /stu/:id_stu/pictos': 'StudentController.pictos',
'GET /stu/:id_stu/methods': 'StudentController.methods',
'GET /stu/:id_stu/lasttries': 'StudentController.lasttries',
......@@ -95,7 +95,7 @@ module.exports.routes = {
'PUT /sup/:id': 'SupervisorController.update',
'POST /sup': 'SupervisorController.create',
'POST /sup/login': 'SupervisorController.login',
'POST /sup/activate': 'SupervisorController.activate',
'GET /sup/activate/:token': 'SupervisorController.activate',
'POST /sup/upload': 'SupervisorController.upload',
'POST /sup/subscribe': 'SupervisorController.subscribe',
'POST /sup/unsubscribe': 'SupervisorController.unsubscribe',
......
......@@ -31,7 +31,7 @@ module.exports.views = {
****************************************************************************/
engine: 'ejs',
/****************************************************************************
* *
......@@ -57,7 +57,7 @@ module.exports.views = {
* *
****************************************************************************/
layout: 'layout'
layout: false
/****************************************************************************
* *
......@@ -77,5 +77,5 @@ module.exports.views = {
* *
****************************************************************************/
};
......@@ -25,6 +25,7 @@
"sails-disk": "~0.10.0",
"sails-generate-auth": "^0.2.0",
"sails-mysql": "^0.12",
"sails-service-mailer": "^3.2.1",
"sails-test-helper": "^0.3.5",
"socket.io": "~1.3.2",
"socket.io-redis": "^0.1.4",
......
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Pictogram Dashboard</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="/app/css/main.css">
</head>
<body>
<img title="Pictogram" alt="Pictogram" src="/app/img/logo_pictogram.png">
<p><strong>Welcome to Pictogram, <%= sup.name %>!</strong></p>
<p>Your account is now active, so you can proceed to <a href="<%= login_url %>">login</a>.</p>
<p></p>
<p><strong>¡Bienvenido a Pictogram, <%= sup.name %>!</strong></p>
<p>Su cuenta está ahora activa, por lo que puede <a href="<%= login_url %>">acceder</a>.</p>
</body>
</html>
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