var majpushed = false; var selectedDay; window.planning = null; //CHARGEMENT DE LA PAGE function init_plugin_planning(){ switch($.urlParam('page')){ default: break; } $(window).resize(function() { if(window.planning) window.planning.setOption('height', $(window).height()*0.83); }); planning_set_type(); if($('.planning-page').attr('data-event-editable')=='0') $('#planning-event-form').find('input,select,textarea').attr('readonly','readonly'); $( "#planning-datepicker" ).datepicker({ dayNames: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"], dayNamesMin: ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"], dayNamesShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], changeMonth: true, changeYear: true, monthNames: ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"], monthNamesShort: ["Jan","Fév","Mars","Avr","Mai","Juin","Juil","Aout","Sept","Oct","Nov","Déc"], onSelect : function(date,element){ date = date.split('/'); window.planning.gotoDate(date[2]+'-'+date[0]+'-'+date[1]); } }); $('#planning-event-form #label').enter(function(){ planning_event_save(); }); planning_search(function(){ planning_calendar_init(); }); $(document).keydown(function(e){ switch(e.keyCode){ //Appuis sur maj case 16: majpushed = true; break; //Appuis sur suppr case 46: var group = $('.event-selected').attr('data-group'); //si le group est vide on supprime uniquement l'event sélectionné if(!group) return planning_event_delete($('.prime-event-selected')); //Si un groupe existe on verifie que d'autres evenements sont liés $.action({ action : 'planning_group_events_search', group : group },function(response){ //Si d'autres évenements sont liés, on propose a l'utilisateur de les supprimer if(response.rows.length > 1){ planning_instance(function(target){ if(target == 'group'){ planning_event_delete($('.event-selected')); }else{ planning_event_delete($('.prime-event-selected')); } }); //Si aucun évenement est lié, on supprime uniquement l'evenement courant }else{ planning_event_delete($('.prime-event-selected')); } }); break; } }); //relachage du maj $(document).keyup(function(e){ if(e.keyCode!=16) return; majpushed = false; }); } function planning_instance(callback){ $('#event-group-modal').modal('show'); $('#event-group-modal .event-group-option li').off('click').click(function(){ $('#event-group-modal').modal('hide'); callback($(this).attr('data-target')); }); } function init_setting_planning(){ planning_event_type_search(); window.onbeforeunload = function(e){ if(!planningMenuEdited) return e = null; return "Certaines modifications sur le menu n'ont pas été sauvgardées.\nÊtes-vous sûr de vouloir quitter la page ?"; }; $( ".planning-types" ).sortable({ handle: ".planning-type-handler", cancel: ".not-editable", helper: "clone", opacity: 0.8, distance : 15, grid: [ 50, 1 ], update : function(){ planningMenuEdited = true; }, start: function(e,ui) { draggedItem = $(ui.item[0]); if(draggedItem.hasClass('planning-line-child')) return; children = []; var borderReached = false; $.each(draggedItem.nextAll('li.planning-line'), function(i, childLine){ var line = $(childLine); if(borderReached || !line.hasClass('planning-line-child')) { borderReached = true; return; } children.push(line); line.addClass('hidden'); }); }, sort: function(event,ui){ var leftLimit = ui.item.hasClass('planning-line-child') ? -20 : 15; if(ui.position.left < leftLimit){ ui.helper.css('left',leftLimit+'px'); } if(ui.position.left > 65){ left = 65; ui.helper.css('left',left+'px'); } if(ui.item.index()==1){ ui.helper.css('left',leftLimit+'px'); } }, stop: function(event,ui){ if(ui.position.left>15){ if(!ui.item.hasClass('planning-line-child')) planningMenuEdited = true; ui.item.addClass('planning-line-child'); }else{ if(ui.item.hasClass('planning-line-child')) planningMenuEdited = true; ui.item.removeClass('planning-line-child'); } if(!children.length) return; $.each(children.reverse(), function(i, row){ $(row).insertAfter(draggedItem).removeClass('hidden'); }); }, placeholder: { element: function(clone, ui) { var placeholderRow = $('
'); /** Lié à la feature de drag&drop de plusieurs lignes à la fois **/ if(!clone.hasClass('planning-line-child')){ var rowNb = 1; var borderReached = false; $.each(clone.nextAll('li.planning-line'), function(i, childLine){ var line = $(childLine); if(borderReached || !line.hasClass('planning-line-child')) { borderReached = true; return; } rowNb += 1 }); placeholderRow.css({ height: 'calc(44px * '+rowNb+')', }); } return placeholderRow; }, update: function() { return; } } }).disableSelection(); } /** PLANNING **/ //Récuperation d'une liste de planning dans le tableau #plannings function planning_search(callback){ $.action({ action:'planning_search' },function(r){ var planning = $('#plannings'); var sharedPlanning = $('#shared-plannings'); planning.find('li:visible').remove(); sharedPlanning.find('li:visible').remove(); var tpl = $('li.hidden',planning).get(0).outerHTML; var options = ''; for(var k in r.rows){ var line = r.rows[k]; options +=''; var li = $(Mustache.render(tpl,line)); if(line.selected) li.find('input').prop('checked',true); if(line.shared){ sharedPlanning.append(li); }else{ planning.append(li); } li.removeClass('hidden'); } $('#event-planning').html(options); if(callback!=null) callback(); }); } //Ajout ou modification d'élément planning function planning_save(){ var data = $('#planning-form').toJson(); data.action = 'planning_save'; $.action(data,function(r){ $.message('success','Enregistré'); $('#planningModal').modal('hide'); planning_search(); }); } //Récuperation ou edition d'élément planning function planning_edit(element){ var data = {}; if(element) data.id = $(element).closest('li').attr('data-id'); $('#planningModal .modal-content').load('action.php?action=planning_edit',data,function(){ init_components('#planningModal .modal-content'); planning_share_search(); }); $('#planningModal').modal('show'); } function planning_set_type(){ var type = $('#planning-event-type option:selected').val() var subInput = $('#planning-event-subtype'); $.action({ action : 'planning_subtype_search', type : type },function(r){ $('option',subInput).remove(); for(var k in r.rows){ var line = r.rows[k]; subInput.append(''); } init_components(subInput.parent()); }); } //Suppression d'élement planning function planning_delete(element){ if(!confirm('Êtes vous sûr de vouloir supprimer cet item ?')) return; var line = $(element).closest('li'); $.action({ action : 'planning_delete', id : line.attr('data-id') },function(r){ line.remove(); window.planning.refetchEvents(); $.message('info','Élement supprimé'); }); } function planning_select(){ window.planning.refetchEvents(); } //Récuperation d'une liste de planning dans le tableau #plannings function planning_calendar_init(callback){ var plannings = []; var planningMenuEdited = false; var clickCnt = 0; var data = $('#planning').data(); window.planning = new FullCalendar.Calendar($('#planning').get(0),{ locale:'fr', initialView: data.view, plugins: [ TeammateViewPlugin ], nextDayThreshold: '00:00:00', height: $(window).height()*0.83, navLinks: true, // can click day/week names to navigate views editable: false, businessHours : true, dayMaxEvents: true, // autorise le lien + d'evenement si trop d'evenements selectable: true, buttonText : { today: 'Aujourd\'hui', month: 'Mois', week: 'Semaine', day: 'Jour', list: 'Liste' }, customButtons: { refreshButton: { text: '', click: function() { window.planning.refetchEvents(); } }, teammateButton: { text: 'Equipe', click: function () { window.planning.changeView('teammate'); } } }, headerToolbar: { left: 'prev,next today refreshButton', center: 'title', //right: 'teammateButton,dayGridMonth,timeGridWeek,timeGridDay,listMonth' right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth' }, //lancé lorsque qu'une nouvelle vue est chargée viewDidMount: function(data) { //force fullcalendar a recharger les evenements lors du changement de la vue (ie: la vue equipe n'affiche pas les même event que la vue mois) window.planning.refetchEvents(); //ajout l'icone de refresh au boutton rafraichir $('.fc-refreshButton-button').html(''); }, //custom d'evenemment en virtual DOM eventContent: function(arg, createElement) { /*var innerText if (arg.event.extendedProps.isUrgent) { innerText = 'urgent event' } else { innerText = 'normal event' } return createElement('div', {}, innerText);*/ }, //modif pour chaque event après chargement eventDidMount: function(data) { if(data.event.end == null || data.event.start == null) return; var event = data.event; var start = moment(event.start); var end = moment(event.end); var startDay = start.format("DD/MM/YYYY"); var endDay = end.format("DD/MM/YYYY"); var startSchedule = start.format("HH:mm"); var endSchedule = end.format("HH:mm"); var location = event.extendedProps.location == null ? '' : event.extendedProps.location; var description = event.extendedProps.description == null ? '' : event.extendedProps.description; var info = "Du "+startDay+" au "+endDay+"\r"+event.title+"\r"+'De '+startSchedule+' à '+endSchedule+"\r"+description+"\r"+location; var element = $(data.el); element.attr("title", info).attr('data-tooltip',event.id).attr('data-id',event.id); if(event.display=='background') return; element.find('.fc-event-title').append(' '); if(event.extendedProps.underlineColor) element.css({ 'border-left':'4px solid '+event.extendedProps.underlineColor, 'border-bottom-left-radius':'0', 'border-top-left-radius':'0' }); //selection de l'event dont l'id est en parametre event si existant if($.urlParam('event')){ if(event.id==$.urlParam('event')) $('.fc-event[data-id="'+$.urlParam('event')+'"]').addClass('event-selected'); $('#planning').addClass('event-selected-mode'); } init_tooltips(element.parent()); }, //options spéciales pour chaques vues views : { //vue teammate teammate : { addTeammate : function(teammates){ $.action({ action : 'planning_teammate_save', teammates : teammates },function(response){ window.planning.view.renderTeammates(response.teammates); window.planning.refetchEvents(); }); }, sortTeammate : function(sort){ $.action({ action : 'planning_teammate_sort', sort : sort },function(response){ }); }, highlight: '.fc-teammate-line[data-teammate="'+$('#planning').attr('data-user')+'"]', dateIncrement: { days: 7 }, visibleRange: function(currentDate) { currentDate = moment(currentDate); var startOfMonth = currentDate.clone().startOf('week'); var endOfMonth = currentDate.clone().endOf('week'); return { start: startOfMonth.clone(), end: endOfMonth.clone() }; }, teammates : JSON.parse($('.planning-teammates').html()), }, }, //Récuperation ajax des évenements events: { url: 'action.php?action=planning_event_search', //parametre ajax dynamic (planning sélectionné, equipiers etc...) extraParams: function(){ parameters = { plannings : [] }; var teammates = JSON.parse($('.planning-teammates').html()); parameters.teammates = []; for(var i in teammates){ parameters.teammates.push(teammates[i].login); } parameters.view = $('.fc-view-harness > div').attr('class'); if(!parameters.view) return; parameters.view = $('.fc-view-harness > div').attr('class').match(/fc-([^-]*)-view/i); parameters.view = parameters.view.length>1 ? parameters.view[1] : ''; $('.planning-list li:visible input:checked').each(function(i,input){ parameters.plannings.push($(input).closest('li').attr('data-id')) }); return parameters; }, failure: function() { $('#script-warning').removeClass('hidden'); } }, //Appellé lors début/fin de chargement du planning loading: function(isLoading){ if(isLoading){ $('.fc-refreshButton-button').html($('.planning-loader').html()); }else{ $('.fc-refreshButton-button').html(''); } }, dateClick: function(data) { $('prime-event-selected').removeClass('prime-event-selected'); $('.event-selected').removeClass('event-selected'); selectedDay = { element : $(this), view : data.view.type, date : moment(data.date) }; if($('.planning-page').attr('data-event-editable')=='0') return; var calculatedEnd = ''+parseInt(selectedDay.date.format("HH"))+1; var newEvent = { startDate : selectedDay.date.format("DD/MM/YYYY"), endDate : selectedDay.date.format("DD/MM/YYYY"), startHour : selectedDay.date.format("HH"), endHour : "00".substring(0, 2 - calculatedEnd.length) + ''+ calculatedEnd, startMinut : selectedDay.date.format("mm"), endMinut : selectedDay.date.format("mm") }; switch(selectedDay.view){ case 'teammate': newEvent.user = selectedDay.element.closest('tr').attr('data-teammate'); if(selectedDay.date.format("HH") == '00'){ var startTime = $('#planning').attr('data-start-hour') ? $('#planning').attr('data-start-hour') : '09:00'; }else{ var startTime = '12:00'; } startTime = startTime.split(':'); newEvent.startHour = startTime[0]; newEvent.startMinut = startTime[1]; break; case 'dayGridMonth': newEvent.startHour = '08'; newEvent.endHour = '12'; newEvent.startMinut = '00'; newEvent.endMinut = '00'; var planningConf = $('#planning').data(); var defaultStart = planningConf.startHour.split(':'); var defaultEnd = planningConf.endHour.split(':'); if(defaultStart.length==2){ newEvent.startHour = defaultStart[0]; newEvent.startMinut = defaultStart[1]; } if(defaultEnd.length==2){ newEvent.endHour = defaultEnd[0]; newEvent.endMinut = defaultEnd[1]; } break; } var end = moment(newEvent.startDate+' '+newEvent.startHour+':'+newEvent.startMinut, 'DD/MM/YYYY HH:mm').add(2,'hour'); newEvent.endHour = end.format('HH'); newEvent.endMinut = end.format('mm'); planning_event_edit(newEvent,$(data.dayEl)); data.jsEvent.stopPropagation(); }, eventClick: function(data) { clickCnt++; //Simple clic, on sélectionne l'event if(clickCnt === 1){ oneClickTimer = setTimeout(function() { clickCnt = 0; if(!majpushed) $('.event-selected').removeClass('event-selected'); var target = $(data.el); var group = target.attr('data-group'); target.addClass('prime-event-selected'); if(group != null && group != ''){ target = $('[data-group="'+group+'"]'); }else{ target = $('[data-id="'+target.attr('data-id')+'"]'); } if(!$(data.el).hasClass('event-selected')){ $('#planning').addClass('event-selected-mode'); target.addClass('event-selected'); target.addClass('prime-event-selected'); }else{ $('#planning').removeClass('event-selected-mode'); target.removeClass('event-selected'); target.removeClass('prime-event-selected'); } }, 400); //Double clic, on ouvre la modale }else if(clickCnt === 2){ clearTimeout(oneClickTimer); clickCnt = 0; $('prime-event-selected').removeClass('prime-event-selected'); $('.event-selected').removeClass('event-selected'); var start = moment(data.event.start); var end = moment(data.event.end); //obligé de copier l'objet car définit comme non extensible par fullcalendar var props = Object.assign({}, data.event.extendedProps, {selected:false}); var event = $.extend(props,{ id : data.event.id, label : data.event.title, startDate : start.format("DD/MM/YYYY"), endDate : end.format("DD/MM/YYYY"), startHour : start.format("HH"), endHour : end.format("HH"), startMinut : start.format("mm"), endMinut : end.format("mm") }); if(data.view.type == 'teammate') event.user = $(this).closest('tr').attr("data-teammate"); planning_event_edit(event,$(data.el).closest('.fc-day')); data.jsEvent.stopPropagation(); } }, /* eventMouseEnter: function(options){}, */ eventDrop: function(data) { if($('.planning-page').attr('data-event-editable')=='0') return; if(data.event == null) return; if(data.event.end == null || data.event.start == null) return null; var event = planning_convert_event(data.event); $.action({ action : 'planning_event_move', view : window.planning.view.type, event : event }); }, eventResize: function(data ) { if($('.planning-page').attr('data-event-editable')=='0') return; if(data.event == null) return; var event = planning_convert_event(data.event); planning_event_save(event,function(r){ if(r.error )revertFunc(); }); } }); window.planning.render(); if($.urlParam('start')) window.planning.gotoDate($.urlParam('start')); $('#planning').click(function(){ planning_panel_show(false); if(!majpushed){ $('.event-selected').removeClass('event-selected'); $('#planning').removeClass('event-selected-mode'); } }); } //verifie la coherence date/heure début/fin et corrige au besoin function planning_checkstart_end(){ if(!$('#startDate').val()) return; var start = moment($('#startDate').val()+' '+$('#startTime').val(),'DD/MM/YYYY HH:mm'); if(!$('#endDate').val()) $('#endDate').val(start.format('DD/MM/YYYY')); if(!$('#endTime').val()) $('#endTime').val( moment(start).add(1,'hour').format('HH:mm') ); var end = moment($('#endDate').val()+' '+$('#endTime').val(),'DD/MM/YYYY HH:mm'); if(end