diff --git a/config/modules.json b/config/modules.json index c290f4e..13e7c3c 100644 --- a/config/modules.json +++ b/config/modules.json @@ -133,9 +133,9 @@ "lastName": { "des": "Professor first name.", "typ": "varchar(2,30,alphanumeric)", "opt": true }, "category": { "des": "Professor category UID.", "typ": "id", "opt": true }, "hoursToDo": { "des": "Number of hours professor have to do", "typ": "id", "opt": true }, - "initials": { "des": "Professor initials", "typ": "varchar(2,2,letters)", "opt": true }, + "initials": { "des": "Professor initials", "typ": "varchar(2,8,letters)", "opt": true }, "isAdmin": { "des": "Whether professor is an admin", "typ": "boolean", "opt": true }, - "casLogin": { "des": "Optional CAS username", "typ": "varchar(6,10,letters)", "opt": true } + "casLogin": { "des": "Optional CAS username", "typ": "varchar(6,16,letters)", "opt": true } }, "out": { "updated": { "des": "Whether the professor has been updated", "typ": "boolean" } diff --git a/webpack/component/teacher/view.vue b/webpack/component/teacher/view.vue index 60121e8..f15391a 100644 --- a/webpack/component/teacher/view.vue +++ b/webpack/component/teacher/view.vue @@ -52,18 +52,40 @@ :data-lname='prof.lastName' :data-fname='prof.firstName'> -
+ + +
-
+
- {{ prof.categorie }} -

{{ prof.firstName }} {{ prof.lastName }} ({{ prof.casLogin }})

+ + {{ prof.categorie }} + + + + + +

{{ prof.firstName }} {{ prof.lastName }} ({{ prof.casLogin }})

+ +

+ + () +

+ +
- {{prof.hoursToDo}} + + {{prof.hoursToDo}} + + + heures à faire
@@ -72,12 +94,23 @@
-
{{ prof.VHCours + prof.VHTd + prof.VHTp }}h physiques prévues
+ +
{{ prof.VHCours + prof.VHTd + prof.VHTp }}h physiques prévues
+ +
{{ gstore.edit_err }}
+ diff --git a/webpack/data/teacher.js b/webpack/data/teacher.js index 04fbd47..f4a8b4c 100644 --- a/webpack/data/teacher.js +++ b/webpack/data/teacher.js @@ -338,7 +338,7 @@ gstore.add('ir_handler', function(prof_id){ /* (2.2) Exit if not found */ if( isNaN(gi) ) return; - local = gstore.get.professors[gi]; + var local = gstore.get.professors[gi]; /* (3) Show popup */ (new Promise( (resolve, reject) => { @@ -398,58 +398,144 @@ gstore.add('ir_handler', function(prof_id){ /* (7) Manage instant edit ---------------------------------------------------------*/ -/* (1) Define edit handler */ -gstore.add('ie_handler', function(prof_id){ +/* (1) Init edit_mode */ +gstore.add('edit_i', -1); - /* (1) Abort if wrong prof_id */ - if( prof_id == null || isNaN(prof_id) ) +/* (2) Initialize inputs */ +gstore.add('edit_cat', '-'); +gstore.add('edit_name', ''); +gstore.add('edit_cas', ''); +gstore.add('edit_h', ''); + +/* (3) Initialize error message */ +gstore.add('edit_err_valid', false); +gstore.add('edit_err', ''); + + +/* (4) Define toggle view */ +gstore.add('ie_toggle', function(prof_i){ + + /* (4.1) Abort if wrong prof_i */ + if( prof_i == null || isNaN(prof_i) || gstore.get.professors[prof_i] == null) + return gstore.add('edit_i', -1); + + /* (4.2) Toggle current value */ + var prof = gstore.get.professors[prof_i]; + + /* (4.3) Pre-fill edit values */ + gstore.get.edit_cat = prof.idCat; + gstore.get.edit_cas = prof.casLogin; + gstore.get.edit_name = prof.firstName+' '+prof.lastName; + gstore.get.edit_h = prof.hoursToDo.toString(); + + /* (4.4) Set card to edit mode */ + gstore.get.edit_i = prof_i; + +}); + +/* (5) Confirm update */ +gstore.add('ie_handler', function(prof_i){ + + /* (5.1) Abort if wrong prof_i */ + if( prof_i == null || isNaN(prof_i) || gstore.get.professors[prof_i] == null) return; - /* (2.1) Find index in gstore */ - var gi = gstore.get.professors.map( (data, i) => { return ( data.idProfesseur && data.idProfesseur == prof_id ) ? i : ''; }).join(''); + /* (5.2) Toggle current value */ + var prof = gstore.get.professors[prof_i]; - /* (2.2) Exit if not found */ - if( isNaN(gi) ) return; - local = gstore.get.professors[gi]; + /* (5.3) Trim text input */ + gstore.get.edit_name = gstore.get.edit_name.trim(); + gstore.get.edit_cas = gstore.get.edit_cas.trim().toLowerCase(); + gstore.get.edit_h = gstore.get.edit_h.trim(); + + /* (5.4) Store values locally */ + var cat = gstore.get.edit_cat; + var name = gstore.get.edit_name.split(' '); + var cas = gstore.get.edit_cas; + var hour = gstore.get.edit_h; + + /* (5.5) Init client-side check */ + var errors = []; + + /* (5.5.1) Check category */ + if( isNaN(cat) ) errors.push('La catégorie de l\'enseignant est manquante'); + + /* (5.5.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"'); + + /* (5.5.3) Check CAS login */ + if( !/^([a-z]{4,16})?$/.test(cas) ) + errors.push('L\'identifiant doit être vide ou comprendre de 4 à 16 lettres'); + + /* (5.5.4) Check hours */ + if( hour === '' || isNaN(hour) || hour < 0 ) + errors.push('Le nombre d\'heures doit être un entier positif.'); + + /* (5.6) Show first error only (for 2s) */ + if( errors.length > 0 ){ + + gstore.get.edit_err = errors[0]; + + return setTimeout(() => gstore.add('edit_err', ''), 2000); + + } - /* (3) Show popup */ + /* (5.7) Création de la requête */ + var rq = {}; + ( name[0] != prof.firstName ) && ( rq.firstName = name[0] ); + ( name[1] != prof.lastName ) && ( rq.lastName = name[1] ); + ( cat != prof.idCat ) && ( rq.category = cat ); + ( hour != prof.hoursToDo ) && ( rq.hoursToDo = hour ); + ( cas != prof.casLogin ) && ( rq.casLogin = cas ); + + // update initials whatever have been modified (to avoid API error when no field given) + rq.initials = name[0].substr(0,2) + name[1].substr(0,2); + (new Promise( (resolve, reject) => { popup.ask({ title: 'Confirmation de modification', - content: "La modification de l'enseignant "+local.firstName+" "+local.lastName+" est irréversible.

Voulez-vous le modifier ?", + content: "La modification de l'enseignant "+prof.firstName+" "+prof.lastName+" est irréversible.

Voulez-vous le modifier ?", action: 'Modifier', type: 'search' }, (popup_rs) => { popup_rs && resolve() }); - /* (4) On pop-up confirmation */ + /* (5.8) On pop-up confirmation */ })).then(function(){ return new Promise( (resolve, reject) => { - /* (4.1) Delete professor */ - api.call('PUT professor/'+prof_id, {}, function(rs){ + /* (5.8.1) Delete professor */ + api.call('PUT professor/'+prof.idProfesseur, rq, function(rs){ - /* (4.1.1) Abort on error */ + /* (5.8.1.1) Abort on error */ if( rs.error !== 0 || rs.updated !== true ) return reject(rs.error); - /* (4.1.2) Success */ + /* (5.8.1.2) Success */ resolve(); }); }); - /* (5) On success */ + /* (5.9) On success */ }).then(function(){ - /* update VueJS element */ - // gstore.get.professors[gi]; + /* (5.9.1) update VueJS element */ + gstore.get.professors[prof_i].idCat = cat; + gstore.get.professors[prof_i].firstName = name[0]; + gstore.get.professors[prof_i].lastName = name[1]; + gstore.get.professors[prof_i].casLogin = cas; + gstore.get.professors[prof_i].hoursToDo = hour; + + /* (5.9.2) Remove edit mode */ + gstore.add('edit_i', -1); - /* (6) On error */ + /* (5.10) On error */ }).catch(function(err_code){ popup.ask({ @@ -461,7 +547,6 @@ gstore.add('ie_handler', function(prof_id){ }); - });