ptut-vhost/webpack/data/ue.js

1322 lines
31 KiB
JavaScript

/* (1) Load formations
---------------------------------------------------------*/
/* (1) Define global filter */
gstore.add('filters', {
formations: [{ visible: false, active: [] }]
});
/* (2) Initialize list */
gstore.add('formations', []);
/* (3) Get Formations */
api.call('GET formation', {}, function(rs){
// {1} If error -> abort //
if( rs.error !== 0 ) return console.log('No formation found, error: '+rs.error);
console.log(rs);
// {2} Format UE filters //
for( var i = 0 ; i < rs.formations.length ; i++ )
gstore.get.formations.push( rs.formations[i] );
// {3} Format formation list for filters
for( var i = 0 ; i < rs.formations.length ; i++ )
gstore.get.filters.formations.push({
code: rs.formations[i].idForm,
name: rs.formations[i].labelForm,
active: false
});
});
/* (4) Get Formation label */
gstore.add('form_by_id', function(form_id){
/* (1) Abort if wrong form_id */
if( form_id == null )
return { idForm: null, labelForm: null };
/* (2.1) Find index in gstore */
var gi = gstore.get.formations.map( (data, i) => { return ( data.idForm && data.idForm == form_id ) ? i : ''; }).join('');
/* (2.2) Exit if not found */
if( isNaN(gi) )
return { idForm: null, labelForm: null };
return gstore.get.formations[gi];
});
/* (2) Load ues
---------------------------------------------------------*/
/* (1) Initialize list */
gstore.add('ues', []);
/* (2) Get ues */
api.call('GET ue/', { vh: true }, function(rs){
// {1} If error -> abort //
if( rs.error !== 0 )return console.log('No UE found, error: '+rs.error);
console.log(rs);
// {2} Store ues //
gstore.get.ues = rs.ues;
});
/* (3) Define filters' callback
---------------------------------------------------------*/
/* (1) Define global callback */
gstore.add('filter_handler', function(){
let filter_ids = [];
// 1. Get each formation ID
for( let form of gstore.get.filters.formations ){
// 1.1. Ignore if 'code' not found
if( form.code === null )
continue;
// 1.2. If active -> add to list
( form.code != null && form.active ) && filter_ids.push(form.code);
}
// 3. For UE element
main_loop: for( let ue of gstore.get.ues ){
// 3.1. Show by default
let element = document.querySelector('section[data-id=\''+ue.code+'\']');
if( !(element instanceof Element) )
continue;
element.remClass('filter-hidden');
// 3.2. If no filter -> let all visible
if( filter_ids.length <= 0 )
continue;
// 3.3. If at least one matching formatiom id -> let visible
for( let fid of filter_ids )
if( ue.formations.indexOf(fid) > -1 )
continue main_loop;
// XXXXX. If did not match -> hide
element.addClass('filter-hidden');
}
});
/* (3) Get Filters
---------------------------------------------------------*/
/* (2) Define filter group show/hide */
gstore.add('show_fgroup', function(gname){
var opened = gstore.get.filters[gname] != null && gstore.get.filters[gname][0].visible;
// {1} hide all by default//
for( var f in gstore.get.filters )
gstore.get.filters[f][0].visible = false;
// {2} If wrong @gname -> abort //
if( gstore.get.filters[gname] == null )
return;
// {3} Show selected filter //
gstore.get.filters[gname][0].visible = !opened;
});
/* (3) Define filter item toggle */
gstore.add('toggle_filter', function(gname, i){
// {1} If wrong @gname -> abort //
if( gstore.get.filters[gname] == null )
return;
// {2} If wrong @i -> abort //
if( gstore.get.filters[gname][i] == null )
return;
// {3} Toggle filter activation //
gstore.get.filters[gname][i].active = !gstore.get.filters[gname][i].active;
// {4} Update active table //
gstore.get.filters[gname][0].active.splice(0);
for( var f = 1 ; f < gstore.get.filters[gname].length ; f++ )
if( gstore.get.filters[gname][f].active )
gstore.get.filters[gname][0].active.push(f);
});
/* (4) Manage Instant Search (IS)
---------------------------------------------------------*/
/* (1) Define global timeout index */
gstore.add('is_to', null);
/* (2) Define search value buffer */
gstore.add('is_buf', null);
/* (3) Define instant search function */
gstore.add('is_handler', function(e){
/* (1) Remove last timeout */
!isNaN(gstore.get.is_to) && clearTimeout(gstore.get.is_to);
/* (2) Store value in buffer */
gstore.get.is_buf = e.target.value.trim().toLowerCase();
/* (3) Launch timeout (wait 1s) before filtering */
gstore.get.is_to = setTimeout(function(){
// 1. Fetch elements
let local_ptr = gstore.get.ues;
let l = gstore.get.ues.length;
let buf = gstore.get.is_buf.replace(/[.?*+^$[\]\\(\){}|-]/g, "\\$&"); // Escape errorful regex characters
// 2. For each element
main_loop: for( let e = 0 ; e < l ; e++ ){
// 2.1. Set visible by default
let element = document.querySelector('section[data-id=\''+local_ptr[e].code+'\']');
if( !(element instanceof Element) )
continue;
element.remClass('search-hidden');
// 2.2. Empty text -> let visible
if( buf.length == 0 )
continue;
// 2.3. Extract name components
let code = local_ptr[e].code.toLowerCase();
let label = local_ptr[e].label.toLowerCase();
let forms = local_ptr[e].formations;
// 2.4-1. Match code -> let visible
if( code.search(buf) >= 0 )
continue;
// 2.4-2. Match label -> let visible
if( label.search(buf) >= 0 )
continue;
// 2.4-3. Check for each formation
for( let f of forms ){
let fetched_form = gstore.get.form_by_id(f);
// if formation not found -> ignore
if( fetched_form == null )
continue;
// if formation LABEL matches -> let visible
if( fetched_form.labelForm.toLowerCase().search(buf) >= 0 )
continue main_loop;
}
// XXXX. Hide all that did not match
element.addClass('search-hidden');
}
}, 250);
});
/* (5) Manage instant create
---------------------------------------------------------*/
/* (1) Initialize toggle show */
gstore.add('create_card', false);
/* (2) Initialize inputs */
gstore.add('create_form', '-');
gstore.add('create_label', '');
gstore.add('create_code', '');
gstore.add('create_vol', { c: '', td: '', tp: ''});
/* (3) Initialize error message */
gstore.add('create_err_valid', false);
gstore.add('create_err', '');
/* (4) Define reset handler */
gstore.add('ic_reset', function(){
gstore.add('create_form', '-');
gstore.add('create_label', '');
gstore.add('create_code', '');
gstore.add('create_vol', { c: '', td: '', tp: ''});
gstore.add('create_err_valid', false);
gstore.add('create_err', '');
});
/* (5) Define create handler */
gstore.add('ic_handler', function(){
/* (4.1) Trim text input */
gstore.get.create_label = gstore.get.create_label.trim();
gstore.get.create_code = gstore.get.create_code.trim().toUpperCase();
gstore.get.create_form = gstore.get.create_form.toString().trim();
gstore.get.create_vol.c = gstore.get.create_vol.c.toString().trim();
gstore.get.create_vol.td = gstore.get.create_vol.td.toString().trim();
gstore.get.create_vol.tp = gstore.get.create_vol.tp.toString().trim();
/* (5.4) Store values locally */
var form = gstore.get.create_form;
var label = gstore.get.create_label;
var code = gstore.get.create_code;
var vco = gstore.get.create_vol.c;
var vtd = gstore.get.create_vol.td;
var vtp = gstore.get.create_vol.tp;
/* (5.5) Init client-side check */
var errors = [];
/* (5.5.1) Check formation */
if( isNaN(form) ) errors.push('La formation de l\'UE est manquante');
/* (5.5.2) Check label */
if( typeof label !== 'string' || label.length < 4 )
errors.push('Le label doit comprendre faire au moins 4 caractères');
/* (5.5.3) Check code */
if( !/^[A-Z0-9]{4,20}$/.test(code) )
errors.push('Le code doit comprendre de 4 à 20 lettres/chiffres');
/* (5.5.4) Check volumes */
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.');
/* (4.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.5.1) Création de la requête */
var rq = {
label: label,
code: code,
volumeCours: parseInt(vco), /*TODO*/
volumeTD: parseInt(vtd), /*TODO*/
volumeTP: parseInt(vtp), /*TODO*/
required: false, /*TODO*/
disabled: false /*TODO*/
};
// optional param
if( form != -1 )
rq.defaultFormation = form;
/* (4.5.2) Send request */
api.call('POST ue', rq, function(rs){
console.log(rs);
/* (4.5.2.1) Manage 'already exist' error */
if( rs.error == 29 ){
gstore.get.create_err = 'Le code est déja utilisé.';
return setTimeout(() => gstore.add('create_err', ''), 2000);
}
/* (4.5.2.2) Manage other errors */
if( rs.error !== 0 ){
gstore.get.create_err = 'erreur ('+rs.error+') Impossible de créer l\'UE';
return setTimeout(() => gstore.add('create_err', ''), 2000);
}
/* (4.5.2.3) Show that user is created */
// display all is ok
gstore.add('create_err_valid', true);
gstore.add('create_err', 'L\'UE a été créé, elle s\'affichera au prochain rechargement');
// empty fields
gstore.get.create_form = '-';
gstore.get.create_label = '';
gstore.get.create_code = '';
// 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(ue_id){
/* (1) Abort if wrong ue_id */
if( ue_id == null )
return;
/* (2.1) Find index in gstore */
var gi = gstore.get.ues.map( (data, i) => { return ( data.code && data.code == ue_id ) ? i : ''; }).join('');
/* (2.2) Exit if not found */
if( gi.length === 0 ) return;
var local = gstore.get.ues[gi];
/* (3) Show popup */
(new Promise( (resolve, reject) => {
popup.ask({
title: 'Confirmation de suppression',
content: "La suppression de l'UE <b>"+local.label+" ("+local.code+")</b> est irréversible.<br><br>Voulez-vous lea supprimer définitivement ?",
action: 'Supprimer',
type: 'invalid'
}, (popup_rs) => { popup_rs && resolve() });
/* (4) On pop-up confirmation */
})).then(function(){
return new Promise( (resolve, reject) => {
/* (4.1) Delete UE */
api.call('DELETE ue/'+ue_id, {}, function(rs){
/* (4.1.1) Abort on error */
if( rs.error !== 0 || rs.deleted !== true )
return reject(rs.error);
/* (4.1.2) Success */
resolve();
});
});
/* (5) On success */
}).then(function(){
/* remove from visible */
gstore.get.ues.splice(gi, 1);
/* (6) 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) Init edit_mode */
gstore.add('edit_i', -1);
/* (2) Initialize inputs */
gstore.add('edit_form', '-');
gstore.add('edit_label', '');
gstore.add('edit_code', '');
gstore.add('edit_vol', { c: '', td: '', tp: ''});
/* (3) Initialize error message */
gstore.add('edit_err_valid', false);
gstore.add('edit_err', '');
/* (4) Define toggle view */
gstore.add('ie_toggle', function(ue_i){
/* (4.1) Abort if wrong ue_i */
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
return gstore.add('edit_i', -1);
/* (4.2) Toggle current value */
var ue = gstore.get.ues[ue_i];
/* (4.3) Pre-fill edit values */
gstore.get.edit_form = ue.idForm;
gstore.get.edit_label = ue.label;
gstore.get.edit_code = ue.code;
gstore.get.edit_vol.c = ue.volumeCours;
gstore.get.edit_vol.td = ue.volumeTD;
gstore.get.edit_vol.tp = ue.volumeTP;
/* (4.4) Set card to edit mode */
gstore.get.edit_i = ue_i;
});
/* (5) Confirm update */
gstore.add('ie_handler', function(ue_i){
/* (5.1) Abort if wrong ue_i */
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
return;
/* (5.2) Toggle current value */
var ue = gstore.get.ues[ue_i];
/* (5.3) Trim text input */
gstore.get.edit_label = gstore.get.edit_label.trim();
gstore.get.edit_code = gstore.get.edit_code.toString().trim().toUpperCase();
gstore.get.edit_vol.c = gstore.get.edit_vol.c.toString().trim();
gstore.get.edit_vol.td = gstore.get.edit_vol.td.toString().trim();
gstore.get.edit_vol.tp = gstore.get.edit_vol.tp.toString().trim();
/* (5.4) Store values locally */
var form = gstore.get.edit_form;
var label = gstore.get.edit_label;
var code = gstore.get.edit_code;
var vco = gstore.get.edit_vol.c;
var vtd = gstore.get.edit_vol.td;
var vtp = gstore.get.edit_vol.tp;
/* (5.5) Init client-side check */
var errors = [];
/* (5.5.1) Check formation */
if( isNaN(form) ) errors.push('La formation de l\'UE est manquante');
/* (5.5.2) Check label */
if( typeof label !== 'string' || label.length < 4 )
errors.push('Le label doit comprendre faire au moins 4 caractères');
/* (5.5.3) Check code */
if( !/^[A-Z0-9]{4,20}$/.test(code) )
errors.push('Le code doit comprendre de 4 à 20 lettres/chiffres');
/* (5.5.4) Check volumes */
if( vco === '' || isNaN(vco) || vco < 0 )
errors.push('Le volume horaire de cours 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);
}
/* (5.7) Création de la requête */
var rq = {};
( label != ue.label ) && ( rq.label = label );
( code != ue.code ) && ( rq.new_code = code );
( vco != ue.volumeCours ) && ( rq.volumeCours = parseInt(vco) );
( vtd != ue.volumeTD ) && ( rq.volumeTD = parseInt(vtd) );
( vtp != ue.volumeTP ) && ( rq.volumeTP = parseInt(vtp) );
( form != ue.idForm ) && ( rq.defaultFormation = parseInt(form) );
(new Promise( (resolve, reject) => {
popup.ask({
title: 'Confirmation de modification',
content: `La modification de l'UE <b>${ue.label} (${ue.code})</b> est irréversible.<br><br>Voulez-vous la modifier ?`,
action: 'Modifier',
type: 'search'
}, (popup_rs) => { popup_rs && resolve() });
/* (5.8) On pop-up confirmation */
})).then(function(){
return new Promise( (resolve, reject) => {
/* (5.8.1) Update UE */
api.call(`PUT ue/${ue.code}`, rq, function(rs){
/* (5.8.1.1) Manage 'already exist' error */
if( rs.error == 29 ){
gstore.get.edit_err = 'Le nouveau code est déja utilisé par une autre UE.';
return setTimeout(() => gstore.add('edit_err', ''), 2000);
}
/* (5.8.1.2) Abort on error */
if( rs.error != 0 || rs.updated != true )
return reject(rs.error);
/* (5.8.1.3) Success */
resolve();
});
});
/* (5.9) On success */
}).then(function(){
/* (5.9.1) update VueJS element */
gstore.get.ues[ue_i].label = label;
gstore.get.ues[ue_i].code = code;
gstore.get.ues[ue_i].idForm = parseInt(form);
gstore.get.ues[ue_i].volumeCours = parseInt(vco);
gstore.get.ues[ue_i].volumeTD = parseInt(vtd);
gstore.get.ues[ue_i].volumeTP = parseInt(vtp);
/* (5.9.2) Try to set the formation label */
var fi = gstore.get.formations.map( (data, i) => { return ( data.idForm && data.idForm == form ) ? i : ''; }).join('');
/* (5.9.3) Exit if not found */
if( isNaN(fi) )
return gstore.add('edit_i', -1);
/* (5.9.4) If not found -> set default text */
if( !gstore.get.formations.hasOwnProperty(fi) )
gstore.get.ues[ue_i].labelForm = '';
/* (5.9.5) If found -> set formation label */
else
gstore.get.ues[ue_i].labelForm = gstore.get.formations[fi].labelForm;
/* (5.9.5) Remove edit mode */
gstore.add('edit_i', -1);
/* (5.10) 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 toggle
---------------------------------------------------------*/
/* (1) Define 'disabled' handler */
gstore.add('ia_handler', function(ue_i){
/* (1) Abort if wrong ue_i */
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
return;
/* (2) Toggle current value */
var local = gstore.get.ues[ue_i];
var is_disabled = local.disabled == '1' || local.disabled === true;
var new_state = !is_disabled;
/* (3.1) Update in database */
api.call('PUT ue/'+local.code, { disabled: 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 \'activée\', erreur '+rs.error);
/* (3.1.2) Success */
gstore.get.ues[ue_i].disabled = new_state ? 1 : 0;
});
});
/* (1) Define 'required' / 'optional handler */
gstore.add('io_handler', function(ue_i){
/* (1) Abort if wrong ue_i */
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
return;
/* (2) Toggle current value */
var local = gstore.get.ues[ue_i];
var is_required = local.required == '1' || local.required === true;
var new_state = !is_required;
/* (3.1) Update in database */
api.call('PUT ue/'+local.code, { required: 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 \'requis\' / \'optionnel\', erreur '+rs.error);
/* (3.1.2) Success */
gstore.get.ues[ue_i].required = new_state ? 1 : 0;
});
});
/* (9) Manage 'manage' sub-page
---------------------------------------------------------*/
/* (1) Initialize current opened UE data */
gstore.add('manage', {
cours: [],
td: [],
tp: [],
prof: []
});
/* (2) Function to load UE data */
gstore.add('load_ue_groups', function(code, recur=0){
/* (1) If UE not already loaded -> wait for 200ms */
if( gstore.get.ues.length === 0 && recur > 0 ){
return new Promise( (rs, rj) => setTimeout( () => {
return gstore.get.load_ue_groups(code, --recur).catch( (rj2) => rj(rj2) );
}, 200) );
}
/* (2.1) Check that code is a valid existing UE code */
if( code == null )
return new Promise( (rs, rj) => rj({label: 'interne', code: -1}) );
/* (2.2) Find index in gstore */
var ue_i = gstore.get.ues.map( (data, i) => { return ( data.code && data.code == code ) ? i : ''; }).join('');
/* (2.3) Exit if not found */
if( ue_i.length === 0 )
return new Promise( (rs, rj) => rj({label: 'interne', code: -1}) );
/* (3) Ask for UE Cours data */
return new Promise( (resolve, reject) => {
api.call(`GET ue/cours/${code}`, {}, function(rs){
// erase data
gstore.get.manage.cours.splice(0);
// reject on error
if( rs.error !== 0 || !(rs['groups'] instanceof Array) )
return reject({ label: 'Cours', code: rs.error});
// store data
// for each field add a 'add_form' for instant-adding formations afterwards
for( var group of rs.groups ){
group.add_form = '-';
( group.idProf == null ) && ( group.idProf = -1 );
group.new_prof = group.idProf;
gstore.get.manage.cours.push( group );
}
// resolve data on success
resolve();
});
/* (4) Ask for UE TD data */
}).then( () => {
return new Promise( (resolve, reject) => {
api.call(`GET ue/td/${code}`, {}, function(rs){
// erase data
gstore.get.manage.td.splice(0);
// reject on error
if( rs.error !== 0 || !(rs['groups'] instanceof Array) )
return reject({ label: 'TD', code: rs.error});
// store data
// for each field add a 'add_form' for instant-adding formations afterwards
for( var group of rs.groups ){
group.add_form = '-';
( group.idProf == null ) && ( group.idProf = -1 );
group.new_prof = group.idProf;
gstore.get.manage.td.push( group );
}
// resolve data on success
resolve();
});
});
/* (5) Ask for UE TP data */
}).then( () => {
return new Promise( (resolve, reject) => {
api.call(`GET ue/tp/${code}`, {}, function(rs){
// erase data
gstore.get.manage.tp.splice(0);
// reject on error
if( rs.error !== 0 || !(rs['groups'] instanceof Array) )
return reject({ label: 'TP', code: rs.error});
// store data
// for each field add a 'add_form' for instant-adding formations afterwards
for( var group of rs.groups ){
group.add_form = '-';
( group.idProf == null ) && ( group.idProf = -1 );
group.new_prof = group.idProf;
gstore.get.manage.tp.push( group );
}
// resolve data on success
resolve();
});
});
/* (6) Ask for professors data */
}).then( () => {
return new Promise( (resolve, reject) => {
// 1. if already downloaded
if( gstore.get.manage.prof.length > 0 )
return resolve();
// 2. Else fetch from database
api.call(`GET professor/0`, {}, function(rs){
// erase data
gstore.get.manage.prof.splice(0);
// reject on error
if( rs.error !== 0 || !(rs['professors'] instanceof Array) )
return reject({ label: 'Professeurs', code: rs.error});
// store data
gstore.get.manage.prof = rs.professors;
// resolve data on success
resolve();
});
});
});
})
/* (10) Manage navigation
---------------------------------------------------------*/
/* (1) Initialize current opened UE */
gstore.add('nav_anim', {
in: false,
out: false
});
/* (2) Manage nav in */
gstore.add('nav_in', function(ue_i){
/* (1) Abort if wrong ue_i */
if( ue_i == null || isNaN(ue_i) || gstore.get.ues[ue_i] == null)
return;
/* 1. Start animation */
gstore.get.nav_anim.in = true;
setTimeout( () => {
/* 2. Load page */
gstore.get.router.push(`/ue/manage/${gstore.get.ues[ue_i].code}`);
/* 3. Stop animation */
gstore.get.nav_anim.in = false;
}, 500 );
});
/* (3) Manage nav out */
gstore.add('nav_out', function(){
/* 1. Start animation */
gstore.get.nav_anim.out = true;
setTimeout( () => {
/* 2. Load page */
gstore.get.router.push(`/ue/view/`);
/* 3. Stop animation */
gstore.get.nav_anim.out = false;
/* 4. Remove 'manage' data */
gstore.get.manage.cours.splice();
gstore.get.manage.td.splice();
gstore.get.manage.tp.splice();
}, 500 );
});
/* (11) Manage 'manage' inline modifications
---------------------------------------------------------*/
/* (1) Remove a formation */
gstore.add('rem_form', function(type, res_i, id_form){
// 1. Check params types
if( isNaN(type) || isNaN(res_i) || isNaN(id_form) )
return;
// 2. Check @type param
if( [0,1,2].indexOf(type) == -1 )
return;
// 3. extract API resource from @type
var res = [ 'cours', 'td', 'tp' ][type];
var resM = [ 'Cours', 'TD', 'TP' ][type];
// 4. Extract @resource from @res_i
var resource = gstore.get.manage[res][res_i];
// 4- Manage unreachable resource
if( resource == null )
return;
// 5. Extract resource ID
var res_id = resource[`id${resM}`];
// 6. Request to remove formation
api.call(`PUT ue/${res}/${res_id}`, { rem_form: [id_form] }, (rs) => {
// 6.1. Manage error
if( rs.error !== 0 || rs.updated !== true )
return;
// 6.2. Get reference of data in gstore (if Cours, TD, TP)
var local = gstore.get.manage[res];
// 6.3. Unset formation to remove from view
for( var f_index in resource.formations ){ // search its index
// if found -> remove by index
if( resource.formations[f_index] === id_form ){
resource.formations.splice(f_index, 1);
break;
}
}
});
});
/* (2) Add a formation */
gstore.add('add_form', function(type, res_i){
// 1. Check params types
if( isNaN(type) || isNaN(res_i) )
return;
// 2. Check @type param
if( [0,1,2].indexOf(type) == -1 )
return;
// 3. extract API resource from @type
var res = [ 'cours', 'td', 'tp' ][type];
var resM = [ 'Cours', 'TD', 'TP' ][type];
// 4. Extract @resource from @res_i
var resource = gstore.get.manage[res][res_i];
// 4- Manage unreachable resource
if( resource == null )
return;
// 5. Extract resource ID
var res_id = resource[`id${resM}`];
// 6. Extract <select> formation id
var id_form = resource.add_form;
// 7. Exit if not a number
if( isNaN(id_form) )
return;
// 8. Request to add formation
api.call(`PUT ue/${res}/${res_id}`, { add_form: [id_form] }, (rs) => {
// 7.1. Manage error
if( rs.error !== 0 || rs.updated !== true )
return;
// 7.2. Unselect the <select>
resource.add_form = '-';
// 7.3. Add formation to update VueJS
resource.formations.push(id_form);
});
});
/* (3) Update a prof (set or unset) */
gstore.add('upd_prof', function(type, res_i){
// 1. Check params types
if( isNaN(type) || isNaN(res_i) )
return;
// 2. Check @type param
if( [0,1,2].indexOf(type) == -1 )
return;
// 3. extract API resource from @type
var res = [ 'cours', 'td', 'tp' ][type];
var resM = [ 'Cours', 'TD', 'TP' ][type];
// 4. Extract @resource from @res_i
var resource = gstore.get.manage[res][res_i];
// 4- Manage unreachable resource
if( resource == null )
return;
// 5. Extract resource ID
var res_id = resource[`id${resM}`];
// 6. Extract <select> professor id
var new_prof_id = resource.new_prof;
// 7. Exit if not a number
if( isNaN(new_prof_id) )
return;
// 8. Exit if same value
if( new_prof_id == resource.idProf )
return;
// 9. Request to add formation
api.call(`PUT ue/${res}/${res_id}`, { idProf: parseInt(new_prof_id) }, (rs) => {
// 9.1. On error -> reset <select> to default value
if( rs.error !== 0 || rs.updated !== true )
return ( resource.new_prof = resource.idProf );
// 9.2. Update the prof data
resource.idProf = new_prof_id;
// 9.3. Update <select> VueJS if changed
resource.new_prof = new_prof_id;
});
});
/* (4) Ordering filters */
gstore.add('order', {
available: ['prof', 'volume', 'forms'],
current: 0,
way: 1 // 1 ASC, -1 DESC
});
gstore.add('order_toggle', function(ord_i){
// 1. Check params types
if( isNaN(ord_i) || gstore.get.order.available[ord_i] == null )
return;
// 2. If new ordering field -> toggle it
if( ord_i !== gstore.get.order.current )
gstore.get.order.current = ord_i;
// 3. If already selected -> toggle way
else
gstore.get.order.way *= -1;
// 4. Get all elements to order
let els = document.querySelectorAll('section[data-prof][data-vol][data-form]');
// 5. Ordering by formations
if( gstore.get.order.current === 2 ){
return els.forEach((el) => {
el.style.order = el.getAttribute('data-form').split('|').length * gstore.get.order.way
});
}
// 6. Ordering by 'volume'
if( gstore.get.order.current === 1 )
return els.forEach((el) => {
el.style.order = parseInt( el.getAttribute('data-vol') ) * gstore.get.order.way
});
// 7. Ordering by 'prof'
els.forEach((el) => {
var profId = parseInt( el.getAttribute('data-prof') );
// outside by default if no prof set
el.style.order = - gstore.get.order.way;
// professors are already sorted
for( pi in gstore.get.manage.prof ) {
if( gstore.get.manage.prof[pi].idProfesseur == profId ){
el.style.order = pi * gstore.get.order.way;
break;
}
}
});
});
/* (12) Create|Remove a Cours|TD|TP
---------------------------------------------------------*/
/* (1) Remove a Cours|TD|TP */
gstore.add('rem', function(type, res_i){
// 1. Check params types
if( isNaN(type) || isNaN(res_i) )
return;
// 2. Check @type param
if( [0,1,2].indexOf(type) == -1 )
return;
// 3. extract API resource from @type
var res = [ 'cours', 'td', 'tp' ][type];
var resM = [ 'Cours', 'TD', 'TP' ][type];
// 4. Extract @resource from @res_i
var resource = gstore.get.manage[res][res_i];
// 4- Manage unreachable resource
if( resource == null )
return;
// 5. Extract resource ID
var res_id = resource[`id${resM}`];
// 6. Popup ask
(new Promise( (resolve, reject) => {
popup.ask({
title: 'Confirmation de suppression',
content: `La suppression du ${resM} est irréversible.<br><br>Voulez-vous le supprimer définitivement ?`,
action: 'Supprimer',
type: 'invalid'
}, (popup_rs) => { popup_rs && resolve() });
// 7. On popup confirm
})).then( () => {
return new Promise( (resolve, reject) => {
// 7.1. delete cours,td,tp
api.call(`DELETE ue/${res}/${res_id}`, {}, function(rs){
// reject on error
if( rs.error !== 0 || rs.deleted !== true )
return reject(rs.error);
// else -> resolve
resolve();
});
});
// 8. On success -> update VueJS
}).then( () => {
/* remove from visible */
gstore.get.manage[res].splice(res_i, 1);
/* (6) 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'
}, () => {});
});
});
/* (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.router.history.current.path.split('/').pop(),
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`] = rs.formations;
newRes[`add_form`] = '-';
newRes[`new_prof`] = prof;
gstore.get.manage[restyp].push(newRes);
});
});