[webpack.ue.manage] CREATE new Cours|TD|TP implemented (with real-time feedback (push into VueJS), then updates/remove works)

This commit is contained in:
xdrm-brackets 2018-03-18 17:17:31 +01:00
parent 861fb49846
commit dc647f567f
6 changed files with 160 additions and 20 deletions

View File

@ -4,7 +4,31 @@
<div class='list container' data-anim-incoming='1' :data-anim-bounce='gstore.nav_anim.out?1:0'>
<!-- <button @click='gstore.nav_out($router)'>Retour</button> -->
<!-- CREATE -->
<section class='cours'
data-anim-incoming='1'
:data-anim-bounce='gstore.nav_anim.out?1:0'>
<div class='icon' @click='gstore.ccreate()'></div>
<select v-model='gstore.ccrea.prof'>
<option value='-1'>Aucun enseignant affecté</option>
<option v-for='p in gstore.manage.prof' :value='p.idProfesseur'>{{ `${p.firstName} ${p.lastName}` }}</option>
</select>
<select v-model='gstore.ccrea.type' class='min'>
<option value='-' disabled>Type</option>
<option value='0'>Cours</option>
<option value='1'>TD</option>
<option value='2'>TP</option>
</select>
<input type='text' placeholder='volume' v-model='gstore.ccrea.vol'>
<div style='margin-left: 1em;' :class="gstore.ccrea.err.length > 0 ? (gstore.ccrea.valid ? 'warning valid' : 'warning invalid') : ''" :data-valid='gstore.ccrea.valid?1:0'>{{ gstore.ccrea.err }}</div>
</section>
<section class='filter'></section>
<!-- FILTERS -->
<section class='filter'>
@ -21,7 +45,7 @@
v-for='(c,i) in gstore.manage.cours'
:data-id='c.idCours'>
<div class='icon' @click='gstore.rem(0, i)'></div>
<div class='icon remove' @click='gstore.rem(0, i)'></div>
<select v-model='c.new_prof' @change='gstore.upd_prof(0, i)'>
<option value='-1' v-show='c.idProf!=-1'>Aucun enseignant affecté</option>
<option v-for='p in gstore.manage.prof' :value='p.idProfesseur' v-show='p.idProfesseur!=c.idProf'>{{ `${p.firstName} ${p.lastName}` }}</option>
@ -56,7 +80,7 @@
data-anim-incoming='1'
:data-anim-bounce='gstore.nav_anim.out?1:0'>
<div class='icon' @click='gstore.rem(1, i)'></div>
<div class='icon remove' @click='gstore.rem(1, i)'></div>
<select v-model='td.new_prof' @change='gstore.upd_prof(1, i)'>
<option value='-1' v-show='td.idProf!=-1'>Aucun enseignant affecté</option>
<option v-for='p in gstore.manage.prof' :value='p.idProfesseur' v-show='p.idProfesseur!=td.idProf'>{{ `${p.firstName} ${p.lastName}` }}</option>
@ -91,7 +115,7 @@
data-anim-incoming='1'
:data-anim-bounce='gstore.nav_anim.out?1:0'>
<div class='icon' @click='gstore.rem(2, i)'></div>
<div class='icon remove' @click='gstore.rem(2, i)'></div>
<select v-model='tp.new_prof' @change='gstore.upd_prof(2, i)'>
<option value='-1' v-show='tp.idProf!=-1'>Aucun enseignant affecté</option>
<option v-for='p in gstore.manage.prof' :value='p.idProfesseur' v-show='p.idProfesseur!=tp.idProf'>{{ `${p.firstName} ${p.lastName}` }}</option>
@ -117,6 +141,10 @@
</div>
</section>
</div>

View File

@ -403,14 +403,6 @@ gstore.add('ie_handler', function(ue_i){
if( vco === '' || isNaN(vco) || vco < 0 )
errors.push('Le volume horaire de cours doit être un entier positif.');
/* (5.5.5) Check TD */
if( vtd === '' || isNaN(vtd) || vtd < 0 )
errors.push('Le volume horaire de TD doit être un entier positif.');
/* (5.5.6) Check TP */
if( vtp === '' || isNaN(vtp) || vtp < 0 )
errors.push('Le volume horaire de TP doit être un entier positif.');
/* (5.6) Show first error only (for 2s) */
if( errors.length > 0 ){
@ -996,4 +988,101 @@ gstore.add('rem', function(type, res_i){
});
});
});
/* (2) Create a Cours|TD|TP */
gstore.add('ccrea', {
type: '-',
prof: -1,
vol: '',
err: '',
valid: false
});
gstore.add('ccreate', function(){
/* (1) Trim text input */
gstore.get.ccrea.vol = gstore.get.ccrea.vol.trim();
/* (2) Store values locally */
var type = gstore.get.ccrea.type;
var prof = gstore.get.ccrea.prof;
var vol = gstore.get.ccrea.vol;
/* (2) Init client-side check */
var errors = [];
/* (2.1) Check type */
if( isNaN(type) || [0,1,2].indexOf(parseInt(type)) <= -1 )
errors.push('Le type de prestation est manquant (Cours, TD, TP)');
/* (2.2) Check prof */
if( isNaN(prof) )
errors.push('L\'enseignant est invalide ou manquant');
/* (2.3) Check volume */
if( vol === '' || isNaN(vol) || vol < 0 )
errors.push('Le volume horaire doit être un entier positif.');
/* (2.4) Show first error only (for 2s) */
if( errors.length > 0 ){
gstore.get.ccrea.valid = false;
gstore.get.ccrea.err = errors[0];
return setTimeout(() => gstore.add('ccrea.err', ''), 2000);
}
/* (3) Extract resource type */
var restyp = ['cours', 'td', 'tp'][type];
var restyp2 = ['Cours', 'TD', 'TP'][type];
/* (4) Create request */
var rq = {
code: gstore.get.URI[2],
volume: parseInt(vol)
};
// optional 'idProf'
( prof > -1 ) && ( rq.idProf = parseInt(prof) );
/* (5) Send request */
api.call(`POST ue/${restyp}`, rq, function(rs){
console.log(rs);
/* (5.1) Manage errors */
if( rs.error !== 0 ){
gstore.get.ccrea.valid = false
gstore.get.create_err = `erreur (${rs.error}) Impossible de créer le ${restyp}`;
return setTimeout(() => gstore.add('create_err', ''), 2000);
}
/* (5.2) Show that Cours|TD|TP is created */
gstore.get.ccrea.valid = true;
gstore.get.ccrea.err = `Le ${restyp} a bien été créé, rechargez la page pour le visualiser.`;
setTimeout(() => gstore.add('create_err', ''), 2000);
/* (5.3) Empty fields */
// empty fields
gstore.get.ccrea.prof = -1;
gstore.get.ccrea.type = '-';
gstore.get.ccrea.vol = '';
/* (5.4) Add resource to list (update VueJS) */
var newRes = {};
newRes[`id${restyp2}`] = rs.created_id;
newRes[`idProf`] = prof;
newRes[`volume`] = vol;
newRes[`formations`] = [];
newRes[`add_form`] = '-';
newRes[`new_prof`] = prof;
gstore.get.manage[restyp].push(newRes);
});
});

View File

@ -236,7 +236,7 @@
margin: 0;
padding: 0;
margin-left: -.4em; // emulate no <select>
margin-top: -1em; // replace as if not a select
margin-top: -1em; // replace as if not a select
margin-bottom: -.3em; // fix layout for following elements
// remove border

View File

@ -42,7 +42,8 @@
flex-wrap: nowrap;
/* (1.1) Element item */
& > div:not(.icon){
& > div:not(.icon),
& > input{
flex: 1 1 0;
// fix
@ -69,7 +70,6 @@
display: inline-block;
position: relative;
height: 1.8em;
width: auto;
margin: 0;
margin-right: 1em;
@ -91,12 +91,25 @@
-moz-appearance: none;
appearance: none;
justify-self: space-around;
flex: 0 1 20em;
&.min{ flex: 0 1 5em; }
}
/* (1.4) Icon (remove) */
/* (1.4) Input */
& > input{
display: inline-block;
position: relative;
min-width: 0;
margin: 0;
padding: .22em .5em;
flex: 0 1 5em;
}
/* (1.5) Icon (remove) */
& > div.icon{
display: inline-block;
width: 1.2em;
@ -104,14 +117,19 @@
margin-right: 1em;
background: url('/asset/svg/cross.svg@aaaaaa') center center no-repeat;
background: url('/asset/svg/plus.svg@aaaaaa') center center no-repeat;
background-size: 60% auto;
overflow: hidden;
cursor: pointer;
&:hover{ background-image: url('/asset/svg/cross.svg@#{$rd-form-invalid-color}'); }
&:hover{ background-image: url('/asset/svg/plus.svg@#{$rd-form-valid-color}'); }
&.remove{
background-image: url('/asset/svg/cross.svg@aaaaaa');
&:hover{ background-image: url('/asset/svg/cross.svg@#{$rd-form-invalid-color}'); }
}
}
}

View File

@ -28,6 +28,10 @@
// force red text
&.invalid{ color: $form-invalid-color; }
&[data-valid='1']{ color: $form-valid-color; }
&[data-neutral='1']{ color: $form-neutral-color; }
&[data-search='1']{ color: $form-search-color; }
}

View File

@ -33,6 +33,7 @@
color: #999;
font-size: .8em;
white-space: nowrap;
cursor: default;