Commit c5e73e2d by Arturo Montejo Ráez

conflicts fixed

parents 5bee4510 f781c996
Showing with 3093 additions and 2670 deletions
...@@ -62,13 +62,6 @@ ...@@ -62,13 +62,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
...@@ -76,22 +69,23 @@ ...@@ -76,22 +69,23 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" /> <sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content> </content>
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" /> <orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
......
-- phpMyAdmin SQL Dump -- MySQL dump 10.13 Distrib 5.7.13, for Linux (x86_64)
-- version 4.1.14
-- http://www.phpmyadmin.net
-- --
-- Servidor: 127.0.0.1 -- Host: localhost Database: pictodb
-- Tiempo de generación: 11-03-2015 a las 03:31:50 -- ------------------------------------------------------
-- Versión del servidor: 5.6.17 -- Server version 5.7.13
-- Versión de PHP: 5.5.12
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */; /*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-- --
-- Base de datos: `pictodb` -- Table structure for table `action`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `action`
-- --
CREATE TABLE IF NOT EXISTS `action` ( DROP TABLE IF EXISTS `action`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `action` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(20) COLLATE utf8_unicode_ci NOT NULL CHECK (type IN ('Add','Select','Delete','Show','Unshow','Pause','tryinit','tryend','initsession','endsession','pausesession','resumesession')), `type` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`timestamp` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3), `timestamp` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`id_sup` int(11) DEFAULT NULL, `id_sup` int(11) DEFAULT NULL,
`id_stu` int(11) NOT NULL, `id_stu` int(11) NOT NULL,
`id_try` int(11) DEFAULT NULL, `id_try` int(11) DEFAULT NULL,
...@@ -35,19 +33,137 @@ CREATE TABLE IF NOT EXISTS `action` ( ...@@ -35,19 +33,137 @@ CREATE TABLE IF NOT EXISTS `action` (
`gps_lat` float DEFAULT NULL, `gps_lat` float DEFAULT NULL,
`gps_lon` float DEFAULT NULL, `gps_lon` float DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
CONSTRAINT uq_stuact UNIQUE (id_stu,timestamp), UNIQUE KEY `uq_stuact` (`id_stu`,`timestamp`),
CONSTRAINT uq_supact UNIQUE (id_sup,timestamp), UNIQUE KEY `id_stu` (`id_stu`,`timestamp`),
UNIQUE (id_stu,timestamp), UNIQUE KEY `uq_supact` (`id_sup`,`timestamp`),
KEY `fk_sup_act` (`id_sup`), KEY `fk_sup_act` (`id_sup`),
KEY `fk_stu_act` (`id_stu`), KEY `fk_stu_act` (`id_stu`),
KEY `id_try` (`id_try`) KEY `id_try` (`id_try`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 CONSTRAINT `fk_stu_act` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
COMMENT="This table registers and action performed by a user at a given time, all information of the action is in JSON format in the 'description' column and the operation performed is one of the possible for the 'type' column. NOTE: timestamps must support fractional seconds, so MySQL versions >= 5.6.4 are required."; CONSTRAINT `fk_sup_act` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`),
CONSTRAINT `fk_try_act` FOREIGN KEY (`id_try`) REFERENCES `try` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=104 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table registers and action performed by a user at a given time, all information of the action is in JSON format in the ''description'' column and the operation performed is one of the possible for the ''type'' column. NOTE: timestamps must support fractional seconds, so MySQL versions >= 5.6.4 are required.';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_NEW_EVENT_ONSESSION
BEFORE INSERT ON action
FOR EACH ROW
thisTrigger: BEGIN
DECLARE idstu INT;
DECLARE idtry INT;
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_BEFORE_INSERT_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
SELECT id_opentry INTO idtry
FROM
stu_opentry
WHERE
id_stu = NEW.id_stu;
IF (idtry IS NOT NULL) THEN
SET NEW.id_try = idtry;
END IF;
IF (NEW.type = 'resumesession')
THEN
SET NEW.id_try=NULL;
END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_NEW_EVENT
AFTER INSERT ON action
FOR EACH ROW
thisTrigger: BEGIN
DECLARE idopentry INT;
DECLARE idws INT;
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_INSERT_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
SELECT id_ws, id_opentry INTO idws, idopentry
FROM
stu_opentry
WHERE
id_stu = NEW.id_stu;
IF (NEW.id_try IS NOT NULL) THEN
UPDATE `try`
SET
end = NEW.timestamp
WHERE
id = idopentry;
END IF;
CASE NEW.type
WHEN 'Show' THEN
INSERT INTO try(`id_ws`)
VALUES (idws);
WHEN 'pausesession' THEN
IF (idopentry IS NOT NULL) THEN
UPDATE try
SET
result = 'DISCARDED'
WHERE
id = idopentry;
END IF;
WHEN 'resumesession' THEN
INSERT INTO try(`id_ws`)
VALUES (idws);
ELSE BEGIN END;
END CASE;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `catexp` -- Table structure for table `catexp`
-- --
DROP TABLE IF EXISTS `catexp`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `catexp` ( CREATE TABLE `catexp` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_cat` int(11) NOT NULL, `id_cat` int(11) NOT NULL,
...@@ -55,113 +171,117 @@ CREATE TABLE `catexp` ( ...@@ -55,113 +171,117 @@ CREATE TABLE `catexp` (
`exp` varchar(30) NOT NULL, `exp` varchar(30) NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `exp` (`exp`,`lang`) UNIQUE KEY `exp` (`exp`,`lang`)
) ENGINE=InnoDB AUTO_INCREMENT=27958 DEFAULT CHARSET=utf8 COMMENT='Stores the expressions available in several languages for a given category (id_cat)'; ) ENGINE=InnoDB AUTO_INCREMENT=27958 DEFAULT CHARSET=latin1 COMMENT='Stores the expressions available in several languages for a given category (id_cat)';
-- -------------------------------------------------------- /*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `method` -- Table structure for table `instruction`
-- --
CREATE TABLE IF NOT EXISTS `method` ( DROP TABLE IF EXISTS `instruction`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `instruction` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `id_met` int(11) NOT NULL,
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL, `name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`id_stu` int(11) NOT NULL, `objective` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL,
`registration` date DEFAULT NULL, `status` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`notes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL, `begin` timestamp(3) NULL DEFAULT NULL,
`end` timestamp(3) NULL DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `fk_stu_met` (`id_stu`) KEY `fk_met_ins` (`id_met`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 KEY `ix_instruction_begin` (`begin`),
COMMENT="Information for a method. A method is composed by a set of instructions"; CONSTRAINT `fk_met_ins` FOREIGN KEY (`id_met`) REFERENCES `method` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='An instruction is a ''phase'' in a method for learning AAC';
-- -------------------------------------------------------- /*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `instruction` -- Table structure for table `license`
-- --
CREATE TABLE IF NOT EXISTS `instruction` ( DROP TABLE IF EXISTS `license`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `license` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_met` int(11) NOT NULL, `id_stu` int(11) DEFAULT NULL,
`name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, `number` varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`objective` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL, `creation_ts` datetime DEFAULT CURRENT_TIMESTAMP,
`status` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL CHECK (status IN ('started','finished')), `activation_ts` datetime DEFAULT NULL,
`begin` timestamp(3) NULL, `expiration_ts` datetime DEFAULT NULL,
`end` timestamp(3) NULL, `duration` int(11) DEFAULT '0',
PRIMARY KEY (`id`) `creator` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 `type` enum('trial','official') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'official',
COMMENT="An instruction is a 'phase' in a method for learning AAC"; PRIMARY KEY (`id`),
UNIQUE KEY `number` (`number`),
-- CREATE INDEX ix_instruction_begin ON instruction (`begin`); KEY `id_stu` (`id_stu`)
) ENGINE=InnoDB AUTO_INCREMENT=147 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Student license number';
/*!40101 SET character_set_client = @saved_cs_client */;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `meta_instruction` -- Table structure for table `meta_instruction`
-- --
CREATE TABLE IF NOT EXISTS `meta_instruction` ( DROP TABLE IF EXISTS `meta_instruction`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `meta_instruction` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, `name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`objective` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL, `objective` varchar(512) COLLATE utf8_unicode_ci DEFAULT NULL,
`id_met` tinyint(4) NOT NULL, `id_met` tinyint(4) NOT NULL,
`lang` char(5) COLLATE utf8_unicode_ci NOT NULL, `lang` char(5) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='One in a set of instructions predefined or stored by users. They are related to a metamethod (id_met)';
COMMENT="One in a set of instructions predefined or stored by users. They are related to a metamethod (id_met)"; /*!40101 SET character_set_client = @saved_cs_client */;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `meta_method` -- Table structure for table `meta_method`
-- --
CREATE TABLE IF NOT EXISTS `meta_method` ( DROP TABLE IF EXISTS `meta_method`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `meta_method` (
`id` tinyint(4) NOT NULL AUTO_INCREMENT, `id` tinyint(4) NOT NULL AUTO_INCREMENT,
`name` varchar(60) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL, `description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
`id_sup` INT( 11 ) DEFAULT NULL, `id_sup` int(11) DEFAULT NULL,
`lang` char(5) COLLATE utf8_unicode_ci NOT NULL, `lang` char(5) COLLATE utf8_unicode_ci NOT NULL,
UNIQUE(name,id_sup), PRIMARY KEY (`id`),
PRIMARY KEY (`id`) UNIQUE KEY `name` (`name`,`id_sup`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Methods predefined in the platform or stored by users for cloning';
COMMENT="Methods predefined in the platform or stored by users for cloning"; /*!40101 SET character_set_client = @saved_cs_client */;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `office` -- Table structure for table `method`
-- --
CREATE TABLE IF NOT EXISTS `office` ( DROP TABLE IF EXISTS `method`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `method` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(80) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`logo_url` varchar(240) COLLATE utf8_unicode_ci NOT NULL, `description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
`address` varchar(180) COLLATE utf8_unicode_ci NOT NULL, `id_stu` int(11) NOT NULL,
`postal_code` char(10) COLLATE utf8_unicode_ci NOT NULL, `registration` date DEFAULT NULL,
`country` varchar(2) COLLATE utf8_unicode_ci NOT NULL, `notes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
`lang` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`contact_person` varchar(80) COLLATE utf8_unicode_ci NOT NULL COMMENT 'Contact person, main responsible',
`email` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
`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 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`), PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`), KEY `fk_stu_met` (`id_stu`),
KEY `fk_admin_tea` (`admin`) CONSTRAINT `fk_stu_met` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=383 ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Information for a method. A method is composed by a set of instructions';
COMMENT="Information about a therapists' office (cabinet)"; /*!40101 SET character_set_client = @saved_cs_client */;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `picto` -- Table structure for table `picto`
-- --
CREATE TABLE IF NOT EXISTS `picto` ( DROP TABLE IF EXISTS `picto`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `picto` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`uri` varchar(250) COLLATE utf8_unicode_ci NOT NULL, `uri` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
`id_src` tinyint(4) NOT NULL, `id_src` tinyint(4) NOT NULL,
...@@ -170,80 +290,77 @@ CREATE TABLE IF NOT EXISTS `picto` ( ...@@ -170,80 +290,77 @@ CREATE TABLE IF NOT EXISTS `picto` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `ck_pic` (`id_owner`,`id_src`,`uri`), UNIQUE KEY `ck_pic` (`id_owner`,`id_src`,`uri`),
KEY `fk_sou_pic` (`id_src`) KEY `fk_sou_pic` (`id_src`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=104142 ) ENGINE=InnoDB AUTO_INCREMENT=130774 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Main information about a pictogram, either coming from a source like Symbolstix or added by a supervisor. It can belongs to a category (id_cat)';
COMMENT="Main information about a pictogram, either coming from a source like Symbolstix or added by a supervisor. It can belongs to a category (id_cat)"; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `picto_acl` -- Table structure for table `picto_acl`
-- NOT IN USE (candidate for removal) --
CREATE TABLE IF NOT EXISTS `picto_acl` ( DROP TABLE IF EXISTS `picto_acl`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `picto_acl` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_sup` int(11) NOT NULL DEFAULT '0', `id_sup` int(11) NOT NULL DEFAULT '0',
`id_pic` int(11) NOT NULL DEFAULT '0', `id_pic` int(11) NOT NULL DEFAULT '0',
`privilege` varchar(1) COLLATE utf8_unicode_ci NOT NULL, `privilege` varchar(1) COLLATE utf8_unicode_ci NOT NULL,
`timestamp` timestamp(3), `timestamp` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `k_pic_aclp` (`id_pic`), KEY `k_pic_aclp` (`id_pic`),
KEY `k_sup_aclp` (`id_sup`) KEY `k_sup_aclp` (`id_sup`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 CONSTRAINT `fk_pic_aclp` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`),
COMMENT="Stablish access rights to pictos"; CONSTRAINT `fk_sup_aclp` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Stablish access rights to pictos';
-- -------------------------------------------------------- /*!40101 SET character_set_client = @saved_cs_client */;
--
-- Estructura de tabla para la tabla `pictocat`
--
CREATE TABLE IF NOT EXISTS `pictocat`(
`id` int(11) PRIMARY KEY,
`id_supercat` int(11) DEFAULT NULL
)
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT="Identifies a category, which, itself, may belong to another category";
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `picto_core` -- Table structure for table `picto_core`
-- --
CREATE TABLE IF NOT EXISTS `picto_core` ( DROP TABLE IF EXISTS `picto_core`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `picto_core` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_pic` int(11) DEFAULT NULL COMMENT 'This is the id of the pictogram', `id_pic` int(11) DEFAULT NULL COMMENT 'This is the id of the pictogram',
`id_cat_pic` int(11) DEFAULT NULL COMMENT 'This is the id of the pictogram that represents the category this entry belongs to', `id_cat_pic` int(11) DEFAULT NULL COMMENT 'This is the id of the pictogram that represents the category this entry belongs to',
`coord_x` tinyint(4) NOT NULL, `coord_x` tinyint(4) NOT NULL,
`coord_y` tinyint(4) NOT NULL, `coord_y` tinyint(4) NOT NULL,
`color`varchar(9) NULL, -- 9 for a #RRGGBBAA color `color` varchar(9) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `id_pic` (`id_pic`), KEY `id_pic` (`id_pic`),
KEY `id_cat_pic` (`id_cat_pic`) KEY `id_cat_pic` (`id_cat_pic`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=124 CONSTRAINT `picto_core_ibfk_1` FOREIGN KEY (`id_cat_pic`) REFERENCES `picto` (`id`),
COMMENT="Default pictos and categories available for a newly created student with default coordinates"; CONSTRAINT `picto_core_ibfk_2` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=233 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Default pictos and categories available for a newly created student with default coordinates';
-- -------------------------------------------------------- /*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `picto_exp` -- Table structure for table `picto_exp`
-- --
CREATE TABLE IF NOT EXISTS `picto_exp` ( DROP TABLE IF EXISTS `picto_exp`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `picto_exp` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_pic` int(11) NOT NULL, `id_pic` int(11) NOT NULL,
`lang` char(5) COLLATE utf8_unicode_ci NOT NULL, `lang` char(5) COLLATE utf8_unicode_ci NOT NULL,
`text` varchar(100) COLLATE utf8_unicode_ci NOT NULL, `text` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `id_pic` (`id_pic`) KEY `id_pic` (`id_pic`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=72565 ) ENGINE=InnoDB AUTO_INCREMENT=270859 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Expression (text label) for a picto (or a category) in different languages. This is used by the TTS engine';
COMMENT="Expression (text label) for a picto (or a category) in different languages. This is used by the TTS engine"; /*!40101 SET character_set_client = @saved_cs_client */;
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `picto_tag` -- Table structure for table `picto_tag`
-- --
CREATE TABLE IF NOT EXISTS `picto_tag` ( DROP TABLE IF EXISTS `picto_tag`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `picto_tag` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_sup` int(11) DEFAULT NULL COMMENT 'If NULL then is a default tag', `id_sup` int(11) DEFAULT NULL COMMENT 'If NULL then is a default tag',
`id_pic` int(11) NOT NULL, `id_pic` int(11) NOT NULL,
...@@ -251,80 +368,114 @@ CREATE TABLE IF NOT EXISTS `picto_tag` ( ...@@ -251,80 +368,114 @@ CREATE TABLE IF NOT EXISTS `picto_tag` (
`lang` char(5) COLLATE utf8_unicode_ci NOT NULL, `lang` char(5) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `id_pic` (`id_pic`), KEY `id_pic` (`id_pic`),
KEY `id_sup` (`id_sup`) KEY `id_sup` (`id_sup`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 CONSTRAINT `fk_con_pt` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`),
COMMENT="Labels assigned to pictos by default or by supervisors"; CONSTRAINT `picto_tag_ibfk_1` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`),
CONSTRAINT `picto_tag_ibfk_2` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`)
-- -------------------------------------------------------- ) ENGINE=InnoDB AUTO_INCREMENT=37052 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Labels assigned to pictos by default or by supervisors';
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `source` -- Table structure for table `pictocat`
-- --
CREATE TABLE IF NOT EXISTS `source` ( DROP TABLE IF EXISTS `pictocat`;
`id` tinyint(4) NOT NULL AUTO_INCREMENT, /*!40101 SET @saved_cs_client = @@character_set_client */;
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL, /*!40101 SET character_set_client = utf8 */;
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL, CREATE TABLE `pictocat` (
`id` int(11) NOT NULL,
`id_supercat` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=2 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Identifies a category, which, itself, may belong to another category';
COMMENT="Contains all possible sources of pictos"; /*!40101 SET character_set_client = @saved_cs_client */;
-- -------------------------------------------------------- --
-- Table structure for table `pictocattree`
--
DROP TABLE IF EXISTS `pictocattree`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `pictocattree` (
`id_cat` int(11) NOT NULL,
`id_ancestor` int(11) NOT NULL,
PRIMARY KEY (`id_cat`,`id_ancestor`),
KEY `id_ancestor` (`id_ancestor`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `student` -- Table structure for table `scene`
-- --
CREATE TABLE IF NOT EXISTS `student` ( DROP TABLE IF EXISTS `scene`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `scene` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`password` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `active` tinyint(1) NOT NULL DEFAULT '0',
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `categories` tinyint(1) NOT NULL DEFAULT '0',
`surname` varchar(60) COLLATE utf8_unicode_ci NOT NULL, `id_sup` int(11) DEFAULT NULL,
`birthdate` date NOT NULL, `id_stu` int(11) NOT NULL,
`gender` char(1) COLLATE utf8_unicode_ci NOT NULL,
`country` char(2) COLLATE utf8_unicode_ci NOT NULL,
`pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'defaultAvatar.jpg',
`notes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
`lang` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`attributes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Attributes describing student along with his/her configuration',
`id_off` int(11) DEFAULT NULL,
`id_active_scene` int(11) DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`), KEY `id_sup` (`id_sup`),
KEY `id_off` (`id_off`) KEY `id_stu` (`id_stu`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=19 CONSTRAINT `scene_ibfk_1` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`),
COMMENT="Students information"; CONSTRAINT `scene_ibfk_2` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=161 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Scene table information. Every scene is related to some stu_pictos';
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `source`
--
-- -------------------------------------------------------- DROP TABLE IF EXISTS `source`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `source` (
`id` tinyint(4) NOT NULL AUTO_INCREMENT,
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Contains all possible sources of pictos';
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `license` -- Table structure for table `stu_opentry`
-- --
CREATE TABLE IF NOT EXISTS `license` ( DROP TABLE IF EXISTS `stu_opentry`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `stu_opentry` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_stu` int(11) DEFAULT NULL, `id_stu` int(11) NOT NULL,
`number` varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `id_sup` int(11) NOT NULL,
`creation_ts` datetime DEFAULT CURRENT_TIMESTAMP, `id_ws` int(11) NOT NULL,
`activation_ts` datetime NULL, `id_opentry` int(11) DEFAULT NULL,
`expiration_ts` datetime NULL, `total_tries` int(11) DEFAULT '0',
`duration` int(11) DEFAULT 0, `begin` timestamp(3) NULL DEFAULT NULL,
`creator` varchar(40) DEFAULT NULL, `end` timestamp(3) NULL DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `number` (`number`), UNIQUE KEY `id_stu` (`id_stu`),
KEY `id_stu` (`id_stu`) UNIQUE KEY `id_sup` (`id_sup`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=19 UNIQUE KEY `id_ws` (`id_ws`),
COMMENT="Student license number"; KEY `id_opentry` (`id_opentry`),
CONSTRAINT `stu_opentry_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
CONSTRAINT `stu_opentry_ibfk_2` FOREIGN KEY (`id_opentry`) REFERENCES `try` (`id`) ON DELETE SET NULL,
-- -------------------------------------------------------- CONSTRAINT `stu_opentry_ibfk_3` FOREIGN KEY (`id_ws`) REFERENCES `working_session` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `stu_picto` -- Table structure for table `stu_picto`
-- --
CREATE TABLE IF NOT EXISTS `stu_picto` ( DROP TABLE IF EXISTS `stu_picto`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `stu_picto` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_stu` int(11) NOT NULL, `id_stu` int(11) NOT NULL,
`id_pic` int(11) NOT NULL, `id_pic` int(11) NOT NULL,
...@@ -332,314 +483,538 @@ CREATE TABLE IF NOT EXISTS `stu_picto` ( ...@@ -332,314 +483,538 @@ CREATE TABLE IF NOT EXISTS `stu_picto` (
`id_scene` int(11) NOT NULL, `id_scene` int(11) NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `fk_picto` (`id_pic`), KEY `fk_picto` (`id_pic`),
KEY `id_stu` (`id_stu`) KEY `id_stu` (`id_stu`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 KEY `stu_picto_scene_fk` (`id_scene`),
COMMENT="This table relates a student with the pictos in her vocabulary"; CONSTRAINT `fk_picto` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`),
CONSTRAINT `stu_picto_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
-- -------------------------------------------------------- CONSTRAINT `stu_picto_scene_fk` FOREIGN KEY (`id_scene`) REFERENCES `scene` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7010 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table relates a student with the pictos in her vocabulary';
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `stu_sup` -- Table structure for table `stu_sup`
-- --
CREATE TABLE IF NOT EXISTS `stu_sup` ( DROP TABLE IF EXISTS `stu_sup`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `stu_sup` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_stu` int(11) NOT NULL, `id_stu` int(11) NOT NULL,
`id_sup` int(11) NOT NULL, `id_sup` int(11) NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `fk_stu_sup_ss` (`id_stu`,`id_sup`), UNIQUE KEY `fk_stu_sup_ss` (`id_stu`,`id_sup`),
KEY `fk_sup_ss` (`id_sup`), KEY `fk_sup_ss` (`id_sup`),
KEY `id_stu` (`id_stu`) KEY `id_stu` (`id_stu`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=26 CONSTRAINT `stu_sup_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`) ON DELETE CASCADE,
COMMENT="This table relates students and supervisors"; CONSTRAINT `stu_sup_ibfk_2` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=92 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table relates students and supervisors';
/*!40101 SET character_set_client = @saved_cs_client */;
-- -------------------------------------------------------- --
-- Table structure for table `student`
--
DROP TABLE IF EXISTS `student`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`name` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
`surname` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`birthdate` date DEFAULT NULL,
`gender` char(1) COLLATE utf8_unicode_ci DEFAULT NULL,
`country` char(2) COLLATE utf8_unicode_ci DEFAULT NULL,
`pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'defaultAvatar.jpg',
`notes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
`lang` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
`attributes` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Attributes describing student along with his/her configuration',
`id_active_scene` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `fk_active_scene` (`id_active_scene`),
CONSTRAINT `fk_active_scene` FOREIGN KEY (`id_active_scene`) REFERENCES `scene` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Students information';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_NEW_STUDENT_UPDATE_ENROLMENTS
AFTER INSERT ON student
FOR EACH ROW
thisTrigger: BEGIN
DECLARE LID INT;
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_INSERT_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
INSERT INTO scene (id_stu,id_sup,name,categories) VALUES (NEW.id, null, 'with_categories', TRUE);
SET LID = LAST_INSERT_ID();
CALL scene_create_core(LID,new.id);
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_DELETE_STUDENT_ENROLMENTS
AFTER DELETE ON student
FOR EACH ROW
thisTrigger: BEGIN
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_DELETE_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
IF old.id_off IS NULL THEN
UPDATE
office
SET
current_students=current_students-1
WHERE
office.id=old.id_off;
END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
--
-- Table structure for table `sup_off`
--
DROP TABLE IF EXISTS `sup_off`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `sup_off` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_sup` int(11) NOT NULL,
`id_off` int(11) DEFAULT NULL,
KEY `fk_sup_off` (`id_sup`),
KEY `fk_off_sup` (`id_off`),
PRIMARY KEY(`id`),
UNIQUE KEY `idx_sup_off` (`id_sup`,`id_off`),
CONSTRAINT `fk_off_sup` FOREIGN KEY (`id_off`) REFERENCES `supervisor` (`id`),
CONSTRAINT `fk_sup_off` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Estructura de tabla para la tabla `supervisor` -- Table structure for table `supervisor`
-- --
CREATE TABLE IF NOT EXISTS `supervisor` ( DROP TABLE IF EXISTS `supervisor`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `supervisor` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
`surname` varchar(60) COLLATE utf8_unicode_ci NOT NULL, `surname` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`gender` char(1) COLLATE utf8_unicode_ci NOT NULL, `gender` char(1) COLLATE utf8_unicode_ci DEFAULT NULL,
`pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'defaultAvatar.jpg', `pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'defaultAvatar.jpg',
`address` varchar(180) COLLATE utf8_unicode_ci DEFAULT NULL, `address` varchar(180) COLLATE utf8_unicode_ci DEFAULT NULL,
`postal_code` char(10) COLLATE utf8_unicode_ci NOT NULL,
`country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(80) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
`phone` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL, `phone` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`lang` varchar(5) COLLATE utf8_unicode_ci NOT NULL, `lang` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
`tts_engine` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, `tts_engine` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`password` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'Encrypted password using the BCrypt algorithm', `password` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'Encrypted password using the BCrypt algorithm',
`id_off` int(11) DEFAULT NULL, `active` tinyint(1) DEFAULT '0',
`active` boolean DEFAULT FALSE, `postal_code` char(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`arasaac_license` boolean DEFAULT FALSE, `arasaac_license` tinyint(1) DEFAULT '0',
`role` enum('tutor','therapist','office','admin') COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`), UNIQUE KEY `email` (`email`)
KEY `id_off` (`id_off`) ) ENGINE=InnoDB AUTO_INCREMENT=84 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Supervisors information';
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=23 /*!40101 SET character_set_client = @saved_cs_client */;
COMMENT="Supervisors information";
-- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `try` -- Table structure for table `try`
-- --
CREATE TABLE IF NOT EXISTS `try` ( DROP TABLE IF EXISTS `try`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `try` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`id_ws` int(11) NOT NULL, `id_ws` int(11) NOT NULL,
`begin` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3), `begin` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`end` timestamp(3) NULL, `end` timestamp(3) NULL DEFAULT NULL,
`result` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL CHECK (result IN ('SUCCESS','SPONTANEUS SUCCESS', 'SUPERVISED SUCCESS', 'FAIL','DISCARDED','MODEL')), `result` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_ws` (`id_ws`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1
COMMENT="This table contains tries information (they belong to a working session)";
-- CREATE INDEX ix_try_begin ON try (`begin`);
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `working_session`
--
-- NOTA: current es un atributo derivado que es necesario porque MySQL 5.1
-- no soporta correctamente indices con valor unico donde un campo es NULL
-- Trabaja en combinación al índice unico (id_sup,current) (idx_ws_supcur)
--
CREATE TABLE IF NOT EXISTS `working_session` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_sup` int(11) NOT NULL,
`id_ins` int(11) NOT NULL,
`begin` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3),
`end` timestamp(3) NULL,
`current` boolean NULL DEFAULT 1,
`description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL, `description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `id_sup` (`id_sup`), KEY `id_ws` (`id_ws`),
KEY `id_ins` (`id_ins`), KEY `ix_try_begin` (`begin`),
CONSTRAINT `try_ibfk_1` FOREIGN KEY (`id_ws`) REFERENCES `working_session` (`id`) ON DELETE CASCADE
-- Integrity rule 6: It is not possible to open a new session when a previous session is opened for a given supervisor ) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table contains tries information (they belong to a working session)';
-- when: state SES and PAU, event a2 /*!40101 SET character_set_client = @saved_cs_client */;
-- (see triggers-sessions-integrity-constraints for the rest of rules) /*!50003 SET @saved_cs_client = @@character_set_client */ ;
-- /*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
CONSTRAINT `idx_ws_supcur` UNIQUE (id_sup, current) /*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 /*!50003 SET collation_connection = utf8_general_ci */ ;
COMMENT="This table stores working session information. Every working session is related to one instruction and one supervisor (and the instruction is related to one method which is related to one student)"; /*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
-- -------------------------------------------------------- DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_NEW_TRY
-- AFTER INSERT ON try
-- Estructura de tabla para la tabla `scene` FOR EACH ROW
-- thisTrigger: BEGIN
CREATE TABLE IF NOT EXISTS `scene` ( DECLARE idstu INT;
`id` int(11) NOT NULL AUTO_INCREMENT, DECLARE idsup INT;
`name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`categories` boolean NOT NULL DEFAULT 0, IF ((@TRIGGER_CHECKS = FALSE)
`id_sup` int(11) DEFAULT NULL, OR (@TRIGGER_AFTER_INSERT_CHECKS = FALSE))
`id_stu` int(11) NOT NULL, AND (USER() = 'root@localhost')
PRIMARY KEY (`id`), THEN
FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`), LEAVE thisTrigger;
FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`) END IF;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1
COMMENT="Scene table information. Every scene is related to some stu_pictos"; SELECT DISTINCT M.id_stu,W.id_sup INTO idstu, idsup
FROM
instruction I,
-- CREATE INDEX ix_ws_begin ON working_session (`begin`); method M,
-- working_session W
-- Restricciones para tablas volcadas WHERE
-- NEW.id_ws=W.id AND
W.id_ins=I.id AND
-- I.id_met=M.id;
-- Filtros para la tabla `action`
-- INSERT INTO stu_opentry(id_stu,id_sup,id_ws,id_opentry, total_tries,begin)
ALTER TABLE `action` VALUES (
ADD CONSTRAINT `fk_stu_act` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`), idstu,
ADD CONSTRAINT `fk_sup_act` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`); idsup,
NEW.id_ws,
-- Integrity rule 8: Every action requires a valid try or null NEW.id,
-- when: state SES, event a3 and a5 0,
-- (see triggers-sessions-integrity-constraints for the rest of rules) NOW(3)
-- )
ALTER TABLE `action` ON DUPLICATE KEY UPDATE id_stu=idstu, id_sup=idsup, id_ws=NEW.id_ws, id_opentry=NEW.id;
ADD CONSTRAINT `fk_try_act` FOREIGN KEY (`id_try`) REFERENCES `try` (`id`) ON DELETE SET NULL;;
END */;;
DELIMITER ;
-- /*!50003 SET sql_mode = @saved_sql_mode */ ;
-- Filtros para la tabla `method` /*!50003 SET character_set_client = @saved_cs_client */ ;
-- /*!50003 SET character_set_results = @saved_cs_results */ ;
ALTER TABLE `method` /*!50003 SET collation_connection = @saved_col_connection */ ;
ADD CONSTRAINT `fk_stu_met` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`); /*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
-- /*!50003 SET @saved_col_connection = @@collation_connection */ ;
-- Filtros para la tabla `instruction` /*!50003 SET character_set_client = utf8 */ ;
-- /*!50003 SET character_set_results = utf8 */ ;
ALTER TABLE `instruction` /*!50003 SET collation_connection = utf8_general_ci */ ;
ADD CONSTRAINT `fk_met_ins` FOREIGN KEY (`id_met`) REFERENCES `method` (`id`); /*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
-- DELIMITER ;;
-- Filtros para la tabla `meta_instruction` /*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_TRY_EVALUATED
-- AFTER UPDATE ON try
ALTER TABLE `meta_instruction` FOR EACH ROW
ADD CONSTRAINT `fk_ins_met` FOREIGN KEY (`id_met`) REFERENCES `meta_method` (`id`); thisTrigger: BEGIN
DECLARE idws INT;
-- DECLARE ws_end DATE;
-- Filtros para la tabla `meta_method` DECLARE ws_old_end DATE;
--
ALTER TABLE `meta_method` IF ((@TRIGGER_CHECKS = FALSE)
ADD CONSTRAINT `fk_met_sup` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`); OR (@TRIGGER_AFTER_UPDATE_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
-- LEAVE thisTrigger;
-- Filtros para la tabla `office` END IF;
--
ALTER TABLE `office`
ADD CONSTRAINT `office_ibfk_1` FOREIGN KEY (`admin`) REFERENCES `supervisor` (`id`); SELECT end INTO ws_end
FROM
-- stu_opentry
-- Filtros para la tabla `picto` WHERE
-- id_ws = NEW.id_ws;
--
-- Filtros para la tabla `picto_acl` IF ( (old.result IS NULL) and (new.result IS NOT NULL) and (new.end>ws_end)) THEN
-- UPDATE stu_opentry
ALTER TABLE `picto_acl` SET
ADD CONSTRAINT `fk_pic_aclp` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`), end = new.end,
ADD CONSTRAINT `fk_sup_aclp` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`); total_tries = total_tries + 1
WHERE
-- id_ws = NEW.id_ws;
-- Filtros para la tabla `picto_core_cat` END IF;
--
ALTER TABLE `picto_core`
ADD CONSTRAINT `picto_core_ibfk_1` FOREIGN KEY (`id_cat_pic`) REFERENCES `picto` (`id`), SELECT end INTO ws_old_end
ADD CONSTRAINT `picto_core_ibfk_2` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`); FROM
working_session
WHERE
-- id = NEW.id_ws;
-- Filtros para la tabla `picto_tag`
--
ALTER TABLE `picto_tag`
ADD CONSTRAINT `fk_con_pt` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`);
--
-- Filtros para la tabla `picto_tag_sup`
--
ALTER TABLE `picto_tag`
ADD CONSTRAINT `picto_tag_ibfk_1` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`),
ADD CONSTRAINT `picto_tag_ibfk_2` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`);
--
-- Filtros para la tabla `stu_picto`
--
ALTER TABLE `stu_picto`
ADD CONSTRAINT `fk_picto` FOREIGN KEY (`id_pic`) REFERENCES `picto` (`id`),
ADD CONSTRAINT `stu_picto_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
ADD CONSTRAINT `stu_picto_scene_fk` FOREIGN KEY (`id_scene`) REFERENCES `scene` (`id`) ON DELETE CASCADE;
--
-- Filtros para la tabla `stu_sup`
--
ALTER TABLE `stu_sup`
ADD CONSTRAINT `stu_sup_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`) ON DELETE CASCADE,
ADD CONSTRAINT `stu_sup_ibfk_2` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`);
-- IF (ws_old_end < NEW.end) THEN
-- Filtros para la tabla `student` UPDATE working_session
-- SET end = NEW.end
ALTER TABLE `student` WHERE id = NEW.id_ws;
ADD CONSTRAINT `student_ibfk_1` FOREIGN KEY (`id_off`) REFERENCES `office` (`id`); END IF;
--
-- Filtros para la tabla `license`
--
ALTER TABLE `license`
ADD CONSTRAINT `license_fk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`) ON DELETE CASCADE;
--
-- Filtros para la tabla `supervisor`
--
ALTER TABLE `supervisor`
ADD CONSTRAINT `supervisor_ibfk_1` FOREIGN KEY (`id_off`) REFERENCES `office` (`id`);
--
-- Filtros para la tabla `try`
--
ALTER TABLE `try`
ADD CONSTRAINT `try_ibfk_1` FOREIGN KEY (`id_ws`) REFERENCES `working_session` (`id`) ON DELETE CASCADE;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
-- --
-- Filtros para la tabla `working_session` -- Temporary view structure for view `v_stu_last_instruction`
-- --
ALTER TABLE `working_session`
ADD CONSTRAINT `fk_ins_ws` FOREIGN KEY (`id_ins`) REFERENCES `instruction` (`id`),
ADD CONSTRAINT `working_session_ibfk_1` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`);
DROP TABLE IF EXISTS `v_stu_last_instruction`;
/*!50001 DROP VIEW IF EXISTS `v_stu_last_instruction`*/;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
/*!50001 CREATE VIEW `v_stu_last_instruction` AS SELECT
1 AS `id_ws`,
1 AS `ws_begin`,
1 AS `ws_end`,
1 AS `ws_description`,
1 AS `ins_name`,
1 AS `met_name`,
1 AS `id_stu`*/;
SET character_set_client = @saved_cs_client;
-- --
-- Estructura para la vista `v_stu_last_instruction` -- Temporary view structure for view `v_stu_last_ws_time`
-- --
DROP TABLE IF EXISTS `v_stu_last_ws_time`;
CREATE ALGORITHM=UNDEFINED /*!50001 DROP VIEW IF EXISTS `v_stu_last_ws_time`*/;
VIEW `v_stu_last_ws_time` AS SET @saved_cs_client = @@character_set_client;
SELECT M.`id_stu` AS id_stu, SET character_set_client = utf8;
MAX(WS.begin) AS time /*!50001 CREATE VIEW `v_stu_last_ws_time` AS SELECT
FROM 1 AS `id_stu`,
`working_session` AS WS join 1 AS `time`*/;
`instruction` AS I join SET character_set_client = @saved_cs_client;
`method` AS M
WHERE
WS.`id_ins` =I.`id`
and I.`id_met` = M.`id`
group by M.`id_stu`;
CREATE ALGORITHM=UNDEFINED
VIEW `v_stu_last_instruction` AS
select
WS.`id` AS `id_ws`,
WS.`begin` AS `ws_begin`,
WS.`end` AS `ws_end`,
WS.`description` AS `ws_description`,
I.`name` AS `ins_name`,
M.`name` AS `met_name`,
M.`id_stu` AS `id_stu`
FROM
`working_session` AS WS join
`instruction` AS I join
`method` AS M join
`v_stu_last_ws_time` AS LAST_WS
WHERE
LAST_WS.time = WS.begin and
LAST_WS.id_stu = M.`id_stu` and
WS.`id_ins` =I.`id`
and I.`id_met` = M.`id`;
-- --
-- VIEW `v_stu_last_instruction` -- Table structure for table `working_session`
-- Datos: Ninguna
-- --
-- DROP TABLE IF EXISTS `working_session`;
-- Vista materializada mv_stu_last_working_session_detail /*!40101 SET @saved_cs_client = @@character_set_client */;
-- Mantenida por /*!40101 SET character_set_client = utf8 */;
-- Utilizada por SAILS:StudentController.lasttries CREATE TABLE `working_session` (
-- `id` int(11) NOT NULL AUTO_INCREMENT,
-- `id_sup` int(11) NOT NULL,
-- CREATE TABLE mv_stu_last_working_session_detail IF NOT EXISTS `mv_stu_last_working_session_detail` ( `id_ins` int(11) NOT NULL,
-- `id` int(11) NOT NULL AUTO_INCREMENT, `begin` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
-- PRIMARY KEY (`id`), `end` timestamp(3) NULL DEFAULT NULL,
-- KEY `id_sup` (`id_sup`), `current` tinyint(1) DEFAULT '1',
-- KEY `id_ins` (`id_ins`) `description` varchar(4096) COLLATE utf8_unicode_ci DEFAULT NULL,
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; PRIMARY KEY (`id`),
UNIQUE KEY `idx_ws_supcur` (`id_sup`,`current`),
KEY `id_sup` (`id_sup`),
KEY `id_ins` (`id_ins`),
KEY `ix_ws_begin` (`begin`),
CONSTRAINT `fk_ins_ws` FOREIGN KEY (`id_ins`) REFERENCES `instruction` (`id`),
CONSTRAINT `working_session_ibfk_1` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table stores working session information. Every working session is related to one instruction and one supervisor (and the instruction is related to one method which is related to one student)';
/*!40101 SET character_set_client = @saved_cs_client */;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_SESSION_NEW
AFTER INSERT ON working_session
FOR EACH ROW
thisTrigger: BEGIN
DECLARE idstu INT;
DECLARE ins_begin DATE;
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_INSERT_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
SELECT begin INTO ins_begin
FROM instruction
WHERE id = NEW.id_ins;
IF (ins_begin IS NULL) THEN
UPDATE instruction
SET
begin = NOW(3),
end = NOW(3)
WHERE
id = NEW.id_ins;
END IF;
UPDATE instruction
SET
status='started',
end = NOW(3)
WHERE
id = NEW.id_ins;
INSERT INTO try(`id_ws`)
VALUES (new.id);
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_SESSION_CLOSING
BEFORE UPDATE ON working_session
FOR EACH ROW
thisTrigger: BEGIN
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_BEFORE_UPDATE_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
IF ((new.end IS NOT NULL) AND (new.current IS NOT NULL)) THEN
SET new.current=NULL;
DELETE FROM stu_opentry
WHERE id_ws = new.id;
DELETE FROM `try`
WHERE
end = NULL AND
id_ws = new.id;
END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
/*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 TRIGGER TRG_SESSION_CLOSED
AFTER UPDATE ON working_session
FOR EACH ROW
thisTrigger: BEGIN
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_UPDATE_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
IF (OLD.end < NEW.end) THEN
UPDATE instruction
SET
end = NEW.end
WHERE
id = NEW.id_ins;
END IF;
IF ((old.end IS NULL) and (new.end IS NOT NULL)) THEN
CALL deleteOpenTry(new.id);
END IF;
END */;;
DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ;
/*!50003 SET character_set_client = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection = @saved_col_connection */ ;
--
-- Final view structure for view `v_stu_last_instruction`
--
/*!50001 DROP VIEW IF EXISTS `v_stu_last_instruction`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = utf8 */;
/*!50001 SET character_set_results = utf8 */;
/*!50001 SET collation_connection = utf8_general_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
/*!50001 VIEW `v_stu_last_instruction` AS select `WS`.`id` AS `id_ws`,`WS`.`begin` AS `ws_begin`,`WS`.`end` AS `ws_end`,`WS`.`description` AS `ws_description`,`I`.`name` AS `ins_name`,`M`.`name` AS `met_name`,`M`.`id_stu` AS `id_stu` from (((`working_session` `WS` join `instruction` `I`) join `method` `M`) join `v_stu_last_ws_time` `LAST_WS`) where ((`LAST_WS`.`time` = `WS`.`begin`) and (`LAST_WS`.`id_stu` = `M`.`id_stu`) and (`WS`.`id_ins` = `I`.`id`) and (`I`.`id_met` = `M`.`id`)) */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
--
-- Final view structure for view `v_stu_last_ws_time`
--
/*!50001 DROP VIEW IF EXISTS `v_stu_last_ws_time`*/;
/*!50001 SET @saved_cs_client = @@character_set_client */;
/*!50001 SET @saved_cs_results = @@character_set_results */;
/*!50001 SET @saved_col_connection = @@collation_connection */;
/*!50001 SET character_set_client = utf8 */;
/*!50001 SET character_set_results = utf8 */;
/*!50001 SET collation_connection = utf8_general_ci */;
/*!50001 CREATE ALGORITHM=UNDEFINED */
/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */
/*!50001 VIEW `v_stu_last_ws_time` AS select `M`.`id_stu` AS `id_stu`,max(`WS`.`begin`) AS `time` from ((`working_session` `WS` join `instruction` `I`) join `method` `M`) where ((`WS`.`id_ins` = `I`.`id`) and (`I`.`id_met` = `M`.`id`)) group by `M`.`id_stu` */;
/*!50001 SET character_set_client = @saved_cs_client */;
/*!50001 SET character_set_results = @saved_cs_results */;
/*!50001 SET collation_connection = @saved_col_connection */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2017-08-10 11:20:52
...@@ -4,434 +4,46 @@ SET foreign_key_checks = 0; ...@@ -4,434 +4,46 @@ SET foreign_key_checks = 0;
SET @TRIGGER_CHECKS = FALSE; SET @TRIGGER_CHECKS = FALSE;
-- --
-- Oficina -- Dumping data for table `supervisor`
-- --
INSERT INTO `office` ( LOCK TABLES `supervisor` WRITE;
`name`, /*!40000 ALTER TABLE `supervisor` DISABLE KEYS */;
`address`, INSERT INTO `supervisor` VALUES (-1,'none','none','M','defaultAvatar.jpg',NULL,'',NULL,'',NULL,'es-es',NULL,'',0,0,'tutor'),(23,'Comunicación Aumentativa JAén (CAJA)','','M','test_caja_dofer.jpg',NULL,'23071',NULL,'dofer@ujaen.es','+34953212888','es-es',NULL,'$2a$10$Q4jHNlC58.ptfl/5wZeHfOIvpJslJHKOFNZO3bWs4it7TifQPQnEa',1,0,'office'),(24,'Miguel Ángel','García Cumbreras','M','test_caja_miguel.jpg',NULL,'23071',NULL,'magc@ujaen.es','+34953212420','es-es',NULL,'$2a$04$XQvWUwGTvjR47ChPwd3f6ukx8Zg.7o1N4Kf6P.zqhVtQxVNArOsXi',1,0,'therapist'),(25,'Arturo','Montejo Ráez','M','test_caja_arturo.jpg',NULL,'23071',NULL,'amontejo@ujaen.es','+34953212882','es-es',NULL,'$2a$04$yoBXAMSgCVGSIr2pnuIOw.J8UCm8f2XkATu5rqsMJiEmlxBHs5.cO',1,0,'therapist'),(26,'Alfonso','Ureña López','M','test_caja_alfonso.jpg',NULL,'23071',NULL,'laurena@ujaen.es','+34953212895','es-es',NULL,'$2a$04$zVGHJFafoZa60wo1yBqF/Oi3RXV/qS2cq0/j/W3Dkf4P1ad0e7.iS',1,0,'therapist'),(27,'Jesús','Navarro Moreno','M','defaultAvatar.jpg',NULL,'23071',NULL,'jnavarro@ujaen.es','+34953211912','es-es',NULL,'$2a$04$8O3Jd5j9/nM/KC.b1a8qRevyUwWUx6XGU3Gm754Y/8PpLO2jv.i76',1,0,'therapist'),(28,'Don Fernando','Padre Fernandito','M','defaultAvatar.jpg','C/ Mayor, 13. Jaén','23071','ES','donfernando@gmail.com','+34 232 232 232','es-es',NULL,'$2a$04$DMOX/cZ4h6cNJW9VlCou7O266q4YDYuS6p0QzP.gBHd08.QnFQWD.',1,0,'tutor'),(29,'Don Arturo','Padre Arturito','M','defaultAvatar.jpg','Avda. Andalucía 1. Jaén','23071','ES','donarturo@gmail.com',NULL,'es-es',NULL,'$2a$04$V2ods9MMmOFvdLTaHJqk3ejKEYdf28gvfDhaBkOSLCFJOC02TweFK',1,0,'tutor'),(30,'Don Miguel','Padre Miguelito','F','defaultAvatar.jpg','C/ Calatrava, 13. Córdoba','23071','ES','donmiguel@gmail.com',NULL,'es-es',NULL,'$2a$04$1UCak614LKz6WpDBtOblQeqFF41tOMy6ERMnP2OuGVZffe8Yi0mJq',1,0,'tutor'),(31,'Don Alfonso','Padre Alfonsito','M','defaultAvatar.jpg','Avda. Andalucía 1. Jaén','23071','ES','donalfonso@gmail.com',NULL,'es-es',NULL,'$2a$06$UtyBV4tLlT7xSqIt8LKPBucGvZ.Wgf7RgGE0fRcjEBDwjxjHlsP3K',1,0,'tutor'),(32,'Doña Alfonsa','Madre Alfonsita','F','defaultAvatar.jpg','C/ Calatrava, 13. Córdoba','23071','ES','doñaalfonsa@gmail.com',NULL,'es-es',NULL,'$2a$04$ALDmQ1oRhRZKUEi1b0eK1ehQmSZiFkhzx48ZBwER0J4vakvlYc5VS',1,0,'tutor'),(33,'Don Jesús','Padre Jesusito','M','defaultAvatar.jpg','Avda. Andalucía 1. Jaén','23071','ES','donjesus@gmail.com',NULL,'es-es',NULL,'$2a$04$Psuu6IMPUj1sbzR.uxq3EOgX1/4dFNmccjkv76LhKp35JzpiCE.fm',1,0,'tutor');
`country`, /*!40000 ALTER TABLE `supervisor` ENABLE KEYS */;
`contact_person`, UNLOCK TABLES;
`email`,
`phone1`,
`lang`,
`postal_code`
) VALUES (
'Comunicación Aumentativa JAén (CAJA)',
'Paraje Las Lagunillas, Ed A3, primera plata, 23071. Jaén',
'ES',
'Fernando Martínez Santiago',
'dofer@ujaen.es',
'+34 953 21 28 88',
'es-es',
'23071'
);
-- --
-- Supervisores -- Dumping data for table `sup_off`
-- --
INSERT INTO `supervisor` ( LOCK TABLES `sup_off` WRITE;
`name`, /*!40000 ALTER TABLE `sup_off` DISABLE KEYS */;
`surname`, INSERT INTO `sup_off` VALUES (-1,NULL),(28,NULL),(29,NULL),(30,NULL),(31,NULL),(32,NULL),(33,NULL),(23,23),(24,23),(25,23),(26,23),(27,23);
`gender`, /*!40000 ALTER TABLE `sup_off` ENABLE KEYS */;
`address`, UNLOCK TABLES;
`email`,
`phone`,
`lang`,
`password`,
`active`,
`postal_code`,
`id_off`,
`pic`
) VALUES (
'Fernando',
'Martínez Santiago',
'M',
NULL,
'dofer@ujaen.es',
'+34953212888',
'es-es',
'$2a$10$Q4jHNlC58.ptfl/5wZeHfOIvpJslJHKOFNZO3bWs4it7TifQPQnEa',
true,
'23071',
(SELECT id from office where email='dofer@ujaen.es'),
'test_caja_dofer.jpg'
), (
'Miguel Ángel',
'García Cumbreras',
'M',
NULL,
'magc@ujaen.es',
'+34953212420',
'es-es',
'$2a$04$XQvWUwGTvjR47ChPwd3f6ukx8Zg.7o1N4Kf6P.zqhVtQxVNArOsXi',
true,
'23071',
(SELECT id from office where email='dofer@ujaen.es'),
'test_caja_miguel.jpg'
), (
'Arturo',
'Montejo Ráez',
'M',
NULL,
'amontejo@ujaen.es',
'+34953212882',
'es-es',
'$2a$04$yoBXAMSgCVGSIr2pnuIOw.J8UCm8f2XkATu5rqsMJiEmlxBHs5.cO',
true,
'23071',
(SELECT id from office where email='dofer@ujaen.es'),
'test_caja_arturo.jpg'
), (
'Alfonso',
'Ureña López',
'M',
NULL,
'laurena@ujaen.es',
'+34953212895',
'es-es',
'$2a$04$zVGHJFafoZa60wo1yBqF/Oi3RXV/qS2cq0/j/W3Dkf4P1ad0e7.iS',
true,
'23071',
(SELECT id from office where email='dofer@ujaen.es'),
'test_caja_alfonso.jpg'
), (
'Jesús',
'Navarro Moreno',
'M',
NULL,
'jnavarro@ujaen.es',
'+34953211912',
'es-es',
'$2a$04$8O3Jd5j9/nM/KC.b1a8qRevyUwWUx6XGU3Gm754Y/8PpLO2jv.i76',
true,
'23071',
(SELECT id from office where email='dofer@ujaen.es'),
'defaultAvatar.jpg'
);
-- --
-- Tutores -- Dumping data for table `stu_sup`
-- --
INSERT INTO `supervisor` ( LOCK TABLES `stu_sup` WRITE;
`name`, /*!40000 ALTER TABLE `stu_sup` DISABLE KEYS */;
`surname`, INSERT INTO `stu_sup` VALUES (27,19,23),(30,19,28),(28,20,23),(48,21,23),(31,21,24),(35,21,30),(49,22,23),(32,22,24),(34,22,25),(29,23,23),(33,23,24),(36,23,25),(38,23,29),(26,24,23),(37,24,25),(39,24,27),(50,25,23),(44,25,26),(47,25,32),(51,26,23),(43,26,26),(46,26,31),(52,27,23),(41,27,27),(53,28,23),(45,28,26),(40,28,27),(42,28,33);
`gender`, /*!40000 ALTER TABLE `stu_sup` ENABLE KEYS */;
`address`, UNLOCK TABLES;
`country`,
`email`,
`phone`,
`lang`,
`password`,
`active`,
`postal_code`
) VALUES (
'Don Fernando',
'Padre Fernandito',
'M',
'C/ Mayor, 13. Jaén',
'ES',
'donfernando@gmail.com',
'+34 232 232 232',
'es-es',
'$2a$04$DMOX/cZ4h6cNJW9VlCou7O266q4YDYuS6p0QzP.gBHd08.QnFQWD.',
true,
'23071'
), (
'Don Arturo',
'Padre Arturito',
'M',
'Avda. Andalucía 1. Jaén',
'ES',
'donarturo@gmail.com',
NULL,
'es-es',
'$2a$04$V2ods9MMmOFvdLTaHJqk3ejKEYdf28gvfDhaBkOSLCFJOC02TweFK',
true,
'23071'
), (
'Don Miguel',
'Padre Miguelito',
'F',
'C/ Calatrava, 13. Córdoba',
'ES',
'donmiguel@gmail.com',
NULL,
'es-es',
'$2a$04$1UCak614LKz6WpDBtOblQeqFF41tOMy6ERMnP2OuGVZffe8Yi0mJq',
true,
'23071'
), (
'Don Alfonso',
'Padre Alfonsito',
'M',
'Avda. Andalucía 1. Jaén',
'ES',
'donalfonso@gmail.com',
NULL,
'es-es',
'$2a$06$UtyBV4tLlT7xSqIt8LKPBucGvZ.Wgf7RgGE0fRcjEBDwjxjHlsP3K',
true,
'23071'
), (
'Doña Alfonsa',
'Madre Alfonsita',
'F',
'C/ Calatrava, 13. Córdoba',
'ES',
'doñaalfonsa@gmail.com',
NULL,
'es-es',
'$2a$04$ALDmQ1oRhRZKUEi1b0eK1ehQmSZiFkhzx48ZBwER0J4vakvlYc5VS',
true,
'23071'
), (
'Don Jesús',
'Padre Jesusito',
'M',
'Avda. Andalucía 1. Jaén',
'ES',
'donjesus@gmail.com',
NULL,
'es-es',
'$2a$04$Psuu6IMPUj1sbzR.uxq3EOgX1/4dFNmccjkv76LhKp35JzpiCE.fm',
true,
'23071'
);
-- --
-- Actualización de `office` con el id del supervisor admin -- Dumping data for table `student`
-- --
UPDATE office LOCK TABLES `student` WRITE;
SET admin=(SELECT id FROM supervisor where email='dofer@ujaen.es') /*!40000 ALTER TABLE `student` DISABLE KEYS */;
WHERE email='dofer@ujaen.es'; INSERT INTO `student` VALUES (19,'faf0001','$2a$10$oy98CXG9YWbjATOESXelDu8HVjDHFPVpX5kmfdQSbkNC965Z2zPkC','Fernandito','Alumno Fernando','2009-12-10','M','ES','test_caja_juan.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"es\" }',NULL),(20,'faf0002','$2a$10$FOJ2fmJaHyI5sWe1tQojFuhoPpqHSTVPwvHPTpWEftFPI28VdyYNq','Fernandita','Alumna Fernando','2009-12-10','F','GB','test_caja_kate.jpg',NULL,'en-gb','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(21,'mam0001','$2a$10$zygC/WviDviyZQsMsNqK8.tSUI4Qr/dLlLrw0i5kR1bbN4SeU5ACq','Miguelín','Alumno Miguel','2009-12-10','M','ES','test_caja_carlos.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"es\" }',NULL),(22,'mam0002','$2a$10$xbyNUhf9rqhdXDBrvUSiOuJIzUVOyyz9ToQMCByFThiiiPwO0PWgK','Miguelita','Alumna Miguel','2009-12-10','F','ES','test_caja_rocio.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(23,'aaa0001','$2a$10$koWKIn42UNSi1N67akxjpOuJNwpXJ/vOe6biD2xkjrUz6dr3g.Wa.','Arturito','Alumno Arturo','2009-12-10','M','ES','test_caja_samuel.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"es\" }',NULL),(24,'aaa0002','$2a$10$ffAjZjWN0UKja0JO7ko6qup4x2phbY3VpC66TmpMnGdWUutBFeWY2','Arturita','Alumna Arturo','2009-12-10','F','ES','test_caja_adela.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(25,'aaa0003','$2a$10$glc5A6vyPve5.4407Vdkau5CHF3GOpA0Uo6rxMDdIopIWTJK0nBse','Alfonsita','Alumna Alfonso','2009-12-10','F','ES','test_caja_adela.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(26,'aaa0004','$2a$10$tezK07jq5ZMdQbCboubEBeHiXWJisZPAbgN301n5kRLXkq8xOlb4O','Alfonsito','Alumno Alfonso','2009-12-10','M','ES','test_caja_juan.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(27,'jaj0001','$2a$10$UQYGXOOE8mxxOjvgo8cjwOpsv5jCtRXpMTLpbD3TzMBiUIv3hXlnO','Jesusita','Alumna Jesús','2009-12-10','F','ES','test_caja_adela.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL),(28,'jaj0002','$2a$10$tVy3Wfu35l4B6bFpnjJCE.ckjncq6YCKMGW4B9abesbiFVeyGu2Dy','Jesusito','Alumno Jesús','2009-12-10','M','ES','test_caja_samuel.jpg',NULL,'es-es','{ \"categories\" : \"on\", \"input feedback\" : [ \"vibration\", \"tts\" ], \"input selection\" : \"click\", \"pictogram size\" : \"medium\", \"tts engine\" : \"IVONA Text-to-Speech HQ\", \"tts voice\": \"en\" }',NULL);
/*!40000 ALTER TABLE `student` ENABLE KEYS */;
UNLOCK TABLES;
--
-- CAJA Students
--
INSERT INTO `student` (
`username`,
`password`,
`name`,
`surname`,
`birthdate`,
`gender`,
`country`,
`pic`,
`notes`,
`lang`,
`attributes`
) VALUES (
'faf0001',
'$2a$10$oy98CXG9YWbjATOESXelDu8HVjDHFPVpX5kmfdQSbkNC965Z2zPkC',
'Fernandito',
'Alumno Fernando',
'2009-12-10',
'M',
'ES',
'test_caja_juan.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "es" }'
), (
'faf0002',
'$2a$10$FOJ2fmJaHyI5sWe1tQojFuhoPpqHSTVPwvHPTpWEftFPI28VdyYNq',
'Fernandita',
'Alumna Fernando',
'2009-12-10',
'F',
'GB',
'test_caja_kate.jpg',
NULL,
'en-gb',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'mam0001',
'$2a$10$zygC/WviDviyZQsMsNqK8.tSUI4Qr/dLlLrw0i5kR1bbN4SeU5ACq',
'Miguelín',
'Alumno Miguel',
'2009-12-10',
'M',
'ES',
'test_caja_carlos.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "es" }'
), (
'mam0002',
'$2a$10$xbyNUhf9rqhdXDBrvUSiOuJIzUVOyyz9ToQMCByFThiiiPwO0PWgK',
'Miguelita',
'Alumna Miguel',
'2009-12-10',
'F',
'ES',
'test_caja_rocio.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'aaa0001',
'$2a$10$koWKIn42UNSi1N67akxjpOuJNwpXJ/vOe6biD2xkjrUz6dr3g.Wa.',
'Arturito',
'Alumno Arturo',
'2009-12-10',
'M',
'ES',
'test_caja_samuel.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "es" }'
), (
'aaa0002',
'$2a$10$ffAjZjWN0UKja0JO7ko6qup4x2phbY3VpC66TmpMnGdWUutBFeWY2',
'Arturita',
'Alumna Arturo',
'2009-12-10',
'F',
'ES',
'test_caja_adela.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'aaa0003',
'$2a$10$glc5A6vyPve5.4407Vdkau5CHF3GOpA0Uo6rxMDdIopIWTJK0nBse',
'Alfonsita',
'Alumna Alfonso',
'2009-12-10',
'F',
'ES',
'test_caja_adela.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'aaa0004',
'$2a$10$tezK07jq5ZMdQbCboubEBeHiXWJisZPAbgN301n5kRLXkq8xOlb4O',
'Alfonsito',
'Alumno Alfonso',
'2009-12-10',
'M',
'ES',
'test_caja_juan.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'jaj0001',
'$2a$10$UQYGXOOE8mxxOjvgo8cjwOpsv5jCtRXpMTLpbD3TzMBiUIv3hXlnO',
'Jesusita',
'Alumna Jesús',
'2009-12-10',
'F',
'ES',
'test_caja_adela.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
), (
'jaj0002',
'$2a$10$tVy3Wfu35l4B6bFpnjJCE.ckjncq6YCKMGW4B9abesbiFVeyGu2Dy',
'Jesusito',
'Alumno Jesús',
'2009-12-10',
'M',
'ES',
'test_caja_samuel.jpg',
NULL,
'es-es',
'{ "categories" : "on", "input feedback" : [ "vibration", "tts" ], "input selection" : "click", "pictogram size" : "medium", "tts engine" : "IVONA Text-to-Speech HQ", "tts voice": "en" }'
);
--
-- CAJA student-supervisor
--
INSERT INTO `stu_sup` (
id_stu,
id_sup
) VALUES (
(SELECT id FROM student WHERE username='aaa0002'),
(SELECT id FROM supervisor WHERE email='dofer@ujaen.es')
);
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Fernandito' and B.name='Fernando';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Fernandita' and B.name='Fernando';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturito' and B.name='Fernando';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Fernandito' and B.name='Don Fernando';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Miguelín' and B.name='Miguel Ángel';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Miguelita' and B.name='Miguel Ángel';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturito' and B.name='Miguel Ángel';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Miguelita' and B.name='Arturo';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Miguelín' and B.name='Don Miguel';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturito' and B.name='Arturo';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturita' and B.name='Arturo';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturito' and B.name='Don Arturo';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Arturita' and B.name='Jesús';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Jesusito' and B.name='Jesús';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Jesusita' and B.name='Jesús';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Jesusito' and B.name='Don Jesús';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Alfonsito' and B.name='Alfonso';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Alfonsita' and B.name='Alfonso';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Jesusito' and B.name='Alfonso';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Alfonsito' and B.name='Don Alfonso';
INSERT INTO `stu_sup`(id_stu,id_sup) SELECT DISTINCT A.id, B.id FROM student A, supervisor B WHERE A.name='Alfonsita' and B.name='Doña Alfonsa';
--
-- Student's CAJA offices
--
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Fernando') WHERE student.name='Fernandito';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Miguel Ángel') WHERE student.name='Miguelín';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Arturo') WHERE student.name='Arturito';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Fernando') WHERE student.name='Fernandita';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Miguel Ángel') WHERE student.name='Miguelita';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Arturo') WHERE student.name='Arturita';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Alfonso') WHERE student.name='Alfonsito';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Alfonso') WHERE student.name='Alfonsita';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Jesús') WHERE student.name='Jesusito';
UPDATE student SET id_off=(SELECT id_off FROM supervisor WHERE supervisor.name='Jesús') WHERE student.name='Jesusita';
// select a.name,b.attributes,text from student a, stu_picto b, picto c, picto_exp d where a.id=b.id_stu and b.id_pic=c.id and c.id=d.id_pic and a.id=23 and a.lang=d.lang;
--
-- CAJA Core vocabulary
--
--
-- INSERT INTO stu_picto(id_stu,id_pic,scene,attributes)
-- SELECT S.id,P.id_pic, concat('{"id_cat":', if (id_cat_pic is null, 'null',id_cat_pic),
-- ',"coord_x":',coord_x,
-- ',"coord_y":',coord_y,
-- ',"status":"invisible"',
-- ',"highlight":false',
-- ',"color":', if (color is null, 'null',concat('"',color,'"')),
-- '}') as attributes
-- FROM student S, picto_core P
-- WHERE S.id_off =(SELECT id from office where name='Comunicación Aumentativa JAén (CAJA)');
--
-- Test method
--
-- INSERT INTO meta_method(name) VALUES (
-- 'Test MetaMethod'
-- );
-- INSERT INTO method(name, id_stu) VALUES (
-- 'Test Method',
-- (SELECT id FROM student WHERE username='aaa0002')
-- );
-- INSERT INTO instruction(name, id_met) VALUES (
-- 'Test Instruction',
-- (SELECT id FROM method WHERE name='Test Method')
-- );
-- INSERT INTO working_session (id_sup, id_ins) VALUES (
-- (SELECT id FROM supervisor WHERE email='dofer@ujaen.es'),
-- (SELECT id FROM instruction WHERE name='Test Instruction')
-- );
SET @TRIGGER_CHECKS = TRUE; SET @TRIGGER_CHECKS = TRUE;
SET foreign_key_checks=1; SET foreign_key_checks=1;
...@@ -84,27 +84,26 @@ END;; ...@@ -84,27 +84,26 @@ END;;
-- Integrity rule 3: office.current_enrolments and supervisor assigments updating. -- Integrity rule 3: office.current_enrolments and supervisor assigments updating.
DROP TRIGGER IF EXISTS TRG_MODIFY_STUDENT_ENROLMENTS; DROP TRIGGER IF EXISTS TRG_MODIFY_STUDENT_ENROLMENTS;
CREATE TRIGGER TRG_MODIFY_STUDENT_ENROLMENTS
AFTER UPDATE ON student
FOR EACH ROW
thisTrigger: BEGIN
IF ((@TRIGGER_CHECKS = FALSE)
OR (@TRIGGER_AFTER_UPDATE_CHECKS = FALSE))
AND (USER() = 'root@localhost')
THEN
LEAVE thisTrigger;
END IF;
IF NOT (old.id_off<=>new.id_off) THEN
IF (old.id_off IS NOT NULL) THEN
DELETE
stu_sup
FROM
stu_sup INNER JOIN supervisor ON (stu_sup.id_sup=supervisor.id)
WHERE
id_stu=new.id AND old.id_off=supervisor.id_off;
END IF;
END IF;
END;;
DELIMITER ; -- CREATE TRIGGER TRG_MODIFY_STUDENT_ENROLMENTS
-- AFTER UPDATE ON student
-- FOR EACH ROW
-- thisTrigger: BEGIN
-- IF ((@TRIGGER_CHECKS = FALSE)
-- OR (@TRIGGER_AFTER_UPDATE_CHECKS = FALSE))
-- AND (USER() = 'root@localhost')
-- THEN
-- LEAVE thisTrigger;
-- END IF;
--
-- IF NOT (old.id_off<=>new.id_off) THEN
-- IF (old.id_off IS NOT NULL) THEN
-- DELETE
-- stu_sup
-- FROM
-- stu_sup INNER JOIN supervisor ON (stu_sup.id_sup=supervisor.id)
-- WHERE
-- id_stu=new.id AND old.id_off=supervisor.id_off;
-- END IF;
-- END IF;
-- END;;
SET foreign_key_checks = 0;
ALTER TABLE supervisor ADD role enum('tutor','therapist','office','admin') NOT NULL;
ALTER TABLE supervisor MODIFY name VARCHAR(40) DEFAULT NULL;
ALTER TABLE supervisor MODIFY surname VARCHAR(60) DEFAULT NULL;
ALTER TABLE supervisor MODIFY gender CHAR(1) DEFAULT NULL;
ALTER TABLE supervisor MODIFY postal_code CHAR(10) DEFAULT NULL;
ALTER TABLE supervisor MODIFY lang VARCHAR(5) DEFAULT NULL;
ALTER TABLE student MODIFY name VARCHAR(40) DEFAULT NULL;
ALTER TABLE student MODIFY surname VARCHAR(60) DEFAULT NULL;
ALTER TABLE student MODIFY birthdate DATE DEFAULT NULL;
ALTER TABLE student MODIFY gender CHAR(1) DEFAULT NULL;
ALTER TABLE student MODIFY country CHAR(2) DEFAULT NULL;
ALTER TABLE student MODIFY lang VARCHAR(5) DEFAULT NULL;
ALTER TABLE license ADD type enum('trial', 'official') NOT NULL DEFAULT 'official';
CREATE TABLE `sup_off` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_sup` int(11) NOT NULL,
`id_off` int(11) DEFAULT NULL,
KEY `fk_sup_off` (`id_sup`),
KEY `fk_off_sup` (`id_off`),
PRIMARY KEY(`id`),
UNIQUE KEY `idx_sup_off` (`id_sup`,`id_off`),
CONSTRAINT `fk_off_sup` FOREIGN KEY (`id_off`) REFERENCES `supervisor` (`id`),
CONSTRAINT `fk_sup_off` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
UPDATE supervisor
SET role = 'office'
WHERE id IN (SELECT admin FROM office WHERE admin IS NOT NULL);
UPDATE supervisor
SET role = 'therapist'
WHERE id NOT IN (SELECT admin FROM office WHERE admin IS NOT NULL);
UPDATE supervisor
SET role = 'tutor'
WHERE id_off IS NULL;
UPDATE license
SET type = 'official'
WHERE type is not 'trial';
DELIMITER $$
DROP PROCEDURE IF EXISTS supervisor_adapt $$
CREATE PROCEDURE supervisor_adapt()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id_admin INT;
DECLARE id_off_actual INT;
DECLARE name_sup VARCHAR(80);
DECLARE office CURSOR FOR SELECT id,name,admin FROM pictodb.office;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN office;
read_loop: LOOP
FETCH office INTO id_off_actual,name_sup,id_admin;
IF done THEN
LEAVE read_loop;
END IF;
UPDATE supervisor SET name = name_sup, surname = '',role = 'office'
WHERE id = id_admin;
UPDATE student SET id_off = id_admin WHERE id_off = id_off_actual;
UPDATE supervisor SET id_off = id_admin WHERE id_off = id_off_actual;
END LOOP;
CLOSE office;
END $$
DELIMITER ;
CALL supervisor_adapt();
INSERT IGNORE INTO stu_sup (id_stu,id_sup)
SELECT id,id_off
FROM student;
INSERT INTO sup_off (id_sup, id_off)
SELECT id, id_off
FROM supervisor;
ALTER TABLE student DROP FOREIGN KEY student_ibfk_1;
ALTER TABLE student DROP COLUMN id_off;
ALTER TABLE supervisor DROP FOREIGN KEY supervisor_ibfk_1;
ALTER TABLE supervisor DROP COLUMN id_off;
DROP TABLE office;
...@@ -5,10 +5,8 @@ the version of AngularJS used. In order to do show, type `bower install` from ...@@ -5,10 +5,8 @@ the version of AngularJS used. In order to do show, type `bower install` from
*assets/app* directory. *assets/app* directory.
## Database Para actualizar instalaciones antiguas ejecutar en vagrant/roles/database/files
Create new tables mysql -u root -p pictodb < upgrade.sql
Relanzar trigger-enrolments-integrity-constraints
Destroy *office* table: `drop table office`
...@@ -43,46 +43,10 @@ module.exports = { ...@@ -43,46 +43,10 @@ module.exports = {
var params = req.allParams(); var params = req.allParams();
function get_new_random_license (callback) {
function random_license () {
var length = 16;
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
var license;
var found = true;
var maxtries = 10;
async.doWhilst(
function (cb) {
license = random_license();
License.findOne({number: license})
.then((l) => {
if (!l)
found = false;
cb();
})
.catch((err) => {
found = false;
cb();
});
},
function () {
return found;
},
function () {
callback(license);
}
);
}
if (!params.duration || params.duration < 0) if (!params.duration || params.duration < 0)
return res.badRequest(); return res.badRequest();
get_new_random_license(function (license) { License.genLicenseNumber(function (license) {
License.create({ License.create({
number: license, number: license,
duration: params.duration, duration: params.duration,
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
Picto */ Picto */
/** /**
/* StudentController /* StudentController
* *
* @description :: Server-side logic for managing students * @description :: Server-side logic for managing students
* @help :: See http://links.sailsjs.org/docs/controllers * @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
...@@ -61,7 +61,7 @@ module.exports = { ...@@ -61,7 +61,7 @@ module.exports = {
if (bcrypt.compareSync(req.body.password, student.password)) { if (bcrypt.compareSync(req.body.password, student.password)) {
student.isStudent = true; student.isStudent = true;
if (!student.license || !student.license[0]) { if (!student.license || !student.license[0]) {
sails.log.error(`Tried to login with non valid license ${req.body.username}`); sails.log.error('Tried to login with non valid license ${req.body.username}');
res.unauthorized("Student has an invalid license"); res.unauthorized("Student has an invalid license");
} else { } else {
var hasExpired = student.license[0].hasExpired(); var hasExpired = student.license[0].hasExpired();
...@@ -75,17 +75,16 @@ module.exports = { ...@@ -75,17 +75,16 @@ module.exports = {
}); });
} }
} else { } else {
sails.log.error(`Invalid student login: user ${student.username}, password\ sails.log.error('Invalid student login: user ${student.username}, password "${req.body.password}"');
"${req.body.password}"`);
res.unauthorized("Invalid username/password"); res.unauthorized("Invalid username/password");
} }
} else { } else {
sails.log.error(`Tried to login as non-existing student ${req.body.username}`); sails.log.error('Tried to login as non-existing student ${req.body.username}');
res.notFound("Student not found"); res.notFound("Student not found");
} }
}) })
.catch(function (err) { .catch(function (err) {
sails.log.error(`Error getting student ${req.body.username} for login: ` + err); sails.log.error('Error getting student ${req.body.username} for login: ' + err);
res.serverError("Error when connecting to database"); res.serverError("Error when connecting to database");
}); });
}, },
...@@ -148,30 +147,15 @@ module.exports = { ...@@ -148,30 +147,15 @@ module.exports = {
.then(function (stu_sup) { .then(function (stu_sup) {
return stu_sup; return stu_sup;
}) })
.error(err => {throw err}); .catch(function (err) { throw err });
return [student, stu_sup]; return [student, stu_sup];
}) })
.spread(function (student, stu_sup) { .spread(function (student, stu_sup) {
// requester has no relation
student.supervision = -1;
if (!stu_sup && req.token.office && student.office == req.token.office.id && req.token.isSupAdmin)
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.supervision = 2; // requester is supervisor of student
else if (req.token.isStudent && req.token.id == student.id)
student.supervision = 3 // requester is the student himself
if (student.supervision == -1) // should not hace access!!!
return res.forbidden("Access to this student should not be granted to you");
// Promisify asynchronous call to Student.supervisors // Promisify asynchronous call to Student.supervisors
var supervisors = new Promise(function(resolve, reject) { var supervisors = new Promise(function (resolve, reject) {
Student.supervisors(student.id, (err, ss) => { Student.validSupervisors(student.id, req.token.id, function (err, ss) {
if (err) return reject(err); if (err) return reject(err);
return resolve(ss); return resolve(ss);
}); });
...@@ -179,10 +163,9 @@ module.exports = { ...@@ -179,10 +163,9 @@ module.exports = {
return [student, supervisors]; return [student, supervisors];
}) })
.spread((student, supervisors) => { .spread(function (student, supervisors) {
student = student.toJSON();
student.supervisors = supervisors; student.supervisors = supervisors;
console.log(JSON.stringify(supervisors));
console.log(JSON.stringify(student.supervisors));
return res.ok(student); return res.ok(student);
}) })
.catch(function (err) { .catch(function (err) {
...@@ -190,31 +173,82 @@ module.exports = { ...@@ -190,31 +173,82 @@ module.exports = {
}); });
}, },
// /**
// Adds a new student into the database * Adds a new student into the database
// * It inmediatly related to the supervisor who created it
* If no license is specified, a test one will be created
* @param {request} req {
* username,
* password,
* id_sup,
* lang
* license (optional)
* }
*/
create: function (req, res) { create: function (req, res) {
var params = req.params.all(); var params = req.allParams();
License.isActivable(params.license_number, function(err) {
if (err)
return res.serverError(err);
Student.create(params) //
.then(function(created) { // License number, if passed is used, otherwise, a trial one is generated
sails.log.debug('Student ' + created.id + ' created: ' + JSON.stringify(created)); //
License.activate(params.license_number, created.id, function(err, license) { new Promise(function(resolve, reject) {
if (params.license_number)
resolve(params.license_number);
else {
License.newTrial(params.id_sup, function(err, license) {
console.log(license.number);
if (err) if (err)
return res.serverError(err); reject(err);
created = created.toJSON(); else
created.license = license.toObject(); resolve(license.number);
return res.ok(created); });
}
})
.then((license_number) => {
// Check license
License.isActivable(license_number, function(err) {
if (err) {
return res.badRequest(err.message);
}
// Create student
Student.create(params)
.then(function(created) {
sails.log.debug('Student ' + created.id + ' created: ' + JSON.stringify(created));
// Activate license
License.activate(license_number, created.id, function(err, license) {
if (err) {
Student.destroy({id: created.id});
return res.badRequest(err);
}
created = created.toJSON();
created.license = license.toObject();
// Link to supervisor
StuSup.create({student: created.id, supervisor: params.id_sup})
.then((stu_sup) => {
if (!stu_sup) {
Student.destroy({id: created.id});
return res.serverError("Unable to link to supervisor");
}
return res.ok(created);
})
.catch((err) => {
Student.destroy({id: created.id});
throw err
});
});
})
.catch(function(err) {
sails.log.debug(err.message);
return res.serverError(err.message);
}); });
})
.error(function(err) {
sails.log.debug(err.message);
return res.serverError(err.message);
}); });
}); })
.catch((err) => {res.serverError(err)});
}, },
/** /**
...@@ -301,7 +335,7 @@ module.exports = { ...@@ -301,7 +335,7 @@ module.exports = {
/** /**
* Return all existing supervisor and therapist from a given student * Return all existing supervisors for a given student that are in our office
* @param {request} req {} (with studentId as url parameter) * @param {request} req {} (with studentId as url parameter)
* @param {response} res * @param {response} res
* [ * [
...@@ -329,106 +363,89 @@ module.exports = { ...@@ -329,106 +363,89 @@ module.exports = {
error: 'No student defined' error: 'No student defined'
}); });
} }
Student.supervisors(req.params.id_stu, function (err, sups) { Student.validSupervisors(req.params.id_stu, req.token.id, function (err, sups) {
if (err) throw err; if (err) throw err;
return res.json(sups); return res.json(sups);
}); });
}, },
/**
* Return all existing therapists from a given student
* @param {request} req {} (with studentId as url parameter)
* @param {response} res
* [
* {
* id: therapistId,
* name: 'John',
* surname: 'Doe',
* gender: 'M/F',
* pic: 'supervisor/avatar.jpg',
* address: 'My Address, n1',
* country: 'ES',
* email: 'john@doe.es',
* phone: '+123123123',
* lang: 'es-es',
* active: true,
* ttsEngine: 'IVONA-Text',
* office: officeId
* },
* ...
* ]
*/
therapists: function (req, res) {
if (!req.params.id_stu) {
return res.json(500, {
error: 'No student defined'
});
}
Student.therapists(req.params.id_stu, function (err, sups) {
if (err) throw err;
return res.json(sups);
});
},
/**
* Return all existing tutors from a given student
* @param {request} req {} (with studentId as url parameter)
* @param {response} res
* [
* {
* id: tutorId,
* name: 'John',
* surname: 'Doe',
* gender: 'M/F',
* pic: 'supervisor/avatar.jpg',
* address: 'My Address, n1',
* country: 'ES',
* email: 'john@doe.es',
* phone: '+123123123',
* lang: 'es-es',
* active: true,
* ttsEngine: 'IVONA-Text',
* office: officeId
* },
* ...
* ]
*/
tutors: function (req, res) {
if (!req.params.id_stu) {
return res.json(500, {
error: 'No student defined'
});
}
Student.tutors(req.params.id_stu, function (err, sups) {
if (err) throw err;
return res.json(sups);
});
},
/** /**
* Creates a relation between the student and a given supervisor. * Creates a relation between the student and a given supervisor.
* It broadcasts the event linkSupervisorToStudent to both the student room * It broadcasts the event linkSupervisorToStudent to both the student room
* and the supervisor room. * and the supervisor room.
* @param {request} { (with id_stu and id_sup as url parameters) * @param {request} { (with id_stu and id_sup as url parameters or with license and id_sup)
* asTherapist: true/false (optional) // assigns supervisor to student's office is true, set id_off to null otherwise
* } * }
* @param {response} {} * @param {response} {}
*/ */
link_supervisor: function (req, res) { link_supervisor: function (req, res) {
StuSup.create({
student: req.param('id_stu'), var params = req.allParams();
supervisor: req.param('id_sup')
// Check input parameters coherence
if (!params.id_sup || !params.id_stu && !params.license)
return res.badRequest("Invalid params");
var stu, stuSup;
//
// Get student ID either because we got it or through a license
// As it can be resolved through two possibilities, better to use promises!
//
var getStudent = new Promise(function(resolve, reject) {
if (!params.id_stu && params.license) {
// get student, license attribute will be completed
License.getStudent(params.license, function(err, s) {
if (err)
reject(err);
else
resolve(s);
});
} else
Student.findOne(params.id_stu)
.populate('license')
.then((s) => {
if (!s)
throw new Error("Student not found");
resolve(s);
})
.catch((err) => {reject(err)});
});
getStudent
.then((s) => {
stu = s;
//
// Let's check it is not already linked
//
return StuSup.findOne({ student: stu.id, supervisor: params.id_sup });
}) })
.then(function (stuSup) { .then((ss) => {
if (!stuSup)
if (ss)
throw new Error('Student already linked');
return StuSup.create({
student: stu.id,
supervisor: params.id_sup
});
})
.then((ss) => {
if (!ss)
throw new Error('stusup not created'); throw new Error('stusup not created');
stuSup = ss;
//
// Send sockets messages
//
const socketToOmit = (req.isSocket) ? req.socket : undefined; const socketToOmit = (req.isSocket) ? req.socket : undefined;
const linkSupervisorToStudentEvent = sails.hooks.events.linkSupervisorToStudent( const linkSupervisorToStudentEvent = sails.hooks.events.linkSupervisorToStudent(
stuSup.supervisor, stuSup.supervisor,
stuSup.student stuSup.student
); );
sails.hooks.events.broadcastEvent( sails.hooks.events.broadcastEvent(
sails.hooks.rooms.supervisor(stuSup.supervisor), sails.hooks.rooms.supervisor(stuSup.supervisor),
linkSupervisorToStudentEvent, linkSupervisorToStudentEvent,
...@@ -440,40 +457,14 @@ module.exports = { ...@@ -440,40 +457,14 @@ module.exports = {
socketToOmit socketToOmit
); );
return stuSup; //
// Done!
//
return res.ok(stu);
}) })
.catch((err) => { .catch((err) => {
StuSup.findOne({ student: req.param('id_stu'), supervisor: req.param('id_sup') }) console.log("Error " + err.message);
.then((stuSup) => { return res.serverError(err);
// 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 && !sup.office) {
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();
}
});
}
});
return res.ok();
})
.catch((err) => {
return res.serverError("Error: " + err);
}); });
}, },
...@@ -838,28 +829,27 @@ module.exports = { ...@@ -838,28 +829,27 @@ module.exports = {
* @param {response} res {} * @param {response} res {}
*/ */
getActiveScene: function(req, res){ getActiveScene: function(req, res){
if (typeof req.params.id_stu == 'undefined' || !req.params.id_stu) if (typeof req.params.id_stu == 'undefined' || !req.params.id_stu)
return res.badRequest("id_stu not defined"); return res.badRequest("id_stu not defined");
Student.findOne({id:req.params.id_stu}).then(function(student){ Student.findOne(req.params.id_stu)
Scene.findOne({id: student.id_active_scene}) .then(function(student) {
.then(function(scene){ if (!student)
if(!scene) throw new Error("Student not found")
return res.badRequest("Scene not found"); return Scene.findOne({id: student.id_active_scene});
else })
Scene.pictos(scene.id, function(err, pictos){ .then(function(scene){
if (err){ if(!scene)
return res.serverError("Error obtaining pictos: "+ err); throw new Error("Scene not found");
} Scene.pictos(scene.id, function(err, pictos){
scene.active = true; if (err)
scene.pictos=pictos; return res.serverError("Error obtaining pictos: "+ err);
return res.ok(scene); scene.active = true;
}); scene.pictos=pictos;
}).catch(function (err){ return res.ok(scene);
return res.serverError("Error finding scene "+err);
});
}).catch(function(err){
return res.badRequest("Student not found");
}); });
}).catch(function(err){
return res.badRequest(err.message);
});
}, },
/** /**
...@@ -1000,7 +990,7 @@ module.exports = { ...@@ -1000,7 +990,7 @@ module.exports = {
}) })
.then((student) => { .then((student) => {
if (!student) { if (!student) {
sails.log.error(`Student ${params.id_stu} not found`); sails.log.error('Student ${params.id_stu} not found');
throw new Error("Student not found"); throw new Error("Student not found");
} }
...@@ -1013,7 +1003,7 @@ module.exports = { ...@@ -1013,7 +1003,7 @@ module.exports = {
}) })
.spread((picto, student) => { .spread((picto, student) => {
if (!picto) { if (!picto) {
sails.log.error(`Picto ${params.id_picto} not found`); sails.log.error('Picto ${params.id_picto} not found');
throw new Error("Picto not found"); throw new Error("Picto not found");
} }
......
...@@ -58,7 +58,6 @@ module.exports = { ...@@ -58,7 +58,6 @@ module.exports = {
* - 400 (Bad request) with error message "Missing parameters" * - 400 (Bad request) with error message "Missing parameters"
* - 401 (Unauthorized) with error message "Invalid email/password" * - 401 (Unauthorized) with error message "Invalid email/password"
* - 404 (Not found) with error message "Supervisor not found" * - 404 (Not found) with error message "Supervisor not found"
* - 401 (Unauthorized) with error message "Supervisor without students"
* - 500 (Server error) with error message "Error when connecting to database" * - 500 (Server error) with error message "Error when connecting to database"
*/ */
login: function (req, res) { login: function (req, res) {
...@@ -83,35 +82,12 @@ module.exports = { ...@@ -83,35 +82,12 @@ module.exports = {
}).then(function (supervisor) { }).then(function (supervisor) {
var stuSup = StuSup.findOne({id_sup: supervisor.id})
.then(function (stuSup) {
return stuSup;
});
var office = Office.findOne({id: supervisor.office})
.then(function (office) {
return office;
});
return [office, stuSup, supervisor];
}).spread(function(office, stuSup, supervisor) {
if (office) {
supervisor.office = office;
supervisor.isSupAdmin = (office.admin === supervisor.id);
}
if (!supervisor.isSupAdmin && !stuSup)
throw new Error("Supervisor without students");
supervisor.isSup = true;
return res.ok({ return res.ok({
user: supervisor, user: supervisor,
server_time: (new Date()).getTime(), server_time: (new Date()).getTime(),
token: sailsTokenAuth.issueToken(supervisor, sails.config.jwt.expiresInMinutes) token: sailsTokenAuth.issueToken(supervisor, sails.config.jwt.expiresInMinutes)
}); });
}) })
.catch(function (err) { .catch(function (err) {
return res.badRequest(err.message); return res.badRequest(err.message);
...@@ -155,31 +131,6 @@ module.exports = { ...@@ -155,31 +131,6 @@ module.exports = {
delete supervisor.password; delete supervisor.password;
supervisor.save(); supervisor.save();
// an email has to be sent to office administrators
if (token.role == 'tutor_office' || token.role === 'therapist_office') {
Office.findOne(token.id_off)
.populate('admin')
.then((off) => {
if (!off)
throw new Error("Office not found: ");
var message = sails.__({
phrase: token.role + '_request',
locale: supervisor.lang
}, {name: supervisor.name + " " + supervisor.surname, email: supervisor.email});
mailService.mailer()
.send({
to: off.admin.email,
text: message
})
.then(() => {})
.catch((err) => {throw err});
})
.catch((err) => {throw err;});
}
// welcome message is returned // welcome message is returned
return res.view('accountActivated', { return res.view('accountActivated', {
welcome_msg1: sails.__({ welcome_msg1: sails.__({
...@@ -247,59 +198,88 @@ module.exports = { ...@@ -247,59 +198,88 @@ module.exports = {
* } * }
*/ */
getByEmail: function (req, res) { getByEmail: function (req, res) {
Supervisor.findOne({ email: req.params.email }).then(function (supervisor) {
if (supervisor) { // Find supervisor
res.ok(supervisor); Supervisor.findOne({ email: req.params.email })
} else { .then((s) => {
res.notFound(); if (!s)
} throw new Error("Not found");
res.ok(s);
}) })
.catch(function () { .catch(function (err) {
res.serverError(); res.serverError(err);
}); });
}, },
/** /**
* Creates a new Supervisor instance * Gets a supervisor by his email (only those that are related to us)
* Important: The user's email needs to be validated after registering in order to use * @param {request} req {} (width email as url parameter)
* the new account. * @param {response} res
* @param {request} req
* { * {
* "name": "John" * "name": "John"
* "surname": "Doe" * "surname": "Doe"
* "gender": "F/M" * "gender": "F/M"
* "password": "1234" * "password": "1234"
* "pic": "url/to/photo.jpg"
* "address": "Nice street"
* "country": "ES/UK/..."
* "email": "john@doe.com" * "email": "john@doe.com"
* "address": "Nice street" (optional) * "phone": "+123456789"
* "country": "ES/UK/..." (optional) * "lang": "ES/EN/..."
* "phone": "+123456789" (optional) * "ttsEngine: "IVONA Text-to-Speech HQ"
* "lang": "ES/EN/..." (optional) * }
* "ttsEngine: "IVONA Text-to-Speech HQ" (optional) */
getFromOfficeByEmail: function (req, res) {
// Find supervisor
Supervisor.findOne({ email: req.params.email })
.then((s) => {
if (!s)
throw new Error("Not found");
// Check is in our office
return SupOff.findOne({supervisor: s.id, office: req.token.id}).populate('supervisor');
})
.then((so) => {
if (!so)
throw new Error("Not in our office");
res.ok(so.supervisor);
})
.catch(function (err) {
res.serverError(err);
});
},
/**
* Creates a new Supervisor instance
* Important: The user's email needs to be validated after registering in order to use
* the new account.
* @param {request} req
* {
* "email": "john@doe.com"
* "password": "2nsodncoiaw3r4"
* "lang": "es-es"
* "role": "tutor"
* } * }
* @param {response} res * @param {response} res
* { * {
* "user": { * "user": {
* "id": 123 * "id": 123
* "name": "John" * "email": "john@doe.com"
* "gender": "M" * "role": "tutor"
* ... (same information specified in the request, without password) * "lang": "es-es"
* }, * },
* "token": "...as892..." * "token": "...as892..."
* } * }
*/ */
create: function (req, res) { create: function (req, res) {
var params = req.params.all(); var params = req.params.all();
var supervisor;
// Send email confirmation // Send email confirmation --------------------------------
function sendConfirmationMail(cb) { function sendConfirmationMail(supervisor, cb) {
console.log("mail------------\n" + JSON.stringify(supervisor));
var token = sailsTokenAuth.issueToken({ var token = sailsTokenAuth.issueToken({
id_sup: supervisor.id, id_sup: supervisor.id,
role: params.role, role: params.role,
id_off: params.id_off,
}, 60*24*7); // expires in 1 week }, 60*24*7); // expires in 1 week
var message = sails.__({ var message = sails.__({
...@@ -317,70 +297,32 @@ module.exports = { ...@@ -317,70 +297,32 @@ module.exports = {
}) })
.then(() => {cb();}) .then(() => {cb();})
.catch((err) => {cb(err);}); .catch((err) => {cb(err);});
} // /sendConfirmationEmail() } // ------------------------------ /sendConfirmationEmail()
sails.log.debug("Creating supervisor with params " + JSON.stringify(params)); sails.log.debug("Creating supervisor with params " + JSON.stringify(params));
if (!params.name || !params.surname || !params.gender || !params.password || !params.email ) if (!params.password || !params.email )
return res.badRequest("Invalid params"); return res.badRequest("Invalid params");
var supData = { var supData = {
name: params.name, role: params.role,
surname: params.surname, name: typeof params.name == 'undefined' ? '' : params.name,
gender: params.gender,
password: params.password, password: params.password,
email: params.email, email: params.email,
pic: sails.config.pictogram.paths.defaultAvatarFileName, pic: sails.config.pictogram.paths.defaultAvatarFileName,
address: params.address || '',
postal_code: params.postalCode || '',
country: params.country || '',
phone: params.phone || '',
lang: params.lang || 'es-es', lang: params.lang || 'es-es',
}; };
if (params.id_off && params.role == 'therapist_office')
supData.id_off = params.id_off;
console.log(JSON.stringify(supData));
Supervisor.create(supData) Supervisor.create(supData)
.then(function (sup) { .then(function (sup) {
if (!sup) if (!sup)
return res.serverError("Supervisor created but returned null"); return res.serverError("Supervisor created but returned null");
supervisor = sup; sendConfirmationMail(sup, (err) => {
if (err) throw err;
if (params.role === 'therapist_office' || params.role === 'tutor_office') { return res.ok();
sendConfirmationMail((err) => { });
if (err) throw err;
return res.ok();
});
} else if (params.role === 'therapist_nooffice' || params.role === 'tutor_nooffice') {
Office.create(params.office)
.then((off) => {
// link supervisor with office
console.log("supervisor: \n" + JSON.stringify(sup));
sup.id_off = off.id;
delete sup.password;
sup.save();
console.log("supervisor: \n" + JSON.stringify(sup));
// set supervisor as admin in the office
off.admin = sup.id;
off.save();
supervisor = sup;
sendConfirmationMail((err) => {
if (err) return res.serverError("Confirmation mail could not be sent: " + err);
return res.ok();
});
})
.catch((err) => {
return res.serverError("Supervisor could not be created: " + err);
});
} else
return res.badRequest("Invalid role");
}).catch(function (err) { }).catch(function (err) {
return res.serverError("Supervisor could not be created: " + err); return res.serverError("Supervisor could not be created: " + err);
}); });
...@@ -484,7 +426,6 @@ module.exports = { ...@@ -484,7 +426,6 @@ module.exports = {
delete supervisor.password; delete supervisor.password;
if (req.body.password && req.body.password.length > 0) if (req.body.password && req.body.password.length > 0)
supervisor.password = req.body.password; supervisor.password = req.body.password;
console.log(supervisor.password);
supervisor.name = req.body.name || supervisor.name; supervisor.name = req.body.name || supervisor.name;
supervisor.surname = req.body.surname || supervisor.surname; supervisor.surname = req.body.surname || supervisor.surname;
supervisor.gender = req.body.gender || supervisor.gender; supervisor.gender = req.body.gender || supervisor.gender;
...@@ -496,7 +437,6 @@ module.exports = { ...@@ -496,7 +437,6 @@ module.exports = {
supervisor.phone = req.body.phone || supervisor.phone; supervisor.phone = req.body.phone || supervisor.phone;
supervisor.lang = req.body.lang || supervisor.lang; supervisor.lang = req.body.lang || supervisor.lang;
supervisor.ttsEngine = req.body.ttsEngine || supervisor.ttsEngine; supervisor.ttsEngine = req.body.ttsEngine || supervisor.ttsEngine;
supervisor.office = req.body.office || supervisor.office;
supervisor.save(function (error) { supervisor.save(function (error) {
if (error) throw error; if (error) throw error;
return res.ok(supervisor); return res.ok(supervisor);
...@@ -539,7 +479,144 @@ module.exports = { ...@@ -539,7 +479,144 @@ module.exports = {
}); });
}, },
/** /**
* Get all supervisors in the database that are linked to the user as office.
* @param {request} req //
* {
id {ID} ID of the office (as a GET parameter)
}
* @param {response} res
* [
* {
* "id": 123,
* "name": "John"
* "surname": "Doe"
* "gender": "F/M"
* "password": "1234"
* "pic": "url/to/photo.jpg" (optional)
* "address": "Nice street" (optional)
* "country": "ES/UK/..." (optional)
* "email": "john@doe.com" (optional)
* "phone": "+123456789" (optional)
* "lang": "ES/EN/..." (optional)
* "tts_engine": "IVONA Text-to-Speech HQ" (optional)
* },
* ...
* ]
*/
supervisors: function (req, res) {
if (!req.params.id)
return res.badRequest("Supervisor ID missing");
var enriched_sups = [];
SupOff.find({office: req.params.id})
.populate('supervisor')
.then(function (supOffs) {
var sups = supOffs.map(so => so.supervisor);
async.eachSeries(sups, function (sup, next) {
if (!sup) return next();
Supervisor.commonStudents(sup.id, req.params.id, function (err, stus) {
if (err)
return next(err);
sup = sup.toJSON();
if (!stus || stus.length == 0)
sup.students = [];
else
sup.students = stus;
enriched_sups.push(sup);
next();
});
},
function (err) {
if (err) throw err;
else res.ok(enriched_sups);
});
})
.catch(function (err) {
res.serverError(err);
});
},
/**
* Links a new supervisor to the office
*
*/
link_supervisor: function (req, res) {
if (!req.params.id_off || !req.params.id_sup)
return res.badRequest();
if (req.params.id_off == req.params.id_sup)
return res.badRequest("Link to yourself is not allowed");
// Check that both ids are valid
Supervisor.findOne(req.params.id_sup)
.then((sup) => {
if (!sup)
throw new Error("Supervisor not found");
return [sup, Supervisor.findOne(req.params.id_off)];
})
.spread((sup, off) => {
if (!off)
throw new Error("Office not found");
return [sup, off, SupOff.create({supervisor: sup.id, office: off.id})];
})
.spread((sup, off, so) => {
if (!so)
throw new Error("Unable to perform linking");
console.log("SUP.LANG:" + sup.lang);
// An notification is sent to added supervisor
mailService.mailer()
.send({
to: sup.email,
text: sails.__({
phrase: 'office_link',
locale: sup.lang || 'es-es'
}, {name: off.name, email: off.email})
})
.then(() => {res.ok()})
.catch((err) => {throw err});
})
.catch((err) => {
res.badRequest(err.message);
});
},
/**
* Unlinks a supervisor from an office
*
*/
unlink_supervisor: function (req, res) {
if (!req.params.id_off || !req.params.id_sup)
return res.badRequest();
// Check that both ids are valid
Supervisor.findOne(req.params.id_sup)
.then((s) => {
if (!s)
throw new Error("Supervisor not found");
return Supervisor.findOne(req.params.id_off);
})
.then((s) => {
if (!s)
throw new Error("Supervisor not found");
return SupOff.destroy({supervisor: req.params.id_sup, office: req.params.id_off});
})
.then((sos) => {
if (!sos)
throw new Error("No link exists");
res.ok();
})
.catch((err) => {
res.badRequest(err.message);
});
},
/**
* Get the list of students linked to this supervisor. * Get the list of students linked to this supervisor.
* The extra supervision attribute indicates the existing relationship between the supervisor and * The extra supervision attribute indicates the existing relationship between the supervisor and
* the student: * the student:
...@@ -585,6 +662,19 @@ module.exports = { ...@@ -585,6 +662,19 @@ module.exports = {
}); });
}, },
/*
Returns all the common students associated to both supervisors
*/
commonStudents: function (req, res) {
if (!req.params.id_sup || !req.params.id_off)
return res.badRequest();
Supervisor.commonStudents(req.params.id_sup, req.params.id_off, function (err, stus) {
if (err) throw err;
return res.ok(stus);
});
},
/** /**
* Get the pictos owned by this supervisor * Get the pictos owned by this supervisor
* @param {request} req {} * @param {request} req {}
......
...@@ -48,6 +48,11 @@ module.exports = { ...@@ -48,6 +48,11 @@ module.exports = {
size: 16, size: 16,
unique: true unique: true
}, },
type: {
type: "string",
enum: ['trial', 'official'],
columnName: 'type'
},
creator: { creator: {
columnName: "creator", columnName: "creator",
type: "string", type: "string",
...@@ -64,6 +69,110 @@ module.exports = { ...@@ -64,6 +69,110 @@ module.exports = {
/** /**
Class methods Class methods
*/ */
hasExpired: function (license) {
return (new Date(license.expiration_ts) - new Date() < 0);
},
/**
* Generates a new trial license
* @param {ID} id_sup ID of the supervisor who creates the license
* @param {function} callback Callback function: (err, license)
*/
newTrial: function(id_sup, callback) {
var now = new Date();
License.genLicenseNumber(function(number) {
if (!number)
callback(new Error("Unable to generate new license"), null);
License.create({
type: 'trial',
creation_ts: now,
duration: sails.config.pictogram.trial_license_duration,
number: number
})
.then((l) => {
if (!l) throw new Error("Unable to create license");
callback(null, l);
})
.catch((err) => {
callback(err, null);
});
});
},
/**
* Generates a random license number (checking that is not duplicated)
* @param {function} callback Prototype: function(license) returns the create number
*/
genLicenseNumber: function(callback) {
function random_license () {
var length = 16;
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
var license;
var found = true;
var maxtries = 10;
async.doWhilst(
function (cb) {
license = random_license();
License.findOne({number: license})
.then((l) => {
if (!l)
found = false;
cb();
})
.catch((err) => {
found = false;
cb();
});
},
function () {
return found;
},
function () {
callback(license);
}
);
},
/**
* Get the student associated to the license
* If the license is not active or doesn't exist, and error is returned
* @param {number} number License number
* @param {function} callback Callback function: err, student
*/
getStudent: function(number, callback) {
License.findOne({ number: number })
.then((l) => {
if (!l || !l.activation_ts || !l.student)
throw new Error("Invalid license: " + number);
// License ok, check student
Student.findOne(l.student)
.then((s) => {
if (!s)
throw new Error("Student not found");
// convert model to normal object to be able to add attributes
s = s.toJSON();
s.license = l;
callback(null, s);
})
.catch((err) => {
throw err;
});
})
.catch((err) => {
callback(err, null);
});
},
/** /**
Activates a license Activates a license
...@@ -72,6 +181,10 @@ module.exports = { ...@@ -72,6 +181,10 @@ module.exports = {
@param {function} callback Callback function with prototype: function(err, license) @param {function} callback Callback function with prototype: function(err, license)
*/ */
activate: function(number, id_stu, callback) { activate: function(number, id_stu, callback) {
if (!number || number.length < 16)
callback(new Error("Invalid license number"));
// Check license // Check license
License.findOne({ number: number }) License.findOne({ number: number })
.then((l) => { .then((l) => {
...@@ -127,6 +240,7 @@ module.exports = { ...@@ -127,6 +240,7 @@ module.exports = {
* Callback function gets instantiated error if not available * Callback function gets instantiated error if not available
*/ */
isActivable: function(number, cb) { isActivable: function(number, cb) {
License.findOne({number: number}) License.findOne({number: number})
.then ((l) => { .then ((l) => {
if (!l) if (!l)
......
/**
* office.js
*
* @description :: TODO: Write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
connection : 'localMysql',
tableName : 'office',
migrate : 'safe',
schema : true,
autoPK : false,
autoCreatedAt : false,
autoUpdatedAt : false,
attributes: {
id: {
type: "integer",
autoIncrement: true,
primaryKey: true,
unique: true
},
name: {
required: true,
type: "string",
size: 80
},
logoUrl: {
columnName: 'logo_url',
type: "string",
size: 240
},
address: {
required: true,
type: "string",
size: 80
},
country: {
type: "string",
size: 5,
required: true
},
lang: {
required: true,
type: "string",
size: 5
},
contactPerson: {
columnName: "contact_person",
required: true,
type: "string",
size: 80
},
email: {
required: true,
type: "string",
size: 80,
unique: true
},
phone1: {
required: true,
type: "string",
size: 20
},
phone2: {
type: "string",
size: 20
},
admin: {
columnName: 'admin',
type: 'integer',
model: 'Supervisor'
},
postalCode: {
columnName: 'postal_code',
required: true,
type: "string",
size: 10
},
// Relación con Teacher. [1 Office to N Teacher]
supervisors: {
collection: "Supervisor",
via: 'office'
},
// Relación con Student. [1 Office to N Student]
students: {
collection: "Student",
via: 'office'
},
toJSON: function() {
var office = this.toObject();
if (!office.logoUrl)
office.logoUrl = '/app/img/logo_pictogram.png';
return office;
}
},
beforeCreate: function (attrs, next) {
if (!attrs.logoUrl)
attrs.logoUrl = '/app/img/logo_pictogram.png';
next();
}
};
...@@ -31,21 +31,17 @@ module.exports = { ...@@ -31,21 +31,17 @@ module.exports = {
size: 40 size: 40
}, },
name: { name: {
required: true,
type: 'string', type: 'string',
size: 40 size: 40
}, },
surname: { surname: {
required: true,
type: 'string', type: 'string',
size: 60 size: 60
}, },
birthdate: { birthdate: {
required: true,
type: 'date' type: 'date'
}, },
gender: { gender: {
required: true,
type: 'string', type: 'string',
size: 1 size: 1
}, },
...@@ -63,16 +59,9 @@ module.exports = { ...@@ -63,16 +59,9 @@ module.exports = {
}, },
lang: { lang: {
columnName: 'lang', columnName: 'lang',
required: true,
type: 'string', type: 'string',
size: 2 size: 2
}, },
office: {
columnName: 'id_off',
type: 'integer',
required: false,
model: 'Office'
},
id_active_scene: { id_active_scene: {
columnName: 'id_active_scene', columnName: 'id_active_scene',
type: 'integer', type: 'integer',
...@@ -120,8 +109,12 @@ module.exports = { ...@@ -120,8 +109,12 @@ module.exports = {
toJSON: function () { toJSON: function () {
var student = this.toObject(); var student = this.toObject();
student.pic = sails.config.pictogram.urls.getStudentAvatarUrl(student.pic); student.pic = sails.config.pictogram.urls.getStudentAvatarUrl(student.pic);
if (student.license) if (student.license) {
student.license = student.license[0] ? student.license[0] : null; student.license = student.license[0] ? student.license[0] : null;
student.license.isValid = !License.hasExpired(student.license);
student.license.isTrial = student.license.type == 'trial';
student.license.isOfficial = student.license.type == 'official';
}
student.attributes = Student.getValidAttributes(student.attributes); student.attributes = Student.getValidAttributes(student.attributes);
delete student.password; delete student.password;
return student; return student;
...@@ -296,70 +289,56 @@ module.exports = { ...@@ -296,70 +289,56 @@ module.exports = {
}, },
// //
// Class method for getting the list of supervisors (therapist + tutors) associated to a given // Class method for getting the list of supervisors associated to a given
// student // student and where the requester is related office
supervisors: function(id_stu, callback) { validSupervisors: function(id_stu, id_sup, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
if (err) // Get all supervisors
return callback(err, []); StuSup.find({id_stu: id_stu})
.populate('supervisor')
.then((stuSups) => {
if (!stuSups || stuSups.length == 0) if (!stuSups || stuSups.length == 0)
return callback(null, []); throw new Error("No supervisors");
var sups = stuSups.map((st) => {return st.supervisor}); // return supervisors and related supervisors to the office
return callback(null, sups); return [stuSups, SupOff.find({office: id_sup}).populate('supervisor')]
}); })
}, .spread((stuSups, supOffs) => {
// if (!supOffs || supOffs.length == 0)
// Class method for getting the list of therapists associated to a given throw new Error("No supervisors");
// student
// NOTE: A therapist is a supervisor assigned to an office // filter null entries and map them to the supervisor object
therapists: function(id_stu, callback) { var ss = _.compact(_.compact(stuSups).map(x => x.supervisor));
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) { var so = _.compact(_.compact(supOffs).map(x => x.supervisor));
var l = [];
// filter from the second list those found in the first list
if (err || !stuSups || stuSups.length == 0) var sups = so.filter(a => ss.findIndex(b => b.id == a.id) >= 0);
return callback(err, l);
return callback(null, sups);
async.eachSeries(stuSups, })
function(stuSup, next) { .catch((err) => {
// stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor return callback(err, []);
if (stuSup.supervisor && stuSup.supervisor.office && stuSup.supervisor.id > 0) {
l.push(stuSup.supervisor);
}
next();
},
function (err) {
return callback(err, l);
}
);
}); });
}, },
// //
// Class method for getting the list of tutors associated to a given // Class method for getting the list of all the supervisors associated to a given
// student // student
// NOTE: A tutor is a supervisor not assigned to any office allSupervisors: function(id_stu, callback) {
tutors: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) { // Get all supervisors
var l = []; StuSup.find({id_stu: id_stu})
.populate('supervisor')
if (err || !stuSups || stuSups.length == 0) .then((stuSups) => {
return callback(err, l); if (!stuSups || stuSups.length == 0)
throw new Error("No supervisors");
async.eachSeries(stuSups, var ss = _.compact(stuSups).map(x => x.supervisor);
function(stuSup, next) { return callback(null, ss);
// stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor })
if (stuSup.supervisor && !stuSup.supervisor.office && stuSup.supervisor.id > 0) { .catch((err) => {
l.push(stuSup.supervisor); return callback(err, []);
}
next();
},
function (err) {
return callback(err, l);
}
);
}); });
}, },
...@@ -536,7 +515,10 @@ module.exports = { ...@@ -536,7 +515,10 @@ module.exports = {
}); });
}, },
// Removes logically a student /**
* Removes logically a student
* The user name is set with a random prefix and the license is removed
*/
logical_delete: function(id_stu, cb) { logical_delete: function(id_stu, cb) {
Student.findOne(id_stu).exec(function(err, student) { Student.findOne(id_stu).exec(function(err, student) {
if (err || !student) if (err || !student)
...@@ -544,7 +526,6 @@ module.exports = { ...@@ -544,7 +526,6 @@ module.exports = {
Student.update(id_stu, Student.update(id_stu,
{ {
username: Math.floor((Math.random() * 100000000) + 1) + "_" + student.username, username: Math.floor((Math.random() * 100000000) + 1) + "_" + student.username,
id_off: null
}) })
.then((updated) => { .then((updated) => {
License.destroy({id_stu: id_stu}).exec(cb); License.destroy({id_stu: id_stu}).exec(cb);
......
/**
* StuSup.js
*
* @description :: TODO: Write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
/**
* This model relates tutors and therapists with offices
*/
module.exports = {
tableName : 'sup_off',
migrate : 'safe',
schema : true,
autoPK : false,
autoCreatedAt : false,
autoUpdatedAt : false,
attributes: {
id: {
type: "integer",
autoIncrement: true,
primaryKey: true,
unique: true
},
supervisor: { // FK de Supervisor. 1 a N
columnName: "id_sup",
required: true,
type: "integer",
model: "Supervisor"
},
office: { // FK de Supervisor. 1 a N
columnName: "id_off",
type: "integer",
model: "Supervisor"
}
}
}
...@@ -30,17 +30,18 @@ module.exports = { ...@@ -30,17 +30,18 @@ module.exports = {
size: 40 size: 40
}, },
name: { name: {
required: true,
type: "string", type: "string",
size: 40 size: 40
}, },
surname: { surname: {
required: true,
type: "string", type: "string",
size: 60 size: 60
}, },
role: {
type: "string",
enum: ['tutor', 'therapist', 'office', 'admin']
},
gender: { gender: {
required: true,
type: "string", type: "string",
size: 1 size: 1
}, },
...@@ -88,12 +89,6 @@ module.exports = { ...@@ -88,12 +89,6 @@ module.exports = {
type: 'boolean', type: 'boolean',
columnName: 'arasaac_license' columnName: 'arasaac_license'
}, },
office: {
columnName: 'id_off',
type: 'integer',
required: false,
model: 'Office'
},
// Relación con WorkingSession. [1 Supervisor to N WorkingSession] // Relación con WorkingSession. [1 Supervisor to N WorkingSession]
workingSessions:{ workingSessions:{
collection: "WorkingSession", collection: "WorkingSession",
...@@ -143,7 +138,6 @@ module.exports = { ...@@ -143,7 +138,6 @@ module.exports = {
// //
beforeCreate: function (attrs, next) { beforeCreate: function (attrs, next) {
var async = require('async'); var async = require('async');
console.log("-->\n" + JSON.stringify(attrs));
async.series( async.series(
[ [
function (cb) { function (cb) {
...@@ -226,7 +220,6 @@ module.exports = { ...@@ -226,7 +220,6 @@ module.exports = {
var l = []; var l = [];
Supervisor.findOne(id) Supervisor.findOne(id)
.populate('office')
.then(function (sup) { .then(function (sup) {
if (!sup) if (!sup)
throw new Error("Not a valid supervisor") throw new Error("Not a valid supervisor")
...@@ -247,64 +240,76 @@ module.exports = { ...@@ -247,64 +240,76 @@ module.exports = {
}) })
.spread(function (sup, stuSups) { .spread(function (sup, stuSups) {
async.eachSeries(stuSups, function(stuSup, next_cb) { async.eachSeries(stuSups, function(stuSup, next_cb) {
// Filter logically deleted students
if (stuSup.student.office == null)
return next_cb();
// set current method and instruction if any // set current method and instruction if any
Student.findOne(stuSup.student.id) Student.findOne(stuSup.student.id)
.populate('lastInstruction') .populate('lastInstruction')
.populate('license') .populate('license')
.then(function (s) { .then(function (s) {
if (!s)
return next_cb();
s = s.toJSON();
s.current_method = s.lastInstruction[0] ? s.lastInstruction[0].met_name : "no_method"; s.current_method = s.lastInstruction[0] ? s.lastInstruction[0].met_name : "no_method";
s.current_instruction = s.lastInstruction[0] ? s.lastInstruction[0].ins_name : "no_instruction"; s.current_instruction = s.lastInstruction[0] ? s.lastInstruction[0].ins_name : "no_instruction";
if (typeof(s.license[0]) != 'undefined') { if (!s.license)
s.licenseIsValid = new Date(s.license[0].expiration_ts) - new Date() > 0 ? true : false; return next_cb();
s.license = s.license[0];
} else {
s.licenseIsValid = false;
s.license = null;
}
s.supervision = sup.office ? 2 : 1; // if Supervisor has office, then is a therapist (2), a tutor (1) otherwise
l.push(s); l.push(s);
next_cb(); next_cb();
}); });
}, },
function (err) { // loop has end function (err) {
// Get all students from the office if user is administrator callback(err, l);
if (sup.office && sup.office.admin == sup.id) { });
var officeStudents;
Student.find({ office: sup.office.id })
.populate('lastInstruction')
.populate('license')
.then(function (officeStudents) {
officeStudents = officeStudents.map((student) => {
student.supervision = 0;
student.current_method = student.lastInstruction[0] ? student.lastInstruction[0].met_name : "no_method";
student.current_instruction = student.lastInstruction[0] ? student.lastInstruction[0].ins_name : "no_instruction";
if (typeof(student.license[0]) != 'undefined') {
student.licenseIsValid = new Date(student.license[0].expiration_ts) - new Date() > 0 ? true : false;
student.license = student.license[0];
} else {
student.licenseIsValid = false;
student.license = null;
}
return student;
});
l = l.concat(officeStudents);
callback(err, lodash.uniq(l, false, 'id'));
})
.catch(function (err) {
callback(err, l);
});
} else {
callback(err, l);
}
}); // end async.eachSeries
}) })
.catch((err) => { .catch((err) => {
callback(err, l); callback(err, l);
}); // end Supervisor.findOne }); // end Supervisor.findOne
},
/***
* Return the list of students that are common to both supervisors
*/
commonStudents: function(id1, id2, callback) {
var l = [];
StuSup.find({ supervisor: id1 })
.then(function (stuSups) {
return [stuSups, StuSup.find({ supervisor: id2 })];
})
.spread((stuSups1, stuSups2) => {
if (!stuSups1 || !stuSups2)
throw new Error("No students");
// Common students
var stuSups = stuSups1.filter(a => stuSups2.findIndex(b => b.student == a.student) >= 0);
// Now, let's take full information about them
async.eachSeries(stuSups, function(stuSup, next_cb) {
// set current method and instruction if any
Student.findOne(stuSup.student)
.populate('lastInstruction')
.populate('license')
.then(function (s) {
if (!s)
return next_cb();
s = s.toJSON();
s.current_method = s.lastInstruction[0] ? s.lastInstruction[0].met_name : "no_method";
s.current_instruction = s.lastInstruction[0] ? s.lastInstruction[0].ins_name : "no_instruction";
if (!s.license)
return next_cb();
l.push(s);
next_cb();
});
},
function (err) {
return callback(err, l);
});
})
.catch((err) => {
return callback(err, l);
});
} }
}; };
module.exports = function isAdmin (req, res, next) { module.exports = function isAdmin (req, res, next) {
// //
// Only if the user that has connected is global administrator (Yotta employee) // Only if the user that has connected is global administrator (Yotta employee)
// //
if (!req.token || !req.token.isAdmin) if (!req.token || req.token.role !== 'admin')
res.json(401, {error: 'Access denied'}); res.json(401, {error: 'Access denied'});
// Finally, if the user has a clean record, we'll call the `next()` function // Finally, if the user has a clean record, we'll call the `next()` function
// to let them through to the next policy or our controller // to let them through to the next policy or our controller
next(); next();
}; };
\ No newline at end of file
module.exports = function isAdmin (req, res, next) { module.exports = function isAdminOrOffice (req, res, next) {
// //
// Only if the user that has connected is global administrator (Yotta employee) // Only if the user that has connected is global administrator (Yotta employee) or is an office
// //
if (!req.token || !req.token.isAdmin && !req.token.isSupAdmin) if (!req.token || req.token.role !== 'admin' && req.token.role !== 'office')
res.json(401, {error: 'Access denied'}); res.json(401, {error: 'Access denied'});
// Finally, if the user has a clean record, we'll call the `next()` function // Finally, if the user has a clean record, we'll call the `next()` function
......
...@@ -3,10 +3,10 @@ module.exports = function isSupAdmin (req, res, next) { ...@@ -3,10 +3,10 @@ module.exports = function isSupAdmin (req, res, next) {
// //
// A SupAdmin is a supervisor that is administrator of an office // A SupAdmin is a supervisor that is administrator of an office
// That means that we can find its id at the admin column in an entry at the office table // That means that we can find its id at the admin column in an entry at the office table
if (!req.token || !req.token.isSupAdmin) if (!req.token || req.token.role !== 'office')
res.json(401, {error: 'Access denied'}); res.json(401, {error: 'Access denied'});
// Finally, if the user has a clean record, we'll call the `next()` function // Finally, if the user has a clean record, we'll call the `next()` function
// to let them through to the next policy or our controller // to let them through to the next policy or our controller
next(); next();
}; };
\ No newline at end of file
module.exports = function isSupervisorOfStudentOrIsStudent (req, res, next) { module.exports = function isStudentOrSupervisorOfStudent (req, res, next) {
// sails.log("TOKEN: " + JSON.stringify(req.token)); // sails.log("TOKEN: " + JSON.stringify(req.token));
if (!req.params.id_stu) if (!req.params.id_stu)
return res.json(401, {error: 'Access denied 1'}); // If it is a student, then is ok return res.json(401, {error: 'Access denied 1'}); // If it is a student, then is ok
if (req.token && req.token.isStudent && req.token.id == req.params.id_stu) if (req.token && req.token.isStudent && req.token.id == req.params.id_stu)
return next(); return next();
// Get list of supervisors for the student // Get list of supervisors for the student
Student.supervisors(req.params.id_stu, function(err, sups) { Student.allSupervisors(req.params.id_stu, function(err, sups) {
if (err) if (err)
return res.json(401, {error: err}); return res.json(401, {error: err});
if (!sups || sups.length == 0) if (!sups || sups.length == 0)
return res.json(401, {error: "This student has no supervisors associated"}); return res.json(401, {error: "This student has no supervisors associated"});
// if supervisor is not in the list of supervisors // if supervisor is not in the list of supervisors
if (sups.map(function(e) {return e.id}).indexOf(req.token.id) < 0) if (_.compact(sups).map(function(e) {return e.id}).indexOf(req.token.id) < 0)
return res.json(401, {error: 'Access denied 3'}); return res.json(401, {error: 'Access denied 3'});
// Finally, if the user has a clean record, we'll call the `next()` function // Finally, if the user has a clean record, we'll call the `next()` function
// to let them through to the next policy or our controller // to let them through to the next policy or our controller
next(); next();
}); });
}; };
/* global sails, Student */ /* global sails, Student */
module.exports = function isSupervisorOfStudent(req, res, next) { module.exports = function isSupervisorOfStudent(req, res, next) {
const supervisorId = req.token.id;
const studentId = req.params.id_stu; if (!req.params.id_stu || !req.token.id)
return res.json(401, {error: 'Access denied'});
if (!studentId || !supervisorId) {
sails.log.error('This request needs an id_stu parameter and a authenticated supervisor');
res.json(401, { error: 'Access denied' }); // Get list of supervisors for the student
} else { Student.allSupervisors(req.params.id_stu, function(err, sups) {
Student.supervisors(studentId, function (err, sups) { if (err)
const studentSupervisorsIds = sups.map((studentSupervisor) => studentSupervisor.id); return res.json(401, {error: err});
if (err || studentSupervisorsIds.length === 0) { if (!sups || sups.length == 0)
sails.log.error(`Student ${studentId} has no supervisor assigned`); return res.json(401, {error: "This student has no supervisors associated"});
res.json(401, { error: 'Access denied' });
} else if (studentSupervisorsIds.indexOf(supervisorId) < 0) { // if supervisor is not in the list of supervisors
sails.log.error(`Supervisor ${supervisorId} is not assigned to Student ${studentId}`); if (_.compact(sups).map(function(e) {return e.id}).indexOf(req.token.id) < 0)
sails.log.debug(`Student supervisors: ${studentSupervisorsIds}`); return res.json(401, {error: 'Access denied 3'});
res.json(401, { error: 'Access denied' });
} else { // Finally, if the user has a clean record, we'll call the `next()` function
sails.log.debug(`Supervisor ${supervisorId} is assigned to Student ${studentId}`); // to let them through to the next policy or our controller
next(); next();
} });
});
}
}; };
/* global sails, Student */
module.exports = function isSupervisorOfStudentOrIsSupAdmin(req, res, next) {
const supervisorId = req.token.id;
const studentId = req.params.id_stu;
if (!studentId || !supervisorId) {
sails.log.error('This request needs an id_stu parameter and a authenticated supervisor');
return res.json(401, { error: 'Access denied' });
} else {
Student.findOne(studentId)
.then(function (s) {
if (req.token.office && s.office == req.token.office.id && req.token.isSupAdmin)
next();
else {
Student.supervisors(studentId, function (err, sups) {
if (err)
return res.json(401, {error: 'Access denied'});
var supIds = sups.map((studentSupervisor) => studentSupervisor.id);
if (supIds.indexOf(supervisorId) >= 0)
return next();
sails.log.error(`Supervisor ${supervisorId} is not assigned to Student ${studentId}`);
return res.json(401, { error: 'Access denied' });
});
}
})
.catch((err) => {
sails.log.error(JSON.stringify(err));
return res.json(401, { error: "No student found" })
});
}
};
module.exports = function isSupervisorOfStudentOrIsSupAdminOrIsStudent (req, res, next) {
// sails.log("TOKEN: " + JSON.stringify(req.token));
if (!req.params.id_stu)
return res.json(401, {error: 'Access denied 1'});
Student.findOne(req.params.id_stu)
.then(function (s) {
if (req.token && req.token.isStudent && req.token.id == req.params.id_stu)
return next(); // Is Student
if (req.token.office && s.office == req.token.office.id && req.token.isSupAdmin)
return next(); // Is Office's administrator
Student.supervisors(req.params.id_stu, function(err, sups) {
if (err || !sups || sups.length == 0)
return res.json(401, {error: "This student has no supervisors associated"});
if (sups.map(function(e) {return e.id}).indexOf(req.token.id) >= 0)
return next(); // Is Supervisor of Student
return res.json(401, {error: "No valid credentials"});
});
})
.catch((err) => {
return res.json(401, {error: "Student not found"});
});
};
...@@ -27,7 +27,7 @@ module.exports = function badRequest(data, options) { ...@@ -27,7 +27,7 @@ module.exports = function badRequest(data, options) {
// Log error to console // Log error to console
if (data !== undefined) { if (data !== undefined) {
sails.log.verbose('Sending 400 ("Bad Request") response: \n',data); sails.log.verbose('Sending 400 ("Bad Request") response: \n', data);
} }
else sails.log.verbose('Sending 400 ("Bad Request") response'); else sails.log.verbose('Sending 400 ("Bad Request") response');
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
"humanize-duration": "~3.0.0", "humanize-duration": "~3.0.0",
"momentjs": "~2.10.3", "momentjs": "~2.10.3",
"ngtoast": "~1.5.4", "ngtoast": "~1.5.4",
"angular-animate": "~1.4.1", "angular-animate": "~1.2.2",
"angular-sanitize": "~1.4.1", "angular-sanitize": "~1.4.1",
"angular-chart.js": "latest", "angular-chart.js": "latest",
"ng-lodash": "~0.3.0", "ng-lodash": "~0.3.0",
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
}, },
"resolutions": { "resolutions": {
"angular": ">=1 <1.3.0", "angular": ">=1 <1.3.0",
"humanize-duration": "~3.0.0", "humanize-duration": "~3.0.0"
"momentjs": "~2.10.3"
} }
} }
{ {
"account": "Account", "account": "Account",
"account_activate": "The account has been activated", "account_activate": "The account has been activated",
"account_available": "Account available",
"account_desc_office": "Manage students, intervention teams along with all therapist related functionalities.",
"account_desc_therapist": "Manage pictograms, devices, record supervised sessions and get progress reports.",
"account_desc_tutor": "Configure your child's pictograms and his/her communication device.",
"account_no_activate": "The account could not be activated", "account_no_activate": "The account could not be activated",
"action-add": "Add picto", "action-add": "Add picto",
"action-delete": "Delete picto", "action-delete": "Delete picto",
...@@ -13,8 +17,12 @@ ...@@ -13,8 +17,12 @@
"action-unshow": "Writing mode", "action-unshow": "Writing mode",
"activation": "Activation", "activation": "Activation",
"add": "Add", "add": "Add",
"add_existing": "Add existing account",
"add_existing_desc": "Link your profile to an already registered student's account to start working with him/her. You'll be asked for the current active license of the student.",
"add_expression": "Add expression", "add_expression": "Add expression",
"add_instruction": "Add instruction", "add_instruction": "Add instruction",
"add_new_official": "New official account",
"add_new_official_desc": "Create a new student account with a new official license.",
"add_office": "Add office", "add_office": "Add office",
"add_picto": "Add pictogram", "add_picto": "Add pictogram",
"add_pictos": "Add pictograms", "add_pictos": "Add pictograms",
...@@ -41,7 +49,9 @@ ...@@ -41,7 +49,9 @@
"August": "August", "August": "August",
"average_time_between_pictos": "Average time between pictograms", "average_time_between_pictos": "Average time between pictograms",
"average_time_per_try": "Average time per try", "average_time_per_try": "Average time per try",
"back": "Back",
"background": "Background", "background": "Background",
"back_to_login": "Back to login",
"beep": "Beep", "beep": "Beep",
"birthdate": "Birthdate", "birthdate": "Birthdate",
"black_and_white": "B&W", "black_and_white": "B&W",
...@@ -114,6 +124,7 @@ ...@@ -114,6 +124,7 @@
"edit": "Edit", "edit": "Edit",
"email": "Email address", "email": "Email address",
"email_confirm": "E-mail address confirmation", "email_confirm": "E-mail address confirmation",
"email_invalid": "Invalid email",
"email_match": "The emails must match", "email_match": "The emails must match",
"email_type": "E-mail address", "email_type": "E-mail address",
"enable_sound_for": "Enable sound for", "enable_sound_for": "Enable sound for",
...@@ -178,6 +189,7 @@ ...@@ -178,6 +189,7 @@
"keep_strip_and_deliveries": "Keep strip and allow several deliveries", "keep_strip_and_deliveries": "Keep strip and allow several deliveries",
"keep_strip_and_one_delivery": "Keep strip and allow only one delivery", "keep_strip_and_one_delivery": "Keep strip and allow only one delivery",
"language": "Language", "language": "Language",
"language_change_warning": "Your preferred language has been changed. Session restarting is recommended.",
"large": "Large", "large": "Large",
"large_picto": "Large pictograms", "large_picto": "Large pictograms",
"last_session": "Last session", "last_session": "Last session",
...@@ -191,11 +203,15 @@ ...@@ -191,11 +203,15 @@
"licenses": "Licenses", "licenses": "Licenses",
"license_already_activated": "License already activated", "license_already_activated": "License already activated",
"license_created": "License created", "license_created": "License created",
"license_expires": "PRO license expires on ", "license_expired_official": "PRO license expired. To maintain access to therapeutical functionalities you can",
"license_expired": "PRO license expired, you can", "license_expired_trial": "Trial license expired. To keep the account you should",
"license_expired_buy": "buy one license",
"license_expired_renew": "renew it", "license_expired_renew": "renew it",
"license_expires_official": "PRO license expires on ",
"license_expires_trial": "Trial license expires on ",
"license_invalid": "Invalid license number", "license_invalid": "Invalid license number",
"license_missing": "Account without PRO license", "license_missing_official": "This PRO license expired. You have no access to therapeutical functionalities, but you can still manage pictograms and devices.",
"license_missing_trial": "Trial license expired. Buy an official one to keep using this account (go to Settings).",
"license_number": "License number", "license_number": "License number",
"license_pro": "Pictogram PRO license", "license_pro": "Pictogram PRO license",
"license_warning": "Only available for professional licenses (Pictogram Pro).", "license_warning": "Only available for professional licenses (Pictogram Pro).",
...@@ -203,6 +219,8 @@ ...@@ -203,6 +219,8 @@
"licenses_left": "{{number}} licenses left", "licenses_left": "{{number}} licenses left",
"light_up": "Light up", "light_up": "Light up",
"link": "Link", "link": "Link",
"link_supervisor": "Link supervisor",
"link_supervisor_desc": "When linking a therapist/parent/tutor, he/she will be notified of this action.",
"loading_pictos": "Loading pictos", "loading_pictos": "Loading pictos",
"login": "Log In", "login": "Log In",
"login_fail": "Invalid user or password", "login_fail": "Invalid user or password",
...@@ -235,17 +253,23 @@ ...@@ -235,17 +253,23 @@
"new_scene_with_categories": "Create scene with categories", "new_scene_with_categories": "Create scene with categories",
"new_scene_without_categories": "Create scene without categories", "new_scene_without_categories": "Create scene without categories",
"new_session": "New session", "new_session": "New session",
"new_test_account": "New test account",
"new_test_account_desc": "Create a test account to try Pictogram for free. You will be able to keep the account beyond the three months trial by activating an official license on the account.",
"next": "Next",
"next_actions": "Next actions", "next_actions": "Next actions",
"next_sessions": "Next sessions", "next_sessions": "Next sessions",
"no": "No", "no": "No",
"no_categories": "Without categories", "no_categories": "Without categories",
"nobegin": "No started", "nobegin": "No started",
"no_instruction": "No instruction defined",
"no_method": "No method defined", "no_method": "No method defined",
"no_office": "No office", "no_office": "No office",
"no_subscribed": "No connection to student account", "no_subscribed": "No connection to student account",
"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_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", "no_space_in_category": "No space left in category",
"no_supervisors": "No supervisors linked. ",
"no_supervisors_desc": "Enter supervisor's email in the input field above to add one.",
"no_supervisor_linked": "Unable to link supervisor",
"normal": "Normal", "normal": "Normal",
"note": "Note", "note": "Note",
"notes": "Notes", "notes": "Notes",
...@@ -258,9 +282,11 @@ ...@@ -258,9 +282,11 @@
"objetive": "Objetive", "objetive": "Objetive",
"October": "October", "October": "October",
"office": "Office", "office": "Office",
"office_account_desc": "Manage students and intervention teams, along with all therapist related functionalities.",
"office_added": "Office added", "office_added": "Office added",
"office_center": "Office or center", "office_center": "Office or center",
"office_deleted": "Office deleted", "office_deleted": "Office deleted",
"office_name": "Office's name",
"office_not_added": "Office not added", "office_not_added": "Office not added",
"office_not_deleted": "Office not deleted", "office_not_deleted": "Office not deleted",
"office_not_updated": "Office not updated", "office_not_updated": "Office not updated",
...@@ -273,6 +299,7 @@ ...@@ -273,6 +299,7 @@
"own_pictos": "Your pictograms", "own_pictos": "Your pictograms",
"tos": "Your pictograms", "tos": "Your pictograms",
"pages": "Pages", "pages": "Pages",
"parents_tutor": "Parent or tutor",
"password": "Password", "password": "Password",
"password_changed": "Password changed sucessfully", "password_changed": "Password changed sucessfully",
"password_confirm": "Repeat password", "password_confirm": "Repeat password",
...@@ -336,6 +363,7 @@ ...@@ -336,6 +363,7 @@
"search_sup_email": "Search supervisor by email", "search_sup_email": "Search supervisor by email",
"search_tutor_email": "Search tutor by email", "search_tutor_email": "Search tutor by email",
"seconds": "seconds", "seconds": "seconds",
"select_account": "Select account type",
"select_instruction": "-- Select an instruction --", "select_instruction": "-- Select an instruction --",
"select_a_method": "-- Select a method --", "select_a_method": "-- Select a method --",
"select_method": "-- Select a method or create it --", "select_method": "-- Select a method or create it --",
...@@ -376,8 +404,10 @@ ...@@ -376,8 +404,10 @@
"state_spontaneous": "Spontaneous", "state_spontaneous": "Spontaneous",
"state_supervised": "Supervised", "state_supervised": "Supervised",
"stop": "Stop", "stop": "Stop",
"student_account_confirm": "The new account is now available from the students list.",
"student_added": "Student added", "student_added": "Student added",
"student_already_exists": "A student with that username already exists, please try with another one", "student_already_exists": "A student with that username already exists, please try with another one",
"student_already_linked": "The student is already linked to your account",
"student_deleted": "Student deleted", "student_deleted": "Student deleted",
"student_not_added": "Student not added", "student_not_added": "Student not added",
"student_not_deleted": "Student not deleted", "student_not_deleted": "Student not deleted",
...@@ -389,19 +419,25 @@ ...@@ -389,19 +419,25 @@
"sup_not_added": "Supervisor not added to the student", "sup_not_added": "Supervisor not added to the student",
"sup_not_deleted": "The supervisor couldn't be deleted by the student", "sup_not_deleted": "The supervisor couldn't be deleted by the student",
"sup_not_found": "There is no supervisor account in Pictogram with this email", "sup_not_found": "There is no supervisor account in Pictogram with this email",
"sup_not_in_office": "There is no supervisor account related to your office/center with this email.",
"supervisor_added": "Supervisor added", "supervisor_added": "Supervisor added",
"supervisor_added_notified": "Supervisor added. A notification email has been sent to his/her email address.",
"supervisor_already_linked": "The supervisor is already linked to your account",
"supervisor_deleted": "Supervisor deleted", "supervisor_deleted": "Supervisor deleted",
"supervisor_not_added": "Supervisor not added", "supervisor_not_added": "Supervisor not added",
"supervisor_not_deleted": "Supervisor not deleted", "supervisor_not_deleted": "Supervisor not deleted",
"supervisor_not_updated": "Supervisor not updated", "supervisor_not_updated": "Supervisor not updated",
"supervisor_note": "If the parent aren't going to register in the platform, the administrator can use the notes field to store their information.", "supervisor_note": "If the parent aren't going to register in the platform, the administrator can use the notes field to store their information.",
"supervisor_updated": "Supervisor updated", "supervisor_updated": "Supervisor updated",
"supervisor_yourself": "This is you. No reason to link to yourself.",
"supervisors": "Supervisors", "supervisors": "Supervisors",
"support": "User support", "support": "User support",
"surname": "Surname", "surname": "Surname",
"tag_deleted": "Tag deleted", "tag_deleted": "Tag deleted",
"tape_background": "Tape background", "tape_background": "Tape background",
"template_deleted": "Template deleted", "template_deleted": "Template deleted",
"therapist": "Therapist",
"therapist_account_desc": "Manage pictograms, devices, record therapy sessions and get evolution reports.",
"therapists": "Therapists", "therapists": "Therapists",
"time_hours": "Time: {{hours}} hours", "time_hours": "Time: {{hours}} hours",
"time_instruction_method": "Time instructions of method", "time_instruction_method": "Time instructions of method",
...@@ -417,6 +453,7 @@ ...@@ -417,6 +453,7 @@
"tpl_date_frame": "de {{ begin | date:'dd-MM-yyyy' }} a {{ end | date:'dd-MM-yyyy' }}", "tpl_date_frame": "de {{ begin | date:'dd-MM-yyyy' }} a {{ end | date:'dd-MM-yyyy' }}",
"tpl_day": "{{ day | date:'yyyy-MM-dd' }}", "tpl_day": "{{ day | date:'yyyy-MM-dd' }}",
"tpl_hours_frame": "from {{ begin | date:'HH:mm:ss' }} to {{ end | date:'HH:mm:ss' }}", "tpl_hours_frame": "from {{ begin | date:'HH:mm:ss' }} to {{ end | date:'HH:mm:ss' }}",
"trial_license": "Trial license",
"tries": "Tries", "tries": "Tries",
"tries_done": "Tries done", "tries_done": "Tries done",
"tries_length": "Tries length", "tries_length": "Tries length",
...@@ -425,7 +462,9 @@ ...@@ -425,7 +462,9 @@
"tries_per_instruction_method": "Tries per instruction of method", "tries_per_instruction_method": "Tries per instruction of method",
"tries_per_months": "Tries per months in", "tries_per_months": "Tries per months in",
"tries_results_instruction": "Tries results in instruction", "tries_results_instruction": "Tries results in instruction",
"tutor": "Parent/tutor",
"tutor_added": "Tutor added to the student", "tutor_added": "Tutor added to the student",
"tutor_account_desc": "Manage child's pictograms and configure his/her communication device.",
"tutor_deleted": "Tutor removed from the student", "tutor_deleted": "Tutor removed from the student",
"tutor_not_added": "Tutor not added to the student.", "tutor_not_added": "Tutor not added to the student.",
"tutor_not_deleted": "Tutor couldn't be removed from the student", "tutor_not_deleted": "Tutor couldn't be removed from the student",
...@@ -439,9 +478,11 @@ ...@@ -439,9 +478,11 @@
"update_supervisor": "Update supervisor", "update_supervisor": "Update supervisor",
"upload_image": "Upload image", "upload_image": "Upload image",
"use_categories": "Use categories", "use_categories": "Use categories",
"username": "Name of account (no spaces)", "username": "Account identifier",
"username_default": "Account identifier (don't use spaces)",
"username_exists": "There is already an account with name '{{username}}'", "username_exists": "There is already an account with name '{{username}}'",
"user_created": "User {{name}} {{surname}} created. An email with instructions to activate the account has been sent.", "user_created": "Account created!",
"user_created_text": "An email with instructions to activate the account has been sent to {{email}}.",
"user_exists": "User with email {{email}} already exists", "user_exists": "User with email {{email}} already exists",
"validate_fail": "The user account couldn't be validated", "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", "validate_success": "The user account has been validated. Now, you can login from the link below",
......
{ {
"account": "Cuenta", "account": "Cuenta",
"account_activate": "La cuenta ha sido activada", "account_activate": "La cuenta ha sido activada",
"account_available": "Cuenta disponible",
"account_desc_office": "Gestione alumnos y equipos de intervención, además de todas las funcionalidades propias de un terapeuta.",
"account_desc_tutor": "Gestione los pictogramas de su hijo o hija y configure su dispositivo de comunicación.",
"account_desc_therapist": "Gestione pictogramas, dispositivos, grabe sesiones de terapia y obtenga estadísticas de progreso.",
"account_no_activate": "La cuenta no se ha podido activar", "account_no_activate": "La cuenta no se ha podido activar",
"action-add": "Añade picto", "action-add": "Añade picto",
"action-delete": "Elimina picto", "action-delete": "Elimina picto",
...@@ -13,8 +17,12 @@ ...@@ -13,8 +17,12 @@
"action-unshow": "Modo escritura", "action-unshow": "Modo escritura",
"activation": "Activación", "activation": "Activación",
"add": "Añadir", "add": "Añadir",
"add_existing": "Asociar cuenta existente",
"add_existing_desc": "Asocie a su perfil la cuenta de un/a alumno/a ya registrado/a para poder gestionarla. Necesitará el número de licencia en uso del estudiante.",
"add_expression": "Añadir expresión", "add_expression": "Añadir expresión",
"add_instruction": "Añadir instrucción", "add_instruction": "Añadir instrucción",
"add_new_official": "Nueva cuenta oficial",
"add_new_official_desc": "Alta de una nueva cuenta de alumno/a con licencia oficial.",
"add_office": "Añadir gabinete", "add_office": "Añadir gabinete",
"add_picto": "Añadir pictograma", "add_picto": "Añadir pictograma",
"add_pictos": "Añadir pictogramas", "add_pictos": "Añadir pictogramas",
...@@ -41,7 +49,9 @@ ...@@ -41,7 +49,9 @@
"August": "Agosto", "August": "Agosto",
"average_time_between_pictos": "Tiempo medio entre pictogramas", "average_time_between_pictos": "Tiempo medio entre pictogramas",
"average_time_per_try": "Tiempo medio por intento", "average_time_per_try": "Tiempo medio por intento",
"back": "Volver",
"background": "Fondo", "background": "Fondo",
"back_to_login": "Volver a inicio de sesión",
"beep": "Pitido", "beep": "Pitido",
"birthdate": "Fecha de nacimiento", "birthdate": "Fecha de nacimiento",
"black_and_white": "ByN", "black_and_white": "ByN",
...@@ -69,8 +79,7 @@ ...@@ -69,8 +79,7 @@
"close_session": "Cerrar sesion", "close_session": "Cerrar sesion",
"collections": "Colecciones", "collections": "Colecciones",
"confirmation": "¿Estás seguro?", "confirmation": "¿Estás seguro?",
"confirm_unlink_therapist": "¿Desligar {{ name }} de {{ student }} como terapeuta?", "confirm_unlink_student": "¿Desligar {{ name }} de {{ student }}?",
"confirm_unlink_tutor": "¿Desligar {{ name }} de {{ student }} como tutor?",
"contact_person": "Persona de contacto", "contact_person": "Persona de contacto",
"contact_person": "Persona de contacto", "contact_person": "Persona de contacto",
"continue_session": "Reanudar sesión", "continue_session": "Reanudar sesión",
...@@ -114,6 +123,7 @@ ...@@ -114,6 +123,7 @@
"edit": "Editar", "edit": "Editar",
"email": "Correo electrónico", "email": "Correo electrónico",
"email_confirm": "Repite tu email", "email_confirm": "Repite tu email",
"email_invalid": "El email no es válido",
"email_match": "Los emails deben coincidir", "email_match": "Los emails deben coincidir",
"email_type": "Introduce tu email", "email_type": "Introduce tu email",
"enable_sound_for": "Habilitar sonido para", "enable_sound_for": "Habilitar sonido para",
...@@ -178,6 +188,7 @@ ...@@ -178,6 +188,7 @@
"keep_strip_and_deliveries": "Mantener cinta y permitir varias entregas", "keep_strip_and_deliveries": "Mantener cinta y permitir varias entregas",
"keep_strip_and_one_delivery": "Mantener cinta y permitir sólo una entrega", "keep_strip_and_one_delivery": "Mantener cinta y permitir sólo una entrega",
"language": "Idioma", "language": "Idioma",
"language_change_warning": "Ha cambiado el idioma. Se recomienda reiniciar sesión.",
"large": "Grande", "large": "Grande",
"large_picto": "Pictogramas grandes", "large_picto": "Pictogramas grandes",
"last_session": "Última sesión", "last_session": "Última sesión",
...@@ -191,18 +202,24 @@ ...@@ -191,18 +202,24 @@
"licenses": "Licencias", "licenses": "Licencias",
"licenses_left": "{{number}} licencias disponibles", "licenses_left": "{{number}} licencias disponibles",
"license_already_activated": "Licencia ya activada previamente", "license_already_activated": "Licencia ya activada previamente",
"license_expires": "La licencia PRO expira el ",
"license_expired": "La licencia PRO expiró, puede",
"license_expired_renew": "renovarla",
"license_created": "Licencia creada", "license_created": "Licencia creada",
"license_expired_official": "La licencia PRO expiró. Para mantener acceso a funcionalidades terapéuticas puede",
"license_expired_trial": "La licencia de prueba expiró. Para mantener la cuenta debería",
"license_expired_buy": "adquirir una licencia",
"license_expired_renew": "renovarla",
"license_expires_official": "La licencia PRO finaliza el ",
"license_expires_trial": "La licencia de prueba finaliza el ",
"license_invalid": "Licencia inválida", "license_invalid": "Licencia inválida",
"license_number": "Número de licencia", "license_number": "Número de licencia",
"license_pro": "Licencia Pictogram PRO", "license_pro": "Licencia Pictogram PRO",
"license_warning": "Sólo disponible para licencias profesionales (Pictogram Pro).", "license_warning": "Sólo disponible para licencias profesionales (Pictogram Pro).",
"license_missing": "Cuenta sin licencia PRO", "license_missing_official": "La licencia PRO expiró. El acceso a las funcionalidades terapéuticas queda restringido, aunque puede seguir gestionando pictogramas y dispositivos.",
"license_missing_trial": "La licencia de prueba expiró. Adquiera una licencia oficial para mantener esta cuenta (puede hacerlo en Configuración).",
"licenses_created": "Licencias creadas", "licenses_created": "Licencias creadas",
"light_up": "Iluminar", "light_up": "Iluminar",
"link": "Vincular", "link": "Vincular",
"link_supervisor": "Vincular supervisor",
"link_supervisor_desc": "Al vincular un terapeuta/padre/madre/tutor se enviará un correo de notificación al mismo.",
"loading_pictos": "Cargando pictos", "loading_pictos": "Cargando pictos",
"login": "Iniciar sesión", "login": "Iniciar sesión",
"login_fail": "Usuario o contraseña incorrectos", "login_fail": "Usuario o contraseña incorrectos",
...@@ -235,6 +252,9 @@ ...@@ -235,6 +252,9 @@
"new_scene_with_categories": "Crear escena con categorías", "new_scene_with_categories": "Crear escena con categorías",
"new_scene_without_categories": "Crear escena sin categorías", "new_scene_without_categories": "Crear escena sin categorías",
"new_session": "Nueva sesión", "new_session": "Nueva sesión",
"new_test_account": "Crear cuenta de prueba",
"new_test_account_desc": "Cree una cuenta temporal para probar gratuitamente Pictogram. Podrá activar una licencia en esta cuenta para mantenerla más allá de los tres meses de prueba.",
"next": "Siguiente",
"next_actions": "Acciones posteriores", "next_actions": "Acciones posteriores",
"next_sessions": "Sesiones posteriores", "next_sessions": "Sesiones posteriores",
"no": "No", "no": "No",
...@@ -242,9 +262,13 @@ ...@@ -242,9 +262,13 @@
"no_method": "Método sin definir", "no_method": "Método sin definir",
"no_office": "Sin centro", "no_office": "Sin centro",
"no_instruction": "Instrucción sin definir", "no_instruction": "Instrucción sin definir",
"no_students_for_user": "Su cuenta no está asociada a ningún estudiante. Por favor, contacte con su gabinete para enlazar su cuenta a un estudiante.", "no_students": "Su cuenta no está asociada a ningún estudiante",
"no_students_desc": "Pulse en 'Añadir estudiante' para vincularse a cuentas de alumnos existentes o dar de alta nuevas",
"no_space_in_category": "No queda espacio en la categoría", "no_space_in_category": "No queda espacio en la categoría",
"no_subscribed": "Sin conexión a la cuenta del estudiante", "no_subscribed": "Sin conexión a la cuenta del estudiante",
"no_supervisors": "No tiene tutores, padres o terapeutas asociados.",
"no_supervisors_desc": "Introduzca el correo electrónico del supervisor en el campo de arriba para añadirlo.",
"no_supervisor_linked": "No se pudo asociar al supervisor",
"nobegin": "Sin iniciar", "nobegin": "Sin iniciar",
"normal": "Normal", "normal": "Normal",
"note": "Nota", "note": "Nota",
...@@ -257,10 +281,12 @@ ...@@ -257,10 +281,12 @@
"num_sessions_per_month_in": "Número de sesiones por meses en", "num_sessions_per_month_in": "Número de sesiones por meses en",
"objetive": "Objetivo", "objetive": "Objetivo",
"October": "Octubre", "October": "Octubre",
"office": "Gabinete", "office": "Gabinete/centro",
"office_account_desc": "Gestione alumnos y equipos de intervención, además de todas las funcionalidades propias de un terapeuta.",
"office_center": "Gabinete/centro", "office_center": "Gabinete/centro",
"office_added": "Gabinete añadido", "office_added": "Gabinete añadido",
"office_deleted": "Gabinete eliminado", "office_deleted": "Gabinete eliminado",
"office_name": "Nombre del centro/gabinete",
"office_not_added": "No se ha podido añadir el gabinete", "office_not_added": "No se ha podido añadir el gabinete",
"office_not_deleted": "No se ha podido eliminar el gabinete", "office_not_deleted": "No se ha podido eliminar el gabinete",
"office_not_updated": "El gabinete no se ha podido actualizar", "office_not_updated": "El gabinete no se ha podido actualizar",
...@@ -272,6 +298,7 @@ ...@@ -272,6 +298,7 @@
"own_labels": "Etiquetas propias", "own_labels": "Etiquetas propias",
"own_pictos": "Pictogramas propios", "own_pictos": "Pictogramas propios",
"pages": "Páginas", "pages": "Páginas",
"parents_tutor": "Padre, madre o tutor",
"password": "Contraseña", "password": "Contraseña",
"password_changed": "La clave ha sido modificada exitosamente.", "password_changed": "La clave ha sido modificada exitosamente.",
"password_confirm": "Repita la contraseña", "password_confirm": "Repita la contraseña",
...@@ -337,6 +364,7 @@ ...@@ -337,6 +364,7 @@
"search_tutor_email": "Buscar tutor por email", "search_tutor_email": "Buscar tutor por email",
"seconds": "segundos", "seconds": "segundos",
"select_instruction": "-- Selecciona una instrucción --", "select_instruction": "-- Selecciona una instrucción --",
"select_account": "Seleccione tipo de cuenta",
"select_a_method": "-- Selecciona un método --", "select_a_method": "-- Selecciona un método --",
"select_method": "-- Selecciona un método o créalo --", "select_method": "-- Selecciona un método o créalo --",
"select_office": "Seleccione una oficina/centro de la lista", "select_office": "Seleccione una oficina/centro de la lista",
...@@ -376,8 +404,10 @@ ...@@ -376,8 +404,10 @@
"state_spontaneous": "Espontáneo", "state_spontaneous": "Espontáneo",
"state_supervised": "Guiado", "state_supervised": "Guiado",
"stop": "Parar", "stop": "Parar",
"student_account_confirm": "La nueva cuenta ahora está disponible en su lista de alumnos.",
"student_added": "Estudiante añadido", "student_added": "Estudiante añadido",
"student_already_exists": "Ya existe un estudiante con ese nombre de usuario. Por favor, inténtelo de nuevo con algo diferente.", "student_already_exists": "Ya existe un estudiante con ese nombre de usuario. Por favor, inténtelo de nuevo con algo diferente.",
"student_already_linked": "El estudiante ya está vinculado a su cuenta",
"student_deleted": "Estudiante eliminado", "student_deleted": "Estudiante eliminado",
"student_not_added": "Estudiante no añadido", "student_not_added": "Estudiante no añadido",
"student_not_deleted": "No se ha podido eliminar el estudiante", "student_not_deleted": "No se ha podido eliminar el estudiante",
...@@ -389,20 +419,26 @@ ...@@ -389,20 +419,26 @@
"sup_not_added": "El supervisor no se ha podido añadir al estudiante.", "sup_not_added": "El supervisor no se ha podido añadir al estudiante.",
"sup_not_deleted": "El supervisor no se ha podido desvincular del alumno.", "sup_not_deleted": "El supervisor no se ha podido desvincular del alumno.",
"sup_not_found": "No hay ningún usuario en Pictogram con ese correo electrónico.", "sup_not_found": "No hay ningún usuario en Pictogram con ese correo electrónico.",
"sup_not_in_office": "No hay ningún usuario asociado a su centro/gabinete con ese correo electrónico.",
"supervisor_added": "Supervisor añadido", "supervisor_added": "Supervisor añadido",
"supervisor_added_notified": "Supervisor añadido. Se le ha enviado al mismo una notificación por correo electrónico.",
"supervisor_already_linked": "El supervisor ya está vinculado",
"supervisor_deleted": "Supervisor eliminado", "supervisor_deleted": "Supervisor eliminado",
"supervisor_not_added": "Supervisor no añadido", "supervisor_not_added": "Supervisor no añadido",
"supervisor_not_deleted": "No se ha podido eliminar el supervisor", "supervisor_not_deleted": "No se ha podido eliminar el supervisor",
"supervisor_not_updated": "El supervisor no se ha podido actualizar", "supervisor_not_updated": "El supervisor no se ha podido actualizar",
"supervisor_note": "Si los padres no se van a dar de alta en la plataforma nunca, el administrador puede anotar la información de contacto en el campo notas.", "supervisor_note": "Si los padres no se van a dar de alta en la plataforma nunca, el administrador puede anotar la información de contacto en el campo notas.",
"supervisor_updated": "Supervisor actualizado", "supervisor_updated": "Supervisor actualizado",
"supervisor_yourself": "Este es usted. No hay razón para añadir a uno mismo.",
"support": "Atención al cliente", "support": "Atención al cliente",
"therapists": "Terapeutas",
"supervisors": "Supervisores", "supervisors": "Supervisores",
"surname": "Apellidos", "surname": "Apellidos",
"tag_deleted": "Etiqueta borrada", "tag_deleted": "Etiqueta borrada",
"tape_background": "Fondo de la cinta", "tape_background": "Fondo de la cinta",
"template_deleted": "Plantilla eliminada", "template_deleted": "Plantilla eliminada",
"therapists": "Terapeutas",
"therapist": "Terapeuta",
"therapist_account_desc": "Gestione pictogramas, dispositivos, grabe sesiones de terapia y obtenga estadísticas de evolución.",
"time_hours": "Tiempo: {{hours}} horas", "time_hours": "Tiempo: {{hours}} horas",
"time_instruction_method": "Tiempo instrucciones del método", "time_instruction_method": "Tiempo instrucciones del método",
"time_sessions_total": "Tiempo total de sesiones", "time_sessions_total": "Tiempo total de sesiones",
...@@ -417,6 +453,7 @@ ...@@ -417,6 +453,7 @@
"tpl_date_frame": "de {{ begin | date:'dd-MM-yyyy' }} a {{ end | date:'dd-MM-yyyy' }}", "tpl_date_frame": "de {{ begin | date:'dd-MM-yyyy' }} a {{ end | date:'dd-MM-yyyy' }}",
"tpl_day": "{{ day | date:'dd-MM-yyyy' }}", "tpl_day": "{{ day | date:'dd-MM-yyyy' }}",
"tpl_hours_frame": "de {{ begin | date:'HH:mm:ss' }} a {{ end | date:'HH:mm:ss' }}", "tpl_hours_frame": "de {{ begin | date:'HH:mm:ss' }} a {{ end | date:'HH:mm:ss' }}",
"trial_license": "Licencia de prueba",
"tries": "Ensayos", "tries": "Ensayos",
"tries_done": "Ensayos realizados", "tries_done": "Ensayos realizados",
"tries_length": "Duración ensayos", "tries_length": "Duración ensayos",
...@@ -425,6 +462,8 @@ ...@@ -425,6 +462,8 @@
"tries_per_instruction_method": "Ensayos por instrucción del método", "tries_per_instruction_method": "Ensayos por instrucción del método",
"tries_per_months": "Número de ensayos por meses en", "tries_per_months": "Número de ensayos por meses en",
"tries_results_instruction": "Resultados ensayos en instrucción", "tries_results_instruction": "Resultados ensayos en instrucción",
"tutor": "Padre/madre/tutor",
"tutor_account_desc": "Gestione los pictogramas de su hijo o hija y configure su dispositivo de comunicación.",
"tutor_added": "Tutor añadido al estudiante", "tutor_added": "Tutor añadido al estudiante",
"tutor_deleted": "Tutor desvinculado del estudiante", "tutor_deleted": "Tutor desvinculado del estudiante",
"tutor_not_added": "El tutor no se ha podido añadir al estudiante", "tutor_not_added": "El tutor no se ha podido añadir al estudiante",
...@@ -439,9 +478,11 @@ ...@@ -439,9 +478,11 @@
"update_supervisor": "Editar supervisor", "update_supervisor": "Editar supervisor",
"upload_image": "Subir imagen", "upload_image": "Subir imagen",
"use_categories": "Usar categorías", "use_categories": "Usar categorías",
"username": "Nombre cuenta (sin espacios)", "username": "Identificador de cuenta",
"username_default": "Identificador cuenta (no use espacios)",
"username_exists": "Ya existe un usuario con nombre de cuenta '{{username}}'", "username_exists": "Ya existe un usuario con nombre de cuenta '{{username}}'",
"user_created": "Usuario {{name}} {{surname}} creado. Se ha enviado un email de confirmación para activar su cuenta.", "user_created": "¡Cuenta creada!",
"user_created_text": "Se ha enviado un email de confirmación para activar su cuenta a la dirección {{email}}.",
"user_exists": "Ya existe el usuario con email '{{email}}'", "user_exists": "Ya existe el usuario con email '{{email}}'",
"validate_fail": "La cuenta no se ha podido validar", "validate_fail": "La cuenta no se ha podido validar",
"validate_success": "Cuenta validada. Puede iniciar sesión desde el enlace inferior", "validate_success": "Cuenta validada. Puede iniciar sesión desde el enlace inferior",
......
...@@ -32,8 +32,9 @@ dashboardControllers.controller('MainCtrl', function MainCtrl($scope, $window, $ ...@@ -32,8 +32,9 @@ dashboardControllers.controller('MainCtrl', function MainCtrl($scope, $window, $
id: '', id: '',
name: '', name: '',
surname: '', surname: '',
email: '',
role: '',
pic: '', pic: '',
office: '',
lang: '' lang: ''
}; };
...@@ -74,7 +75,7 @@ dashboardControllers.controller('MainCtrl', function MainCtrl($scope, $window, $ ...@@ -74,7 +75,7 @@ dashboardControllers.controller('MainCtrl', function MainCtrl($scope, $window, $
// Returns the full name of the user // Returns the full name of the user
$scope.user.getFullName = function(){ $scope.user.getFullName = function(){
return $scope.user.name + " " + $scope.user.surname; return $scope.user.name + ($scope.user.isOffice ? "" : " " + $scope.user.surname);
}; };
// Logout // Logout
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
dashboardControllers.controller('LoginCtrl', dashboardControllers.controller('LoginCtrl',
function LoginCtrl( function LoginCtrl(
$scope, $scope,
$rootScope,
$http, $http,
$window, $window,
$translate, $translate,
...@@ -15,82 +16,160 @@ function LoginCtrl( ...@@ -15,82 +16,160 @@ function LoginCtrl(
$location, $location,
config, config,
$stateParams, $stateParams,
ngToast) { $timeout,
ngToast,
CONSTANTS,
vcRecaptchaService) {
/* Slider object */
$scope.slide = {
state: 'login',
prev: 'login',
back: false,
rightTo: function (state) {
$scope.slide.back = false;
$scope.slide.prev = $scope.slide.state;
$timeout(function () {
$scope.slide.state = state;
}, 0);
},
leftTo: function (state) {
$scope.slide.back = true;
$scope.slide.prev = $scope.slide.state;
$timeout(function () {
$scope.slide.state = state;
}, 0);
}
};
/*
LOGIN --------------------------
*/
/* Login credentials */
$scope.credentials = { $scope.credentials = {
email: '', email: '',
password: '', password: '',
lang: 'es-es' lang: 'es-es'
}; };
$scope.office = { /* Login function */
logoUrl : 'img/logo_pictogram.png',
name : 'Pictogram'
};
// Corporate login, office code has been passed
if ($stateParams.office) {
$http
.get(config.backend + '/office/' + $stateParams.office)
.success(function (data) {
$scope.office = data;
});
}
$scope.login = function () { $scope.login = function () {
$scope.submitted = true; $scope.submitted = true;
$http $http
.post(config.backend + '/sup/login', $scope.credentials) .post(config.backend + '/sup/login', $scope.credentials)
.success(function (data) { .success(function (data) {
// default logo to Pictogram logo
if (!data.user.office) {
data.user.office = $scope.office;
data.user.isTutor = true;
} else
data.user.isTutor = false;
if (data.user.office.logoUrl.length < 5)
data.user.office.logoUrl = 'img/logo_pictogram.png';
$window.sessionStorage.token = data.token; $window.sessionStorage.token = data.token;
//User data correct //User data correct
if (data.user) { if (data.user) {
// Adapt language en-us to en-gb (the latter is the one supported for 'en') // Adapt language en-us to en-gb (the latter is the one supported for 'en')
if (data.user.lang === 'en-us') { if (data.user.lang === 'en-us')
data.user.lang = 'en-gb'; data.user.lang = 'en-gb';
}
//Update $scope data.user.isTutor = data.user.role == 'tutor';
data.user.isTherapist = data.user.role == 'therapist';
data.user.isOffice = data.user.role == 'office';
data.user.isAdmin = data.user.role == 'admin';
$scope.lang = data.user.lang; $scope.lang = data.user.lang;
//Update $translate
$translate.use($scope.lang); $translate.use($scope.lang);
} else { } else {
//No user data, use default lang
$translate.use($scope.lang); $translate.use($scope.lang);
$location.path('/sup/login');
} }
// Change
$window.sessionStorage.user = JSON.stringify(data.user); $window.sessionStorage.user = JSON.stringify(data.user);
$translate('login_success').then(function (translation) {
ngToast.success({ content: translation });
});
// Name in login success message
$scope.name = data.user.name;
// Redirección
$location.path('/students'); $location.path('/students');
}) })
.error(function (err) { .error(function (err) {
$scope.submitted = false; $scope.submitted = false;
delete $window.sessionStorage.token; delete $window.sessionStorage.token;
if (err.search("without students") > 0) { if (err.search("not been activated") > 0)
ngToast.warning($translate.instant('no_students_for_user')); ngToast.danger($translate.instant('inactive_account'));
} else if (err.search("not been activated") > 0) { else
ngToast.danger($translate.instant('inactive_account')); ngToast.danger($translate.instant("login_fail"));
} else {
ngToast.danger($translate.instant("login_fail"));
}
}); });
}; };
/*
SIGNUP ------------------------------
*/
/* form data */
var formdata_empty = {
name: '',
email: '',
password: '',
password_confirm: '',
lang: '',
role: '',
};
$scope.minlength = CONSTANTS.password_minlength;
/* Forms objects */
$scope.forms = {};
$scope.reset = function () {
$scope.formdata = formdata_empty;
};
$scope.reset();
// Signup form submit
$scope.signup = function (formName) {
var form;
// select form according to account
if (formName == 'tutorForm')
form = $scope.forms.tutorForm;
else if (formName == 'therapistForm')
form = $scope.forms.therapistForm;
else
form = $scope.forms.officeForm;
// set language according to interface settings
$scope.formdata.lang = $translate.use();
//
// check validity of fields
//
if (typeof $scope.formdata.email == 'undefined' || form.email.$invalid) {
ngToast.danger($translate.instant('email_invalid'));
return;
}
if ($scope.formdata.password.length < CONSTANTS.password_minlength) {
ngToast.danger($translate.instant('password_short', {minlength: CONSTANTS.password_minlength}));
return;
}
if ($scope.formdata.password !== $scope.formdata.password_confirm) {
ngToast.danger($translate.instant('password_match'));
return;
}
if (!$scope.formdata.disclaimer_accepted) {
ngToast.danger($translate.instant('disclaimer_requested'));
return;
}
if (form.$invalid)
return;
$http
.post(config.backend + '/sup', $scope.formdata)
.success(function () {
$scope.slide.rightTo('confirmation');
})
.error(function () {
ngToast.danger({ content: $translate.instant('user_exists', {email: $scope.formdata.email}) });
});
};
}); });
/* global dashboardControllers */
'use strict';
//-------------------
// SignIn Controller
//-------------------
dashboardControllers.controller('SignInCtrl',
function SignInCtrl($scope,
$http,
$window,
$translate,
$rootScope,
config,
CONSTANTS,
ngToast,
vcRecaptchaService)
{
$scope.reset = function () {
$scope.formdata = {
name: '',
surname: '',
address: '',
postalCode: '',
country: '00',
phone: '',
gender: 'F',
email: '',
email_confirm: '',
password: '',
password_confirm: '',
lang: '00',
role: 'therapist_office',
office: {
name: '',
address: '',
postalCode: '',
country: '00',
contactPerson: '',
phone1: '',
email: '',
logoUrl: ''
},
id_off: -1
};
};
$scope.reset();
// Get the list of offices
$http
.get(config.backend + '/office/get_all')
.success(function (offices) {
$scope.offices = offices;
})
.error(function () {
ngToast.danger({ content: $translate.instant('server_error') });
});
// Copy fields from supervisor to office
$scope.copyFields = function () {
$scope.formdata.office.address = $scope.formdata.address;
$scope.formdata.office.postalCode = $scope.formdata.postalCode;
$scope.formdata.office.country = $scope.formdata.country;
$scope.formdata.office.lang = $scope.formdata.lang;
$scope.formdata.office.email = $scope.formdata.email;
$scope.formdata.office.phone1 = $scope.formdata.phone;
$scope.formdata.office.contactPerson = $scope.formdata.name + " " + $scope.formdata.surname;
};
// Form submit
$scope.signin = function () {
// Validate email match
if ($scope.formdata.email !== $scope.formdata.email_confirm) {
ngToast.danger({ content: $translate.instant('email_match') });
return;
}
// Validate password match
if ($scope.formdata.password !== $scope.formdata.password_confirm) {
ngToast.danger({ content: $translate.instant('password_match') });
return;
}
if ($scope.formdata.password.length < CONSTANTS.password_minlength) {
ngToast.danger({ content: $translate.instant('password_short', {minlength: CONSTANTS.password_minlength}) });
return;
}
if ($scope.formdata.country == '00') {
ngToast.danger({ content: $translate.instant('country_requested') });
return;
}
if (($scope.formdata.role == 'therapist_office' || $scope.formdata.role == 'tutor_office') && $scope.formdata.id_off == -1) {
ngToast.danger({ content: $translate.instant('select_office') });
return;
}
if ($scope.formdata.role == 'therapist_nooffice' && $scope.formdata.office.country == '00') {
ngToast.danger({ content: $translate.instant('country_office_requested') });
return;
}
if (!$scope.formdata.disclaimer_accepted) {
ngToast.danger({ content: $translate.instant('disclaimer_requested') });
return;
}
if (!$scope.formdata.role) {
ngToast.danger({ content: $translate.instant('case_requested') });
return;
}
if (!$scope.signInForm.$valid)
return;
$scope.showdialog = true;
if ($scope.formdata.id_off == -1)
delete $scope.formdata.id_off;
if ($scope.formdata.role === 'tutor_nooffice') {
$scope.formdata.office.name = 'no_office';
$scope.formdata.office.address = $scope.formdata.address;
$scope.formdata.office.postalCode = $scope.formdata.postalCode;
$scope.formdata.office.country = $scope.formdata.country;
$scope.formdata.office.contactPerson = $scope.formdata.name + " " + $scope.formdata.surname;
$scope.formdata.office.phone1 = $scope.formdata.phone;
$scope.formdata.office.email = $scope.formdata.email;
$scope.formdata.office.lang = $scope.formdata.lang;
}
$http
.post(config.backend + '/sup', $scope.formdata)
.success(function () {
ngToast.success({ content: $translate.instant('user_created', { name: $scope.formdata.name, surname: $scope.formdata.surname }) });
$scope.reset();
})
.error(function () {
ngToast.danger({ content: $translate.instant('user_exists', {email: $scope.formdata.email}) });
});
};
});
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="header-image"> <div class="header-image">
<div class="row"> <div class="row">
<div class="col-md-12 text-center"> <div class="col-md-12 text-center">
<img ng-src="{{office.logoUrl}}" alt="{{office.name}}" title="{{office.name}}"> <img ng-src="img/logo_pictogram.png" alt="Pictogram" title="Pictogram">
</div> </div>
</div> </div>
</div> </div>
...@@ -10,69 +10,322 @@ ...@@ -10,69 +10,322 @@
<br> <br>
<div id="main-content" class="container"> <div id="main-content">
<div class="row">
<!-- Form column and offset --> <div class="row">
<div class="col-md-4 col-md-offset-2"> <div class="col-md-2">
<div id="login"> </div>
<!-- Formulario --> <div class="col-md-8">
<!-- LoginCtrl controls here, see app.js --> <div class="switch-panel-body height600" ng-switch="slide.state">
<form name="loginForm" ng-submit="login()" novalidate>
<!-- Email --> <!--
<div class="form-group"> SLIDE 1: login pane
<label translate>email</label>: -->
<input type="email" class="form-control" id="login_email" placeholder="{{ 'your_email' | translate}}" required ng-model="credentials.email" /> <div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="login">
</div> <div class="row">
<!-- Password --> <div class="col-md-2">
<div class="form-group"> </div>
<label translate>password</label>: <div class="col-md-4">
<input type="password" class="form-control" id="login_password" placeholder="{{ 'your_password' | translate}}" required ng-model="credentials.password" /> <!-- Formulario -->
<!-- LoginCtrl controls here, see app.js -->
<form name="loginForm" ng-submit="login()" novalidate>
<!-- Email -->
<div class="form-group">
<label translate>email</label>:
<input type="email" class="form-control" id="login_email" placeholder="{{ 'your_email' | translate}}" required ng-model="credentials.email" />
</div>
<!-- Password -->
<div class="form-group">
<label translate>password</label>:
<input type="password" class="form-control" id="login_password" placeholder="{{ 'your_password' | translate}}" required ng-model="credentials.password" />
</div>
<div class="row">
<div class="col-xs-6">
<!-- Login -->
<div class="pull-left">
<button type="submit" class="btn btn-primary" translate>login</button>
</div>
<!-- Spinner -->
<div class="pull-left">
<i ng-class="{'fa fa-spinner fa-spin fa-2x fa-fw margin-bottom': true, 'spin_disabled': !submitted}"></i>
</div>
</div>
<div class="col-xs-6 margin-top7">
<!-- Remember -->
<div class="checkbox">
<label>
<input type="checkbox" id="login_savepassword" ng-model="credentials.savepassword" />{{ 'remember' | translate }}
</label>
</div>
</div>
</div>
<br>
<!-- Remember password -->
<div class="row text-center">
<a href="/app/#/changepass" translate>password_forgotten</a>
</div>
<!-- Create account -->
<div class="row text-center">
<a ng-click="slide.rightTo('accounts')" translate>create_an_account</a>
</div>
</form>
</div>
<!--/. form column -->
<!-- Image column -->
<div class="col-md-4 text-center">
<img src="img/login.png" alt="Pictogram" title="Pictogram" />
</div>
<!--/. image column -->
<div class="col-md-2">
</div>
</div>
</div> </div>
<div class="row">
<div class="col-xs-6"> <!--
<!-- Login --> SLIDE 2: Account selection
<div class="pull-left"> -->
<button type="submit" class="btn btn-primary" translate>login</button>
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="accounts">
<h2 translate>select_account</h2>
<div class="row">
<div class="col-md-4">
<legend translate>parents_tutor</legend>
<div class="text-center">
<a ng-click="slide.rightTo('tutor'); formdata.role = 'tutor'">
<img src="img/parents.png" alt="{{'parents_tutor' | translate}}" title="{{'parents_tutor' | translate}}"
ng-class="{'img-200': hover_tutor}"
ng-mouseenter="hover_tutor = true"
ng-mouseleave="hover_tutor = false"/>
</a>
</div>
</div>
<div class="col-md-4">
<legend translate>therapist</legend>
<div class="text-center">
<a ng-click="slide.rightTo('therapist'); formdata.role = 'therapist'">
<img src="img/therapist.png" alt="{{'therapist' | translate}}" title="{{'therapist' | translate}}"
ng-class="{'img-200': hover_therapist}"
ng-mouseenter="hover_therapist = true"
ng-mouseleave="hover_therapist = false"/>
</a>
</div>
</div> </div>
<!-- Spinner --> <div class="col-md-4">
<div class="pull-left"> <legend translate>office_center</legend>
<i ng-class="{'fa fa-spinner fa-spin fa-2x fa-fw margin-bottom': true, 'spin_disabled': !submitted}"></i> <div class="text-center">
<a ng-click="slide.rightTo('office'); formdata.role = 'office'">
<img src="img/office.jpg" alt="{{'office_center' | translate}}" title="{{'office_center' | translate}}"
ng-class="{'img-200': hover_office}"
ng-mouseenter="hover_office = true"
ng-mouseleave="hover_office = false"/>
</a>
</div>
</div> </div>
</div> </div>
<div class="col-xs-6 margin-top7"> <div class="row">
<!-- Remember --> <div class="col-md-4">
<div class="checkbox"> <p translate>account_desc_tutor</p>
<label> </div>
<input type="checkbox" id="login_savepassword" ng-model="credentials.savepassword" />{{ 'remember' | translate }} <div class="col-md-4">
</label> <p translate>account_desc_therapist</p>
</div>
<div class="col-md-4">
<p translate>account_desc_office</p>
</div> </div>
</div> </div>
</div> </div>
<br> <!--
SLIDE 3: Tutor account form
-->
<form name="forms.tutorForm" role="form" ng-submit="signup('tutorForm')" novalidate ng-if="formdata.role == 'tutor'">
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="tutor">
<legend translate>parents_tutor</legend>
<div class="row">
<div class="col-md-4 text-center">
<img src="img/parents.png" alt="{{'parents_tutor' | translate}}" title="{{'parents_tutor' | translate}}" />
</div>
<div class="form-group col-md-4">
<input type="hidden" ng-model="formdata.role" value="tutor"></input>
<div class="form-group">
<label translate>email</label>
<div class="form-group">
<input type="email" class="form-control" name="email" placeholder="{{ 'email' | translate }}" ng-model="formdata.email"/>
<span class="color_red text_sm pull-right" ng-show="forms.tutorForm.email.$dirty && forms.tutorForm.email.$invalid" translate>email_invalid</span>
</div>
</div>
<fieldset>
<label translate>password</label>
<div class="form-group">
<input type="password" class="form-control" id="signin_password1" placeholder="{{ 'password_type' | translate }}" name="password" required ng-model="formdata.password"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password.length < minlength && forms.tutorForm.password.$dirty && forms.tutorForm.password_confirm.$dirty"> {{ 'password_short' | translate:'{ minlength: minlength }' }}</span>
</div>
<div class="form-group">
<input type="password" class="form-control" id="signin_password2" placeholder="{{ 'password_confirm' | translate }}" name="password_confirm" required ng-model="formdata.password_confirm"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm && forms.tutorForm.password.$dirty && forms.tutorForm.password_confirm.$dirty" translate>password_match</span>
</div>
</fieldset>
<div class="form-group">
<input type="checkbox" ng-model="formdata.disclaimer_accepted">
<span translate>disclaimer_accept</span>
</div>
<div class="form-group">
<label>Captcha</label>
<div vc-recaptcha></div>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-4">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary" ng-disabled="forms.tutorForm.$invalid || !formdata.disclaimer_accepted">{{ 'create_account' | translate }} &gt;&gt; </button>
</div>
</div>
</div>
</form>
<!--
SLIDE 4: Therapist account form
-->
<form name="forms.therapistForm" role="form" ng-submit="signup('therapistForm')" novalidate ng-if="formdata.role == 'therapist'">
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="therapist">
<legend translate>therapist</legend>
<div class="row">
<div class="col-md-4 text-center">
<img src="img/therapist.png" alt="{{'therapist' | translate}}" title="{{'therapist' | translate}}" />
</div>
<div class="form-group col-md-4" id="tutor_form">
<div class="form-group">
<label translate>email</label>
<input type="email" class="form-control" name="email" placeholder="{{ 'email' | translate }}" ng-model="formdata.email"/>
<span class="color_red text_sm pull-right" ng-show="forms.therapistForm.email.$dirty && forms.therapistForm.email.$invalid" translate>email_invalid</span>
</div>
<fieldset>
<label translate>password</label>
<div class="form-group">
<input type="password" class="form-control" id="signin_password1" placeholder="{{ 'password_type' | translate }}" name="password" required ng-model="formdata.password"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password.length < minlength && forms.therapistForm.password.$dirty && forms.therapistForm.password_confirm.$dirty"> {{ 'password_short' | translate:'{ minlength: minlength }' }}</span>
</div>
<div class="form-group">
<input type="password" class="form-control" id="signin_password2" placeholder="{{ 'password_confirm' | translate }}" name="password_confirm" required ng-model="formdata.password_confirm"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm && forms.therapistForm.password.$dirty && forms.therapistForm.password_confirm.$dirty" translate>password_match</span>
</div>
</fieldset>
<div class="form-group">
<input type="checkbox" ng-model="formdata.disclaimer_accepted">
<span translate>disclaimer_accept</span>
</div>
<div class="form-group">
<label>Captcha</label>
<div vc-recaptcha></div>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-4">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary" ng-disabled="forms.therapistForm.$invalid || !formdata.disclaimer_accepted">{{ 'create_account' | translate }} &gt;&gt; </button>
</div>
</div>
</div>
</form>
<!--
SLIDE 5: Office account form
-->
<form name="forms.officeForm" role="form" ng-submit="signup('officeForm')" novalidate ng-if="formdata.role == 'office'">
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="office">
<legend translate>office_center</legend>
<div class="row">
<div class="col-md-4 text-center">
<img src="img/office.jpg" alt="{{'office_center' | translate}}" title="{{'office_center' | translate}}" />
</div>
<div class="form-group col-md-4" id="office_form">
<div class="form-group">
<label translate>name</label>
<input type="text" class="form-control" placeholder="{{ 'name' | translate }}" name="name" required ng-model="formdata.name"/>
</div>
<div class="form-group">
<label translate>email</label>
<input type="email" class="form-control" placeholder="{{ 'email' | translate }}" name="email" required ng-model="formdata.email"/>
<span class="color_red text_sm pull-right" ng-show="forms.officeForm.email.$dirty && forms.officeForm.email.$invalid" translate>email_invalid</span>
</div>
<fieldset>
<label translate>password</label>
<div class="form-group">
<input type="password" class="form-control" id="signin_password1" placeholder="{{ 'password_type' | translate }}" name="password" required ng-model="formdata.password"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password.length < minlength && forms.officeForm.password.$dirty && forms.officeForm.password_confirm.$dirty"> {{ 'password_short' | translate:'{ minlength: minlength }' }}</span>
</div>
<div class="form-group">
<input type="password" class="form-control" id="signin_password2" placeholder="{{ 'password_confirm' | translate }}" name="password_confirm" required ng-model="formdata.password_confirm"/>
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm && forms.officeForm.password.$dirty && forms.officeForm.password_confirm.$dirty" translate>password_match</span>
</div>
</fieldset>
<div class="form-group">
<input type="checkbox" ng-model="formdata.disclaimer_accepted">
<span translate>disclaimer_accept</span>
</div>
<div class="form-group">
<label>Captcha</label>
<div vc-recaptcha></div>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-4">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary" ng-disabled="forms.officeForm.$invalid">{{ 'create_account' | translate }} &gt;&gt; </button>
</div>
</div>
</div>
</form>
<!--
SLIDE 6: Confirmation message
-->
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="confirmation">
<h2>{{ 'user_created' | translate }} </h2>
<p> {{ 'user_created_text' | translate:'{ email: formdata.email }' }} </p>
<br>
<img src="img/child.png"/>
<!-- Remember password -->
<div class="row text-center">
<a href="/app/#/changepass" translate>password_forgotten</a>
</div>
<!-- Create account -->
<div class="row text-center">
<a href="/app/#/signin" translate>create_an_account</a>
</div> </div>
</form>
</div>
</div>
<div class="col-md-2">
</div> </div>
<!--/. login -->
</div> </div>
<!--/. form column --> <div class="text-center">
<a ng-click="slide.leftTo('login')" ng-if="slide.state != 'login'"><< {{ 'back_to_login' | translate}}</a>
<!-- Image column -->
<div class="col-xs-12 col-md-4 text-center">
<img src="img/login.png" alt="Pictogram" title="Pictogram" />
</div> </div>
<!--/. image column -->
</div> </div>
</div> </div>
<footer-translate></footer-translate> <footer-translate></footer-translate>
<!-- SigningCtrl controls here, see app.js -->
<div class="container">
<div class="row">
<!-- Rejilla 3 elementos de igual ancho -->
<div class="col-lg-2">&nbsp;</div>
<div class="col-lg-8">
<p>&nbsp;</p>
<p class="text-center">
<a href="/app"><img src="img/logo_pictogram.png" alt="Pictogram" title="Pictogram" style="border-style: none"/></a>
</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>
<legend translate>personal_data</legend>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="text" class="form-control" id="signin_name" placeholder="{{ 'name' | translate }}" required ng-model="formdata.name"/>
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<input type="text" class="form-control" id="signin_surname" placeholder="{{ 'surname' | translate }}" required ng-model="formdata.surname"/>
</div>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control" id="signin_address" placeholder="{{ 'address' | translate }}" ng-model="formdata.address"/ required>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<input type="text" class="form-control" id="signin_postal_code" placeholder="{{ 'postal_code' | translate }}" required ng-model="formdata.postalCode" ng-change="formdata.postalCode = formdata.postalCode.toUpperCase()"/>
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<select class="form-control" ng-model="formdata.country" required ng-change="load_tries()">
<option value="00" selected disabled hidden>{{ 'country' | translate }}</option>
<option value="ES">España</option>
<option value="US">United States</option>
<option value="UK">United Kingdom</option>
<option value="IE">Ireland</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" id="signin_phone" placeholder="{{ 'phone' | translate }}" ng-model="formdata.phone"/>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<select class="form-control" name="signin_gender" id="signin_gender" ng-model="formdata.gender">
<option value="F" translate>woman</option>
<option value="M" translate>man</option>
</select>
</div>
</div>
</div>
</fieldset>
<fieldset>
<div class="row">
<div class="col-md-12">
<span class="color_red text_sm pull-right" ng-show="formdata.email != formdata.email_confirm" translate>email_match</span>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<input type="email" class="form-control" id="email" name="email" placeholder="{{ 'email_type' | translate }}" required ng-model="formdata.email" />
</div>
<div class="col-md-6">
<input type="email" class="form-control" id="email_confirm" name="email_confirm" placeholder="{{ 'email_confirm' | translate }}" required ng-model="formdata.email_confirm" />
</div>
</div>
</div>
</fieldset>
<fieldset>
<div class="row">
<div class="col-md-12">
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm" translate>password_match</span>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-6">
<input type="password" class="form-control" id="signin_password1" placeholder="{{ 'password_type' | translate }}" required ng-model="formdata.password" />
</div>
<div class="col-md-6">
<input type="password" class="form-control" id="signin_password2" placeholder="{{ 'password_confirm' | translate }}" required ng-model="formdata.password_confirm" />
</div>
</div>
</div>
</fieldset>
<fieldset>
<div class="form-group">
<select class="form-control" name="signin_language" id="signin_language" ng-model="formdata.lang" required>
<option value="00" selected disabled hidden>{{ 'language' | translate }}</option>
<option value="es-es" selected>Español</option>
<option value="en-gb">English</option>
</select>
</div>
</fieldset>
<fieldset>
<legend translate>case_title</legend>
<div class="form-group">
<div class="row">
<div class="col-md-1 text-right">
<input
type="radio"
ng-model="formdata.role"
value="therapist_office"
onClick="$('#office_selection').slideDown(); $('#office_form').slideUp();">
</div>
<div class="col-md-11">
{{ 'case_therapist_office' | translate }}
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-1 text-right">
<input
type="radio"
ng-model="formdata.role"
value="therapist_nooffice"
onClick="$('#office_selection').slideUp(); $('#office_form').slideDown();"
ng-click="copyFields();">
</div>
<div class="col-md-11">
{{ 'case_therapist_nooffice' | translate }}
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-1 text-right">
<input
type="radio"
ng-model="formdata.role"
value="tutor_office"
onClick="$('#office_selection').slideDown(); $('#office_form').slideUp();">
</div>
<div class="col-md-11">
{{ 'case_tutor_office' | translate }}
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-md-1">
<input
type="radio"
ng-model="formdata.role"
value="tutor_nooffice"
onClick="$('#office_selection').slideUp(); $('#office_form').slideUp(); copyFields();"
ng-click="copyFields();">
</div>
<div class="col-md-11">
{{ 'case_tutor_nooffice' | translate }}
</div>
</div>
</div>
</fieldset>
<div class="form-group" id="office_form" hidden>
<legend translate>office_center</legend>
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'name' | translate }}" ng-model="formdata.office.name" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'logo_url' | translate }}" ng-model="formdata.office.logoUrl"/>
</div>
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'address' | translate }}" ng-model="formdata.office.address" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'postal_code' | translate }}" ng-model="formdata.office.postalCode" ng-change="formdata.office.postalCode = formdata.office.postalCode.toUpperCase()" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'contact_person' | translate }}" ng-model="formdata.office.contactPerson" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input type="email" class="form-control" placeholder="{{ 'email' | translate }}" ng-model="formdata.office.email" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input type="text" class="form-control" placeholder="{{ 'phone' | translate }}" ng-model="formdata.office.phone1" ng-required="formdata.role == 'therapist_nooffice'"/>
</div>
</div>
</div>
</div>
<div class="form-group" id="office_selection">
<legend translate>office_center</legend>
<select class="form-control" ng-model="formdata.id_off" ng-required="formdata.role == 'therapist_office' || formdata.role == 'tutor_office'">
<option selected disabled hidden value="-1">{{ 'select_office' | translate }}</option>
<option ng-repeat="office in offices | orderBy: 'name' track by office.id" ng-value="office.id"> {{ office.name }} </option>
</select>
</div>
<div class="form-group">
<legend></legend>
<input type="checkbox" ng-model="formdata.disclaimer_accepted">
<span translate>disclaimer_accept</span>
</div>
<div class="form-group">
<legend>Captcha</legend>
<div vc-recaptcha></div>
</div>
<p class="text-center">
<a href="/app/#/login" class="btn btn-default" translate>cancel</a>
<button type="submit" class="btn btn-primary" ng-disabled="signInForm.$invalid" translate>create_account</button>
</p>
</form>
</div>
<!-- Fin signin -->
</div>
<div class="col-lg-2">&nbsp;</div>
</div>
<!-- Fin de row -->
</div>
<!-- Fin de container -->
<footer-translate></footer-translate>
...@@ -26,7 +26,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -26,7 +26,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
});*/ });*/
$scope.supsForm = {}; $scope.supsForm = {};
$scope.section = 'account'; $scope.section = {val: 'account'};
$scope.changeImg = function () { $scope.changeImg = function () {
...@@ -148,11 +148,11 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -148,11 +148,11 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
.error(function (err) { .error(function (err) {
console.log(err); console.log(err);
if (err.message && err.message.search('nvalid license') > 0) if (err.message && err.message.search('nvalid license') > 0)
ngToast.danger({ content: $translate.instant('license_invalid') }); ngToast.danger($translate.instant('license_invalid'));
else if (err.message && err.message.search('in use') > 0) else if (err.message && err.message.search('in use') > 0)
ngToast.danger({ content: $translate.instant('license_already_activated') }); ngToast.danger($translate.instant('license_already_activated'));
else else
ngToast.danger({ content: $translate.instant('student_not_updated') }); ngToast.danger($translate.instant('student_not_updated'));
}); });
}; };
...@@ -161,26 +161,21 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -161,26 +161,21 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
* The email used for search is fetched from $scope.email_sup. * The email used for search is fetched from $scope.email_sup.
*/ */
$scope.search_sup = function () { $scope.search_sup = function () {
console.log("--> " + $scope.supsForm.email_sup);
// Find tutor by email // Find tutor by email
$http.get(config.backend + '/sup/email/' + $scope.supsForm.email_sup) $http.get(config.backend + '/sup/off/email/' + $scope.supsForm.email_sup)
.success(function (data) { .success(function (data) {
if (data) { if (data) {
$scope.supToAdd = data; $scope.supToAdd = data;
$scope.showmessagesupfound = true; $scope.showmessagesupfound = true;
$scope.showmessagesupnotfound = false; $scope.showmessagesupnotfound = false;
} else { } else {
$translate('sup_not_found').then(function (translation) { ngToast.danger($translate.instant('sup_not_in_office'));
ngToast.danger({ content: translation });
});
// Hide the success message (if it exists by other query) // Hide the success message (if it exists by other query)
$scope.showmessagesupfound = false; $scope.showmessagesupfound = false;
} }
}) })
.error(function () { .error(function () {
$translate('sup_not_found').then(function (translation) { ngToast.danger($translate.instant('sup_not_in_office'));
ngToast.danger({ content: translation });
});
}); });
}; };
...@@ -193,13 +188,13 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -193,13 +188,13 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
// Ensure supervisor is not already in the list // Ensure supervisor is not already in the list
if ($scope.studentSupervisors.map((s) => s.id).includes($scope.supToAdd.id)) { if ($scope.studentSupervisors.map((s) => s.id).includes($scope.supToAdd.id)) {
ngToast.danger({ content: $translate.instant('sup_already_added') }); ngToast.danger($translate.instant('sup_already_added'));
$scope.supsForm.email_sup = ''; $scope.supsForm.email_sup = '';
$scope.showmessagesupfound = false; $scope.showmessagesupfound = false;
return; return;
} }
$http.post(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.supToAdd.id, {asTherapist: true}) $http.post(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + $scope.supToAdd.id)
.success(function (data) { .success(function (data) {
// Assign the info of supervisor to add // Assign the info of supervisor to add
stusup.supervisor = $scope.supToAdd; stusup.supervisor = $scope.supToAdd;
...@@ -214,7 +209,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -214,7 +209,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
$scope.showmessagesupfound = false; $scope.showmessagesupfound = false;
}) })
.error(function () { .error(function () {
ngToast.danger({ content: $translate.instant('sup_not_added') }); ngToast.danger($translate.instant('sup_not_added'));
}); });
}; };
...@@ -226,7 +221,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -226,7 +221,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
var deleteSup = $window.confirm( var deleteSup = $window.confirm(
$translate.instant( $translate.instant(
'confirm_unlink_therapist', 'confirm_unlink_student',
{name: $scope.studentSupervisors[i].name, student: $scope.studentData.name} {name: $scope.studentSupervisors[i].name, student: $scope.studentData.name}
)); ));
...@@ -243,95 +238,6 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -243,95 +238,6 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
} }
}; };
// Search tutor by email
$scope.search_tutor = function () {
// Find tutor by email
$http.get(config.backend + '/sup/email/' + $scope.supsForm.email_tutor)
.success(function (data) {
// If it found the length is > 0
if (data) {
$scope.tutorToAdd = data;
// Show message for validate
$scope.showmessagetutorfound = true;
$scope.showmessagetutornotfound = false;
} else {
$translate('tutor_not_found').then(function (translation) {
ngToast.danger({ content: translation });
});
// Hide the success message (if it exists by other query)
$scope.showmessagetutorfound = false;
}
})
.error(function () {
$translate('tutor_not_found').then(function (translation) {
ngToast.danger({ content: translation });
});
});
};
// Add tutor
$scope.add_tutor = function () {
var stusup = {
student: $scope.studentData.id,
supervisor: $scope.tutorToAdd.id
};
// Ensure supervisor is not already in the list
if ($scope.studentTutors.map((s) => s.id).includes($scope.tutorToAdd.id)) {
ngToast.danger({ content: $translate.instant('sup_already_added') });
$scope.supsForm.email_tutor = '';
$scope.showmessagetutorfound = false;
return;
}
$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;
stusup.id = data.id;
// Add to the list of tutors in view
$scope.studentTutors.push($scope.tutorToAdd);
// Delete the email form field
$scope.supsForm.email_tutor = '';
// Hide the message of tutor founded
$scope.showmessagetutorfound = false;
$translate('tutor_added').then(function (translation) {
ngToast.success({ content: translation });
});
})
.error(function () {
$translate('tutor_not_added').then(function (translation) {
ngToast.danger({ content: translation });
});
});
};
// Delete tutor
$scope.delete_tutor = function (id_sup) {
//Se recorre el array de objetos json para buscarlo
var i;
for (i = 0; i < $scope.studentTutors.length && id_sup !== $scope.studentTutors[i].id; i++);
var deleteTutor = $window.confirm(
$translate.instant(
'confirm_unlink_tutor',
{name: $scope.studentTutors[i].name, student: $scope.studentData.name}
));
if (deleteTutor) {
$http.delete(config.backend + '/stu/' + $scope.studentData.id + '/sup/' + id_sup)
.success(function () {
// Eliminar de la vista
$scope.studentTutors.splice(i, 1);
ngToast.success({ content: $translate.instant('tutor_deleted') });
})
.error(function () {
ngToast.danger({ content: $translate.instant('tutor_not_deleted') });
});
}
};
// ******************************************************* // *******************************************************
// Setup // Setup
// $scope.studentData.attributes // $scope.studentData.attributes
...@@ -342,14 +248,10 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -342,14 +248,10 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
attributes: $scope.studentData.attributes attributes: $scope.studentData.attributes
}) })
.success(function () { .success(function () {
$translate('attributes_updated').then(function (translation) { ngToast.success($translate.instant('attributes_updated'));
ngToast.success({ content: translation });
});
}) })
.error(function () { .error(function () {
$translate('attributes_not_updated').then(function (translation) { ngToast.danger($translate.instant('attributes_not_updated'));
ngToast.danger({ content: translation });
});
}); });
}, 300); }, 300);
}); });
...@@ -32,10 +32,6 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl( ...@@ -32,10 +32,6 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
number: '' number: ''
}, },
license_expired: false, license_expired: false,
office: {
id: '',
name: ''
},
stuSup: [], stuSup: [],
pcb_count: 0, pcb_count: 0,
pdb_count: 1 pdb_count: 1
...@@ -84,15 +80,14 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl( ...@@ -84,15 +80,14 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
$scope.studentData.license_expired = new Date($scope.studentData.license.expiration_ts) - new Date() < 0; $scope.studentData.license_expired = new Date($scope.studentData.license.expiration_ts) - new Date() < 0;
moment.locale($translate.use().substr(0, 2)); moment.locale($translate.use().substr(0, 2));
$scope.studentData.expiration_date = moment($scope.studentData.license.expiration_ts).format('L'); $scope.studentData.expiration_date = moment($scope.studentData.license.expiration_ts).format('L');
console.log("updateLicenseExpiration");
}; };
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// MAIN
// //
// Load student account information // Load student account information
// //
//
$http.get(config.backend + '/stu/' + $scope.studentData.id) $http.get(config.backend + '/stu/' + $scope.studentData.id)
.success(function (data) { .success(function (data) {
$scope.studentData.id = data.id; $scope.studentData.id = data.id;
...@@ -105,8 +100,6 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl( ...@@ -105,8 +100,6 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
$scope.studentData.gender = data.gender; $scope.studentData.gender = data.gender;
$scope.studentData.lang = data.lang; $scope.studentData.lang = data.lang;
$scope.studentData.notes = data.notes; $scope.studentData.notes = data.notes;
$scope.studentData.office.id = data.office.id;
$scope.studentData.office.name = data.office.name;
$scope.studentData.stuSup = data.stuSup; $scope.studentData.stuSup = data.stuSup;
$scope.studentData.attributes = data.attributes; $scope.studentData.attributes = data.attributes;
$scope.studentData.current_method = data.current_method; $scope.studentData.current_method = data.current_method;
...@@ -148,27 +141,22 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl( ...@@ -148,27 +141,22 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
ngToast.danger({ content: $translate.instant('no_subscribed') }); ngToast.danger({ content: $translate.instant('no_subscribed') });
}); });
//
// For tab navigation, initially blank goes to collections // For tab navigation, initially blank goes to collections
// Defined as JSON object to be available in in children as the same scope // Defined as JSON object to be available in in children as the same scope
//
$scope.nav = { $scope.nav = {
tab: 'collections' tab: 'collections'
}; };
//
// Load student supervisors
//
$scope.studentSupervisors = []; $scope.studentSupervisors = [];
$http.get(config.backend + '/stu/' + $scope.studentData.id + '/therapists') $http.get(config.backend + '/stu/' + $scope.studentData.id + '/supervisors')
.success(function (data) { .success(function (data) {
$scope.studentSupervisors = data; $scope.studentSupervisors = data;
}) })
.error(function () { .error(function (err) {});
// TODO show error with ngToast
});
$scope.studentTutors = [];
$http.get(config.backend + '/stu/' + $scope.studentData.id + '/tutors')
.success(function (data) {
$scope.studentTutors = data;
})
.error(function () {
// TODO show error with ngToast
});
}); });
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
ng-init="rowIndex = $index" ng-init="rowIndex = $index"
class="picto-grid__row"> class="picto-grid__row">
<div <div
class="picto pull-left ng-class:{'picto-out': studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)};" ng-hide="studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)"
class="picto pull-left"
data-row="{{ rowIndex }}" data-row="{{ rowIndex }}"
data-column="{{ colIndex }}" data-column="{{ colIndex }}"
id="student-picto-{{ id="student-picto-{{
...@@ -117,7 +118,8 @@ ...@@ -117,7 +118,8 @@
ng-init="rowIndex = $index" ng-init="rowIndex = $index"
class="picto-grid__row"> class="picto-grid__row">
<div <div
class="picto pull-left ng-class:{'picto-out': studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)};" ng-hide="studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)"
class="picto pull-left"
ng-repeat="studentPicto in studentPictoRow track by $index" ng-repeat="studentPicto in studentPictoRow track by $index"
ng-init="colIndex = $index" ng-init="colIndex = $index"
popover="{{ studentPicto != emptyStudentPicto ? studentPicto.attributes.expression : ''}}" popover="{{ studentPicto != emptyStudentPicto ? studentPicto.attributes.expression : ''}}"
...@@ -231,7 +233,8 @@ ...@@ -231,7 +233,8 @@
ng-init="rowIndex = $index" ng-init="rowIndex = $index"
class="picto-grid__row"> class="picto-grid__row">
<div <div
class="picto pull-left ng-class:{'picto-out': studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)};" ng-hide="studentData.attributes.size == 'large' && (rowIndex > 3 || colIndex > 7)"
class="picto pull-left"
data-row="{{ rowIndex }}" data-row="{{ rowIndex }}"
data-column="{{ colIndex }}" data-column="{{ colIndex }}"
id="student-picto-{{ id="student-picto-{{
......
...@@ -50,17 +50,17 @@ ...@@ -50,17 +50,17 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<ul class="nav nav-tabs tabs_student"> <ul class="nav nav-tabs tabs_student">
<!-- 0: admin, 1: tutor, 2: therapist --> <!-- 0: admin, 1: tutor, 2: therapist -->
<li role="presentation" ng-class="{'active' : nav.tab == 'collections'}" ng-if="studentData.supervision != 0"> <li role="presentation" ng-class="{'active' : nav.tab == 'collections'}" ng-if="studentData.license.isValid || !studentData.license.isTrial">
<a href="/app/#/student/{{studentData.id}}/collections" ng-click="nav.tab = ''"><span class="glyphicon glyphicon-th" aria-hidden="true"></span> {{ 'collections' | translate }}</a> <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>
<li role="presentation" ng-class="{'active' : nav.tab == 'instructions'}" ng-if="studentData.supervision == 2"> <li role="presentation" ng-class="{'active' : nav.tab == 'instructions'}" ng-if="studentData.license.isValid && !user.isTutor">
<a href="/app/#/student/{{studentData.id}}/instructions" ng-click="nav.tab = 'instructions'"><span class="glyphicon glyphicon-tasks" aria-hidden="true"></span> {{ 'instructions' | translate }}</a> <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>
<li role="presentation" ng-class="{'active' : nav.tab == 'session'}" ng-if="studentData.supervision == 2"> <li role="presentation" ng-class="{'active' : nav.tab == 'session'}" ng-if="studentData.license.isValid && !user.isTutor">
<a href="/app/#/student/{{studentData.id}}/session" ng-click="nav.tab = 'session'"><span class="glyphicon glyphicon-transfer" aria-hidden="true"></span> {{ 'sessions' | translate }}</a> <a href="/app/#/student/{{studentData.id}}/session" ng-click="nav.tab = 'session'"><span class="glyphicon glyphicon-transfer" aria-hidden="true"></span> {{ 'sessions' | translate }}</a>
</li> </li>
<li role="presentation" ng-class="{'active' : nav.tab == 'reports'}" ng-if="studentData.supervision != 1"> <li role="presentation" ng-class="{'active' : nav.tab == 'reports'}" ng-if="studentData.license.isValid && !user.isTutor">
<a href="/app/#/student/{{studentData.id}}/reports" ng-click="nav.tab = 'reports'"><i class="fa fa-bar-chart" aria-hidden="true"></i> {{ 'reports' | translate }}</a> <a href="/app/#/student/{{studentData.id}}/reports" ng-click="nav.tab = 'reports'"><i class="fa fa-bar-chart" aria-hidden="true"></i> {{ 'reports' | translate }}</a>
</li> </li>
<li role="presentation" ng-class="{'active' : nav.tab == 'setup'}"> <li role="presentation" ng-class="{'active' : nav.tab == 'setup'}">
......
...@@ -2,18 +2,21 @@ ...@@ -2,18 +2,21 @@
<div class="panel-body"> <div class="panel-body">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-default" btn-radio="'account'" ng-model="section"> <button class="btn btn-default" btn-radio="'account'" ng-model="section.val">
<i class="fa fa-user" aria-hidden="true"></i> {{ 'account' | translate }} <i class="fa fa-user" aria-hidden="true"></i> {{ 'account' | translate }}
</button> </button>
<button class="btn btn-default" btn-radio="'device'" ng-model="section"> <button class="btn btn-default" btn-radio="'device'" ng-model="section.val" ng-if="studentData.license.isValid || studentData.license.isOfficial">
<i class="fa fa-tablet" aria-hidden="true"></i> {{ 'device' | translate }} <i class="fa fa-tablet" aria-hidden="true"></i> {{ 'device' | translate }}
</button> </button>
<button class="btn btn-default" btn-radio="'supervisors'" ng-model="section"> <button class="btn btn-default" btn-radio="'supervisors'" ng-model="section.val" ng-if="user.isOffice">
<i class="fa fa-users" aria-hidden="true"></i> {{ 'supervisors' | translate }} <i class="fa fa-users" aria-hidden="true"></i> {{ 'supervisors' | translate }}
</button> </button>
</div> </div>
<div class="row" ng-show="section == 'account'"> <!-- ***********************************************************************
Sección: Configuración de la cuenta del estudiante
-->
<div class="row" ng-show="section.val == 'account'">
<!-- Parte izquierda: Datos personales --> <!-- Parte izquierda: Datos personales -->
<div class="col-md-6"> <div class="col-md-6">
<legend translate>account</legend> <legend translate>account</legend>
...@@ -51,25 +54,42 @@ ...@@ -51,25 +54,42 @@
<label translate>license_number</label> <label translate>license_number</label>
<input type="text" id="setup_license" class="form-control" mask="wwww-wwww-wwww-wwww" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formUser.license_number" required> <input type="text" id="setup_license" class="form-control" mask="wwww-wwww-wwww-wwww" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formUser.license_number" required>
<!-- With license --> <!-- With official license -->
<div ng-show="studentData.license && !studentData.license_expired" class="alert alert-info" role="alert"> <div ng-show="studentData.license && studentData.license.isValid && studentData.license.isOfficial" class="alert alert-info" role="alert">
<div class="row"> <div class="row">
<div class="col-xs-2"><i class="fa fa-info-circle fa-lg" aria-hidden="true"></i></div> <div class="col-xs-2"><i class="fa fa-certificate fa-lg" aria-hidden="true"></i></div>
<div class="col-xs-10"> <div class="col-xs-10">
{{ 'license_expires' | translate }} <b>{{ studentData.expiration_date }}</b> {{ 'license_expires_official' | translate }} <b>{{ studentData.expiration_date }}</b>
</div> </div>
</div> </div>
</div> </div>
<!-- License expired --> <!-- With trial license -->
<div ng-show="studentData.license && studentData.license_expired" class="alert alert-warning" role="alert"> <div ng-show="studentData.license && studentData.license.isValid && studentData.license.isTrial" class="alert alert-info" role="alert">
<div class="row"> <div class="row">
<div class="col-xs-2"><i class="fa fa-exclamation-circle fa-lg" aria-hidden="true"></i></div> <div class="col-xs-2"><i class="fa fa-flask fa-lg" aria-hidden="true"></i></div>
<div class="col-xs-10"> <div class="col-xs-10">
<h4 class="alert-heading"> {{ 'license_expired' | translate }} </h4> {{ 'license_expires_trial' | translate }} <b>{{ studentData.expiration_date }}</b>
<p> </div>
<a href="http://pictogramweb.com/caracteristicas-de-pictogram/">{{ 'license_expired_renew' | translate }}</a> </div>
</p> </div>
<!-- Official license expired -->
<div ng-show="studentData.license && !studentData.license.isValid && studentData.license.isOfficial" class="alert alert-warning" role="alert">
<div class="row">
<div class="col-xs-2"><i class="fa fa-certificate fa-lg text-danger" aria-hidden="true"></i></div>
<div class="col-xs-10">
{{ 'license_expired_official' | translate }} <a href="http://pictogramweb.com/caracteristicas-de-pictogram/">{{ 'license_expired_renew' | translate }}</a>.
</div>
</div>
</div>
<!-- Trial license expired -->
<div ng-show="studentData.license && !studentData.license.isValid && studentData.license.isTrial" class="alert alert-warning" role="alert">
<div class="row">
<div class="col-xs-2"><i class="fa fa-flask fa-lg text-danger" aria-hidden="true"></i></div>
<div class="col-xs-10">
{{ 'license_expired_trial' | translate }} <a href="http://pictogramweb.com/caracteristicas-de-pictogram/">{{ 'license_expired_buy' | translate }}</a>.
</div> </div>
</div> </div>
</div> </div>
...@@ -170,9 +190,12 @@ ...@@ -170,9 +190,12 @@
</div> <!-- Fin de student_personal_edit --> </div> <!-- Fin de student_personal_edit -->
<!-- ***********************************************************************
Sección: Configuración del dispositivo
-->
<!-- Configuración dispositivo --> <!-- Configuración dispositivo -->
<div id="device_setup" ng-show="section == 'device'"> <div id="device_setup" ng-show="section.val == 'device'">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<legend translate>device_setup</legend> <legend translate>device_setup</legend>
...@@ -308,18 +331,32 @@ ...@@ -308,18 +331,32 @@
</div> </div>
</div> </div>
<!-- ***********************************************************************
Sección: Gestión de supervisores
-->
<!-- Tutores y dispositivos --> <!-- Tutores y dispositivos -->
<div id="supervisors_section" ng-show="section == 'supervisors'"> <div id="supervisors_section" ng-show="section.val == 'supervisors'" ng-if="user.isOffice">
<legend translate>link_supervisor</legend>
<div class="row"> <div class="row">
<div class="col-md-5" ng-if="studentData.supervision != 1">
<div class="col-md-5">
<div class="alert alert-info">
<p translate>link_supervisor_desc</p>
<p translate>supervisor_note</p>
</div>
</div>
<div class="col-md-5">
<!-- Supervisores (terapeutas) del alumno --> <!-- Supervisores (terapeutas) del alumno -->
<div id="student_sups"> <div id="student_sups">
<legend translate>therapists</legend>
<!-- Buscador de supervisores --> <!-- Buscador de supervisores -->
<p> <p>
<form role="search" ng-submit="search_sup()"> <form role="search" ng-submit="search_sup()">
<div class="input-group" ng-if="user.isSupAdmin"> <div class="input-group">
<input type="email" class="form-control" placeholder="{{ 'search_sup_email' | translate }}" name="email_sup" id="email_sup" ng-model="supsForm.email_sup" required> <input type="email" class="form-control" placeholder="{{ 'search_sup_email' | translate }}" name="email_sup" id="email_sup" ng-model="supsForm.email_sup" required>
<div class="input-group-btn"> <div class="input-group-btn">
<button class="btn btn-default" type="submit"> <button class="btn btn-default" type="submit">
...@@ -336,71 +373,34 @@ ...@@ -336,71 +373,34 @@
<img ng-src="{{supToAdd.pic}}" class="profile" alt="" title="" /> {{ supToAdd.name }} {{ supToAdd.surname }} <img ng-src="{{supToAdd.pic}}" class="profile" alt="" title="" /> {{ supToAdd.name }} {{ supToAdd.surname }}
<a class="btn btn-default btn-sm pull-right" role="button" ng-click="add_sup()" translate>add</a> <a class="btn btn-default btn-sm pull-right" role="button" ng-click="add_sup()" translate>add</a>
</div> </div>
<!-- Fin de buscador de supervisores -->
<!-- Supervisores asignados --> <!-- Supervisores asignados -->
<ul class="list-group" id="user_sups"> <ul class="list-group" id="user_sups">
<li class="list-group-item" ng-repeat="sup in studentSupervisors"> <li class="list-group-item" ng-repeat="sup in studentSupervisors">
<!-- Imagen de perfil del supervisor --> <div class="row">
<img ng-src="{{sup.pic}}" class="profile" alt="" title="" /> <div class="col-xs-2">
{{sup.name}} {{sup.surname}} <!-- Imagen de perfil del supervisor -->
<a ng-if="user.isSupAdmin" ng-click="delete_sup(sup.id)" class="delete_sup" title="{{ 'unlink' | translate}}"> <img ng-src="{{sup.pic}}" class="profile" alt="" title="" />
<span class="color_red glyphicon glyphicon-remove-circle" aria-hidden="true"></span> </div>
</a> <div class="col-xs-8">
</li> {{ sup.name }} {{ sup.surname }} <br> <span class="text-muted">{{ sup.role | translate }}</span>
</ul> </div>
<!-- Fin de Supervisores asignados --> <div class="col-xs-2">
</div> <a ng-click="delete_sup(sup.id)" class="delete_sup" title="{{ 'unlink' | translate}}">
<!-- Fin de id student-sups --> <span class="color_red glyphicon glyphicon-remove-circle" aria-hidden="true"></span>
</div> </a>
<div class="col-md-5">
<!-- Tutores (Padres) -->
<div id="student_tutors" ng-if="studentData.supervision != 1">
<legend translate>tutors</legend>
<!-- Buscador de tutores -->
<p>
<form role="search" ng-submit="search_tutor()">
<div class="input-group" ng-if="user.isSupAdmin">
<input type="email" class="form-control" placeholder="{{ 'search_tutor_email' | translate }}" name="email_tutor" id="email_tutor" ng-model="supsForm.email_tutor" required>
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</div> </div>
</div> </div>
</form>
</p>
<!-- Alert and success messages for tutor found -->
<div ng-show="{{ 'showmessagetutorfound' }}" class="alert alert-info">
<!-- Imagen de perfil del tutor -->
<img ng-src="{{tutorToAdd.pic}}" class="profile" alt="" title="" />
{{ tutorToAdd.name }} {{ tutorToAdd.surname }}
<a class="btn btn-default btn-sm pull-right" role="button" ng-click="add_tutor()" translate>add</a>
</div>
<!-- Fin de buscador de tutores -->
<!-- Tutores asignados -->
<ul class="list-group" id="user_tutors">
<li class="list-group-item" ng-repeat="tutor in studentTutors">
<!-- Imagen de perfil del tutor -->
<img ng-src="{{tutor.pic}}" class="profile" alt="" title="" />
{{tutor.name}} {{tutor.surname}}
<a ng-if="user.isSupAdmin" ng-click="delete_tutor(tutor.id)" class="delete_tutor" title="{{ 'unlink' | translate}}">
<span class="color_red glyphicon glyphicon-remove-circle" aria-hidden="true"></span>
</a>
</li> </li>
</ul> </ul>
<!-- Fin de Tutores asignados --> <!-- Fin de Supervisores asignados -->
<!-- Info message -->
<div class="alert alert-info">{{ 'supervisor_note' | translate }}</div>
</div> </div>
<!-- Fin de id student-tutors --> <!-- Fin de id student-sups -->
</div> </div>
</div> </div>
</div> <!-- /supervisores --> </div> <!-- /supervisores -->
</div> </div>
<!-- Fin de panel body --> <!-- Fin de panel body -->
</div> </div>
......
...@@ -124,6 +124,8 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl( ...@@ -124,6 +124,8 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl(
user.phone = data.phone; user.phone = data.phone;
user.email = data.email; user.email = data.email;
user.lang = data.lang; user.lang = data.lang;
user.pic = data.pic;
user.role = data.role;
// Delete because at the beginning the variable user is bind // Delete because at the beginning the variable user is bind
// with the form // with the form
...@@ -132,6 +134,9 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl( ...@@ -132,6 +134,9 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl(
$window.sessionStorage.user = JSON.stringify(user); $window.sessionStorage.user = JSON.stringify(user);
$location.path("/students");
//$scope.$apply();
}) })
.error(function () { .error(function () {
ngToast.danger({ content: $translate.instant('data_no_saved') }); ngToast.danger({ content: $translate.instant('data_no_saved') });
......
...@@ -13,123 +13,167 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl( ...@@ -13,123 +13,167 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
$window, $window,
$translate, $translate,
ngToast, ngToast,
IOService) { $timeout,
$scope.formdatastudent = { IOService,
username: '', CONSTANTS) {
password: '',
name: '',
surname: '',
birthdate: '',
country: 'ES',
gender: 'M',
lang: 'es-es',
notes: '',
office: $scope.user.office || { name: '' }
};
// Flags for showing buttons according to role // Flags for showing buttons according to role
$scope.user = JSON.parse($window.sessionStorage.user); $scope.user = JSON.parse($window.sessionStorage.user);
// Identify if the user is office administrator // --------------------------------------------------------
if ($scope.user.office) { // Create new account
if ($scope.user.office.admin === $scope.user.id) { // --------------------------------------------------------
$scope.user.isAdmin = true;
} $scope.minlength = CONSTANTS.password_minlength;
} else {
$scope.user.office = { name: '' };
}
// Hide new student form // Hide new student form
$scope.hidestudentadd = true; $scope.hidestudentadd = true;
// Get list of supervisor's students // forms container
$http.get(config.backend + '/sup/' + $scope.user.id + '/students') $scope.forms = {};
.success(function (data) {
$scope.students = data; // slider object
}) $scope.slide = {
.error(function () { state: 'accounts',
ngToast.danger({ content: $translate.instant('error_fetching_students') }); prev: 'accounts',
}); back: false,
show: false,
rightTo: function (state) {
$scope.slide.back = false;
$scope.slide.prev = $scope.slide.state;
$timeout(function () {
$scope.slide.state = state;
}, 0);
},
leftTo: function (state) {
$scope.slide.back = true;
$scope.slide.prev = $scope.slide.state;
$timeout(function () {
$scope.slide.state = state;
}, 0);
}
};
// Reset form Student // Show student form
$scope.resetForm = function () { $scope.showForm = function () {
// Empty the form // Reset the form
$scope.formdatastudent = { $scope.formdata = {
username: '', username: '',
password: '', password: '',
password_confirm: '', password_confirm: '',
name: '', name: $translate.instant('name'),
surname: '', surname: $translate.instant('surname'),
birthdate: '', birthdate: Date(),
country: 'ES', country: 'ES',
gender: 'M', gender: 'M',
lang: 'es-es', lang: 'es-es',
notes: '', notes: '',
office: $scope.user.office || { name: '' },
current_method: 'no_method', current_method: 'no_method',
current_instruction: 'no_instruction', current_instruction: 'no_instruction',
license_number: '' license_number: null,
id_sup: $scope.user.id
}; };
// Hide the form $scope.slide.state ='accounts';
$scope.hidestudentadd = true; $scope.slide.show = true;
$('#addform').slideDown('slow', function() {});
}; };
$scope.hideForm = function () {
$('#addform').slideUp('slow', function() {
$scope.slide.show = false;
$scope.$apply();
});
}
/**
* Add existing account
*/
$scope.addExisting = function () {
// Send link call to server
$http.post(config.backend + '/stu/license/sup/' + $scope.user.id, {license: $scope.formdata.license_number})
.success(function (data) {
loadStudents();
$scope.slide.rightTo('confirmation');
})
.error(function (err) {
var errorMessage = 'student_not_added';
if (err.message && err.message.search('nvalid license') > 0)
errorMessage = 'license_invalid';
else if (err.message && err.message.search('in use') > 0)
errorMessage = 'license_already_activated';
else if (err.message && err.message.search("lready linked") > 0)
errorMessage = 'student_already_linked';
else if (err && err.status === 400)
errorMessage = 'invalid_fields';
ngToast.danger($translate.instant(errorMessage));
});
}
/** /**
* Add Student * Add new account
*/ */
$scope.add_student = function () { $scope.addNew = function (type) {
var student = $scope.formdatastudent;
// set language according to interface settings
$scope.formdata.lang = $translate.use();
// Validate password match // Validate password match
if (student.password_confirm.length && student.password !== student.password_confirm) { if ($scope.formdata.password_confirm.length && $scope.formdata.password !== $scope.formdata.password_confirm) {
ngToast.danger({ content: $translate.instant('password_match') }); ngToast.danger($translate.instant('password_match'));
return; return;
} }
// password not changed (don't send it to DB) // Send creating call to server
if (!student.password_confirm.length) { $http.post(config.backend + '/stu', $scope.formdata)
delete student.password;
delete student.password_confirm;
}
$http.post(config.backend + '/stu', student)
.success(function (data) { .success(function (data) {
ngToast.success({ content: $translate.instant('student_added') }); loadStudents();
$scope.slide.rightTo('confirmation');
// default values
data.supervision = 0; // by default, only related to office administrator
data.current_method = $translate.instant('no_method');
data.current_instruction = $translate.instant('no_instruction');
data.licenseIsValid = new Date(data.license.expiration_ts) - new Date() > 0 ? true : false;
$scope.students.push(data);
$scope.resetForm();
$scope.hidestudentadd = true;
}) })
.error(function (err) { .error(function (err) {
console.log(typeof err);
console.log(err);
var errorMessage = 'student_not_added'; var errorMessage = 'student_not_added';
if (err.message && err.message.search('nvalid license') > 0) if (err.message && err.message.search('nvalid license') > 0 || typeof err == "string" && err.search('nvalid license') > 0)
errorMessage = 'license_invalid'; errorMessage = 'license_invalid';
else if (err.message && err.message.search('in use') > 0) else if (err.message && err.message.search('in use') > 0 || typeof err == "string" && err.search('in use') > 0)
errorMessage = 'license_already_activated'; errorMessage = 'license_already_activated';
else if (typeof err == "string" && err.search("Maximum number of enrolments reached") > 0) else if (err.message && err.message.search('already exists') > 0 || typeof err == "string" && err.search("already exists") > 0)
errorMessage = 'max_licenses_reached';
else if (typeof err == "string" && err.search("already exists") > 0)
errorMessage = 'student_already_exists'; errorMessage = 'student_already_exists';
else if (err && err.status === 400) else if (err && err.status === 400)
errorMessage = 'invalid_fields'; errorMessage = 'invalid_fields';
ngToast.danger({ content: $translate.instant(errorMessage) }); ngToast.danger({ content: $translate.instant(errorMessage) });
}); });
};
}
// --------------------------------------------------------
// Students list
// --------------------------------------------------------
function loadStudents() {
// Get list of supervisor's students
$http.get(config.backend + '/sup/' + $scope.user.id + '/students')
.success(function (data) {
$scope.students = data;
})
.error(function () {
ngToast.danger({ content: $translate.instant('error_fetching_students') });
});
}
/** /**
* Delete Student * Unlink Student
*/ */
$scope.delete_student = function (student) { $scope.unlink_student = function (student) {
if ($window.confirm($translate.instant('confirmation'))) { if ($window.confirm($translate.instant('confirmation'))) {
$http.delete(config.backend + '/stu/' + student.id) $http.delete(config.backend + '/stu/' + student.id + '/sup/' + $scope.user.id)
.success(function () { .success(function () {
var i; var i;
for (i = 0; i < $scope.students.length; i++) { for (i = 0; i < $scope.students.length; i++) {
...@@ -149,6 +193,11 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl( ...@@ -149,6 +193,11 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
} }
}; };
/**
* WEBSOCKETS
*/
// When a new student is added to the supervisor, we should update // When a new student is added to the supervisor, we should update
// the student list if necesary // the student list if necesary
IOService.on('linkSupervisorToStudent', function (eventData) { IOService.on('linkSupervisorToStudent', function (eventData) {
...@@ -173,15 +222,8 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl( ...@@ -173,15 +222,8 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
}); });
} }
}); });
});
/** // Main
* StudentAddCtrl loadStudents();
*/
dashboardControllers.controller('StudentAddCtrl', function StudentsCtrl($scope) {
$scope.open_calendar = function ($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened_cal_student = true;
};
}); });
...@@ -24,15 +24,15 @@ dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl( ...@@ -24,15 +24,15 @@ dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl(
// Assign values this way (like an object) to ensure it's the parent scope // Assign values this way (like an object) to ensure it's the parent scope
$scope.user.id = user.id; $scope.user.id = user.id;
$scope.user.name = user.name; $scope.user.role = user.role;
$scope.user.surname = user.surname; $scope.user.name = user.name || $translate.instant('name');
$scope.user.surname = user.surname || $translate.instant('surname');
$scope.user.pic = user.pic; $scope.user.pic = user.pic;
$scope.user.office = user.office;
if ($scope.user.office.name == 'no_office')
$scope.user.office.name = $translate.instant('no_office');
$scope.user.lang = user.lang; $scope.user.lang = user.lang;
$scope.user.isSupAdmin = user.isSupAdmin; $scope.user.isOffice = user.isOffice;
$scope.user.isTutor = user.isTutor; $scope.user.isTutor = user.isTutor;
$scope.user.isAdmin = user.isAdmin;
$scope.user.isTherapist = user.isTherapist;
$scope.user.arasaacLicense = user.arasaacLicense; $scope.user.arasaacLicense = user.arasaacLicense;
// Link to setup // Link to setup
......
...@@ -5,16 +5,105 @@ ...@@ -5,16 +5,105 @@
//-------------------------- //--------------------------
dashboardControllers.controller('SupervisorsCtrl', function SupervisorsCtrl($scope, $window, $http, config, $translate, ngToast) { dashboardControllers.controller('SupervisorsCtrl', function SupervisorsCtrl($scope, $window, $http, config, $translate, ngToast) {
$http $scope.inputs = {
.get(config.backend+'/office/get/' + $scope.user.office.id + '/supervisors') search_str: '',
.success(function(data, status, headers, config) { email: ''
$scope.supervisors_list = data; };
console.log($scope.supervisors_list);
}) $scope.supToAdd = {};
.error(function(data, status, headers, config) {
$translate('error_downloading_supervisors').then(function (translation) { function loadSupervisors() {
ngToast.danger({ content: translation }); $http
.get(config.backend+'/sup/' + $scope.user.id + '/supervisors')
.success(function(data, status, headers, config) {
$scope.supervisors_list = data;
console.log($scope.supervisors_list);
})
.error(function(data, status, headers, config) {
ngToast.danger($translate.instant('error_downloading_supervisors'));
}); });
}
/**
* Get a supervisor by their email and updates the $scope.supToAdd element.
* The email used for search is fetched from $scope.email_sup.
*/
$scope.searchSup = function () {
if (!$scope.user.isOffice) {
console.log("Forbidden action. You're not an office!");
return;
}
if ($scope.inputs.email.length == 0)
return;
// Find tutor by email
$http.get(config.backend + '/sup/email/' + $scope.inputs.email)
.success(function (data) {
if (data) {
$scope.supToAdd = data;
$scope.showmessagesupfound = true;
} else {
ngToast.danger($translate.instant('sup_not_found'));
// Hide the success message (if it exists by other query)
$scope.showmessagesupfound = false;
}
})
.error(function () {
ngToast.danger($translate.instant('sup_not_found'));
}); });
};
/**
* Links a new supervisor
*/
$scope.confirmLink = function () {
if (!$scope.user.isOffice) {
console.log("Forbidden action. You're not an office!");
return;
}
$scope.showmessagesupfound = false;
$http
.post(config.backend+'/sup/' + $scope.supToAdd.id + '/off/' + $scope.user.id)
.success(function(data, status, headers, config) {
loadSupervisors();
ngToast.success($translate.instant('supervisor_added_notified'));
})
.error(function(error) {
var message = typeof error == 'string' ? error : error.message;
if (message.search('already exists') > 0)
ngToast.danger($translate.instant('supervisor_already_linked'));
else if (message.search('yourself') > 0)
ngToast.danger($translate.instant('supervisor_yourself'));
else
ngToast.danger($translate.instant('no_supervisor_linked'));
});
};
/**
* Unlinks a supervisor
*/
$scope.unlinkSupervisor = function (id) {
if (!$scope.user.isOffice) {
console.log("Forbidden action. You're not an office!");
return;
}
$http
.delete(config.backend+'/sup/' + id + '/off/' + $scope.user.id)
.success(function(data, status, headers, config) {
loadSupervisors();
ngToast.success($translate.instant('supervisor_deleted'));
})
.error(function(data, status, headers, config) {
ngToast.danger($translate.instant('general_error'));
});
};
// MAIN
loadSupervisors();
}); });
...@@ -8,16 +8,39 @@ ...@@ -8,16 +8,39 @@
href="/app/#/students"> href="/app/#/students">
<img <img
class="topbar__logo__image" class="topbar__logo__image"
ng-src="{{user.office.logoUrl}}" src="/app/img/logo_pictogram.png"
alt="{{user.office.name}}" alt="Pîctogram"
title="{{user.office.name}}" /> title="Pictogram" />
</a> </a>
</div> </div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li ng-class="{active: $location.url() == '/students'}">
<a href="/app/#/students">
<i class="fa fa-users" aria-hidden="true"></i> {{ 'students' | translate }}
</a>
</li>
<li ng-if="user.isOffice" ng-class="{active: $location.url() == '/supervisor/list'}">
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/supervisor/list">
<i class="fa fa-users" aria-hidden="true"></i> {{ 'supervisors' | translate }}
</a>
</li>
<li ng-if="!user.isTutor" ng-class="{active: $location.url() == '/instructions'}">
<a href="/app/#/instructions">
<i class="glyphicon glyphicon-tasks" aria-hidden="true"></i> {{ 'instructions' | translate }}
</a>
</li>
<li>
<a ng-click="own_pictos()">
<i class="glyphicon glyphicon-picture" aria-hidden="true"></i> {{ 'own_pictos' | translate }}
</a>
</li>
</ul>
<div class="topbar__supervisor nav navbar-nav navbar-right"> <div class="topbar__supervisor nav navbar-nav navbar-right">
<div class="dropdown"> <div class="dropdown">
<div class="topbar__supervisor__name"> <div class="topbar__supervisor__name">
<div class="topbar__supervisor__name__fullname">{{user.getFullName()}}</div> <div class="topbar__supervisor__name__fullname">{{user.getFullName()}}</div>
<div class="topbar__supervisor__name__office">{{user.office.name}}</div> <div class="topbar__supervisor__name__role ng-binding">{{ user.role | translate }}</div>
</div> </div>
<div <div
class="topbar__supervisor__avatar thumbnail" class="topbar__supervisor__avatar thumbnail"
...@@ -26,18 +49,18 @@ ...@@ -26,18 +49,18 @@
<img id="supervisor_profile" ng-src="{{user.pic}}" alt="Supervisor" title="Supervisor" /> <img id="supervisor_profile" ng-src="{{user.pic}}" alt="Supervisor" title="Supervisor" />
</div> </div>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li> <!-- li>
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/students"> <a class="pointer" role="menuitem" tabindex="0" href="/app/#/students">
<i class="fa fa-users" aria-hidden="true"></i> <i class="fa fa-users" aria-hidden="true"></i>
{{ 'students' | translate }} {{ 'students' | translate }}
</a> </a>
</li> </li>
<li ng-if="user.isSupAdmin == true"> <li ng-if="user.isOffice">
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/supervisor/list"> <a class="pointer" role="menuitem" tabindex="0" href="/app/#/supervisor/list">
<i class="fa fa-users" aria-hidden="true"></i> <i class="fa fa-users" aria-hidden="true"></i>
{{ 'supervisors' | translate }} {{ 'supervisors' | translate }}
</a> </a>
<li ng-if="user.isTutor == false"> <li ng-if="!user.isTutor">
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/instructions"> <a class="pointer" role="menuitem" tabindex="0" href="/app/#/instructions">
<i class="glyphicon glyphicon-tasks" aria-hidden="true"></i> <i class="glyphicon glyphicon-tasks" aria-hidden="true"></i>
{{ 'instructions' | translate }} {{ 'instructions' | translate }}
...@@ -48,7 +71,7 @@ ...@@ -48,7 +71,7 @@
<i class="glyphicon glyphicon-picture" aria-hidden="true"></i> <i class="glyphicon glyphicon-picture" aria-hidden="true"></i>
{{ 'own_pictos' | translate }} {{ 'own_pictos' | translate }}
</a> </a>
</li> </li -->
<li> <li>
<a class="pointer" role="menuitem" tabindex="0" href="/app/#/setup"> <a class="pointer" role="menuitem" tabindex="0" href="/app/#/setup">
<i class="glyphicon glyphicon-cog" aria-hidden="true"></i> <i class="glyphicon glyphicon-cog" aria-hidden="true"></i>
...@@ -65,4 +88,5 @@ ...@@ -65,4 +88,5 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</nav> </nav>
<!-- InstructionsCtrl controls here, see app.js --> <!-- InstructionsCtrl controls here, see app.js -->
<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title" translate>own_instructions</h3></div>
<div class="panel-body">
<div class="row"> <div class="panel panel-default">
<div class="col-sm-6"> <!-- Default panel contents -->
<!-- Select to add new method --> <div class="panel-heading">
<div class="form-group"> <div class="row">
<!-- Botón añadir método --> <div class="col-xs-4">
<button ng-click="add_method()" class="btn btn-success btn-sm" popover="{{ 'add' | translate }}" popover-trigger="mouseenter"> <h3 translate>own_instructions</h3>
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <span translate>new_method</span> </div>
</button> <div class="col-xs-4 margin-top20">
</div> <div class="form-group">
</div> <!-- Botón añadir método -->
<button ng-click="add_method()" class="btn btn-success btn-sm" popover="{{ 'add' | translate }}" popover-trigger="mouseenter">
<div class="col-sm-6 text-right" ng-if="!minimalMode"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <span translate>new_method</span>
<button class="btn btn-primary" ng-click="enable_minimal()"><i class="fa fa-eye-slash" aria-hidden="true"></i> Ver menos detalles</button> </button>
</div>
<div class="col-sm-6 text-right" ng-if="minimalMode">
<button class="btn btn-primary" ng-click="enable_minimal()"><i class="fa fa-eye" aria-hidden="true"></i> Ver todo</button>
</div>
</div> </div>
</div>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-sm-12 text-right" ng-if="!minimalMode">
<button class="btn btn-primary" ng-click="enable_minimal()"><i class="fa fa-eye-slash" aria-hidden="true"></i> Ver menos detalles</button>
</div>
<div class="col-sm-12 text-right" ng-if="minimalMode">
<button class="btn btn-primary" ng-click="enable_minimal()"><i class="fa fa-eye" aria-hidden="true"></i> Ver todo</button>
</div>
</div>
<!-- Method instructions --> <!-- Method instructions -->
<div class="method" ng-repeat="m in methods"> <div class="method" ng-repeat="m in methods">
......
<!-- SetupCtrl controls here, see app.js --> <!-- SetupCtrl controls here, see app.js -->
<div> <div>
<div class="page-header"> <div class="page-header">
<h2 translate>setup</h2> <h3 translate>setup</h3>
</div> </div>
<div id="signin"> <div>
<!-- Logo Pictogram --> <!-- Logo Pictogram -->
<!-- Formulario --> <!-- Formulario -->
<form name="setupForm" enctype="multipart/form-data" role="form" ng-submit="setup()"> <form name="setupForm" enctype="multipart/form-data" role="form" ng-submit="setup()">
<!-- Preview --> <div class="row">
<img class="thumbnail preview" ng-src="{{user.pic}}" /> <div class="col-md-3 col-md-offset-1">
<!-- Fin Cambiar imagen de perfil --> <!-- Preview -->
<div class="form-group"> <img class="thumbnail preview" ng-src="{{user.pic}}" />
<!-- input type="file" ng-file-select="onFileSelect($files)" accept="image/*"></input --> <!-- Fin Cambiar imagen de perfil -->
<button class="btn btn-default" ngf-select ng-model="picFile" accept="image/*" ngf-change="changeImg()">
<span class="glyphicon glyphicon-folder-open"></span> {{ 'change_picture' | translate }}
</button>
</div>
<fieldset>
<legend translate>personal_data</legend>
<div class="form-group">
<input type="text" class="form-control" id="signin_name" placeholder="{{ 'name' | translate }}" required ng-model="formdata.name" />
</div>
<div class="form-group">
<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 }}" ng-model="formdata.address" />
</div>
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control" id="signin_phone" placeholder="{{ 'phone' | translate }}" ng-model="formdata.phone" /> <!-- input type="file" ng-file-select="onFileSelect($files)" accept="image/*"></input -->
<button class="btn btn-default" ngf-select ng-model="picFile" accept="image/*" ngf-change="changeImg()">
<span class="glyphicon glyphicon-folder-open"></span> {{ 'change_picture' | translate }}
</button>
</div> </div>
</fieldset> </div>
<div class="col-md-4">
<fieldset>
<legend translate>personal_data</legend>
<div class="form-group">
<input type="text" class="form-control" id="signin_name" placeholder="{{ 'name' | translate }}" required ng-model="formdata.name" />
</div>
<div class="form-group" ng-if="!user.isOffice">
<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 }}" ng-model="formdata.address" />
</div>
<div class="form-group">
<input type="text" class="form-control" id="signin_phone" placeholder="{{ 'phone' | translate }}" ng-model="formdata.phone" />
</div>
</fieldset>
<fieldset> <fieldset>
<legend translate>email</legend> <legend translate>language</legend>
<div class="form-group"> <div class="form-group">
<input type="email" class="form-control" id="signin_email1" placeholder="{{ 'email' | translate }}" required ng-model="formdata.email" /> <select class="form-control" name="signin_language" id="signin_language" ng-model="formdata.lang">
</div> <option value="es-es">Español</option>
</fieldset> <option value="en-gb">English</option>
</select>
</div>
</fieldset>
<fieldset> </div>
<legend translate>change_password</legend>
<div class="form-group">
<input style="display:none" type="password" name="fakepasswordremembered"/>
<input type="password" class="form-control" id="setup_password1" placeholder="{{ 'password_new_type' | translate }}" ng-model="formdata.password" />
</div>
<div class="form-group">
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" ng-model="formdata.password_confirm" />
</div>
<fieldset>
<fieldset> <div class="col-md-4">
<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-es">Español</option>
<option value="en-gb">English</option>
</select>
</div>
</fieldset>
<p class="text-center"> <fieldset>
<button type="submit" class="btn btn-primary" translate>save</button> <legend translate>email</legend>
</p> <div class="form-group">
</form> <input type="email" class="form-control" id="signin_email1" placeholder="{{ 'email' | translate }}" required ng-model="formdata.email" />
</div>
</fieldset>
<fieldset>
<legend translate>change_password</legend>
<div class="form-group">
<input style="display:none" type="password" name="fakepasswordremembered"/>
<input type="password" class="form-control" id="setup_password1" placeholder="{{ 'password_new_type' | translate }}" ng-model="formdata.password" />
</div>
<div class="form-group">
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" ng-model="formdata.password_confirm" />
</div>
<fieldset>
</div>
</div> </div>
<!-- Fin signin -->
<div class="row">
<p class="text-right">
<button type="submit" class="btn btn-primary" translate>save</button>
</p>
</div>
</form>
</div>
<!-- Fin signin -->
<!-- DIV Modal cropper para recorte de imagen --> <!-- DIV Modal cropper para recorte de imagen -->
<div class="modal fade" id="bootstrap-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade" id="bootstrap-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
......
<!-- StudentsCtrl controls here, see app.js --> <!-- StudentsCtrl controls here, see app.js -->
<div class="panel panel-default"> <div class="panel panel-default">
<!-- Default panel contents --> <!-- Default panel contents -->
<div class="panel-heading"><h3 class="panel-title" translate>students</h3> <div class="panel-heading">
<!-- span ng-if="user.isAdmin">({{user.office.currentStudents}}/{{user.office.maxStudents}} - <span translate="licenses_left" translate-values="{number: num_licenses_left}"></span>)</span --> <div class="row">
<div class="panel-body"> <div class="col-xs-4">
<h3 translate>students</h3>
</div>
<div class="col-xs-4 margin-top20">
<!-- Add Student Form --> <p class="text-left" ng-hide="slide.show">
<div ng-include="'modules/supervisor/views/students_add.html'" ng-init="hidestudentadd = true" ng-hide="hidestudentadd"></div> <a ng-click="showForm()" class="btn btn-success btn-sm" role="button">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> {{ 'add_student' | translate }}
</a>
</p>
<!-- Add Student button and Search row --> <p class="text-left" ng-show="slide.show">
<div class="row"> <a ng-click="hideForm()" class="btn btn-danger btn-sm" role="button">
<div class="col-xs-3"> <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> {{ 'close' | translate }}
<p class="text-left" ng-hide="!user.isSupAdmin || !hidestudentadd"> </a>
<a ng-click="resetForm(); hidestudentadd = false" class="btn btn-success btn-sm" role="button"> </p>
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> {{ 'add_student' | translate }}
</a> </div>
</p> <div class="col-xs-4 margin-top20">
</div> <div class=" input-group">
<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"> <input type="text" ng-model="search_students" id="search_students" placeholder="{{ 'filter' | translate }}" class="form-control" aria-describedby="basic-addon2">
<span class="input-group-addon"><span class="glyphicon glyphicon-search" id="basic-addon2" aria-hidden="true"></span></span> <span class="input-group-addon"><span class="glyphicon glyphicon-search" id="basic-addon2" aria-hidden="true"></span></span>
</div> </div>
<div class="col-xs-3">
</div>
</div> </div>
</div> </div>
<!-- Fin .panel-body --> </div>
<!-- Add Student Form -->
<div ng-include="'modules/supervisor/views/students_add.html'" hidden="true" id="addform"></div>
</div>
<!-- Fin .panel-body -->
<!-- Table --> <!-- Table -->
<div ng-show="students.length == 0"> <div class="table-responsive">
{{ no_students_for_user | translate }}
</div>
<table id="table_students" class="table table-hover"> <table id="table_students" class="table table-hover">
<tr ng-repeat="student in students | filter:search_students | orderBy: ['surname', 'name']"> <tr ng-repeat="student in students | filter:search_students | orderBy: ['surname', 'name']">
<td> <td>
...@@ -39,8 +45,10 @@ ...@@ -39,8 +45,10 @@
</div> </div>
</td> </td>
<td> <td>
<i ng-show="!student.licenseIsValid" class="fa fa-exclamation-circle fa-lg text-danger license-warning" aria-hidden="true" popover="{{ 'license_missing' | translate}}" popover-trigger="mouseenter"></i> <i ng-show="student.license.isValid && !student.license.isTrial" class="fa fa-certificate fa-lg text-primary license-warning" aria-hidden="true" popover="{{ 'license_pro' | translate}}" popover-trigger="mouseenter"></i>
<i ng-show="student.licenseIsValid" class="fa fa-certificate fa-lg text-primary license-warning" aria-hidden="true" popover="{{ 'license_pro' | translate}}" popover-trigger="mouseenter"></i> <i ng-show="student.license.isTrial && student.license.isValid" class="fa fa-flask fa-lg text-warning license-warning" aria-hidden="true" popover="{{ 'trial_license' | translate}}" popover-trigger="mouseenter"></i>
<i ng-show="!student.license.isValid && student.license.isOfficial" class="fa fa-certificate fa-lg text-danger license-warning" aria-hidden="true" popover="{{ 'license_missing_official' | translate}}" popover-trigger="mouseenter"></i>
<i ng-show="!student.license.isValid && student.license.isTrial" class="fa fa-flask fa-lg text-danger license-warning" aria-hidden="true" popover="{{ 'license_missing_trial' | translate}}" popover-trigger="mouseenter"></i>
</td> </td>
<td> <td>
<h4>{{student.surname}}, {{student.name}}</h4> <h4>{{student.surname}}, {{student.name}}</h4>
...@@ -50,32 +58,69 @@ ...@@ -50,32 +58,69 @@
</td> </td>
<td> <!-- BUTTONS --> <td> <!-- BUTTONS -->
<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> <a
class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/collections"
<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> alt="{{ 'collections' | translate }}" popover="{{ 'collections' | translate }}" popover-trigger="mouseenter" ng-if="student.license.isValid || student.license.isOfficial">
<span class="glyphicon glyphicon-th" aria-hidden="true"></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> </a>
<span
<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> class="btn btn-default btn-lg" role="button"
alt="{{ 'collections' | translate }}" popover="{{ 'collections' | translate }}" popover-trigger="mouseenter" ng-if="!student.license.isValid && student.license.isTrial">
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/session" alt="{{ 'session' | translate}}" popover="{{ 'session' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 2"><span class="glyphicon glyphicon-transfer" aria-hidden="true"></span></a> <span class="glyphicon glyphicon-th" aria-hidden="true" style="color: #bbb" ></span>
</span>
<span class="btn btn-default btn-lg" role="button" alt="{{ 'session' | translate}}" popover="{{ 'session' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision != 2"><span class="glyphicon glyphicon-transfer" aria-hidden="true" style="color: #bbb"></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="!user.isTutor && student.license.isValid">
<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="user.isTutor || !student.license.isValid">
<span class="glyphicon glyphicon-tasks" aria-hidden="true" style="color: #bbb" ></span>
</span>
<a class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/reports" alt="{{ 'reports' | translate}}" popover="{{ 'reports' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision != 1"><i class="fa fa-bar-chart" aria-hidden="true"></i></a> <a
class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/session"
alt="{{ 'session' | translate }}" popover="{{ 'session' | translate }}" popover-trigger="mouseenter" ng-if="!user.isTutor && student.license.isValid">
<span class="glyphicon glyphicon-transfer" aria-hidden="true"></span>
</a>
<span
class="btn btn-default btn-lg" role="button"
alt="{{ 'session' | translate }}" popover="{{ 'session' | translate }}" popover-trigger="mouseenter" ng-if="user.isTutor || !student.license.isValid">
<span class="glyphicon glyphicon-transfer" aria-hidden="true" style="color: #bbb"></span>
</span>
<span class="btn btn-default btn-lg" role="button" alt="{{ 'reports' | translate}}" popover="{{ 'reports' | translate}}" popover-trigger="mouseenter" ng-if="student.supervision == 1"><i class="fa fa-bar-chart" aria-hidden="true" style="color: #bbb"></i></span> <a
class="btn btn-default btn-lg" role="button" href="/app/#/student/{{student.id}}/reports"
alt="{{ 'reports' | translate }}" popover="{{ 'reports' | translate }}" popover-trigger="mouseenter" ng-if="!user.isTutor && student.license.isValid">
<i class="fa fa-bar-chart" aria-hidden="true"></i>
</a>
<span class="btn btn-default btn-lg" role="button"
alt="{{ 'reports' | translate }}" popover="{{ 'reports' | translate }}" popover-trigger="mouseenter" ng-if="user.isTutor || !student.license.isValid">
<i class="fa fa-bar-chart" aria-hidden="true" style="color: #bbb"></i>
</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">
<span class="glyphicon glyphicon-cog" aria-hidden="true"></span>
</a>
</td> <!-- /BUTTONS --> </td> <!-- /BUTTONS -->
<td> <td>
<a ng-if="user.isSupAdmin" ng-click="delete_student(student)" class="delete_stu" title="{{ 'delete' | translate}}"> <a ng-click="unlink_student(student)" class="delete_stu" title="{{ 'unlink' | translate}}">
<span class="glyphicon glyphicon-remove-circle text-danger" aria-hidden="true"></span> <span class="glyphicon glyphicon-remove-circle text-danger" aria-hidden="true"></span>
</a> </a>
</td> </td>
</tr> </tr>
</table> </table>
<div class="alert alert-warning" ng-if="students.length == 0">
<strong translate>no_students</strong>. {{ 'no_students_desc' | translate }}.
</div>
</div> </div>
<!-- Fin de row --> <!-- Fin de row -->
<h3 class="color_green" translate>add_student</h3>
<form name="AddStudentForm" role="form" ng-submit="add_student()" ng-controller="StudentAddCtrl"> <div class="switch-panel-body height400" ng-switch="slide.state">
<div class="row">
<div class="col-sm-6"> <!--
<fieldset> SLIDE 1: Account type selection
-->
<legend translate>account</legend> <div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="accounts">
<div class="form-group"> <div class="row">
<input type="username" class="form-control" id="setup_username" placeholder="{{ 'username' | translate }}" required ng-model="formdatastudent.username" /> <div class="col-md-4">
</div> <legend translate>add_existing</legend>
<div class="text-center">
<div class="form-group"> <a ng-click="slide.rightTo('existing')">
<input type="password" class="form-control" id="setup_password1" placeholder="{{ 'password_new_type' | translate }}" ng-model="formdatastudent.password" required /> <img src="img/child-existing.png" alt="{{'parents_tutor' | translate}}" title="{{'parents_tutor' | translate}}"
ng-class="{'img-120': hover_existing}"
ng-mouseenter="hover_existing = true"
ng-mouseleave="hover_existing = false"/>
</a>
</div>
</div>
<div class="col-md-4">
<legend translate>add_new_official</legend>
<div class="text-center">
<a ng-click="slide.rightTo('new')">
<img src="img/child-new.png" alt="{{'therapist' | translate}}" title="{{'therapist' | translate}}"
ng-class="{'img-120': hover_new}"
ng-mouseenter="hover_new = true"
ng-mouseleave="hover_new = false"/>
</a>
</div>
</div>
<div class="col-md-4">
<legend translate>new_test_account</legend>
<div class="text-center">
<a ng-click="slide.rightTo('test')">
<img src="img/child-test.png" alt="{{'office_center' | translate}}" title="{{'office_center' | translate}}"
ng-class="{'img-120': hover_test}"
ng-mouseenter="hover_test = true"
ng-mouseleave="hover_test = false"/>
</a>
</div>
</div>
</div> </div>
<div class="form-group"> <div class="row">
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" ng-model="formdatastudent.password_confirm" required /> <div class="col-md-4">
<p translate>add_existing_desc</p>
</div>
<div class="col-md-4">
<p translate>add_new_official_desc</p>
</div>
<div class="col-md-4">
<p translate>new_test_account_desc</p>
</div>
</div> </div>
</div>
<div class="form-group"> <!--
{{ 'language' | translate }}: <select class="form-control" name="student_language" id="student_language" ng-model="formdatastudent.lang"> SLIDE 2: Associate existing account
<option value="es-es" selected>Español</option> -->
<option value="en-us">English</option> <form name="forms.existing" role="form" ng-submit="addExisting()" novalidate>
</select>
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="existing">
<legend translate>add_existing</legend>
<div class="row">
<div class="col-md-4 col-md-offset-2 text-center">
<img src="img/child-existing.png" alt="{{'parents_tutor' | translate}}" title="{{'parents_tutor' | translate}}" />
</div>
<div class="form-group col-md-4">
<label translate>license_number</label>
<input class="form-control" type="text" id="student_license" mask="wwww-wwww-wwww-wwww" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formdata.license_number" required>
</div>
</div>
<div class="row form-group">
<div class="col-md-4 col-md-offset-2 ">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary float-right" ng-disabled="forms.existing.$invalid">{{ 'link' | translate }} &gt;&gt; </button>
</div>
</div>
</div> </div>
<div class="form-group"> </form>
<input class="form-control" type="text" id="student_license" mask="wwww-wwww-wwww-wwww" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formdatastudent.license_number" required>
<!--
SLIDE 3: New official account
-->
<form name="forms.new" role="form" ng-submit="addNew('new')" novalidate>
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="new">
<legend translate>add_new_official</legend>
<div class="row">
<div class="col-md-4 col-md-offset-2 text-center">
<img src="img/child-new.png" alt="{{'therapist' | translate}}" title="{{'therapist' | translate}}" />
</div>
<div class="form-group col-md-4">
<div class="form-group">
<label translate>username</label>
<input type="username" class="form-control" id="setup_username" placeholder="{{ 'username_default' | translate }}" required ng-model="formdata.username" />
</div>
<div class="form-group">
<label translate>password</label>
<input type="password" class="form-control" id="setup_password1" placeholder="{{ 'password_new_type' | translate }}" name="password" ng-model="formdata.password" required />
<span class="color_red text_sm pull-right" ng-show="formdata.password.length < minlength && forms.new.password.$dirty && forms.new.password_confirm.$dirty"> {{ 'password_short' | translate:'{ minlength: minlength }' }}</span>
</div>
<div class="form-group">
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" name="password_confirm" ng-model="formdata.password_confirm" required />
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm && forms.new.password.$dirty && forms.new.password_confirm.$dirty" translate>password_match</span>
</div>
<div class="form-group">
<label translate>license_number</label>
<input class="form-control" type="text" id="student_license" mask="wwww-wwww-wwww-wwww" clean="true" placeholder="{{ 'license_number' | translate }}" ng-model="formdata.license_number" required>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-4 col-md-offset-2 ">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary float-right" ng-disabled="forms.new.$invalid">{{ 'create_account' | translate }} &gt;&gt; </button>
</div>
</div>
</div> </div>
</form>
<!--
SLIDE 5: Office account form
-->
<form name="forms.test" role="form" ng-submit="addNew('test')" novalidate>
<div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="test">
<legend translate>new_test_account</legend>
<div class="row">
<div class="col-md-4 col-md-offset-2 text-center">
<img src="img/child-test.png" alt="{{'office_center' | translate}}" title="{{'office_center' | translate}}" />
</div>
<div class="form-group col-md-4" id="office_form">
<div class="form-group">
<label translate>username</label>
<input type="username" class="form-control" id="setup_username" placeholder="{{ 'username_default' | translate }}" required ng-model="formdata.username" />
</div>
<div class="form-group">
<label translate>password</label>
<input type="password" class="form-control" id="setup_password1" placeholder="{{ 'password_new_type' | translate }}" name="password" ng-model="formdata.password" required />
<span class="color_red text_sm pull-right" ng-show="formdata.password.length < minlength && forms.test.password.$dirty && forms.test.password_confirm.$dirty"> {{ 'password_short' | translate:'{ minlength: minlength }' }}</span>
</div>
<div class="form-group">
<input type="password" class="form-control" id="setup_password2" placeholder="{{ 'password_confirm' | translate }}" name="password_confirm" ng-model="formdata.password_confirm" required />
<span class="color_red text_sm pull-right" ng-show="formdata.password != formdata.password_confirm && forms.test.password.$dirty && forms.test.password_confirm.$dirty" translate>password_match</span>
</div>
</div>
</div>
<div class="row form-group">
<div class="col-md-4 col-md-offset-2 ">
<button class="btn btn-default" ng-click="slide.leftTo('accounts')">&lt;&lt; {{ 'back' | translate }} </button>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary float-right" ng-disabled="forms.test.$invalid">{{ 'create_account' | translate }} &gt;&gt; </button>
</div>
</div>
</div>
</div> </form>
<div class="col-sm-6">
<legend translate>personal_data</legend>
<div class="form-group">
<input type="text" class="form-control" id="student_name" placeholder="{{ 'name' | translate }}" required ng-model="formdatastudent.name" />
</div>
<div class="form-group">
<input type="text" class="form-control" id="student_surname" placeholder="{{ 'surname' | translate }}" required ng-model="formdatastudent.surname" />
</div>
<div class="row">
<div class="col-sm-6"> <!--
<div class="form-group"> SLIDE 6: Confirmation message
<p class="input-group"> -->
<input type="text" class="form-control" datepicker-popup="{{ 'day_format' | translate }}" ng-model="formdatastudent.birthdate" placeholder="{{ 'birthdate' | translate }}" is-open="opened_cal_student" close-text="{{'close' | translate}}" required /> <div ng-class="slide.back ? 'switch-animation-back' : 'switch-animation'" ng-switch-when="confirmation">
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open_calendar($event)"><i class="glyphicon glyphicon-calendar"></i></button>
</span>
</p>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<select class="form-control" name="student_gender" id="student_gender" ng-model="formdatastudent.gender" required>
<option value="F" selected translate>woman</option>
<option value="M" translate>man</option>
</select>
</div>
</div>
</div> <h2>{{ 'account_available' | translate }} </h2>
<p translate>student_account_confirm</p>
<br>
<img src="img/child.png"/>
<div class="form-group">
<span translate>country</span>:
<select class="form-control" name="student_country" id="student_country" ng-model="formdatastudent.country" required>
<option value="ES" selected>España</option>
<option value="US">United States</option>
<option value="UK">United Kingdom</option>
<option value="IE">Ireland</option>
</select>
</div> </div>
</div> </div>
</div>
<!-- Fin de row -->
<div class="form-group text-center">
<button type="button" class="btn btn-default" ng-click="resetForm()">{{'cancel'|translate}}</button>
<button type="submit" class="btn btn-primary" translate>add</button>
</div>
</form>
<hr /> <hr />
...@@ -4,37 +4,60 @@ ...@@ -4,37 +4,60 @@
<div class="panel-heading"> <div class="panel-heading">
<div class="row"> <div class="row">
<div class="col-xs-4"> <div class="col-xs-4">
<h5 translate>supervisors</h5> <h3 translate>supervisors</h3>
</div> </div>
<div class="col-xs-4"> <div class="col-xs-4 margin-top20">
<div class=" input-group">
<input type="text" ng-model="inputs.email" placeholder="{{ 'email' | translate }}" class="form-control">
<span class="input-group-btn" popover="{{ 'link_supervisor_desc' | translate }}" popover-trigger="mouseenter">
<button ng-click="searchSup()" class="btn btn-success btn-sm" role="button">
{{ 'link_supervisor' | translate }}
</button>
</span>
</div>
<!-- Alert and success messages for supervisor found -->
<div ng-show="{{ 'showmessagesupfound' }}" class="alert alert-info overlap-result">
<!-- Imagen de perfil del tutor -->
<img ng-src="{{supToAdd.pic}}" class="profile" alt="" title="" /> {{ supToAdd.name }} {{ supToAdd.surname }}
<a class="btn btn-default btn-sm pull-right" role="button" ng-click="confirmLink()" translate>add</a>
</div>
</div> </div>
<div class="col-xs-4"> <div class="col-xs-4 margin-top20">
<div class=" input-group"> <div class=" input-group">
<input type="text" ng-model="search_sups" id="search_sups" placeholder="{{ 'filter' | translate }}" class="form-control" aria-describedby="basic-addon2"> <input type="text" ng-model="inputs.search_str" id="search_sups" placeholder="{{ 'filter' | translate }}" class="form-control" aria-describedby="basic-addon2">
<span class="input-group-addon"><span class="glyphicon glyphicon-search" id="basic-addon2" aria-hidden="true"></span></span> <span class="input-group-addon"><span class="glyphicon glyphicon-search" id="basic-addon2" aria-hidden="true"></span></span>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Fin .panel-body -->
<div class="table-responsive"> <div class="table-responsive">
<table class="table"> <table class="table" id="table_supervisors">
<thead class="thead-default"> <thead class="thead-default">
<tr> <tr>
<th translate>supervisors</th> <th class="col-xs-8" translate>supervisors</th>
<th translate>students</th> <th class="col-xs-4" translate>students</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="active" ng-repeat="supervisor in supervisors_list | filter:search_sups | orderBy: 'name'"> <tr class="active" ng-repeat="supervisor in supervisors_list | filter:inputs.search_str | orderBy: 'name'">
<td> <td>
<div> <div class="row">
<div class="col-xs-2"> <div class="col-xs-2">
<div class="thumbnail"> <div class="thumbnail">
<img ng-src="/upload/supervisorAvatar/{{supervisor.pic}}" alt="Supervisor" title="Supervisor" /> <img ng-src="{{supervisor.pic}}" alt="Supervisor" title="Supervisor" />
</div> </div>
</div> </div>
<div class="col-xs-10"> <div class="col-xs-1">
<a ng-click="unlinkSupervisor(supervisor.id)" class="delete_sup" title="{{ 'unlink' | translate }}">
<span class="glyphicon glyphicon-remove-circle text-danger" aria-hidden="true"></span>
</a>
</div>
<div class="col-xs-9">
<h4>{{supervisor.name}} {{supervisor.surname}}</h4> <h4>{{supervisor.name}} {{supervisor.surname}}</h4>
<p><i class="fa fa-envelope" aria-hidden="true">&nbsp</i><a href="mailto:{{supervisor.email}}">{{supervisor.email}}</a></p> <p><i class="fa fa-envelope" aria-hidden="true">&nbsp</i><a href="mailto:{{supervisor.email}}">{{supervisor.email}}</a></p>
<p><i class="fa fa-phone-square" aria-hidden="true"></i>&nbsp<a href="tel:{{supervisor.phone}}">{{supervisor.phone}}</a></p> <p><i class="fa fa-phone-square" aria-hidden="true"></i>&nbsp<a href="tel:{{supervisor.phone}}">{{supervisor.phone}}</a></p>
...@@ -52,6 +75,9 @@ ...@@ -52,6 +75,9 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="alert alert-warning" ng-if="supervisors_list.length == 0">
<strong translate>no_supervisors</strong> {{ 'no_supervisors_desc' | translate }}
</div>
</div> </div>
</div> </div>
...@@ -8,6 +8,7 @@ dashboardControllers.controller('TranslateController', function( ...@@ -8,6 +8,7 @@ dashboardControllers.controller('TranslateController', function(
$scope, $scope,
$window, $window,
$http, $http,
$timeout,
config, config,
ngToast, ngToast,
vcRecaptchaService vcRecaptchaService
...@@ -44,7 +45,7 @@ dashboardControllers.controller('TranslateController', function( ...@@ -44,7 +45,7 @@ dashboardControllers.controller('TranslateController', function(
//Server PUT //Server PUT
$http.put(config.backend + '/sup/' + $scope.user.id, { "lang": langKey }) $http.put(config.backend + '/sup/' + $scope.user.id, { "lang": langKey })
.success(function (data) { .success(function (data) {
ngToast.success({ content: $translate.instant('data_saved') }); ngToast.success({ content: $translate.instant('language_change_warning') });
console.log("OK: Update supervisor language"); console.log("OK: Update supervisor language");
}) })
.error(function () { .error(function () {
...@@ -63,7 +64,5 @@ dashboardControllers.controller('TranslateController', function( ...@@ -63,7 +64,5 @@ dashboardControllers.controller('TranslateController', function(
vcRecaptchaService.useLang(0, langKey.substr(0,2)); vcRecaptchaService.useLang(0, langKey.substr(0,2));
} catch (err) {} } catch (err) {}
// Reload page
$window.location.reload();
}; };
}); });
...@@ -58,10 +58,18 @@ ...@@ -58,10 +58,18 @@
margin-top: 15px; margin-top: 15px;
} }
.margin-top20 {
margin-top: 20px;
}
.margin-top7 { .margin-top7 {
margin-top: 7px; margin-top: 7px;
} }
.margin-top10 {
margin-top: 10px;
}
.table .table-striped .striped { .table .table-striped .striped {
background-color: lightgray !important; background-color: lightgray !important;
} }
...@@ -870,7 +878,8 @@ img.profile{ ...@@ -870,7 +878,8 @@ img.profile{
#user_tutors .list-group-item:hover .delete_tutor, #user_tutors .list-group-item:hover .delete_tutor,
#user_sups .list-group-item:hover .delete_sup, #user_sups .list-group-item:hover .delete_sup,
#table_students tr:hover .delete_stu{ #table_supervisors tr:hover .delete_sup,
#table_students tr:hover .delete_stu {
opacity: 1; opacity: 1;
} }
...@@ -1098,3 +1107,82 @@ input.editable.scene-name { ...@@ -1098,3 +1107,82 @@ input.editable.scene-name {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
} }
.float-right {
float: right;
}
.float-left {
float: left;
}
/* Cambiar tamaño imagen */
.img-200 {
margin-top: 25px;
width: 200px;
}
.img-120 {
margin-top: 25px;
width: 120px;
}
/* Estilos para ngSwitch */
.switch-panel-body {
position:relative;
width: 930px;
margin: auto;
overflow:hidden;
}
.height600 {
height: 600px;
}
.height400 {
height: 400px;
}
.switch-animation,
.switch-animation-back {
width: 900px;
}
.switch-animation.ng-enter,
.switch-animation.ng-leave,
.switch-animation-back.ng-enter,
.switch-animation-back.ng-leave {
-webkit-transition:0.5s linear all;
-moz-transition:0.5s linear all;
-o-transition:0.5s linear all;
transition: 0.5s linear all;
position:absolute;
}
.switch-animation.ng-enter,
.switch-animation-back.ng-leave.ng-leave-active {
left:100%;
}
.switch-animation.ng-leave,
.switch-animation.ng-enter.ng-enter-active,
.switch-animation-back.ng-leave,
.switch-animation-back.ng-enter.ng-enter-active {
left:0;
}
.switch-animation.ng-leave.ng-leave-active,
.switch-animation-back.ng-enter {
left:-100%;
}
.switch-panel {
overflow:hidden;
}
.overlap-result {
z-index:20;
position:absolute;
width:100%
}
...@@ -29,11 +29,13 @@ ...@@ -29,11 +29,13 @@
padding: 0.5em; padding: 0.5em;
&__fullname, &__fullname,
&__office { &__office,
&__role {
text-align: right; text-align: right;
} }
&__office { &__office,
&__role {
opacity: 0.75; opacity: 0.75;
} }
} }
......
...@@ -8,5 +8,6 @@ ...@@ -8,5 +8,6 @@
"therapist_office_request": "{{ name }}, with email {{ email }}, is requesting to be linked as therapist to any of your students.", "therapist_office_request": "{{ name }}, with email {{ email }}, is requesting to be linked as therapist to any of your students.",
"tutor_office_request": "{{ name }}, with email {{ email }}, is requesting to be linked as tutor/father/mother to any of your students.", "tutor_office_request": "{{ name }}, with email {{ email }}, is requesting to be linked as tutor/father/mother to any of your students.",
"welcome_msg1": "Welcome to Pictogram, {{ name }}!", "welcome_msg1": "Welcome to Pictogram, {{ name }}!",
"welcome_msg2": "Your account is now active. You can proceed to" "welcome_msg2": "Your account is now active. You can proceed to",
"office_link": "The office/center \"{{ name }}\" with email \"{{ email }}\" has added you as part of its team in Pictogram."
} }
...@@ -8,5 +8,6 @@ ...@@ -8,5 +8,6 @@
"therapist_office_request": "El/la terapeuta {{ name }}, con correo electrónico {{ email }}, pide ser asociado a algún estudiante.", "therapist_office_request": "El/la terapeuta {{ name }}, con correo electrónico {{ email }}, pide ser asociado a algún estudiante.",
"tutor_office_request": "El/la tutor/a/padre/madre {{ name }}, con correo electrónico {{ email }}, pide ser asociado a algún estudiante.", "tutor_office_request": "El/la tutor/a/padre/madre {{ name }}, con correo electrónico {{ email }}, pide ser asociado a algún estudiante.",
"welcome_msg1": "¡Bienvenido a Pictogram, {{ name }}!", "welcome_msg1": "¡Bienvenido a Pictogram, {{ name }}!",
"welcome_msg2": "Su cuenta está ahora activa, por lo que puede" "welcome_msg2": "Su cuenta está ahora activa, por lo que puede",
"office_link": "El centro/gabinete \"{{ name }}\", con correo electrónico \"{{ email }}\" le ha añadido como parte de su equipo."
} }
...@@ -21,7 +21,7 @@ module.exports.pictogram = { ...@@ -21,7 +21,7 @@ module.exports.pictogram = {
], ],
serialSize: 10, // number of characters in generated serial numbers serialSize: 10, // number of characters in generated serial numbers
pageLimit: 10, // number of elements per "page" pageLimit: 10, // number of elements per "page"
trial_license_duration: 3, // number of moths the trial license is valid
password_minlength: 8, // minimal size for the password string password_minlength: 8, // minimal size for the password string
urls: { urls: {
...@@ -54,11 +54,11 @@ module.exports.pictogram = { ...@@ -54,11 +54,11 @@ module.exports.pictogram = {
*/ */
getSupervisorCustomPictoUrl: function (filename) { getSupervisorCustomPictoUrl: function (filename) {
return `/upload/supervisorCustomPicto/${filename}`; return `/upload/supervisorCustomPicto/${filename}`;
}, },
/** /**
* Gets the public url of a sound for a given picto * Gets the public url of a sound for a given picto
* @param {String} filename filename of sound * @param {String} filename filename of sound
* @return {String} Public url of the picto sound * @return {String} Public url of the picto sound
*/ */
getSoundUrl: function (filename) { getSoundUrl: function (filename) {
return `/upload/pictoSound/${filename}`; return `/upload/pictoSound/${filename}`;
...@@ -72,7 +72,7 @@ module.exports.pictogram = { ...@@ -72,7 +72,7 @@ module.exports.pictogram = {
supervisorAvatarDirectory: path.join(UPLOAD_PATH, 'supervisorAvatar'), supervisorAvatarDirectory: path.join(UPLOAD_PATH, 'supervisorAvatar'),
studentAvatarDirectory: path.join(UPLOAD_PATH, 'studentAvatar'), studentAvatarDirectory: path.join(UPLOAD_PATH, 'studentAvatar'),
supervisorCustomPictoDirectory: path.join(UPLOAD_PATH, 'supervisorCustomPicto'), supervisorCustomPictoDirectory: path.join(UPLOAD_PATH, 'supervisorCustomPicto'),
pictoSoundDirectory: path.join(UPLOAD_PATH, 'pictoSound'), pictoSoundDirectory: path.join(UPLOAD_PATH, 'pictoSound'),
/** /**
* Get a random name used for uploaded file names * Get a random name used for uploaded file names
* @param {string} randomString String used for generating the name * @param {string} randomString String used for generating the name
......
...@@ -21,6 +21,8 @@ module.exports.policies = { ...@@ -21,6 +21,8 @@ module.exports.policies = {
'*': false, '*': false,
// TODO: habría que revisar estas políticas, porque creo que hay bastantes brechas abiertas
ActionController: { ActionController: {
create: ['tokenAuth'], create: ['tokenAuth'],
createlist: ['tokenAuth'] createlist: ['tokenAuth']
...@@ -44,11 +46,11 @@ module.exports.policies = { ...@@ -44,11 +46,11 @@ module.exports.policies = {
}, },
MetaMethodController: { MetaMethodController: {
supVisible: ['tokenAuth'], supVisible: ['tokenAuth'],
supOwned: ['tokenAuth'], supOwned: ['tokenAuth'],
create: ['tokenAuth'], create: ['tokenAuth'],
update: ['tokenAuth'], update: ['tokenAuth'],
destroy: ['tokenAuth'] destroy: ['tokenAuth']
}, },
MethodController: { MethodController: {
...@@ -59,13 +61,6 @@ module.exports.policies = { ...@@ -59,13 +61,6 @@ module.exports.policies = {
destroy: ['tokenAuth'], destroy: ['tokenAuth'],
}, },
OfficeController: {
getAll: true,
get: ['tokenAuth'],
getBasic: true,
supervisors: ['tokenAuth', 'isAdminOrIsSupAdmin']
},
PictoController: { PictoController: {
upload: ['tokenAuth'], upload: ['tokenAuth'],
add_tag: ['tokenAuth'], add_tag: ['tokenAuth'],
...@@ -81,13 +76,13 @@ module.exports.policies = { ...@@ -81,13 +76,13 @@ module.exports.policies = {
}, },
SceneController:{ SceneController:{
create: ['tokenAuth', 'isSupervisorOfStudent'], create: ['tokenAuth', 'isSupervisorOfStudent'],
update: ['tokenAuth', 'isSupervisorOfStudent'], update: ['tokenAuth', 'isSupervisorOfStudent'],
destroy: ['tokenAuth', 'isSupervisorOfStudent'], destroy: ['tokenAuth', 'isSupervisorOfStudent'],
duplicate: ['tokenAuth', 'isSupervisorOfStudent'], duplicate: ['tokenAuth', 'isSupervisorOfStudent'],
getScene: ['tokenAuth'], getScene: ['tokenAuth'],
getStudentScenes: ['tokenAuth'], getStudentScenes: ['tokenAuth'],
scene: true scene: true
}, },
ServerController: { ServerController: {
...@@ -97,11 +92,11 @@ module.exports.policies = { ...@@ -97,11 +92,11 @@ module.exports.policies = {
StudentController: { StudentController: {
eternal: true, eternal: true,
getInfo: ['tokenAuth', 'isSupervisorOfStudentOrIsSupAdminOrIsStudent'], getInfo: ['tokenAuth', 'isStudentOrSupervisorOfStudent'],
supervisors: ['tokenAuth'], supervisors: ['tokenAuth'],
therapists: ['tokenAuth'], therapists: ['tokenAuth'],
tutors: ['tokenAuth'], tutors: ['tokenAuth'],
link_supervisor: ['tokenAuth', 'isSupAdmin'], link_supervisor: ['tokenAuth'],
pictos: ['tokenAuth'], pictos: ['tokenAuth'],
methods: ['tokenAuth'], methods: ['tokenAuth'],
lasttries: ['tokenAuth'], lasttries: ['tokenAuth'],
...@@ -113,7 +108,7 @@ module.exports.policies = { ...@@ -113,7 +108,7 @@ module.exports.policies = {
update_legend: ['tokenAuth'], update_legend: ['tokenAuth'],
update_category: ['tokenAuth', 'isSupervisorOfStudent'], update_category: ['tokenAuth', 'isSupervisorOfStudent'],
login: true, login: true,
create: ['tokenAuth', 'isSupAdmin'], create: ['tokenAuth'],
upload: ['tokenAuth'], upload: ['tokenAuth'],
upload_sound: ['tokenAuth'], upload_sound: ['tokenAuth'],
add_picto: ['tokenAuth', 'isSupervisorOfStudent'], add_picto: ['tokenAuth', 'isSupervisorOfStudent'],
...@@ -123,8 +118,8 @@ module.exports.policies = { ...@@ -123,8 +118,8 @@ module.exports.policies = {
action: true, action: true,
config: true, config: true,
actions_batch: ['tokenAuth'], actions_batch: ['tokenAuth'],
delete: ['tokenAuth', 'isSupAdmin'], delete: ['tokenAuth', 'isAdmin'],
unlink_supervisor: ['tokenAuth', 'isSupAdmin'], unlink_supervisor: ['tokenAuth', 'isSupervisorOfStudent'],
delete_picto: ['tokenAuth', 'isSupervisorOfStudent'], delete_picto: ['tokenAuth', 'isSupervisorOfStudent'],
getActiveScene: ['tokenAuth'], getActiveScene: ['tokenAuth'],
getScenes: ['tokenAuth'], getScenes: ['tokenAuth'],
...@@ -143,7 +138,8 @@ module.exports.policies = { ...@@ -143,7 +138,8 @@ module.exports.policies = {
list: ['tokenAuth', 'isAdmin'], list: ['tokenAuth', 'isAdmin'],
students: ['tokenAuth'], students: ['tokenAuth'],
pictos: ['tokenAuth'], pictos: ['tokenAuth'],
getByEmail: ['tokenAuth'], getByEmail: ['tokenAuth', 'isOffice'],
getFromOfficeByEmail: ['tokenAuth', 'isOffice'],
update: ['tokenAuth'], update: ['tokenAuth'],
create: true, create: true,
login: true, login: true,
...@@ -154,7 +150,10 @@ module.exports.policies = { ...@@ -154,7 +150,10 @@ module.exports.policies = {
upload: ['tokenAuth'], upload: ['tokenAuth'],
subscribe: ['tokenAuth'], subscribe: ['tokenAuth'],
unsubscribe: ['tokenAuth'], unsubscribe: ['tokenAuth'],
delete: ['tokenAuth', 'isAdmin'] delete: ['tokenAuth', 'isAdmin'],
supervisors: ['tokenAuth', 'isOffice'],
link_supervisor: ['tokenAuth', 'isOffice'],
unlink_supervisor: ['tokenAuth', 'isOffice']
}, },
TryController: { TryController: {
......
...@@ -55,11 +55,6 @@ module.exports.routes = { ...@@ -55,11 +55,6 @@ module.exports.routes = {
'PUT /method/template/:id': 'MetaMethodController.update', 'PUT /method/template/:id': 'MetaMethodController.update',
'DELETE /method/template/:id': 'MetaMethodController.destroy', 'DELETE /method/template/:id': 'MetaMethodController.destroy',
'GET /office/get_all': 'OfficeController.getAll',
'GET /office/:code': 'OfficeController.getBasic',
'GET /office/get/:id': 'OfficeController.get',
'GET /office/get/:id/supervisors': 'OfficeController.supervisors',
'GET /picto/:lang/pic_categories/:id_cat': 'PictoController.categories', 'GET /picto/:lang/pic_categories/:id_cat': 'PictoController.categories',
'GET /picto/:lang/pic_fromcategory/:id_cat': 'PictoController.fromcategory', 'GET /picto/:lang/pic_fromcategory/:id_cat': 'PictoController.fromcategory',
'GET /picto/:lang/pic_fromSymbolStx/page/:page/limit/:limit': 'PictoController.fromSymbolStx', 'GET /picto/:lang/pic_fromSymbolStx/page/:page/limit/:limit': 'PictoController.fromSymbolStx',
...@@ -87,8 +82,7 @@ module.exports.routes = { ...@@ -87,8 +82,7 @@ module.exports.routes = {
'GET /stu/:id_stu': 'StudentController.getInfo', 'GET /stu/:id_stu': 'StudentController.getInfo',
'GET /stu/:id_stu/supervisors': 'StudentController.supervisors', 'GET /stu/:id_stu/supervisors': 'StudentController.supervisors',
'GET /stu/:id_stu/therapists': 'StudentController.therapists', 'POST /stu/license/sup/:id_sup': "StudentController.link_supervisor",
'GET /stu/:id_stu/tutors': 'StudentController.tutors',
'POST /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/pictos': 'StudentController.pictos',
'GET /stu/:id_stu/activeScene': 'StudentController.getActiveScene', 'GET /stu/:id_stu/activeScene': 'StudentController.getActiveScene',
...@@ -104,7 +98,7 @@ module.exports.routes = { ...@@ -104,7 +98,7 @@ module.exports.routes = {
'PUT /stu/:id_stu/legend/:legend_value': 'StudentController.update_legend', 'PUT /stu/:id_stu/legend/:legend_value': 'StudentController.update_legend',
'PUT /stu/:id_stu/picto': 'StudentController.update_picto', 'PUT /stu/:id_stu/picto': 'StudentController.update_picto',
'PUT /stu/:id_stu/cat': 'StudentController.update_category', 'PUT /stu/:id_stu/cat': 'StudentController.update_category',
'PUT /stu/:id_stu/activeScene/:id_scene': 'StudentController.updateActiveScene', 'PUT /stu/:id_stu/activeScene/:id_scene': 'StudentController.updateActiveScene',
'POST /stu/login': 'StudentController.login', 'POST /stu/login': 'StudentController.login',
'POST /stu': 'StudentController.create', 'POST /stu': 'StudentController.create',
'POST /stu/upload': 'StudentController.upload', 'POST /stu/upload': 'StudentController.upload',
...@@ -125,9 +119,13 @@ module.exports.routes = { ...@@ -125,9 +119,13 @@ module.exports.routes = {
'GET /sup/all': 'SupervisorController.list', 'GET /sup/all': 'SupervisorController.list',
'GET /sup/:id/students': 'SupervisorController.students', 'GET /sup/:id/students': 'SupervisorController.students',
'GET /sup/:id/supervisors': 'SupervisorController.supervisors',
'POST /sup/:id_sup/off/:id_off': 'SupervisorController.link_supervisor',
'DELETE /sup/:id_sup/off/:id_off': 'SupervisorController.unlink_supervisor',
'GET /sup/:id/pictos': 'SupervisorController.pictos', 'GET /sup/:id/pictos': 'SupervisorController.pictos',
'GET /sup/email/:email': 'SupervisorController.getByEmail', 'GET /sup/email/:email': 'SupervisorController.getByEmail',
'GET /sup/off/email/:email': 'SupervisorController.getFromOfficeByEmail',
'GET /sup/changepass/:email': 'SupervisorController.request_change_password', 'GET /sup/changepass/:email': 'SupervisorController.request_change_password',
'GET /sup/arasaac_license/:id': 'SupervisorController.accept_arasaac', 'GET /sup/arasaac_license/:id': 'SupervisorController.accept_arasaac',
'PUT /sup/changepass': 'SupervisorController.change_password', 'PUT /sup/changepass': 'SupervisorController.change_password',
......
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