Various fixes

This commit is contained in:
Reynaldo Reyes
2016-05-20 23:00:34 -04:00
parent b220f21065
commit 48e8b73111
55 changed files with 714 additions and 690 deletions

View File

@@ -15,23 +15,35 @@
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
$stateProvider
.state('index', {
abstract: true,
views: {
'sidebar': {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
'navbar': {
templateUrl: 'partials/sidebar/navbar.html',
controller: 'NavbarCtrl',
controllerAs: 'vm'
},
}
})
.state('login', {
url: '/login',
views: {
content: {
templateUrl: 'partials/login/login.html',
controller: 'loginCtrl',
controllerAs: 'vm'
templateUrl: 'partials/login/login.html',
controller: 'loginCtrl',
controllerAs: 'vm'
}
}
}
})
})
})
.run(function ($rootScope) {
$rootScope.domainUrl = 'Localhost:3000';
$rootScope.professorId = '56f5fd3a20047f3c15b05f0e';
});
})();

View File

@@ -55,6 +55,7 @@
<!-- ====================================================-->
<script src="app.js"></script>
<script src="partials/sidebar/sidebar.controllers.js"></script>
<script src="partials/sidebar/navbar.controllers.js"></script>
<script src="partials/course/course.module.js"></script>
<script src="partials/course/course_create.controller.js"></script>
@@ -64,6 +65,7 @@
<script src="partials/login/login.module.js"></script>
<script src="partials/login/login.controllers.js"></script>
<script src="partials/login/login.services.js"></script>
<script src="partials/login/authentication.service.js"></script>
<script src="partials/professor/professor.module.js"></script>
<script src="partials/professor/professor_create.controller.js"></script>

View File

@@ -15,43 +15,28 @@
getRoutes.$inject = ['$stateProvider', '$urlRouterProvider'];
function getRoutes($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/CourseList');
$stateProvider
.state('CourseList', {
parent: 'index',
url: '/CourseList',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/course/course_list.html',
controller: 'CourseListCtrl',
controllerAs: "vm"
}
}
})
.state('CourseCreate', {
parent:'index',
url: '/CourseCreate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/course/course_create.html',
controller: 'CourseCreateCtrl',
controllerAs: "vm"
}
}
})
};
})();

View File

@@ -7,6 +7,13 @@
courses.$inject = ['$resource','$rootScope'];
function courses($resource, $rootScope){
return $resource('http://'+$rootScope.domainUrl+'/professors/:id/courses', null);
return $resource('http://'+$rootScope.domainUrl+'/professors/:id/courses', {}, {
get: {
method: 'GET',
headers: {
Authorization: 'Bearer '+ authentication.getToken()
}
}
});
};
})();
})();

View File

@@ -6,11 +6,12 @@
.controller('CourseCreateCtrl', CourseCreateCtrl)
CourseCreateCtrl.$inject =
['$scope', '$rootScope', '$modal', '$state', 'professors'];
function CourseCreateCtrl($scope, $rootScope, $modal, $state, professors) {
['$scope', '$modal', '$state', 'professors', 'authentication'];
function CourseCreateCtrl($scope, $modal, $state, professors, authentication) {
var vm = this;
$scope.mensaje = "";
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
professors.get({ id: professorid },
function (successResult){

View File

@@ -6,10 +6,11 @@
.controller('CourseListCtrl',CourseListCtrl)
CourseListCtrl.$inject =
['$scope', '$rootScope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse'];
function CourseListCtrl($scope, $rootScope, $state, professors, $modal, profesorSeleccionado, selectedCourse) {
['$scope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse', 'authentication'];
function CourseListCtrl($scope, $state, professors, $modal, profesorSeleccionado, selectedCourse, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
professors.get({ id: professorid },
function (successResult){

View File

@@ -8,28 +8,15 @@
<tr>
<th width="10%">
Código
<span ng-show="sortType == 'code' &&
!sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'code' &&
sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Nombre
<span ng-show="sortType == 'name' &&
!sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'name' &&
sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="10%">
Creditos
<span ng-show="sortType == 'credits' &&
!sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'credits' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="40%" style="text-align: center">
Descripción
Descripción
</th>
<th width="10%" style="text-align: center">
Secciones
@@ -47,7 +34,7 @@
<td style="vertical-align:middle">{{ course.description }}</td>
<td style="text-align: center">
<span
title="Click aqui para ver Secciones"
title="Haga click para listar las secciones de esta materia"
class="glyphicon glyphicon-list"
aria-hidden="true"
ng-click="vm.listarSecciones($index)"
@@ -55,7 +42,7 @@
</td>
<td style="text-align: center">
<span
title="Click aqui para Eliminar la Materia"
title="Haga click para eliminar esta materia"
class="glyphicon glyphicon-remove"
aria-hidden="true"
ng-click="vm.eliminarMateriaModal($index)"

View File

@@ -0,0 +1,65 @@
(function(){
'use strict';
angular
.module('app.login')
.service('authentication', authentication);
authentication.$inject = ['$http', '$window'];
function authentication ($http, $window) {
var saveToken = function (token) {
$window.localStorage['mean-token'] = token;
};
var getToken = function () {
return $window.localStorage['mean-token'];
};
var logout = function() {
$window.localStorage.removeItem('mean-token');
};
var isLoggedIn = function() {
var token = getToken();
var payload;
if(token){
payload = token.split('.')[1];
payload = $window.atob(payload);
payload = JSON.parse(payload);
return payload.exp > Date.now() / 1000;
} else {
return false;
}
};
var currentUser = function() {
if(isLoggedIn()){
var token = getToken();
var payload = token.split('.')[1];
payload = $window.atob(payload);
payload = JSON.parse(payload);
return {
_id: payload._id,
role: payload.role
};
}
};
var login = function(user) {
return $http.post('http://'+$rootScope.domainUrl+'/login', user).success(function(data) {
saveToken(data.token);
});
};
return {
saveToken : saveToken,
getToken : getToken,
logout : logout,
isLoggedIn : isLoggedIn,
currentUser : currentUser
};
}
})();

View File

@@ -5,69 +5,49 @@
.module('app.login')
.controller('loginCtrl', loginCtrl)
loginCtrl.$inject = ['$rootScope', '$scope', '$state'];
function loginCtrl($rootScope, $scope, $state){
loginCtrl.$inject = ['$scope', '$state', 'login', 'authentication', '$modal'];
function loginCtrl($scope, $state, login, authentication, $modal){
var vm = this;
vm.user;
vm.credentials = {};
vm.submit = function() {
if (vm.data_input_form.$valid){
vm.pkg = {
"Nickname": vm.user.nickname,
"Password": vm.user.password
var professor = {
"id": vm.user.nickname,
"password": vm.user.password
};
/*$rootScope.mensaje = "";
$rootScope.bcancel = false;
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'LoginModal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
});
Login.save(vm.pkg,
function(data){
if(data.Data._value != null){
$rootScope.actOk = true;
$rootScope.urlLo = 'listarProfesor';
$rootScope.bcancel = false;
}else{
$rootScope.bcancel = true;
$rootScope.mensaje = data.Data._error;
}
},
function(data){
verificar = data.Data;
if(verificar){
alert("no existe el usuario");
}
})
GetRol.get({id:vm.user.Nickname},
login.save(professor,
function(data){
$rootScope.role = data.Data;
},
function(){
authentication.saveToken(data.token);
var permission = authentication.currentUser();
if(permission.role=='admin'){
$state.go('ProfessorList');
};
if(permission.role=='professor'){
$state.go('CourseList');
};
});*/
$state.go('CourseList');
},
function(data){
vm.message = 'Usuario/Clave incorrecto. Por favor intente de nuevo.'
vm.botonOk = true;
$scope.modalInstance = $modal.open({
templateUrl:
'/partials/login/modal/login_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
}
}
});
});
}
};
/*$rootScope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$rootScope.opened = true;
};*/
$scope.ok = function (urlLo) {
$location.url(urlLo);
$scope.ok = function () {
$state.reload();
$scope.modalInstance.dismiss('cancel');
};

View File

@@ -21,7 +21,7 @@
</div>
<div class="col-md-4 column">
<label for="password">Contraseña</label>
<input type="password" class="form-control" id="password" name="password" ng-model="vm.user.password" maxlength="8" required/>
<input type="password" class="form-control" id="password" name="password" ng-model="vm.user.password" required/>
<div ng-show=false> {{ vm.password = vm.user.Password }}</div>
<div class="error" ng-show="vm.submitted && vm.data_input_form.password.$invalid">
<small class="error" ng-show="vm.data_input_form.password.$error.required">

View File

@@ -3,47 +3,12 @@
angular
.module('app.login')
.factory('Login', Login)
.factory('GetRol', GetRol)
.factory('hash', hash)
.value('algoritmo','SHA-1')
.factory('login', login)
.value('user',{})
.value('id',{})
Login.$inject = ['$resource','$rootScope'];
function Login($resource, $rootScope){
return $resource('http://'+$rootScope.domainUrl+'/api/VerifyUser');
login.$inject = ['$resource','$rootScope'];
function login($resource, $rootScope){
return $resource('http://'+$rootScope.domainUrl+'/login');
};
GetRol.$inject = ['$resource','$rootScope'];
function GetRol($resource, $rootScope){
return $resource('http://'+$rootScope.domainUrl+'/api/User/:id');
};
hash.$inject = ['algoritmo'];
function hash(algoritmo){
var hashFunction;
if (algoritmo==="MD5") {
hashFunction=CryptoJS.MD5;
} else if (algoritmo==="SHA-1") {
hashFunction=CryptoJS.SHA1;
} else if (algoritmo==="SHA-2-256") {
hashFunction=CryptoJS.SHA256;
} else if (algoritmo==="SHA-2-512") {
hashFunction=CryptoJS.SHA512;
} else {
throw Error("El tipo de algoritmo no es válido:"+algoritmo);
}
var hash=function(message) {
var objHashResult=hashFunction(message);
var strHashResult=objHashResult.toString(CryptoJS.enc.Base64);
return strHashResult;
}
return hash;
};
})();
})();

View File

@@ -0,0 +1,10 @@
<div class="modal-header">
<h3 class="modal-title">Error</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ vm.message }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="vm.botonOk" type="button"
ng-click="ok()">Aceptar</button>
</div>

View File

@@ -2,9 +2,9 @@
<h3 class="modal-title">Crear Profesor</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
ng-click="ok(urlLo)">OK</button>
<button class="btn btn-primary" ng-show="vm.botonOk" type="button"
ng-click="ok()">OK</button>
</div>

View File

@@ -2,13 +2,19 @@
<h3 class="modal-title">Eliminar Profesor</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="acceptButton" type="button"
ng-click="ok(urlLo)">Aceptar</button>
<button class="btn btn-primary" ng-show="botonOK" type="button"
<button class="btn btn-primary"
ng-show="vm.acceptButton"
type="button"
ng-click="ok()">Aceptar</button>
<button class="btn btn-primary"
ng-show="vm.botonOK"
type="button"
ng-click="vm.eliminarProfesor(index)">OK</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancel</button>
</div>

View File

@@ -2,11 +2,15 @@
<h3 class="modal-title">Modificar Profesor</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
ng-click="ok(urlLo)">OK</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="ok()">OK</button>
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancel</button>
</div>

View File

@@ -18,17 +18,10 @@
$stateProvider
.state('ProfessorList', {
parent: 'index',
url: '/ProfessorList',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/professor/professor_list.html',
controller: 'ProfessorListCtrl',
controllerAs: 'vm'
@@ -37,16 +30,10 @@
})
.state('ProfessorCreate', {
parent: 'index',
url: '/ProfessorCreate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/professor/professor_create.html',
controller: 'ProfessorCreateCtrl',
controllerAs: 'vm'
@@ -55,16 +42,10 @@
})
.state('ProfessorUpdate', {
parent: 'index',
url: '/ProfessorUpdate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/professor/professor_update.html',
controller: 'ProfessorUpdateCtrl',
controllerAs: 'vm'

View File

@@ -10,11 +10,34 @@
.value('profesorSeleccionado',{})
.value('data',{});
professors.$inject = ['$resource','$rootScope'];
function professors($resource, $rootScope){
return $resource('http://'+$rootScope.domainUrl+'/professors/:id', null,
{
'update': {method:'PUT'}
professors.$inject = ['$resource','$rootScope','authentication'];
function professors($resource, $rootScope, authentication){
return $resource('http://'+$rootScope.domainUrl+'/professors/:id', {}, {
get: {
method: 'GET',
headers: {
Authorization: 'Bearer '+ authentication.getToken()
}
},
update: {
method: 'PUT',
headers: {
Authorization: 'Bearer '+ authentication.getToken()
}
},
delete: {
method: 'DELETE',
headers: {
Authorization: 'Bearer '+ authentication.getToken()
}
},
query: {
method: 'GET',
isArray:true,
headers: {
Authorization: 'Bearer '+ authentication.getToken()
}
}
});
};
})();

View File

@@ -6,11 +6,12 @@
.controller('ProfessorCreateCtrl', ProfessorCreateCtrl)
ProfessorCreateCtrl.$inject =
['$scope','$rootScope', '$state', 'professors', '$modal'];
function ProfessorCreateCtrl($scope, $rootScope, $state, professors, $modal){
['$scope', '$state', 'professors', '$modal','authentication'];
function ProfessorCreateCtrl($scope, $state, professors, $modal, authentication){
var vm = this;
$rootScope.mensaje = "";
vm.botonOk = false;
vm.mensaje = "";
vm.submit = function() {
if (vm.data_input_form.$valid){
@@ -24,39 +25,32 @@
"password": vm.profesor.Password
};
$rootScope.botonOk = false;
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/professor/modal/create_professor_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
});
professors.save(professor,
function(){
$rootScope.botonOk = true;
$rootScope.mensaje =
function(data){
authentication.saveToken(data.token);
vm.botonOk = true;
vm.mensaje =
"Profesor " + vm.profesor.Apellido + ", " + vm.profesor.Nombre + " agregado";
},
function(){
$rootScope.botonOk = true;
$rootScope.urlLo = 'listarProfesor';
$rootScope.mensaje =
vm.botonOk = true;
vm.mensaje =
"Error al agregar al profesor " + vm.profesor.Apellido + ", " + vm.profesor.Nombre;
});
}else{
vm.submitted = true;
}
}
$scope.ok = function (urlLo) {
$scope.ok = function () {
$state.go('ProfessorList');
$scope.modalInstance.dismiss('cancel');
};

View File

@@ -78,7 +78,7 @@
</div>
<div class="col-md-4 column">
<label for="password">Contraseña *</label>
<input type="password" class="form-control" ng-model="vm.profesor.Password" maxlength="8" required/>
<input type="password" class="form-control" ng-model="vm.profesor.Password" maxlength="20" required/>
<div class="error" ng-show="vm.submitted && vm.data_input_form.password.$invalid">
<small class="error" ng-show="vm.data_input_form.password.$error.required">
La Contraseña del Profesor es obligatorio.

View File

@@ -6,14 +6,11 @@
.controller('ProfessorListCtrl', ProfessorListCtrl)
ProfessorListCtrl.$inject =
[ '$scope', '$rootScope', '$state', 'professors', '$modal', 'profesorSeleccionado' ];
function ProfessorListCtrl( $scope, $rootScope, $state, professors, $modal, profesorSeleccionado ){
[ '$scope', '$state', 'professors', '$modal', 'profesorSeleccionado' ];
function ProfessorListCtrl( $scope, $state, professors, $modal, profesorSeleccionado ){
var vm = this;
vm.lista = true;
$rootScope.actOk = false;
$rootScope.loading = true;
$rootScope.table = false;
var profesorArray = [];
professors.query(
@@ -28,8 +25,6 @@
Correo: value.email
});
});
$rootScope.loading = false;
$rootScope.table = true;
vm.listaProfesor = profesorArray;
},
@@ -38,50 +33,42 @@
});
vm.eliminarProfesorModal = function (index) {
$rootScope.index = index;
$rootScope.botonOK = true;
$rootScope.botonCancelar = true;
$rootScope.acceptButton = false;
$scope.index = index;
vm.botonOK = true;
vm.botonCancelar = true;
vm.acceptButton = false;
$rootScope.rsplice = false;
$rootScope.mensaje = "¿Seguro que desea eliminar el Profesor?";
vm.rsplice = false;
vm.mensaje = "¿Seguro que desea eliminar el Profesor?";
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/professor/modal/list_professor_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return "";
}
}
size: 'sm'
});
};
vm.eliminarProfesor = function (index) {
$rootScope.botonOK = false;
$rootScope.acceptButton = true;
$rootScope.botonCancelar = false;
vm.botonOK = false;
vm.acceptButton = true;
vm.botonCancelar = false;
professors.delete({id: vm.profesor[index]._id},
function () {
$rootScope.rsplice = true;
$rootScope.mensaje =
vm.rsplice = true;
vm.mensaje =
"Profesor " + vm.profesor[index].name + " eliminado";
},
function () {
$rootScope.listarProfesorsLoading = false;
$rootScope.mensaje =
vm.mensaje =
"Error eliminando al Profesor " + vm.profesor[index].name;
});
};
vm.removeProfesorSplice = function(index, rsplice) {
if(rsplice){
if(vm.rsplice){
vm.listaProfesor.splice(index, 1);
$rootScope.rsplice = false;
vm.rsplice = false;
}
};
@@ -95,13 +82,7 @@
$state.go('ProfessorUpdate');
};
$rootScope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$rootScope.opened = true;
};
$scope.ok = function (urlLo) {
$scope.ok = function () {
$state.reload();
$scope.modalInstance.dismiss('cancel');
};
@@ -109,7 +90,5 @@
$scope.cancel = function () {
$scope.modalInstance.dismiss('cancel');
};
return vm;
};
})();

View File

@@ -7,18 +7,12 @@
<tr>
<th width="20%">
Cedula
<span ng-show="sortType == 'Cedula' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'Cedula' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Nombre
<span ng-show="sortType == 'Nombre' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'Nombre' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Apellido
<span ng-show="sortType == 'Apellido' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'Apellido' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%" style="text-align: center">
Modificar
@@ -34,10 +28,18 @@
<td style="vertical-align:middle">{{ profesor.Nombre }}</td>
<td style="vertical-align:middle">{{ profesor.Apellido }}</td>
<td style="text-align: center">
<span title="Click aqui para Modificar un Profesor" class="glyphicon glyphicon-edit" aria-hidden="true" ng-click="vm.modificarProfesor($index)" style="cursor:pointer"></span>
<span title="Haga click para Modificar un Profesor"
class="glyphicon glyphicon-edit"
aria-hidden="true"
ng-click="vm.modificarProfesor($index)"
style="cursor:pointer"></span>
</td>
<td style="text-align: center">
<span title="Click aqui para Eliminar un Profesor" class="glyphicon glyphicon-remove" aria-hidden="true" ng-click="vm.eliminarProfesorModal($index)" style="cursor:pointer"></span>
<span title="Haga click para Eliminar un Profesor"
class="glyphicon glyphicon-remove"
aria-hidden="true"
ng-click="vm.eliminarProfesorModal($index)"
style="cursor:pointer"></span>
</td>
</tr>
</tbody>

View File

@@ -6,13 +6,14 @@
.controller('ProfessorUpdateCtrl', ProfessorUpdateCtrl)
ProfessorUpdateCtrl.$inject =
['$scope','$rootScope', '$state', 'professors', '$modal', 'profesorSeleccionado' ];
function ProfessorUpdateCtrl ( $scope, $rootScope, $state, professors, $modal, profesorSeleccionado ){
['$scope', '$state', 'professors', '$modal', 'profesorSeleccionado' ];
function ProfessorUpdateCtrl ( $scope, $state, professors, $modal, profesorSeleccionado ){
var vm = this;
vm.botonOk = false;
vm.mensaje = "";
vm.profesor = profesorSeleccionado;
$rootScope.mensaje = "";
$rootScope.actOk = false;
vm.submit = function() {
@@ -26,35 +27,28 @@
"password": vm.profesor.Password
};
$rootScope.botonOk = false;
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/professor/modal/update_professor_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
});
professors.update({ id: vm.profesor._id}, professor,
function(){
$rootScope.botonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje =
vm.botonOk = true;
vm.botonCancelar = false;
vm.mensaje =
"Profesor " + vm.profesor.Apellido + ", " + vm.profesor.Nombre + " actualizado";
},
function(){
$rootScope.botonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje =
vm.botonOk = true;
vm.botonCancelar = false;
vm.mensaje =
"Error al modificar al profesor " + vm.profesor.Apellido + ", " + vm.profesor.Nombre;
});
}
$scope.ok = function (urlLo) {
$scope.ok = function () {
$state.go('ProfessorList');
$scope.modalInstance.dismiss('cancel');
};

View File

@@ -6,10 +6,11 @@
.controller('CourseAssistCtrl', CourseAssistCtrl)
CourseAssistCtrl.$inject =
['$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedCourse'];
function CourseAssistCtrl($scope, $rootScope, $state, professors, $modal, selectedCourse) {
['$scope', '$state', 'professors', '$modal', 'selectedCourse', 'authentication'];
function CourseAssistCtrl($scope, $state, professors, $modal, selectedCourse, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.course = null;
vm.lectures = 0;
vm.percentage = 0;

View File

@@ -6,10 +6,11 @@
.controller('CourseReportCtrl', CourseReportCtrl)
CourseReportCtrl.$inject =
['$scope', '$rootScope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse'];
function CourseReportCtrl($scope, $rootScope, $state, professors, $modal, profesorSeleccionado, selectedCourse) {
['$scope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse', 'authentication'];
function CourseReportCtrl($scope, $state, professors, $modal, profesorSeleccionado, selectedCourse, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
professors.get({ id: professorid },
function (successResult){

View File

@@ -33,14 +33,14 @@
<td style="vertical-align:middle">{{ course.credits }}</td>
<td style="vertical-align:middle">{{ course.description }}</td>
<td style="text-align: center">
<span
<span title="Haga click para ver los reportes de esta materia"
class="glyphicon glyphicon-list-alt"
aria-hidden="true"
ng-click="vm.courseReports($index)"
style="cursor:pointer"></span>
</td>
<td style="text-align: center">
<span
<span title="Haga click para ver el listado de las secciones de esta materia"
class="glyphicon glyphicon-list"
aria-hidden="true"
ng-click="vm.listSections($index)"

View File

@@ -18,16 +18,10 @@
$stateProvider
.state('courseReport', {
parent: 'index',
url: '/reportesPorMateria',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/course_report.html',
controller: 'CourseReportCtrl',
controllerAs: 'vm'
@@ -35,16 +29,10 @@
}
})
.state('sectionReport', {
parent: 'index',
url: '/reportesPorSeccion',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/section_report.html',
controller: 'SectionReportCtrl',
controllerAs: 'vm'
@@ -52,16 +40,10 @@
}
})
.state('studentReport', {
parent: 'index',
url: '/reportesPorEstudiante',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/student_report.html',
controller: 'StudentReportCtrl',
controllerAs: 'vm'
@@ -69,16 +51,10 @@
}
})
.state('studentAssist', {
parent: 'index',
url: '/asistenciaPorEstudiante',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/student_assist.html',
controller: 'StudentAssistCtrl',
controllerAs: 'vm'
@@ -86,16 +62,10 @@
}
})
.state('sectionAssist', {
parent: 'index',
url: '/asistenciaPorSeccion',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/section_assist.html',
controller: 'SectionAssistCtrl',
controllerAs: 'vm'
@@ -103,16 +73,10 @@
}
})
.state('courseAssist', {
parent: 'index',
url: '/asistenciaPorMateria',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/report/course_assist.html',
controller: 'CourseAssistCtrl',
controllerAs: 'vm'

View File

@@ -6,10 +6,11 @@
.controller('SectionAssistCtrl', SectionAssistCtrl)
SectionAssistCtrl.$inject =
['$scope', '$rootScope','$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent'];
function SectionAssistCtrl($scope, $rootScope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent) {
['$scope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent', 'authentication'];
function SectionAssistCtrl($scope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.section = [];
vm.lectures = 0;
vm.percentage = 0;

View File

@@ -6,9 +6,17 @@
<div> Estadisticas </div>
<div> Porcentaje de Asistencia: {{vm.percentage}} % </div>
<div> Total de Dias de Clase: {{vm.lectures}} </div>
<br><br/>
<br>
</div>
<button class = "btn-warning btn"
type = "button"
style = "margin: 10px"
ng-click = "vm.back()">
Regresar
</button>
<br><br/>
<div ng-show="vm.flag">
<h4 style="color: red"> Estudiantes con menos de 75% de Asistencia </h4>
<table class="table table-bordered table-striped">
@@ -57,11 +65,4 @@
</tr>
</tbody>
</table>
<button class = "btn-warning btn"
type = "button"
style = "margin: 10px"
ng-click = "vm.back()">
Regresar
</button>
</div>

View File

@@ -6,10 +6,11 @@
.controller('SectionReportCtrl', SectionReportCtrl)
SectionReportCtrl.$inject =
['$scope', '$rootScope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse', 'selectedSection'];
function SectionReportCtrl($scope, $rootScope, $state, professors, $modal, profesorSeleccionado, selectedCourse, selectedSection) {
['$scope', '$state', 'professors', '$modal', 'profesorSeleccionado', 'selectedCourse', 'selectedSection', 'authentication'];
function SectionReportCtrl($scope, $state, professors, $modal, profesorSeleccionado, selectedCourse, selectedSection, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.section = [];
vm.professor = null;

View File

@@ -39,13 +39,15 @@
<td style="vertical-align:middle">{{ section.code }}</td>
<td style="vertical-align:middle">{{ section.semester }}</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-list-alt"
<span title="Haga click para ver los reportes de esta sección"
class="glyphicon glyphicon-list-alt"
aria-hidden="true"
ng-click="vm.sectionReport($index)"
style="cursor:pointer"></span>
</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-list"
<span title="Haga click para ver el listado de estudiantes de esta sección"
class="glyphicon glyphicon-list"
aria-hidden="true"
ng-click="vm.listStudents($index)"
style="cursor:pointer"></span>

View File

@@ -6,10 +6,11 @@
.controller('StudentAssistCtrl', StudentAssistCtrl)
StudentAssistCtrl.$inject =
['$scope', '$rootScope','$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent'];
function StudentAssistCtrl($scope, $rootScope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent) {
['$scope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent', 'authentication'];
function StudentAssistCtrl($scope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.section = [];
vm.lectures = 0;
vm.percentage = 0;

View File

@@ -6,10 +6,11 @@
.controller('StudentReportCtrl', StudentReportCtrl)
StudentReportCtrl.$inject =
['$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent'];
function StudentReportCtrl($scope, $rootScope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent) {
['$scope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'selectedStudent', 'authentication'];
function StudentReportCtrl($scope, $state, professors, $modal, selectedCourse, selectedSection, selectedStudent, authentication) {
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.section = [];
vm.professor = null;

View File

@@ -32,7 +32,8 @@
<td style="vertical-align:middle">{{ student.name }}</td>
<td style="vertical-align:middle">{{ student.lastname }}</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-list-alt"
<span title="Haga click para ver la asistencia de este estudiante"
class="glyphicon glyphicon-list-alt"
aria-hidden="true"
ng-click="vm.studentReports($index)"
style="cursor:pointer"></span>

View File

@@ -2,11 +2,15 @@
<h3 class="modal-title">Crear Sección</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
ng-click="ok(urlLo)">Aceptar</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="ok()">Aceptar</button>
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
</div>

View File

@@ -2,13 +2,19 @@
<h3 class="modal-title">Eliminar Sección</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="vm.eliminarMatricula(index)">OK</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
<button class="btn btn-primary" ng-show="otroBotonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.otroBotonOk"
type="button"
ng-click="ok(urlLo)">Aceptar</button>
</div>

View File

@@ -2,13 +2,19 @@
<h3 class="modal-title">Liberar BT</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="vm.freeBTAddress(index)">OK</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
<button class="btn btn-primary" ng-show="otroBotonOk" type="button"
ng-click="ok(urlLo)">Aceptar</button>
<button class="btn btn-primary"
ng-show="vm.otroBotonOk"
type="button"
ng-click="ok()">Aceptar</button>
</div>

View File

@@ -2,13 +2,19 @@
<h3 class="modal-title">Retirar Estudiante</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="vm.retirarEstudiante(index)">OK</button>
<button class="btn btn-primary" ng-show="otroBotonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.otroBotonOk"
type="button"
ng-click="ok()">Aceptar</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
</div>

View File

@@ -17,54 +17,33 @@
$urlRouterProvider.otherwise('/SectionList');
$stateProvider
.state('SectionList', {
parent: 'index',
url: '/SectionList',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/section/section_list.html',
controller: 'SectionListCtrl',
controllerAs: 'vm'
}
}
})
.state('SectionCreate', {
parent: 'index',
url: '/SectionCreate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/section/section_create.html',
controller: 'SectionCreateCtrl',
controllerAs: 'vm'
}
}
})
.state('SectionUpdate', {
.state('SectionUpdate', {
parent: 'index',
url: '/SectionUpdate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/section/section_update.html',
controller: 'SectionUpdateCtrl',
controllerAs: 'vm'

View File

@@ -6,16 +6,17 @@
.controller('SectionCreateCtrl', SectionCreateCtrl)
SectionCreateCtrl.$inject =
['$scope','$rootScope', '$state', 'professors', '$modal', 'selectedCourse'];
function SectionCreateCtrl($scope, $rootScope, $state, professors, $modal, selectedCourse){
var professorid = $rootScope.professorId;
['$scope', '$state', 'professors', '$modal', 'selectedCourse','authentication'];
function SectionCreateCtrl($scope, $state, professors, $modal, selectedCourse, authentication){
var user = authentication.currentUser();
var professorid = user._id;
var vm = this;
vm.course = {};
vm.itExists = false;
vm.selectedCourse = selectedCourse;
vm.submitted = false;
vm.semester, vm.section, vm.materias;
$rootScope.mensaje = "";
vm.mensaje = "";
vm.students = [];
professors.get({ id: professorid },
@@ -47,15 +48,9 @@
};
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/section/modal/create_section_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
size: 'sm'
});
@@ -72,19 +67,17 @@
vm.professor.courses[vm.index].sections.push(vm.package);
professors.update({ id: professorid }, vm.professor,
function(){
$rootScope.botonOk = true;
$rootScope.mensaje = "Sección " + vm.name + " creada";
vm.botonOk = true;
vm.mensaje = "Sección " + vm.name + " creada";
},
function(){
$rootScope.botonOk = true;
$rootScope.mensaje = "Error creando la seccion " + vm.name;
vm.botonOk = true;
vm.mensaje = "Error creando la seccion " + vm.name;
});
}else{
$rootScope.botonOk = true;
$rootScope.mensaje = "Sección Duplicada, " + vm.name + " existe en el semestre "+ vm.semester + ".";
vm.botonOk = true;
vm.mensaje = "Sección Duplicada, " + vm.name + " existe en el semestre "+ vm.semester + ".";
}
}else{
vm.submitted = true;
}
};

View File

@@ -5,10 +5,11 @@
.module('app.section')
.controller('SectionListCtrl', SectionListCtrl)
SectionListCtrl.$inject = [ '$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection'];
function SectionListCtrl ( $scope, $rootScope, $state, professors, $modal, selectedCourse, selectedSection ){
SectionListCtrl.$inject = [ '$scope', '$state', 'professors', '$modal', 'selectedCourse', 'selectedSection', 'authentication'];
function SectionListCtrl ( $scope, $state, professors, $modal, selectedCourse, selectedSection, authentication ){
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.section = [];
vm.professor = null;
@@ -27,60 +28,45 @@
function (){
console.log("Error al obtener los datos.");
});
/**************************Eliminar Matricula**************************/
/* En este proceso, primero se llama a un Modal el cual se cerciora que
el usuario se asegure de eliminar la matricula escogida, el usuario al
confirmar su decision llama automaticamente a la funcion que hara la
llamada a servicio que borrara la matricula de la base de datos.
*/
});
vm.createSection = function () {
$state.go('SectionCreate');
};
vm.eliminarMatriculaModal = function (index) {
$rootScope.index = index;
$rootScope.botonOk = true;
$rootScope.otroBotonOk = false;
$rootScope.botonCancelar = true;
$rootScope.rsplice = false;
$scope.index = index;
vm.botonOk = true;
vm.otroBotonOk = false;
vm.botonCancelar = true;
vm.rsplice = false;
var name = vm.section[index].name;
$rootScope.mensaje = "¿Seguro que desea eliminar la sección "+name+"?";
vm.mensaje = "¿Seguro que desea eliminar la sección "+name+"?";
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: '/partials/section/modal/delete_section_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return "";
}
}
size: 'sm'
});
};
vm.eliminarMatricula = function (index) {
$rootScope.botonOk = false;
$rootScope.otroBotonOk = true;
$rootScope.botonCancelar = false;
vm.botonOk = false;
vm.otroBotonOk = true;
vm.botonCancelar = false;
var name = vm.section[index].name;
vm.professor.courses[vm.index].sections.splice(index, 1);
professors.update({ id: professorid }, vm.professor,
function () {
$rootScope.rsplice = true;
$rootScope.mensaje = "Sección " + name + " eliminada";
vm.rsplice = true;
vm.mensaje = "Sección " + name + " eliminada";
},
function () {
$rootScope.mensaje = "Error eliminando la sección " + name;
vm.mensaje = "Error eliminando la sección " + name;
});
};
/*************************Fin de Eliminar Matricula*******************/
vm.modificarMatricula = function (index) {
selectedSection._id = vm.section[index]._id;
selectedCourse.index = vm.index;

View File

@@ -12,23 +12,15 @@
<tr>
<th width="20%">
Sección
<span ng-show="sortType == 'name' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'name' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Nombre de la Materia
<span ng-show="sortType == 'course' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'course' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Codigo de la Materia
<span ng-show="sortType == 'code' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'code' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%">
Semestre
<span ng-show="sortType == 'semester' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'semester' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="10%" style="text-align: center">
Matricula
@@ -45,14 +37,16 @@
<td style="vertical-align:middle">{{ section.code }}</td>
<td style="vertical-align:middle">{{ section.semester }}</td>
<td style="text-align: center">
<span title="Click aqui para Modificar la Matricula"
class="glyphicon glyphicon-edit" aria-hidden="true"
<span title="Haga click para modificar la matricula"
class="glyphicon glyphicon-edit"
aria-hidden="true"
ng-click="vm.modificarMatricula($index)"
style="cursor:pointer"></span>
</td>
<td style="text-align: center">
<span title="Click aqui para Eliminar la Matricula"
class="glyphicon glyphicon-remove" aria-hidden="true"
<span title="Haga click para eliminar la matricula"
class="glyphicon glyphicon-remove"
aria-hidden="true"
ng-click="vm.eliminarMatriculaModal($index)"
style="cursor:pointer"></span>
</td>

View File

@@ -5,9 +5,10 @@
.module('app.section')
.controller('SectionUpdateCtrl', SectionUpdateCtrl)
SectionUpdateCtrl.$inject = ['$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse','data'];
function SectionUpdateCtrl($scope, $rootScope, $state, professors, $modal, selectedSection, selectedCourse, data){
var professorid = $rootScope.professorId;
SectionUpdateCtrl.$inject = ['$scope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse','data', 'authentication'];
function SectionUpdateCtrl($scope, $state, professors, $modal, selectedSection, selectedCourse, data, authentication){
var user = authentication.currentUser();
var professorid = user._id;
var vm = this;
vm.section = {};
vm.students = [];
@@ -39,22 +40,15 @@
};
vm.freeBTAddressModal = function (index) {
$rootScope.index = index;
$rootScope.botonOk = true;
$rootScope.otroBotonOk = false;
$rootScope.botonCancelar = true;
$rootScope.eliminarLoading = false;
$rootScope.mensaje = "¿Desea liberar la dirección de BT del estudiante "+ vm.students[index].lastname +", "+ vm.students[index].name + "?";
$scope.index = index;
vm.botonOk = true;
vm.otroBotonOk = false;
vm.botonCancelar = true;
vm.mensaje = "¿Desea liberar la dirección de BT del estudiante "+ vm.students[index].lastname +", "+ vm.students[index].name + "?";
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/section/modal/student_bt_removal_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return "";
}
}
size: 'sm'
});
};
@@ -66,36 +60,30 @@
professors.update({ id: professorid }, vm.professor,
function(){
$rootScope.botonOk = false;
$rootScope.otroBotonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje = "Dirección BT de " + vm.student.lastname + ", " + vm.student.name + " fue liberada";
vm.botonOk = false;
vm.otroBotonOk = true;
vm.botonCancelar = false;
vm.mensaje = "Dirección BT de " + vm.student.lastname + ", " + vm.student.name + " fue liberada";
},
function(){
$rootScope.botonOk = false;
$rootScope.otroBotonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje = "Error al liberar dirección de BT del estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
vm.botonOk = false;
vm.otroBotonOk = true;
vm.botonCancelar = false;
vm.mensaje = "Error al liberar dirección de BT del estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
});
};
vm.retirarEstudianteModal = function (index) {
$rootScope.index = index;
$rootScope.botonOk = true;
$rootScope.otroBotonOk = false;
$rootScope.botonCancelar = true;
$rootScope.eliminarLoading = false;
$rootScope.mensaje = "¿Desea retirar al estudiante "+ vm.students[index].lastname +", "+ vm.students[index].name + "?";
$scope.index = index;
vm.botonOk = true;
vm.otroBotonOk = false;
vm.botonCancelar = true;
vm.eliminarLoading = false;
vm.mensaje = "¿Desea retirar al estudiante "+ vm.students[index].lastname +", "+ vm.students[index].name + "?";
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/section/modal/update_section_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return "";
}
}
size: 'sm'
});
};
@@ -104,16 +92,16 @@
professors.update({ id: professorid }, vm.professor,
function (){
$rootScope.botonOk = false;
$rootScope.otroBotonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje = "Sección "+ vm.section.name +" actualizada";
vm.botonOk = false;
vm.otroBotonOk = true;
vm.botonCancelar = false;
vm.mensaje = "Sección "+ vm.section.name +" actualizada";
},
function (){
$rootScope.botonOk = false;
$rootScope.otroBotonOk = true;
$rootScope.botonCancelar = false;
$rootScope.mensaje = "Error al actualizar la Sección "+ vm.section.name;
vm.botonOk = false;
vm.otroBotonOk = true;
vm.botonCancelar = false;
vm.mensaje = "Error al actualizar la Sección "+ vm.section.name;
});
};

View File

@@ -12,31 +12,21 @@
<tr>
<th width="10%" style="text-align: center">
Cedula
<span ng-show="sortType == 'id' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'id' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%" style="text-align: center">
Nombre
<span ng-show="sortType == 'name' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'name' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%" style="text-align: center">
Apellido
<span ng-show="sortType == 'lastname' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'lastname' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="20%" style="text-align: center">
Correo
<span ng-show="sortType == 'email' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'email' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="10%" style="text-align: center">
Actualizar Correo
</th>
<th width="10%" style="text-align: center">
Dirección BT
<span ng-show="sortType == 'email' && !sortReverse" class="fa fa-caret-down"></span>
<span ng-show="sortType == 'email' && sortReverse" class="fa fa-caret-up"></span>
</th>
<th width="10%" style="text-align: center">
Liberar Dirección BT
@@ -53,20 +43,23 @@
<td style="vertical-align:middle">{{ student.lastname }}</td>
<td style="vertical-align:middle">{{ student.email }}</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-envelope"
<span title="Haga click para actualizar dirección de correo del estudiante"
class="glyphicon glyphicon-envelope"
aria-hidden="true"
ng-click="vm.mailUpdate($index)"
style="cursor:pointer;"></span>
</td>
<td style="vertical-align:middle">{{ student.btaddress }}</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-signal"
<span title="Haga click para liberar la dirección MAC del telefono del estudiante"
class="glyphicon glyphicon-signal"
aria-hidden="true"
ng-click="vm.freeBTAddressModal($index)"
style="cursor:pointer;"></span>
</td>
<td style="text-align: center">
<span class="glyphicon glyphicon-remove"
<span title="Haga click para retirar al estudiante de la sección"
class="glyphicon glyphicon-remove"
aria-hidden="true"
ng-click="vm.retirarEstudianteModal($index)"
style="cursor:pointer;"></span>

View File

@@ -0,0 +1,17 @@
(function(){
'use strict';
angular
.module('app')
.controller('NavbarCtrl', NavbarCtrl)
NavbarCtrl.$inject = ['$scope', 'authentication', '$state'];
function NavbarCtrl($scope, authentication, $state) {
var vm = this;
vm.logout = function () {
authentication.logout();
$state.go('login');
};
};
})();

View File

@@ -15,7 +15,13 @@
<ul class="nav navbar-nav navbar-right">
<div class="container-fluid">
</br>
<a href="#login" class="btn-danger btn" style=" margin: 10px"><span class="glyphicon glyphicon-log-out" aria-hidden="true"></span> Salir</a>
<button class="btn-danger btn"
style=" margin: 10px"
ng-click= "vm.logout()">
<span class="glyphicon glyphicon-log-out"
aria-hidden="true"></span>
Salir
</button>
</div>
</ul>
</div>

View File

@@ -5,49 +5,68 @@
.module('app')
.controller('SidebarCtrl', SidebarCtrl)
SidebarCtrl.$inject = ['$scope'];
function SidebarCtrl($scope) {
SidebarCtrl.$inject = ['$scope', 'authentication'];
function SidebarCtrl($scope, authentication) {
var that = this;
$scope.showChilds = function(item){
item.active = !item.active;
$scope.showChilds = function(index){
$scope.items[index].active = !$scope.items[index].active;
collapseAnother(index);
};
$scope.items = [
{
text: 'Módulo de Administración',
subItems: [
{
state: 'ProfessorList',
text: 'Listado de Profesores'
},
{
state: 'ProfessorCreate',
text: 'Nuevo Profesor'
}
]
},
{
text: 'Módulo de Materias',
subItems: [
{
state: 'CourseList',
text: 'Listado de Materias'
},
{
state: 'CourseCreate',
text: 'Nueva Materia'
}
]
},
{
text: 'Módulo de Reportes',
subItems: [
{
state: 'courseReport',
text: 'Reportes por Materia'
}
]
var collapseAnother = function(index){
for(var i=0; i<$scope.items.length; i++){
if(i!=index){
$scope.items[i].active = false;
}
}
];
};
$scope.items = [];
var permission = authentication.currentUser();
if(permission.role=='admin'){
$scope.items = [
{
text: 'Módulo de Administración',
subItems: [
{
state: 'ProfessorList',
text: 'Listado de Profesores'
},
{
state: 'ProfessorCreate',
text: 'Nuevo Profesor'
}
]
}
];
}
if(permission.role=='professor'){
$scope.items = [
{
text: 'Módulo de Materias',
subItems: [
{
state: 'CourseList',
text: 'Listado de Materias'
},
{
state: 'CourseCreate',
text: 'Nueva Materia'
}
]
},
{
text: 'Módulo de Reportes',
subItems: [
{
state: 'courseReport',
text: 'Reportes por Materia'
}
]
}
];
}
};
})();

View File

@@ -4,10 +4,14 @@
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li ng-repeat="item in items" ng-click="showChilds(item)">
<li ng-repeat="item in items"
ng-click="showChilds($index)">
<a>{{item.text}}</a>
<ul class="nav nav-sidebar text-center">
<li ng-repeat="subItem in item.subItems" ng-show="item.active">
<li ng-repeat="subItem in item.subItems"
ng-show="item.active"
ng-click="showChilds($index)"
ui-sref-active="active">
<a data-ui-sref="{{ subItem.state ? subItem.state : false }}">{{subItem.text}}
</li>
</ul>

View File

@@ -2,8 +2,11 @@
<h3 class="modal-title">Crear Estudiante</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button" ng-click="ok(urlLo)">Aceptar</button>
<div class="modal-footer">
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="ok()">Aceptar</button>
</div>

View File

@@ -2,13 +2,19 @@
<h3 class="modal-title">Eliminar Estudiante</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="acceptButton" type="button"
ng-click="ok(urlLo)">Aceptar</button>
<button class="btn btn-primary" ng-show="botonOK" type="button"
<div class="modal-footer">
<button class="btn btn-primary"
ng-show="vm.acceptButton"
type="button"
ng-click="ok()">Aceptar</button>
<button class="btn btn-primary"
ng-show="vm.botonOK"
type="button"
ng-click="vm.eliminarEstudiante(index)">OK</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
</div>

View File

@@ -2,11 +2,15 @@
<h3 class="modal-title">Actualizar Estudiante</h3>
</div>
<div style="text-align: center" class="modal-body">
{{ mensaje }}
{{ vm.mensaje }}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-show="botonOk" type="button"
<button class="btn btn-primary"
ng-show="vm.botonOk"
type="button"
ng-click="ok()">Aceptar</button>
<button class="btn btn-warning" ng-show="botonCancelar" type="button"
<button class="btn btn-warning"
ng-show="vm.botonCancelar"
type="button"
ng-click="cancel()">Cancelar</button>
</div>

View File

@@ -18,16 +18,10 @@
$stateProvider
.state('StudentCreate', {
parent: 'index',
url: '/StudentCreate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/students/student_create.html',
controller: 'StudentCreateCtrl',
controllerAs: 'vm'
@@ -35,16 +29,10 @@
}
})
.state('StudentUpdate', {
parent: 'index',
url: '/StudentUpdate',
views: {
sidebar: {
templateUrl: 'partials/sidebar/sidebar.html',
controller: 'SidebarCtrl'
},
navbar: {
templateUrl: 'partials/sidebar/navbar.html'
},
content: {
'content@': {
templateUrl: 'partials/students/student_update.html',
controller: 'StudentUpdateCtrl',
controllerAs: 'vm'

View File

@@ -5,15 +5,16 @@
.module('app.student')
.controller('StudentCreateCtrl', StudentCreateCtrl)
StudentCreateCtrl.$inject = ['$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse'];
function StudentCreateCtrl($scope, $rootScope, $state, professors, $modal, selectedSection, selectedCourse){
StudentCreateCtrl.$inject = ['$scope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse', 'authentication'];
function StudentCreateCtrl($scope, $state, professors, $modal, selectedSection, selectedCourse, authentication){
var vm = this;
var duplicated = false;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.professor = {};
$rootScope.mensaje = "";
$rootScope.actOk = false;
vm.mensaje = "";
vm.actOk = false;
professors.get({ id: professorid },
function (successResult){
@@ -25,7 +26,6 @@
});
vm.submit = function() {
if (vm.data_input_form.$valid){
var person = {
"id": vm.estudiante.Cedula,
@@ -34,18 +34,11 @@
"email": vm.estudiante.Correo
};
$rootScope.crearEstudianteLoading = true;
$rootScope.botonOk = false;
vm.botonOk = false;
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/students/modal/create_students_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
size: 'sm'
});
angular.forEach (vm.professor.courses[selectedCourse.index].sections[selectedSection.index].students,
@@ -57,24 +50,18 @@
professors.update({ id: professorid }, vm.professor,
function(){
$rootScope.botonOk = true;
$rootScope.urlLo = 'actualizarMatricula';
$rootScope.mensaje = "Estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre + " agregado";
$rootScope.crearEstudianteLoading = false;
vm.botonOk = true;
vm.mensaje = "Estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre + " agregado";
},
function(){
$rootScope.botonOk = true;
$rootScope.mensaje = "Error al agregar al estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
$rootScope.crearEstudianteLoading = false;
vm.botonOk = true;
vm.mensaje = "Error al agregar al estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
});
} else {
$rootScope.botonOk = true;
$rootScope.mensaje = "Estudiante con cedula " + vm.estudiante.Cedula + " ya esta en la lista.";
$rootScope.crearEstudianteLoading = false;
vm.botonOk = true;
vm.mensaje = "Estudiante con cedula " + vm.estudiante.Cedula + " ya esta en la lista.";
}
}else{
vm.submitted = true;
}
}
@@ -87,17 +74,8 @@
$scope.modalInstance.dismiss('cancel');
};
$rootScope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$rootScope.opened = true;
};
vm.back = function () {
$state.go('SectionUpdate');
};
return vm;
};
})();

View File

@@ -5,14 +5,15 @@
.module('app.student')
.controller('StudentUpdateCtrl', StudentUpdateCtrl)
StudentUpdateCtrl.$inject = ['$scope', '$rootScope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse', 'data'];
function StudentUpdateCtrl($scope, $rootScope, $state, professors, $modal, selectedSection, selectedCourse, data){
StudentUpdateCtrl.$inject = ['$scope', '$state', 'professors', '$modal', 'selectedSection', 'selectedCourse', 'data', 'authentication'];
function StudentUpdateCtrl($scope, $state, professors, $modal, selectedSection, selectedCourse, data, authentication){
var vm = this;
var professorid = $rootScope.professorId;
var user = authentication.currentUser();
var professorid = user._id;
vm.professor = {};
$rootScope.mensaje = "";
$rootScope.actOk = false;
vm.mensaje = "";
vm.actOk = false;
vm.newMail = null;
vm.student = data.Student
@@ -36,18 +37,11 @@
if (vm.data_input_form.$valid){
vm.student.email = vm.newMail;
$rootScope.crearEstudianteLoading = true;
$rootScope.botonOk = false;
vm.botonOk = false;
$scope.modalInstance = $modal.open({
animation: $rootScope.animationsEnabled,
templateUrl: 'partials/students/modal/update_students_modal.html',
scope: $scope,
size: 'sm',
resolve: {
items: function () {
return $rootScope.items;
}
}
size: 'sm'
});
vm.professor.courses[selectedCourse.index].sections[selectedSection.index].students.splice(data.Index, 1);
@@ -56,12 +50,12 @@
professors.update({ id: professorid }, vm.professor,
function(){
$rootScope.botonOk = true;
$rootScope.mensaje = "Estudiante " + vm.student.lastname + ", " + vm.student.name + " actualizado";
vm.botonOk = true;
vm.mensaje = "Estudiante " + vm.student.lastname + ", " + vm.student.name + " actualizado";
},
function(){
$rootScope.botonOk = true;
$rootScope.mensaje = "Error al actualizar al estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
vm.botonOk = true;
vm.mensaje = "Error al actualizar al estudiante " + vm.estudiante.Apellido + ", " + vm.estudiante.Nombre;
});
}
};

View File

@@ -1,16 +1,30 @@
var mongoose = require('mongoose');
var express = require('express');
var path = require ('path');
var favicon = require ('serve-favicon');
var logger = require('morgan');
var cookieparser = require('cookie-parser');
var app = express();
var db = mongoose.connection;
//var Professor = require('./models/professor');
var crypto = require('crypto');
var bodyParser = require('body-parser');
var jwbt = require('jsonwebtoken');
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport('smtps://reynaldo.reyes.4@gmail.com:zwvdhyensrwnfipt@smtp.gmail.com');
var jwt = require('express-jwt');
var auth = jwt({
secret: 'MY_SECRET',
userProperty: 'payload'
});
app.use(express.static(__dirname));
app.use(bodyParser.json());
var nodemailer = require('nodemailer');
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport('smtps://reynaldo.reyes.4@gmail.com:zwvdhyensrwnfipt@smtp.gmail.com');
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401);
res.json({"message" : err.name + ": " + err.message});
}
});
db.on('error', console.error);
db.once('open', function() {
@@ -47,21 +61,59 @@ db.once('open', function() {
});
var professorSchema = new mongoose.Schema({
id: Number,
name: String,
lastname: String,
email: String,
number: String,
role: String,
password: String,
courses: [courseSchema]
id: {
type: Number,
unique: true,
required: true
},
name: String,
lastname: String,
email: String,
number: String,
role: String,
hash: String,
salt: String,
courses: [courseSchema]
});
var Professor = mongoose.model('Professor', professorSchema);
//Professor CRUD
professorSchema.methods.setPassword = function(password){
this.salt = crypto.randomBytes(16).toString('hex');
this.hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex');
};
app.get('/professors', function(req, res){
professorSchema.methods.validPassword = function(password){
var hash = crypto.pbkdf2Sync(password, this.salt, 1000, 64).toString('hex');
return this.hash === hash;
};
professorSchema.methods.generateJwt = function() {
var profile = {
_id: this._id,
role: this.role
};
return jwbt.sign(profile, "MY_SECRET", { expiresIn: 18000 });
};
var Professor = mongoose.model('professor', professorSchema);
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy({
usernameField: 'id'
},
function(username, password, done) {
Professor.findOne({ id: username }, function (err, professor) {
if (err) return done(err);
if (!professor) return done(null, false, {message: 'professor not found'});
if (!professor.validPassword(password)) return done(null, false, {message: 'Password is wrong'});
return done(null, professor);
});
}));
app.use(passport.initialize());
app.get('/professors', auth, function(req, res){
console.log('Received GET ALL professors request');
Professor.find(function(err, docs){
//console.log(docs);
@@ -69,7 +121,7 @@ db.once('open', function() {
})
});
app.get('/professors/:id', function(req, res){
app.get('/professors/:id', auth, function(req, res){
console.log('Received GET professor request');
console.log(req.params);
Professor.findById(req.params.id,
@@ -79,7 +131,7 @@ db.once('open', function() {
})
});
app.post('/professors', function(req, res){
app.post('/professors', function(req, res){
console.log('Received ADD professor request');
//console.log(req.body);
@@ -90,35 +142,32 @@ db.once('open', function() {
email: req.body.email,
number: req.body.number,
role: req.body.role,
password: req.body.password,
course: [
{ name:"Materia" }
]
course: [{ name:"Materia" }]
})
professor.setPassword(req.body.password);
professor.save(
function(err, docs){
// setup e-mail data with unicode symbols
var mailOptions = {
from: '"Rey Reyes" <reynaldo.reyes.4@gmail.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Registro en la aplicación M.A.S.A.',
text: 'Este es un correo automatizado para informarle que ha sido registrado en la aplicación M.A.S.A. sus credenciales son: '+ req.body.id +' / '+ req.body.password,
html: 'Este es un correo automatizado para informarle que ha sido registrado en la aplicación <b> M.A.S.A.</b> sus credenciales son: '+ req.body.id +' / '+ req.body.password
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
res.json(docs);
})
// setup e-mail data with unicode symbols
var mailOptions = {
from: '"Rey Reyes" <reynaldo.reyes.4@gmail.com>', // sender address
to: req.body.email, // list of receivers
subject: 'Registro en la aplicación M.A.S.A.',
text: 'Este es un correo automatizado para informarle que ha sido registrado en la aplicación M.A.S.A. sus credenciales son: '+ req.body.id +' / '+ req.body.password,
html: 'Este es un correo automatizado para informarle que ha sido registrado en la aplicación <b> M.A.S.A.</b> sus credenciales son: '+ req.body.id +' / '+ req.body.password
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info){
if(error) return console.log(error);
console.log('Message sent: ' + info.response);
});
var token = professor.generateJwt();
res.status(200);
res.json({"token" : token});
})
});
app.delete('/professors/:id', function(req, res){
app.delete('/professors/:id', auth, function(req, res){
console.log("Received DELETE professor request...");
console.log(req.params);
Professor.findByIdAndRemove(req.params.id,
@@ -128,7 +177,7 @@ db.once('open', function() {
});
});
app.put('/professors/:id', function(req, res){
app.put('/professors/:id', auth, function(req, res){
console.log("Received UPDATE professor request");
console.log("params:" + req.params);
console.log("body:" + req.body);
@@ -147,9 +196,30 @@ db.once('open', function() {
});
});
});
app.post('/login', function(req, res){
passport.authenticate('local', function(err, professor, info){
var token;
// If Passport throws/catches an error
if (err) {
res.status(404).json(err);
return;
}
// If a user is found
if(professor){
token = professor.generateJwt();
res.status(200);
res.json({
"token" : token
});
// If user is not found
} else {
res.status(401).json(info);
}
})(req, res);
});
});
mongoose.connect('mongodb://localhost/AttendanceDB');
app.listen(3000);
console.log("server running on port 3000");

View File

@@ -1,7 +1,7 @@
{
"name": "masa-front",
"name": "masa",
"version": "1.0.0",
"description": "Frontend for M.A.S.A. App.",
"description": "NPM Package for M.A.S.A. App.",
"main": "app/index.html",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@@ -17,8 +17,16 @@
},
"dependencies": {
"body-parser": "latest",
"express" : "latest",
"gulp":"latest",
"mongoose":"latest"
"cookie-parser": "^1.4.1",
"express": "latest",
"express-jwt": "^3.4.0",
"favicon": "0.0.2",
"gulp": "latest",
"jsonwebtoken": "^6.2.0",
"mongoose": "latest",
"morgan": "^1.7.0",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"serve-favicon": "^2.3.0"
}
}