fullcalendar.kiss.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*var FC = $.fullCalendar; // a reference to FullCalendar's root namespace
  2. var View = FC.View; // the class that all views must inherit from
  3. var TeammateView = FC.ListView = View.extend({ // make a subclass of View
  4. initialize: function () {
  5. //console.log("initialize");
  6. },
  7. destroy: function() {
  8. //console.log('destroy ');
  9. // <your custom cleanup-code here>
  10. // call the super-class's method, forwarding all arguments
  11. //View.prototype.triggerViewDestroy.apply(this, arguments);
  12. },
  13. setHeight: function(height, isAuto) {
  14. //console.log('set height',height,isAuto);
  15. // responsible for adjusting the pixel-height of the view. if isAuto is true, the
  16. // view may be its natural height, and `height` becomes merely a suggestion.
  17. console.log('setHeight ');
  18. },
  19. destroyEvents: function() {
  20. // console.log('destroy events');
  21. $('.fc-event',this.el).remove();
  22. // responsible for undoing everything in renderEvents
  23. },
  24. render: function () {
  25. // console.log('render');
  26. var view = this;
  27. //if(this.el.find('.fc-teammate').length!=0) return;
  28. //Récuperation du squelette html de la vue
  29. view.el.addClass('fc-teammate-view').html( $('.planning-teammate-view').html());
  30. view.el.find('.fc-widget-content').sortable({
  31. handle: ".fc-teammate-label",
  32. axis: "y",
  33. update : function(){
  34. if(!view.options.views.teammate.sortTeammate) return;
  35. var sort = [];
  36. $('.fc-teammate-line:visible',view.el).each(function(i,tr){
  37. sort.push($(tr).attr('data-teammate'));
  38. });
  39. view.options.views.teammate.sortTeammate(sort);
  40. },
  41. //permet de conserver la largeur des lignes lors du sort
  42. helper: function(e, tr)
  43. {
  44. var originals = tr.children();
  45. var helper = tr.clone();
  46. helper.children().each(function(index)
  47. {
  48. $(this).width(originals.eq(index).width());
  49. });
  50. return helper;
  51. }
  52. });
  53. var teammates = view.options.views.teammate.teammates;
  54. //rendu des jours
  55. view.renderHeader();
  56. //rendu des equipiers
  57. view.renderTeammates(teammates);
  58. //evenements
  59. //ouverture de la modale de gesiton equipiers
  60. $('.btn-teammate-add',view.el).click(function(){
  61. $('#teammate-modal').modal();
  62. var teammates = view.options.views.teammate.teammates;
  63. var logins = [];
  64. for(var k in teammates){
  65. logins.push(teammates[k].login);
  66. }
  67. //Affichage des equipiers sélectionnés
  68. $('.teammate-picker input').each(function(i,input){
  69. var user = $(input).data();
  70. $(input).prop('checked',(logins.indexOf(user.login) !== -1)).trigger('change');
  71. });
  72. });
  73. //Sauvegarde des equipiers
  74. $('#teammate-modal .btn-save').click(function(){
  75. if(view.options.views.teammate.addTeammate){
  76. var teammates = [];
  77. var teammatesLogins = [];
  78. $('.teammate-picker input').each(function(i,input){
  79. var user = $(input).data();
  80. if($(input).prop('checked')){
  81. teammates.push(user);
  82. teammatesLogins.push(user.login);
  83. }
  84. });
  85. var response = view.options.views.teammate.addTeammate(teammatesLogins);
  86. if(response != false){
  87. view.options.views.teammate.teammates = teammates;
  88. $('#teammate-modal').modal('hide');
  89. }
  90. }
  91. });
  92. },
  93. setHeight: function (height, isAuto) {
  94. //console.log("setHeight");
  95. },
  96. //Rendu des lignes equipiers
  97. renderTeammates : function(teammates){
  98. var view = this;
  99. var bodyTable = this.el.find('.fc-widget-content');
  100. $('.fc-teammate-line').remove();
  101. for(var k in teammates){
  102. var user = teammates[k];
  103. var current = moment(this.start).add(-1 , 'days');
  104. html = '<tr class="fc-teammate-line" data-teammate="'+user.login+'">';
  105. html += '<td class="fc-teammate-label"><div class="media"><img class="avatar avatar-mini avatar-rounded align-self-center mr-2" src="'+user.avatar+'"><span class="media-body">'+user.firstname+' '+user.name+'</span></div></td>';
  106. for(i=0;i<7;i++){
  107. current.add(1 , 'days');
  108. html+= '<td class="fc-day fc-widget-content fc-'+current.format('dd')+' '+(current.format('DD-MM-YYYY') == moment().format('DD-MM-YYYY') ? 'fc-today' :'') +'" data-date="'+current.format('YYYY-MM-DD')+'"><div class="morning"></div><div class="afternoon"></div></td>';
  109. }
  110. html += '</tr>';
  111. bodyTable.append(html);
  112. }
  113. if(view.options.highlight) $(view.options.highlight).addClass('highlight');
  114. },
  115. //Rendu des jours dans l'en-tete tableau
  116. renderHeader : function(){
  117. var headTable = this.el.find('.fc-head-container tr');
  118. var current = moment(this.start).add(-1 , 'days');
  119. for(i=0;i<7;i++){
  120. current.add(1 , 'days');
  121. headTable.append('<th class="fc-day-header fc-widget-header fc-'+current.format('dd')+'"><span>'+current.format('dddd Do')+'</span></th>');
  122. }
  123. },
  124. //rendu des cellules de jour pour chaque ligne equipier
  125. renderUserDate : function(){
  126. var teammates = this.options.views.teammate.teammates;
  127. for(var k in teammates){
  128. var user = teammates[k];
  129. var current = moment(this.start).add(-1 , 'days');
  130. var userLine = $('tr[data-teammate="'+user.login+'"]');
  131. //userLine.find('.fc-event').remove();
  132. for(i=0;i<7;i++){
  133. current.add(1 , 'days');
  134. var cell = userLine.find('td.fc-day:eq('+i+')');
  135. cell.attr('class','fc-day fc-widget-content fc-'+current.format('dd')+' '+(current.format('DD-MM-YYYY') == moment().format('DD-MM-YYYY') ? 'fc-today' :'') )
  136. .attr('data-date',current.format('YYYY-MM-DD'));
  137. }
  138. }
  139. },
  140. //rendu des évenements dans les cellules de jours equipiers
  141. renderEvents: function (events) {
  142. //console.log("renderEvents");
  143. var dailyEvents = [];
  144. var bodyTable = this.el.find('.fc-widget-content');
  145. var headTable = this.el.find('.fc-head-container tr');
  146. var teammates = this.options.views.teammate.teammates;
  147. var current = moment(this.start).add(-1 , 'days');
  148. for(i=0;i<7;i++){
  149. current.add(1 , 'days');
  150. var cell = headTable.find('.fc-day-header:eq('+(i)+')');
  151. cell.attr('class','fc-day-header fc-widget-header fc-'+current.format('dd')).find('span').html(current.format('dddd Do'));
  152. }
  153. this.renderUserDate();
  154. var view = this;
  155. if(view.options.dayClick){
  156. $('.fc-day .morning,.fc-day .afternoon').click(function(jsEvent){
  157. var day = $(this).parent();
  158. this.dayClick = view.options.dayClick;
  159. this.dayClick(moment(day.attr('data-date')+' '+ ($(this).hasClass('morning')? '00:00': '12:00') ),jsEvent,view);
  160. });
  161. }
  162. this.el.find('.fc-day').css('backgroundColor','');
  163. //events
  164. for(var i in events){
  165. var event = events[i];
  166. if(event.rendering && event.rendering=='background'){
  167. this.el.find('.fc-day[data-date="'+event.start.format('YYYY-MM-DD')+'"]').css('backgroundColor',event.backgroundColor);
  168. continue;
  169. }
  170. htmlEvent = '<div data-id="'+event.id+'" data-group="'+event.group+'" \
  171. style="background-color:'+event.backgroundColor+';color:'+event.textColor+';border-color:'+event.borderColor+';" \
  172. class="fc-event fc-content pointer '+(!event.editable ?'event-readonly':'')+'" \
  173. title="'+event.title+'"><i class="far fa-user-circle"></i> '+event.title+'</div>';
  174. for (i=0;i<= event.end.diff(event.start, 'days');i++){
  175. current = moment(event.start).add(i, 'days');
  176. var cell = this.el.find('tr[data-teammate="'+event.planningOwner+'"] [data-date="'+current.format('YYYY-MM-DD')+'"]');
  177. var halfes = [];
  178. //si le jour est entre les deux dates on remplis après midi et matin
  179. if( event.start.format('D') == current.format('D') ){
  180. if(event.start.format('H') < 12) halfes.push('morning');
  181. if(event.start.format('H') >= 12 || event.start.format('D')<event.end.format('D') ) halfes.push('afternoon');
  182. }
  183. if(current.format('D') == event.end.format('D') ){
  184. if(event.end.format('H') < 12) halfes.push('morning');
  185. if(event.end.format('H') >= 12) halfes.push('afternoon');
  186. }
  187. if( event.start.format('D') < current.format('D') && current.format('D') < event.end.format('D')){
  188. halfes.push('morning');
  189. halfes.push('afternoon');
  190. }
  191. //déduplique les matinée / après midi en double
  192. halfes = halfes.filter((item,index)=> halfes.indexOf(item) === index);
  193. for(var u in halfes){
  194. var nodeEvent = $(htmlEvent);
  195. nodeEvent.data('event',event);
  196. cell.find('.'+halfes[u]).append(nodeEvent);
  197. if(view.options.eventClick ){
  198. nodeEvent.click(function(jsEvent){
  199. this.eventClick = view.options.eventClick;
  200. this.eventClick(event,jsEvent,view);
  201. });
  202. }
  203. if(view.options.eventMouseover){
  204. nodeEvent.mouseover(function(jsEvent){
  205. this.eventMouseover = view.options.eventMouseover;
  206. this.eventMouseover(event,jsEvent,view);
  207. });
  208. }
  209. }
  210. if(this.options.eventRender) this.options.eventRender(event, nodeEvent,this);
  211. }
  212. var view = this;
  213. $(".fc-event:not(.event-readonly)" ).draggable({
  214. revert: "invalid", // when not dropped, the item will revert back to its initial position
  215. containment: ".fc-body",
  216. snap: ".afternoon,.morning",
  217. cursor: "move"
  218. });
  219. $( ".afternoon,.morning" ).droppable({
  220. accept: ".fc-event",
  221. classes: {
  222. "ui-droppable-active": "custom-state-active"
  223. },
  224. drop: function( event, ui ) {
  225. $(this).append(ui.draggable.detach().css({
  226. top : 0,
  227. left : 0
  228. }));
  229. var date = $(this).closest('.fc-day').attr('data-date');
  230. var event = ui.draggable.data('event');
  231. if($(this).hasClass('morning')){
  232. event.start = moment(date+' 08:00');
  233. event.end = moment(date+' 11:59');
  234. }else{
  235. event.start = moment(date+' 12:01');
  236. event.end = moment(date+' 17:00');
  237. }
  238. event.teammate = $(this).closest('.fc-teammate-line').attr('data-teammate');
  239. if(view.options.eventDrop) view.options.eventDrop(event,null,function(){
  240. });
  241. }
  242. });
  243. }
  244. if(view.options.eventAfterAllRender) view.options.eventAfterAllRender();
  245. }
  246. });
  247. //Enregistrement de la classe de vue dans les vues fullcalendar
  248. FC.views.teammate = TeammateView ;
  249. */
  250. const { sliceEvents, createPlugin, Calendar } = FullCalendar
  251. const CustomViewConfig = {
  252. classNames: [ 'custom-view' ],
  253. content: function(props,callback) {
  254. console.log('content');
  255. //console.log(props);
  256. let segs = sliceEvents(props, true); // allDay=true
  257. var html = '';
  258. var view = $($('.planning-teammate-view').html());
  259. var data = { days : []};
  260. var current = moment(props.dateProfile.currentRange.start).add(-1 , 'days');
  261. for(i=0;i<7;i++){
  262. current.add(1 , 'days');
  263. view.find('.fc-head tr:eq(0)s').append('<th class="fc-day-header fc-widget-header fc-'+current.format('dd')+'"><span>'+current.format('dddd Do')+'</span></th>');
  264. }
  265. html = view.get(0).outerHTML;
  266. /*html +=
  267. '<div class="view-title">' +
  268. props.dateProfile.currentRange.start.toUTCString() +
  269. '</div>' +
  270. '<div class="view-events">' +
  271. segs.length + ' events:' +
  272. '<ul>' +
  273. segs.map(function(seg) {
  274. return seg.def.title + ' (' + seg.range.start.toUTCString() + ')'
  275. }).join('') +
  276. '</ul>' +
  277. '</div>'*/
  278. return { html: html }
  279. },
  280. didMount : function(data){
  281. console.log('didmount');
  282. console.log(data);
  283. /* //ouverture de la modale de gesiton equipiers
  284. $('.btn-teammate-add',view.el).click(function(){
  285. $('#teammate-modal').modal();
  286. var teammates = view.options.views.teammate.teammates;
  287. var logins = [];
  288. for(var k in teammates){
  289. logins.push(teammates[k].login);
  290. }
  291. //Affichage des equipiers sélectionnés
  292. $('.teammate-picker input').each(function(i,input){
  293. var user = $(input).data();
  294. $(input).prop('checked',(logins.indexOf(user.login) !== -1)).trigger('change');
  295. });
  296. });
  297. //Sauvegarde des equipiers
  298. $('#teammate-modal .btn-save').click(function(){
  299. if(view.options.views.teammate.addTeammate){
  300. var teammates = [];
  301. var teammatesLogins = [];
  302. $('.teammate-picker input').each(function(i,input){
  303. var user = $(input).data();
  304. if($(input).prop('checked')){
  305. teammates.push(user);
  306. teammatesLogins.push(user.login);
  307. }
  308. });
  309. var response = view.options.views.teammate.addTeammate(teammatesLogins);
  310. if(response != false){
  311. view.options.views.teammate.teammates = teammates;
  312. $('#teammate-modal').modal('hide');
  313. }
  314. }
  315. });*/
  316. },
  317. component: function(data){
  318. console.log('component');
  319. console.log(data);
  320. },
  321. /*dateProfileGeneratorClass: function(data){
  322. console.log('dateProfileGeneratorClass');
  323. console.log(data);
  324. },*/
  325. willUnmount: function(data){
  326. console.log('willUnmount');
  327. console.log(data);
  328. },
  329. //type: String,
  330. //component: ct,
  331. //buttonText: String,
  332. // buttonTextKey: String,
  333. // dateProfileGeneratorClass: ct,
  334. // usesMinMaxTime: Boolean,
  335. //didMount: ct,
  336. //willUnmount: ct
  337. }
  338. const TeammateViewPlugin = createPlugin({
  339. views: {
  340. teammate: CustomViewConfig
  341. }
  342. })