planning-calendar.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <!-- custom scripts -->
  2. <script type="text/javascript" src='client-assets/fullcalendar/js/moment.min.js'></script>
  3. <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/en-au.js"></script>
  4. <!-- fullcalendar -->
  5. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.0/fullcalendar.css" />
  6. <!-- <link rel="stylesheet" href="client-assets/fullcalendar/css/fullcalendar.print.css" media='print' /> -->
  7. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.print.css" integrity="sha256-eODYvezY8MWH5O2DbXi3BwOJESNqpDfU1rmBLT72PyQ=" crossorigin="anonymous" media='print' />
  8. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.0/fullcalendar.js"></script>
  9. <!-- scheduler -->
  10. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.css" />
  11. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar-scheduler/1.9.4/scheduler.js"></script>
  12. <script type="text/javascript" src="https://use.fontawesome.com/1e2844bb90.js"></script>
  13. <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" integrity="sha384-gfdkjb5BdAXd+lj+gudLWI+BXq4IuLW5IT+brZEZsLFm++aCMlF1V92rMkPaX4PP" crossorigin="anonymous" />
  14. <!-- Include Bootstrap Datepicker -->
  15. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.css" integrity="sha256-b5ZKCi55IX+24Jqn638cP/q3Nb2nlx+MH/vMMqrId6k=" crossorigin="anonymous" />
  16. <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js" integrity="sha256-5YmaxAwMjIpMrVlK84Y/+NjCpKnFYa8bWWBbUHSBGfU=" crossorigin="anonymous"></script>
  17. <!-- Bootstrap Date-Picker Plugin -->
  18. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/js/bootstrap-datepicker.min.js"></script>
  19. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/css/bootstrap-datepicker3.css"/>
  20. <style>
  21. .fc-view table {
  22. margin-bottom: 0px;
  23. }
  24. .fc-content {
  25. /* color: white !important; */
  26. }
  27. .fc-head-container {
  28. background-color: #D82508;
  29. color: white;
  30. border: 1px solid #D82508 !important;
  31. }
  32. </style>
  33. <div class="container-fluid">
  34. <div class="row">
  35. <div class="col">
  36. <div id="calendar"></div>
  37. </div>
  38. </div>
  39. </div>
  40. <!-- Modal to Add Event -->
  41. <div class="modal" id="createEventModal" tabindex="-1" role="dialog" aria-hidden="true" >
  42. <div class="modal-dialog" role="document">
  43. <!-- Modal content-->
  44. <div class="modal-content">
  45. <div id="modalHeader" class="modal-header">
  46. <h4 class="modal-title">Add Event to Schedule</h4>
  47. <button type="button" class="close" data–dismiss="createEventModal" aria-label="Close">
  48. <span aria-hidden="true">&times;</span>
  49. </button>
  50. </div>
  51. <div class="modal-body">
  52. <div class="control-group">
  53. <label class="control-label" for="inputPatient">Event:</label>
  54. <div class="field desc">
  55. <input class="form-control" id="title" name="title" placeholder="Event" type="text" value="">
  56. <input type="hidden" id="modx_user_id" value="[[+modx.user.id]]">
  57. </div>
  58. </div>
  59. <hr>
  60. <div class="row">
  61. <div class="col">
  62. <label class="control-label" for="startTime">Start Time:</label>
  63. <input class="form-control startTime" type="text" id="startTime" >
  64. </div>
  65. <div class="col">
  66. <label class="control-label" for="endTime">End Time:</label>
  67. <input class="form-control endTime" type="text" id="endTime" >
  68. </div>
  69. </div>
  70. <script type="text/javascript">
  71. $(function () {
  72. $('.startTime').datetimepicker();
  73. $('.endTime').datetimepicker({
  74. //format: 'L',
  75. format: 'yyyy-mm-dd hh:ii',
  76. daysOfWeekDisabled: [0, 6],
  77. collapse: true,
  78. useCurrent: false //Important! See issue #1075
  79. });
  80. $(".startTime").on("dp.change", function (e) {
  81. $('.endTime').data("DateTimePicker").minDate(e.date);
  82. });
  83. $(".endTime").on("dp.change", function (e) {
  84. $('.startTime').data("DateTimePicker").maxDate(e.date);
  85. });
  86. });
  87. </script>
  88. </div>
  89. <div id="modalFooter" class="modal-footer">
  90. <button type="button" class="btn btn-secondary" data–dismiss="createEventModal" aria–hidden="true">Close</button>
  91. <button type="submit" class="btn btn-success" id="submitButton" aria–hidden="true">Save</button>
  92. </div>
  93. <!--
  94. <div class="control-group">
  95. <label class="control-label" for="when">When:</label>
  96. <div class="controls controls-row" id="when" style="margin-top:5px;"> </div>
  97. </div>
  98. -->
  99. </div>
  100. </div>
  101. </div>
  102. </div>
  103. <!-- Modal to Event Details -->
  104. <div class="modal" id="calendarModal" tabindex="-1" role="dialog" aria-hidden="true" >
  105. <div class="modal-dialog" role="document">
  106. <div class="modal-content">
  107. <div id="modalHeader" class="modal-header">
  108. <h4 class="modal-title">Event Details</h4>
  109. <button type="button" class="close" data–dismiss="calendarModal" aria-label="Close">
  110. <span aria-hidden="true">&times;</span>
  111. </button>
  112. </div>
  113. <div id="modalBody" class="modal-body">
  114. <!-- <div id="modalWhen" style="margin-top:5px;"></div> -->
  115. <div class="row">
  116. <div class="col" >
  117. <h4 id="modalTitle" class="modal-title"></h4>
  118. </div>
  119. </div>
  120. <hr>
  121. <div class="row">
  122. <div class="col" >
  123. <label for="eventID">From:</label>
  124. <input type="text" class="form-control form-control-sm datetimepicker" id="startTime" readonly>
  125. </div>
  126. </div>
  127. <div class="row">
  128. <div class="col" >
  129. <label for="eventID">To:</label>
  130. <input type="text" class="form-control form-control-sm datetimepicker" id="endTime" readonly>
  131. </div>
  132. </div>
  133. <!--
  134. <hr>
  135. <div class="row">
  136. <div class="col" >
  137. <div id="modalWhen" style="margin-top:5px;"></div>
  138. </div>
  139. </div>
  140. -->
  141. <script type="text/javascript">
  142. $(document).ready(function(){
  143. $('.datetimepicker').datetimepicker({
  144. format: 'dddd, MMMM Do YYYY, h:mm',
  145. showTodayButton: true,
  146. useCurrent: true,
  147. stepping: 60,
  148. daysOfWeekDisabled: [0, 6],
  149. collapse: true,
  150. useCurrent: false //Important! See issue #1075
  151. });
  152. });
  153. </script>
  154. </div>
  155. <input type="hidden" id="eventID"/>
  156. <div class="modal-footer">
  157. <button type="button" class="btn btn-secondary" data–dismiss="modal" aria–hidden="true">Cancel</button>
  158. <button type="submit" class="btn btn-success" id="updateButton" aria–hidden="true">Update</button>
  159. <button type="submit" class="btn btn-danger" id="deleteButton">Delete</button>
  160. </div>
  161. </div>
  162. </div>
  163. </div>
  164. <!-- Modal-->
  165. <script type="text/javascript">
  166. $(document).ready(function(){
  167. var calendar = $('#calendar').fullCalendar({ // assign calendar
  168. plugins: [ 'bootstrap4', 'interaction', 'list' ],
  169. themeSystem: 'bootstrap4',
  170. timeZone: 'UTC',
  171. defaultView: 'month',
  172. aspectRatio: 2,
  173. allDayDefault: true,
  174. stick: true,
  175. header: {
  176. left: 'today prev,next',
  177. center: 'title ',
  178. right: 'timeGridThreeMonths, month, listWeek, listMonth' //agendaWeek, agendaDay,
  179. },
  180. droppable: true, // this allows things to be dropped onto the calendar
  181. eventLimit: true, // when too many events in a day, show the popover
  182. displayEventTime: false, //https://fullcalendar.io/docs/displayEventTime
  183. editable: true, // enable draggable events
  184. eventStartEditable: true,
  185. eventResizableFromStart: true,
  186. eventDurationEditable: true,
  187. resizable: true,
  188. selectable: true,
  189. allDaySlot: false,
  190. contentHeight: 'auto',
  191. weekNumbers: true,
  192. weekNumbersWithinDays: true,
  193. views: {
  194. timeGridFourDays: {
  195. type: 'timeline',
  196. duration: { days: 5 },
  197. buttonText: '4 days'
  198. },
  199. timeGridFourWeeks: {
  200. type: 'timeline',
  201. duration: { days: 28 },
  202. buttonText: '4 Weeks'
  203. },
  204. timeGridThreeMonths: {
  205. buttonText: '3 Months',
  206. type: 'timeline',
  207. duration: { days: 95 },
  208. buttonText: '3 Months'
  209. },
  210. month: {
  211. buttonText: 'Month',
  212. titleFormat: '#M. MMMM YYYY'
  213. //allDay: true
  214. },
  215. agendaWeek: {
  216. allDaySlot: true,
  217. nowIndicator: true
  218. },
  219. agendaDay: {
  220. minTime: '05:00:00',
  221. maxTime: '19:00:00',
  222. nowIndicator: true
  223. },
  224. listDay: {
  225. buttonText: 'List Day'
  226. },
  227. listWeek: { buttonText: 'List Week' },
  228. listMonth: { buttonText: 'List Month' }
  229. },
  230. resourceLabelText: 'Current Jobs',
  231. schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
  232. //resources: 'https://fullcalendar.io/demo-resources.json?with-nesting&with-colors',
  233. //events: 'https://fullcalendar.io/demo-events.json?single-day&for-resource-timeline'
  234. //events: "index.php?view=1", // request to load current events
  235. //events: '[[!calendar_index? &view=1]]',
  236. eventSources: [
  237. 'ci.html?view=1',
  238. 'http://api.openweathermap.org/data/2.5/forecast?lat=-41.179&lon=147.545&cnt=10&mode=json&units=metric&appid=a164361b43628b08cfa06c0a9fd03a02', //needs formatting to show min-max temps for each day
  239. ],
  240. eventTextColor: '#fff !important',
  241. eventRender: function(event, element) {
  242. // PLANT IS GREEN
  243. if(event.type == 'plant' || event.type == 'Dry Ash Test') {
  244. element.css({
  245. 'background-color': '#008000',
  246. 'border-color': '#008000'
  247. });
  248. }
  249. // SOIL IS BROWN
  250. else if(event.type == 'soil' || event.type == 'Soil Test') {
  251. element.css({
  252. 'background-color': '#a52a2a',
  253. 'border-color': '#a52a2a'
  254. });
  255. }
  256. // WATER IS BLUE
  257. else if(event.type == 'water') {
  258. element.css({
  259. 'background-color': '#0000FF',
  260. 'border-color': '#0000FF',
  261. });
  262. }
  263. // ANIMAL IS ORANGE
  264. else if(event.type == 'animal') {
  265. element.css({
  266. 'background-color': '#FFA500',
  267. 'border-color': '#FFA500'
  268. });
  269. }
  270. // WEATHER IS BLACK
  271. else if(event.type == 'weather') {
  272. element.css({
  273. 'background-color': '#ffffff',
  274. 'border-color': '#ffffff',
  275. 'color': '#212529 !important',
  276. 'font-weight': 'bold',
  277. 'text-align': 'center'
  278. });
  279. }
  280. // REST IS SILVER
  281. else {
  282. element.css({
  283. 'background-color': '#C0C0C0',
  284. 'border-color': '#C0C0C0'
  285. });
  286. }
  287. },
  288. eventClick: function(event, jsEvent, view) { // when some one click on any event
  289. endtime = $.fullCalendar.moment(event.end).format('dddd, MMMM Do YYYY, h:mm');
  290. starttime = $.fullCalendar.moment(event.start).format('dddd, MMMM Do YYYY, h:mm');
  291. var mywhen = starttime + ' – ' + endtime;
  292. $('#calendarModal #modx_user_id').html(modx_user_id);
  293. $('#calendarModal #modalTitle').html(event.title);
  294. $('#calendarModal #modalWhen').text(mywhen);
  295. $('#calendarModal #eventID').val(event.id);
  296. $('#calendarModal #startTime').val(starttime);
  297. $('#calendarModal #endTime').val(endtime);
  298. $('#calendarModal').modal();
  299. },
  300. select: function(start, end, jsEvent) { // click on empty time slot
  301. endtime = $.fullCalendar.moment(end).format('dddd, MMMM Do YYYY, h:mm');
  302. starttime = $.fullCalendar.moment(start).format('dddd, MMMM Do YYYY, h:mm');
  303. var mywhen = starttime + ' – ' + endtime;
  304. start = moment(start).format('YYYY-MM-DD hh:mm');
  305. end = moment(end).format('YYYY-MM-DD hh:mm');
  306. $('#createEventModal #startTime').val(start);
  307. $('#createEventModal #endTime').val(end);
  308. $('#createEventModal #when').text(mywhen);
  309. $('#createEventModal').modal('toggle');
  310. },
  311. eventDrop: function(event, delta){ // event drag and drop
  312. $.ajax({
  313. //url: 'index.php',
  314. url: '[[!calendar_index]]',
  315. data: 'action=update&title='+event.title+'&start='+moment(event.start).format()+'&end='+moment(event.end).format()+'&id='+event.id+'&modx_user_id='+modx_user_id ,
  316. type: "POST",
  317. success: function(json) {
  318. //alert(json);
  319. }
  320. });
  321. },
  322. eventResize: function(event) { // resize to increase or decrease time of event
  323. $.ajax({
  324. //url: 'index.php',
  325. url: '[[!calendar_index]]',
  326. data: 'action=update&title='+event.title+'&start='+moment(event.start).format()+'&end='+moment(event.end).format()+'&id='+event.id+'&modx_user_id='+modx_user_id,
  327. type: "POST",
  328. success: function(json) {
  329. //alert(json);
  330. }
  331. });
  332. }
  333. });
  334. $('#deleteButton').on('click', function(e){ // delete event clicked
  335. // We don't want this to act as a link so cancel the link action
  336. e.preventDefault();
  337. doDelete(); // send data to delete function
  338. });
  339. function doDelete(){ // delete event
  340. $("#calendarModal").modal('hide');
  341. var eventID = $('#eventID').val();
  342. var modx_user_id = $('#modx_user_id').val();
  343. $.ajax({
  344. //url: 'index.php',
  345. url: '[[!calendar_index]]',
  346. data: 'action=delete&id='+eventID+'&modx_user_id='+modx_user_id,
  347. type: "POST",
  348. success: function(json) {
  349. if(json == 1)
  350. $("#calendar").fullCalendar('removeEvents',eventID);
  351. else
  352. return false;
  353. }
  354. });
  355. }
  356. $('#submitButton').on('click', function(e){ // add event submit
  357. // We don't want this to act as a link so cancel the link action
  358. e.preventDefault();
  359. doSubmit(); // send to form submit function
  360. });
  361. function doSubmit(){ // add event
  362. $("#createEventModal").modal('hide');
  363. var title = $('#title').val();
  364. var modx_user_id = $('#modx_user_id').val();
  365. var startTime = $('#startTime').val();
  366. var endTime = $('#endTime').val();
  367. $.ajax({
  368. //url: 'index.php',
  369. url: '[[!calendar_index]]',
  370. data: 'action=add&title='+title+'&start='+startTime+'&end='+endTime+'&modx_user_id='+modx_user_id,
  371. type: "POST",
  372. success: function(json) {
  373. $("#calendar").fullCalendar('renderEvent',
  374. {
  375. id: json.id,
  376. title: title,
  377. start: startTime,
  378. end: endTime,
  379. },
  380. true);
  381. }
  382. });
  383. }
  384. $('#updateButton').on('click', function(e){ // delete event clicked
  385. // We don't want this to act as a link so cancel the link action
  386. e.preventDefault();
  387. doUpdate(); //send data to delete function
  388. });
  389. function doUpdate(){ // delete event
  390. $("#calendarModal").modal('hide');
  391. var startTime = $('#calendarModal #startTime').val();
  392. var endTime = $('#calendarModal #endTime').val();
  393. var quote = $('#calendarModal #quote').val();
  394. var eventType = $('#calendarModal #eventType').val();
  395. var eventID = $('#calendarModal #eventID').val();
  396. var quid = $('#calendarModal #quid').val();
  397. $.ajax({
  398. //url: 'index.php',
  399. url: '[[!calendar_index]]',
  400. data: 'action=project_update&id='+eventID+'&quote='+quote+'&title='+title+'&start='+startTime+'&end='+endTime+'&eventType='+eventType+'&quid='+quid,
  401. type: "POST",
  402. success: function(json) {
  403. $("#calendar").fullCalendar('renderEvent',
  404. {
  405. id: eventID,
  406. quote: quote,
  407. title: quote,
  408. start: startTime,
  409. end: endTime,
  410. type: eventType,
  411. quid: quid,
  412. },
  413. true);
  414. }
  415. });
  416. }
  417. function fetchWeatherForecast(location, $http, $filter){
  418. $http.get("http://api.openweathermap.org/data/2.5/forecast?lat=-41.179&lon=147.545&cnt=10&mode=json&units=metric&appid=a164361b43628b08cfa06c0a9fd03a02").success(function(data) {
  419. addWeatherToCalendar(data, $filter);
  420. });
  421. }
  422. function addWeatherToButton(weatherData, $filter){
  423. var date = new Date();
  424. for (var i = 0; i < weatherData.list.length; i++) {
  425. var element = angular.element('td.fc-day[data-date="' + $filter('date')(date, 'yyyy-MM-dd').toString() + '"]')
  426. var html = element[0].innerHTML
  427. var icon = weatherData.list[i].weather[0].icon
  428. var temp = weatherData.list[i].temp.max + "-" +weatherData.list[i].temp.min
  429. element.append("<span><img src='http://openweathermap.org/img/w/"+icon+".png'/>"+temp+"</span>")
  430. date.setDate(date.getDate() + 1);
  431. }
  432. }
  433. });
  434. </script>