diff --git a/webpack/data/teacher.js b/webpack/data/teacher.js
index ab499ee..878bc27 100644
--- a/webpack/data/teacher.js
+++ b/webpack/data/teacher.js
@@ -204,3 +204,288 @@ gstore.add('is_handler', function(e){
});
+
+
+
+/* (5) Manage instant create
+---------------------------------------------------------*/
+/* (1) Initialize inputs */
+gstore.add('create_cat', '-');
+gstore.add('create_name', '');
+gstore.add('create_cas', '');
+gstore.add('create_h', '');
+
+/* (2) Initialize error message */
+gstore.add('create_err_valid', false);
+gstore.add('create_err', '');
+
+/* (3) Define create handler */
+gstore.add('ic_handler', function(prof_id){
+
+ /* (3.1) Trim text input */
+ gstore.get.create_name = gstore.get.create_name.trim();
+ gstore.get.create_cas = gstore.get.create_cas.trim().toLowerCase();
+ gstore.get.create_h = gstore.get.create_h.trim();
+
+ /* (3.2) Store values locally */
+ var cat = gstore.get.create_cat;
+ var name = gstore.get.create_name.split(' ');
+ var cas = gstore.get.create_cas;
+ var hour = gstore.get.create_h;
+
+ /* (3.3) Init client-side check */
+ var errors = [];
+
+ /* (3.3.1) Check category */
+ if( isNaN(cat) ) errors.push('La catégorie de l\'enseignant est manquante');
+
+ /* (3.3.2) Check name */
+ if( name.length !== 2 || name[0].length < 2 || name[1].length < 2 )
+ errors.push('Le nom doit suivre le format "Prénom Nom"');
+
+ /* (3.3.3) Check CAS login */
+ if( !/^([a-z]{4,16})?$/.test(cas) )
+ errors.push('L\'identifiant doit être vide ou comprendre de 4 à 16 lettres');
+
+ /* (3.3.4) Check hours */
+ if( hour === '' || isNaN(hour) || hour < 0 )
+ errors.push('Le nombre d\'heures doit être un entier positif.');
+
+ /* (3.4) Show first error only (for 2s) */
+ if( errors.length > 0 ){
+
+ gstore.get.create_err = errors[0];
+
+ return setTimeout(() => gstore.add('create_err', ''), 2000);
+
+ }
+
+
+
+ /* (4.1) Création de la requête */
+ var rq = {
+ firstName: name[0],
+ lastName: name[1],
+ category: cat,
+ initials: name[0].substr(0,2)+name[1].substr(0,2),
+ hoursToDo: hour,
+ isAdmin: false
+ };
+
+ // optional cas_login
+ if( cas.length > 0 ) rq.casLogin = cas;
+
+
+ /* (4.2) Send request */
+ api.call('POST professor', rq, function(rs){
+
+ console.log(rs);
+
+ /* (4.2.1) Manage 'already exist' error */
+ if( rs.error == 29 ){
+ gstore.get.create_err = 'Le couple Nom-Prénom est déja utilisé.';
+ return setTimeout(() => gstore.add('create_err', ''), 2000);
+ }
+
+ /* (4.2.2) Manage other errors */
+ if( rs.error !== 0 ){
+ gstore.get.create_err = 'erreur ('+rs.error+') Impossible de créer l\'enseignant';
+ return setTimeout(() => gstore.add('create_err', ''), 2000);
+ }
+
+ /* (4.2.3) Show that user is created */
+ // display all is ok
+ gstore.add('create_err_valid', true);
+ gstore.add('create_err', 'L\'enseignant a été créé, il s\'affichera au prochain rechargement');
+
+ // empty fields
+ gstore.get.create_cat = '-';
+ gstore.get.create_name = '';
+ gstore.get.create_cas = '';
+ gstore.get.create_h = '';
+
+ return setTimeout(() => {
+ gstore.add('create_err', '');
+ gstore.add('create_err_valid', false);
+ }, 2000);
+
+
+ });
+
+
+
+
+});
+
+
+
+
+
+/* (6) Manage instant remove
+---------------------------------------------------------*/
+/* (1) Define remove handler */
+gstore.add('ir_handler', function(prof_id){
+
+ /* (1) Abort if wrong prof_id */
+ if( prof_id == null || isNaN(prof_id) )
+ return;
+
+ /* (2) Show popup */
+ (new Promise( (resolve, reject) => {
+
+ popup.ask({
+ title: 'Confirmation de suppression',
+ content: "La suppression de l'enseignant sadkfjsdlkf est irréversible.
Voulez-vous le supprimer définitivement ?",
+ action: 'Supprimer',
+ type: 'invalid'
+ }, (popup_rs) => { popup_rs && resolve() });
+
+ })).then(function(){
+
+
+ return new Promise( (resolve, reject) => {
+
+ /* (2.1) Delete professor */
+ api.call('DELETE professor/'+prof_id, {}, function(rs){
+
+ /* (2.1.1) Abort on error */
+ if( rs.error !== 0 || rs.deleted !== true )
+ return reject(rs.error);
+
+ /* (2.1.2) Success */
+ resolve();
+
+ });
+
+ });
+
+ /* (3) On success */
+ }).then(function(){
+
+ /* (3.1) Find index in gstore */
+ var gi = gstore.get.professors.map( (data, i) => { return ( data.idProfesseur && data.idProfesseur == prof_id ) ? i : ''; }).join('');
+
+ /* (3.2) Do nothing if not found */
+ if( isNaN(gi) ) return;
+
+ /* (3.3) Else -> remove from visible */
+ gstore.get.professors.splice(gi, 1);
+
+
+ /* (4) On error */
+ }).catch(function(err_code){
+
+ popup.ask({
+ title: 'Error ('+err_code+')',
+ content: 'La suppression a échouée. Veuillez réessayer ultérieurement.',
+ action: 'OK',
+ type: 'neutral'
+ }, () => {});
+
+ });
+
+
+});
+
+
+
+
+
+/* (7) Manage instant edit
+---------------------------------------------------------*/
+/* (1) Define edit handler */
+gstore.add('ie_handler', function(prof_id){
+
+ /* (1) Abort if wrong prof_id */
+ if( prof_id == null || isNaN(prof_id) )
+ return;
+
+ /* (2) Show popup */
+ (new Promise( (resolve, reject) => {
+
+ popup.ask({
+ title: 'Confirmation de modification',
+ content: "La modification de l'enseignant sadkfjsdlkf est irréversible.
Voulez-vous le modifier ?",
+ action: 'Modifier',
+ type: 'search'
+ }, (popup_rs) => { popup_rs && resolve() });
+
+ })).then(function(){
+
+
+ return new Promise( (resolve, reject) => {
+
+ /* (2.1) Delete professor */
+ api.call('PUT professor/'+prof_id, {}, function(rs){
+
+ /* (2.1.1) Abort on error */
+ if( rs.error !== 0 || rs.updated !== true )
+ return reject(rs.error);
+
+ /* (2.1.2) Success */
+ resolve();
+
+ });
+
+ });
+
+ /* (3) On success */
+ }).then(function(){
+
+ /* (3.1) Find index in gstore */
+ var gi = gstore.get.professors.map( (data, i) => { return ( data.idProfesseur && data.idProfesseur == prof_id ) ? i : ''; }).join('');
+
+ /* (3.2) Do nothing if not found */
+ if( isNaN(gi) ) return;
+
+ /* (3.3) Else -> update VueJS element */
+ // gstore.get.professors[gi];
+
+
+
+ /* (4) On error */
+ }).catch(function(err_code){
+
+ popup.ask({
+ title: 'Error ('+err_code+')',
+ content: 'La modification a échouée. Veuillez réessayer ultérieurement.',
+ action: 'OK',
+ type: 'neutral'
+ }, () => {});
+
+ });
+
+
+});
+
+
+
+
+
+/* (8) Manage instant admin
+---------------------------------------------------------*/
+/* (1) Define admin handler */
+gstore.add('ia_handler', function(prof_i){
+
+ /* (1) Abort if wrong prof_i */
+ if( prof_i == null || isNaN(prof_i) || gstore.get.professors[prof_i] == null)
+ return;
+
+ /* (2) Toggle current value */
+ var local = gstore.get.professors[prof_i];
+ var is_admin = local.admin == '1' || local.admin === true;
+ var new_state = !is_admin;
+
+ /* (3.1) Update in database */
+ api.call('PUT professor/'+local.idProfesseur, { isAdmin: new_state }, function(rs){
+
+ /* (3.1.1) Abort on error */
+ if( rs.error !== 0 || rs.updated !== true )
+ return console.log('Impossible de changer le status \'admin\', erreur '+rs.error);
+
+ /* (3.1.2) Success */
+ gstore.get.professors[prof_i].admin = new_state ? 1 : 0;
+
+ });
+
+});
\ No newline at end of file
diff --git a/webpack/scss/constants.scss b/webpack/scss/constants.scss
index 7525ff5..089657b 100644
--- a/webpack/scss/constants.scss
+++ b/webpack/scss/constants.scss
@@ -10,7 +10,7 @@ $error-color: #cc5857;
/* FORMULAIRES */
$form-valid-color: #20d696;
$form-neutral-color: #b8c0c8;
-$form-search-color: #e5c41d;
+$form-search-color: #1d74e5;
$form-invalid-color: #ea4b35;
$form-grey-color: lighten($secondary-color, 5%);
@@ -19,10 +19,10 @@ $form-grey-color: lighten($secondary-color, 5%);
// POUR RESOURCE_DISPATCHER
-$rd-form-valid-color: '27a560';
-$rd-form-neutral-color: '2193e6';
-$rd-form-search-color: '5630ed';
-$rd-form-invalid-color: 'd52918';
+$rd-form-valid-color: '20d696';
+$rd-form-neutral-color: 'b8c0c8';
+$rd-form-search-color: '1d74e5';
+$rd-form-invalid-color: 'ea4b35';
// Menu
$menu-bg: #fff;
diff --git a/webpack/scss/container.scss b/webpack/scss/container.scss
index e09d3f3..6aeca7d 100644
--- a/webpack/scss/container.scss
+++ b/webpack/scss/container.scss
@@ -217,6 +217,10 @@
// border: 1px solid darken(#fff, 10%);
box-shadow: 0 1px 1px darken(#fff, 20%);
+ box-shadow: 0 1px 1px darken(#fff, 20%);
+ &.invalid{ box-shadow: 0; border: 1px solid $form-invalid-color; }
+ &.valid{ box-shadow: 0; border: 1px solid $form-valid-color; }
+
background-color: #fff;
color: $primary-color;
@@ -235,12 +239,62 @@
&.search-hidden,
&.filter-hidden{ display: none; }
- /* (2) Card generic title */
+
+ /* (2) REMOVE+EDIT+ADMIN button */
+ & > div.remove[data-remove],
+ & > div.edit[data-edit],
+ & > div.admin[data-admin]{
+ display: inline-block;
+ position: absolute;
+ top: 1.3em;
+ left: calc( 100% - 2em );
+ width: 1em;
+ height: 1em;
+
+ background: url('/asset/svg/remove.svg@bbbbbb') center center no-repeat;
+ background-size: auto 100%;
+
+ cursor: pointer;
+
+ &:hover{
+ background-image: url('/asset/svg/remove.svg@#{$rd-form-invalid-color}');
+ }
+
+ }
+
+ /* (2.1) EDIT button */
+ & > div.edit[data-edit]{
+ left: calc( 100% - 2em - 1.3em );
+
+ background-image: url('/asset/svg/td.svg@bbbbbb');
+ background-size: 80% auto;
+
+ &:hover{
+ background-image: url('/asset/svg/td.svg@#{$rd-form-search-color}');
+ }
+
+ }
+
+ /* (2.2) ADMIN switch */
+ & > div.admin[data-admin]{
+ left: calc( 100% - 2em - 1.3em - 1.3em );
+
+ background-image: url('/asset/svg/admin.svg@bbbbbb');
+ background-size: 85% auto;
+
+ &:hover{ background-image: url('/asset/svg/admin.svg@bbbbbb'); }
+
+ &[data-active='1']{ background-image: url('/asset/svg/admin.svg@f4bd18'); }
+
+ }
+
+ /* (4) Card generic title */
& > span.category,
& > select.category{
display: block;
position: relative;
+ width: calc( 100% - 5em );
margin-bottom: .5em;
@@ -251,9 +305,10 @@
}
- /* (2-edot) Card generic title (select) */
+ /* (4-edit) Card generic title (select) */
& > select.category{
+ width: calc( 100% + 1em );
margin: 0;
padding: 0;
margin-left: -.4em; // emulate no