#189 Start working on customer-side calendar
parent
914fb0ff9c
commit
8e51429dce
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
/*******************************************************************************
|
||||||
|
* Title: Help Desk Software HESK
|
||||||
|
* Version: 2.6.5 from 28th August 2015
|
||||||
|
* Author: Klemen Stirn
|
||||||
|
* Website: http://www.hesk.com
|
||||||
|
********************************************************************************
|
||||||
|
* COPYRIGHT AND TRADEMARK NOTICE
|
||||||
|
* Copyright 2005-2015 Klemen Stirn. All Rights Reserved.
|
||||||
|
* HESK is a registered trademark of Klemen Stirn.
|
||||||
|
* The HESK may be used and modified free of charge by anyone
|
||||||
|
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
|
||||||
|
* By using this code you agree to indemnify Klemen Stirn from any
|
||||||
|
* liability that might arise from it's use.
|
||||||
|
* Selling the code for this program, in part or full, without prior
|
||||||
|
* written consent is expressly forbidden.
|
||||||
|
* Using this code, in part or full, to create derivate work,
|
||||||
|
* new scripts or products is expressly forbidden. Obtain permission
|
||||||
|
* before redistributing this software over the Internet or in
|
||||||
|
* any other medium. In all cases copyright and header must remain intact.
|
||||||
|
* This Copyright is in full effect in any country that has International
|
||||||
|
* Trade Agreements with the United States of America or
|
||||||
|
* with the European Union.
|
||||||
|
* Removing any of the copyright notices without purchasing a license
|
||||||
|
* is expressly forbidden. To remove HESK copyright notice you must purchase
|
||||||
|
* a license for this script. For more information on how to obtain
|
||||||
|
* a license please visit the page below:
|
||||||
|
* https://www.hesk.com/buy.php
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
define('IN_SCRIPT', 1);
|
||||||
|
define('HESK_PATH', './');
|
||||||
|
define('PAGE_TITLE', 'CUSTOMER_CALENDAR');
|
||||||
|
define('MFH_CUSTOMER_CALENDAR', 1);
|
||||||
|
|
||||||
|
/* Get all the required files and functions */
|
||||||
|
require(HESK_PATH . 'hesk_settings.inc.php');
|
||||||
|
require(HESK_PATH . 'inc/common.inc.php');
|
||||||
|
|
||||||
|
// Are we in maintenance mode?
|
||||||
|
hesk_check_maintenance();
|
||||||
|
|
||||||
|
hesk_load_database_functions();
|
||||||
|
|
||||||
|
hesk_session_start();
|
||||||
|
/* Connect to database */
|
||||||
|
hesk_dbConnect();
|
||||||
|
$modsForHesk_settings = mfh_getSettings();
|
||||||
|
|
||||||
|
$categories = [];
|
||||||
|
$orderBy = $modsForHesk_settings['category_order_column'];
|
||||||
|
$categorySql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `usage` <> 1 AND `type` = '0' ORDER BY '" . $orderBy . "'";
|
||||||
|
$categoryRs = hesk_dbQuery($categorySql);
|
||||||
|
while ($row = hesk_dbFetchAssoc($categoryRs))
|
||||||
|
{
|
||||||
|
$row['css_style'] = $row['color'] == null ? 'color: black; border: solid 1px #000' : 'background: ' . $row['color'];
|
||||||
|
$categories[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once(HESK_PATH . 'inc/header.inc.php');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="row pad-20">
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4>Categories</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
<?php foreach ($categories as $category): ?>
|
||||||
|
<li class="move-down-20 move-right-20">
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" name="category-toggle" value="<?php echo $category['id']; ?>" checked>
|
||||||
|
</div>
|
||||||
|
<span class="label background-volatile category-label" style="<?php echo $category['css_style']; ?>">
|
||||||
|
<?php echo $category['name']; ?>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4>
|
||||||
|
Calendar
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div id="calendar"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,204 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
$('#calendar').fullCalendar({
|
||||||
|
header: {
|
||||||
|
left: 'prevYear,prev,next,nextYear today',
|
||||||
|
center: 'title',
|
||||||
|
right: 'month,agendaWeek,agendaDay'
|
||||||
|
},
|
||||||
|
editable: false,
|
||||||
|
eventLimit: true,
|
||||||
|
timeFormat: 'H:mm',
|
||||||
|
axisFormat: 'H:mm',
|
||||||
|
events: function(start, end, timezone, callback) {
|
||||||
|
$.ajax({
|
||||||
|
url: getHelpdeskUrl() + '/internal-api/calendar/?start=' + start + '&end=' + end,
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(data) {
|
||||||
|
var events = [];
|
||||||
|
$(data).each(function() {
|
||||||
|
events.push(buildEvent(this.id, this));
|
||||||
|
});
|
||||||
|
callback(events);
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
console.error(data);
|
||||||
|
$.jGrowl('An error occurred when trying to load events', { theme: 'alert-danger', closeTemplate: '' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
eventMouseover: function(event) {
|
||||||
|
if (event.type === 'TICKET') {
|
||||||
|
// Don't build a popover for tickets
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contents = $('.popover-template').html();
|
||||||
|
var $contents = $(contents);
|
||||||
|
|
||||||
|
var format = 'dddd, MMMM Do YYYY';
|
||||||
|
var endDate = event.end == null ? event.start : event.end;
|
||||||
|
|
||||||
|
if (!event.allDay) {
|
||||||
|
format += ', HH:mm';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.location === '') {
|
||||||
|
$contents.find('.popover-location').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
$contents.find('.popover-category span').text(event.categoryName).end()
|
||||||
|
.find('.popover-location span').text(event.location).end()
|
||||||
|
.find('.popover-from span').text(event.start.format(format)).end()
|
||||||
|
.find('.popover-to span').text(endDate.format(format));
|
||||||
|
var $eventMarkup = $(this);
|
||||||
|
$eventMarkup.popover({
|
||||||
|
title: event.title,
|
||||||
|
html: true,
|
||||||
|
content: $contents,
|
||||||
|
animation: true,
|
||||||
|
container: 'body',
|
||||||
|
placement: 'auto'
|
||||||
|
}).popover('show');
|
||||||
|
},
|
||||||
|
eventMouseout: function(event) {
|
||||||
|
if (event.type === 'TICKET') {
|
||||||
|
// There's no popover to destroy
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).popover('destroy');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#create-form').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var start = $('#create-form input[name="start-date"]').val();
|
||||||
|
var end = $('#create-form input[name="end-date"]').val();
|
||||||
|
var dateFormat = 'YYYY-MM-DD';
|
||||||
|
var allDay = $('#create-form input[name="all-day"]').is(':checked');
|
||||||
|
|
||||||
|
if (!allDay) {
|
||||||
|
start += ' ' + $('#create-form input[name="start-time"]').val();
|
||||||
|
end += ' ' + $('#create-form input[name="end-time"]').val();
|
||||||
|
dateFormat = 'YYYY-MM-DD HH:mm:ss';
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
title: $('#create-form input[name="name"]').val(),
|
||||||
|
location: $('#create-form input[name="location"]').val(),
|
||||||
|
startTime: moment(start).format(dateFormat),
|
||||||
|
endTime: moment(end).format(dateFormat),
|
||||||
|
allDay: allDay,
|
||||||
|
comments: $('#create-form textarea[name="comments"]').val(),
|
||||||
|
categoryId: $('#create-form select[name="category"]').val(),
|
||||||
|
action: 'create',
|
||||||
|
type: 'CALENDAR',
|
||||||
|
categoryColor: $('#create-form select[name="category"] :selected').attr('data-color'),
|
||||||
|
categoryName: $('#create-form select[name="category"] :selected').text().trim(),
|
||||||
|
reminderValue: $('#create-form input[name="reminder-value"]').val(),
|
||||||
|
reminderUnits: $('#create-form select[name="reminder-unit"]').val()
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
method: 'POST',
|
||||||
|
url: getHelpdeskUrl() + '/internal-api/admin/calendar/',
|
||||||
|
data: data,
|
||||||
|
success: function(id) {
|
||||||
|
addToCalendar(id, data, "Event successfully created");
|
||||||
|
$('#create-event-modal').modal('hide');
|
||||||
|
updateCategoryVisibility();
|
||||||
|
},
|
||||||
|
error: function(data) {
|
||||||
|
$.jGrowl('An error occurred when trying to create the event', { theme: 'alert-danger', closeTemplate: '' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('input[name="category-toggle"]').change(updateCategoryVisibility);
|
||||||
|
});
|
||||||
|
|
||||||
|
function addToCalendar(id, event, successMessage) {
|
||||||
|
var eventObject = buildEvent(id, event);
|
||||||
|
$('#calendar').fullCalendar('renderEvent', eventObject);
|
||||||
|
$.jGrowl(successMessage, { theme: 'alert-success', closeTemplate: '' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildEvent(id, dbObject) {
|
||||||
|
if (dbObject.type == 'TICKET') {
|
||||||
|
var endOfDay = moment(dbObject.startTime)
|
||||||
|
.set('hour', 23)
|
||||||
|
.set('minute', 59)
|
||||||
|
.set('second', 59)
|
||||||
|
.set('millisecond', 999);
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: dbObject.title,
|
||||||
|
trackingId: dbObject.trackingId,
|
||||||
|
start: moment(dbObject.startTime),
|
||||||
|
url: dbObject.url,
|
||||||
|
color: dbObject.categoryColor === '' || dbObject.categoryColor === null ? '#fff' : dbObject.categoryColor,
|
||||||
|
allDay: true,
|
||||||
|
type: dbObject.type,
|
||||||
|
categoryId: dbObject.categoryId,
|
||||||
|
className: 'category-' + dbObject.categoryId,
|
||||||
|
textColor: calculateTextColor(dbObject.categoryColor)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
title: dbObject.title,
|
||||||
|
allDay: dbObject.allDay,
|
||||||
|
start: moment(dbObject.startTime),
|
||||||
|
end: moment(dbObject.endTime),
|
||||||
|
comments: dbObject.comments,
|
||||||
|
location: dbObject.location,
|
||||||
|
type: dbObject.type,
|
||||||
|
categoryId: dbObject.categoryId,
|
||||||
|
categoryName: dbObject.categoryName,
|
||||||
|
className: 'category-' + dbObject.categoryId,
|
||||||
|
color: dbObject.categoryColor === '' || dbObject.categoryColor === null ? '#fff' : dbObject.categoryColor,
|
||||||
|
textColor: calculateTextColor(dbObject.categoryColor),
|
||||||
|
reminderValue: dbObject.reminderValue == null ? '' : dbObject.reminderValue,
|
||||||
|
reminderUnits: dbObject.reminderUnits
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateTextColor(color) {
|
||||||
|
if (color === null || color === '') {
|
||||||
|
return 'black';
|
||||||
|
}
|
||||||
|
|
||||||
|
var red = 0;
|
||||||
|
var green = 0;
|
||||||
|
var blue = 0;
|
||||||
|
|
||||||
|
// If hex value is 3 characters, take each value and concatenate it to itself
|
||||||
|
if (color.length === 3) {
|
||||||
|
red = parseInt(color.substring(1, 2), 16);
|
||||||
|
green = parseInt(color.substring(2, 3), 16);
|
||||||
|
blue = parseInt(color.substring(3, 4), 16);
|
||||||
|
} else {
|
||||||
|
red = parseInt(color.substring(1, 3), 16);
|
||||||
|
green = parseInt(color.substring(3, 5), 16);
|
||||||
|
blue = parseInt(color.substring(5, 7), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
var gray = red * 0.299 + green * 0.587 + blue * 0.114;
|
||||||
|
|
||||||
|
return gray > 186 ? 'black' : 'white';
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCategoryVisibility() {
|
||||||
|
$('input[name="category-toggle"]').each(function() {
|
||||||
|
$this = $(this);
|
||||||
|
|
||||||
|
if ($this.is(':checked')) {
|
||||||
|
$('.category-' + $this.val()).show();
|
||||||
|
} else {
|
||||||
|
$('.category-' + $this.val()).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue