Merge remote-tracking branch 'remotes/origin/master' into api-rewrite

remotes/upstream/api-rewrite
Mike Koch 7 years ago
commit 999cb74865

@ -2,15 +2,15 @@
So you want to contribute to Mods for HESK? Awesome! However, there are a few guidelines that need to be followed so the project can be as easy to maintain as possible.
## Submitting an issue
If all you are doing is submitting an issue, please check if your "issue" qualifies as a GitHub issue:
- **Feature Requests:** Feature requests are now being recorded at the Mods for HESK [UserVoice page](https://mods-for-hesk.uservoice.com/forums/254758-general). Please do not open these types of issues on GitHub. Issues opened that are "feature requests" will be closed.
- **Translations:** Translations are now being recorded at the official Mods for HESK [website](https://mods-for-hesk.mkochcs.com/download.php). Please do not open these types of issues on GitHub. Issues opened that pertain to submitting new translations will be closed.
If all you are doing is submitting an issue, please check if your "issue" qualifies as a GitLab issue:
- **Feature Requests:** Feature requests are now being recorded at the Mods for HESK [UserVoice page](https://mods-for-hesk.uservoice.com/forums/254758-general). Please do not open these types of issues on GitLab. Issues opened that are "feature requests" will be closed.
- **Translations:** Translations are now being recorded at the official Mods for HESK [website](https://mods-for-hesk.mkochcs.com/download.php). Please do not open these types of issues on GitLab. Issues opened that pertain to submitting new translations will be closed.
- **Bugs:** Yes, please open these types of issues here. :grinning:
## Getting Started
If you have already completed any of these steps in the past (such as creating a GitHub account), you can skip the respective step.
- Make sure you have a [GitHub account](http://github.com/signup/free)
- Fork the repository on GitHub (for more help consult the [GitHub documentation](https://help.github.com/articles/fork-a-repo/))
If you have already completed any of these steps in the past (such as creating a GitLab account), you can skip the respective step.
- Make sure you have a [GitLab account](https://gitlab.com/users/sign_in)
- Fork the repository on GitLab
## Making Changes
- Create a feature branch from where to base your work off of
@ -22,7 +22,6 @@ If you have already completed any of these steps in the past (such as creating a
## Submitting Changes
- Push your changes to a topic branch in your fork of the repository
- Submit a pull request to the official Mods for HESK repository (mkoch227/Mods-for-HESK)
- If necessary, sign the Contributor License Agreement by checking the "status checks" area of your pull request.
- The owner of Mods for HESK will then inspect and test the code in the pull request. Feedback will be given via GitHub comments.
- Submit a pull request to the official Mods for HESK repository (mike-koch/Mods-for-HESK)
- The owner of Mods for HESK will then inspect and test the code in the pull request. Feedback will be given via GitLab comments.
- The owner of Mods for HESK expects responses within two weeks of the original comment. If there is no feedback within that time range, the pull request will be considered abandoned and subsequently will be closed.

@ -234,7 +234,7 @@ if ($ticket['locked']) {
if ($ticket['status'] != $new_status) {
// Does this status close the ticket?
$newStatusRs = hesk_dbQuery('SELECT `IsClosed`, `Key` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `ID` = ' . hesk_dbEscape($new_status));
$newStatusRs = hesk_dbQuery('SELECT `IsClosed`, `Key` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `ID` = ' . intval($new_status));
$newStatus = hesk_dbFetchAssoc($newStatusRs);
if ($newStatus['IsClosed'] && hesk_checkPermission('can_resolve', 0)) {

@ -470,12 +470,12 @@ if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) {
}
//-- Check if the ticket is already a child.
$childRs = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` WHERE `parent` = ' . $ticket['id'] . ' AND `trackid` = \'' . $_POST['childTrackingId'] . '\'');
$childRs = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` WHERE `parent` = ' . intval($ticket['id']) . ' AND `trackid` = \'' . hesk_dbEscape(hesk_POST(['childTrackingId'])) . '\'');
if (hesk_dbNumRows($childRs) > 0) {
hesk_process_messages(sprintf($hesklang['is_already_linked'], $_POST['childTrackingId']), 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'NOTICE');
}
hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = ' . $ticket['id'] . ' WHERE `trackid` = \'' . $_POST['childTrackingId'] . '\'');
hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = ' . intval($ticket['id']) . ' WHERE `trackid` = \'' . hesk_dbEscape(hesk_POST('childTrackingId')) . '\'');
hesk_process_messages(sprintf($hesklang['link_added'], $_POST['childTrackingId']), 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
}
@ -746,7 +746,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
if ($ticket['parent'] != null) {
//-- Get the tracking ID of the parent
$parentRs = hesk_dbQuery('SELECT `trackid` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets`
WHERE `ID` = ' . hesk_dbEscape($ticket['parent']));
WHERE `ID` = ' . intval($ticket['parent']));
$parent = hesk_dbFetchAssoc($parentRs);
echo '<a href="admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) . '&deleteParent=true">
<i class="fa fa-times-circle" data-toggle="tooltip" data-placement="top" title="' . $hesklang['delete_relationship'] . '"></i></a>';
@ -755,7 +755,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
//-- Check if any tickets have a parent set to this tracking ID
$hasRows = false;
$childrenRS = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets`
WHERE `parent` = ' . hesk_dbEscape($ticket['id']));
WHERE `parent` = ' . intval($ticket['id']));
while ($row = hesk_dbFetchAssoc($childrenRS)) {
$hasRows = true;
echo '<a href="admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) . '&deleteChild=' . $row['id'] . '">
@ -916,7 +916,24 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
</h1>
<div class="pull-right">
<?php echo hesk_getAdminButtons($category['id']); ?>
<?php echo hesk_getAdminButtons($category['id']);
// Only output JavaScript if we have coordinates
if (strpos($ticket['latitude'], 'E') === false):
?>
<script>
var latitude = '';
latitude = <?php echo $ticket['latitude'] != '' ? $ticket['latitude'] : -1; ?>;
var longitude = '';
longitude = <?php echo $ticket['longitude'] != '' ? $ticket['longitude'] : -1; ?>;
$('#more-modal').on('shown.bs.modal', function() {
initializeMapForStaff(latitude, longitude, "<?php echo $hesklang['users_location']; ?>");
});
</script>
<?php
endif;
?>
</div>
</div>
<div class="table-bordered status-row">
@ -1014,13 +1031,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
{
echo '<input type="hidden" name="unassigned" value="1">';
}
echo '</form></div>';
echo '</form>';
} else {
echo '<p class="ticket-property-text">';
echo isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] :
($can_assign_self ? $hesklang['unas'] . ' [<a href="assign_owner.php?track=' . $trackingID . '&amp;owner=' . $_SESSION['id'] . '&amp;token=' . hesk_token_echo(0) . '&amp;unassigned=1">' . $hesklang['asss'] . '</a>]' : $hesklang['unas']);
echo '</p>';
}
echo '</div>';
echo '<div class="col-md-3 col-sm-12 ticket-cell-admin"><p class="ticket-property-title">' . $hesklang['category'] . '</p>';
if (strlen($categories_options) && ($can_change_cat || $can_change_own_cat)) {
echo '
@ -1280,7 +1298,7 @@ function hesk_getAdminButtons($category_id)
}
}
$isTicketClosedSql = 'SELECT `IsClosed`, `Closable` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `ID` = ' . $ticket['status'];
$isTicketClosedSql = 'SELECT `IsClosed`, `Closable` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `ID` = ' . intval($ticket['status']);
$isTicketClosedRs = hesk_dbQuery($isTicketClosedSql);
$isTicketClosedRow = hesk_dbFetchAssoc($isTicketClosedRs);
$isTicketClosed = $isTicketClosedRow['IsClosed'];
@ -1297,15 +1315,22 @@ function hesk_getAdminButtons($category_id)
}
$dropdown = '
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-ellipsis-h"></i> ' . hesk_htmlspecialchars($hesklang['more']) . ' <span class="caret"></span>
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#more-modal">
<i class="fa fa-ellipsis-h"></i> ' . hesk_htmlspecialchars($hesklang['more']) . '
</button>
<ul class="dropdown-menu pull-right">';
<div class="modal fade" id="more-modal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title">
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4>' . hesk_htmlspecialchars($hesklang['more']) . '</h4>
</div>
</div>
<div class="modal-body">
';
// Location and UA
$has_location_or_user_agent = false;
if ($modsForHesk_settings['display_user_agent_information']
&& $ticket['user_agent'] !== NULL
&& $ticket['screen_resolution_height'] !== NULL
@ -1313,112 +1338,95 @@ function hesk_getAdminButtons($category_id)
&& $ticket['screen_resolution_width'] !== NULL
&& $ticket['screen_resolution_width'] != 0
) {
$has_location_or_user_agent = true;
$dropdown .=
'<li><a href="javascript:;" data-toggle="modal" data-target="#user-agent-modal"><i class="fa fa-desktop fa-fw"></i> ' . $hesklang['device_information'] . '</a></li>';
buildUserAgentModal($ticket['user_agent'], $ticket['screen_resolution_width'], $ticket['screen_resolution_height']);
'<div class="panel panel-default">
<div class="panel-heading">
<h4 style="text-transform: capitalize"><i class="fa fa-desktop fa-fw"></i> '.$hesklang['device_information'].'</h4>
</div>
'.buildUserAgentBody($ticket['user_agent'], $ticket['screen_resolution_width'], $ticket['screen_resolution_height']).'
</div>';
} else if ($modsForHesk_settings['display_user_agent_information']) {
$has_location_or_user_agent = true;
$dropdown .=
'<li><span href="javascript:;" class="linkless-dropdown gray"><i class="fa fa-desktop fa-fw"></i> ' . $hesklang['no_device_information'] . '</span></li>';
'<div class="panel panel-default">
<div class="panel-heading">
<h4 style="text-transform: capitalize"><i class="fa fa-desktop fa-fw"></i> '.$hesklang['device_information'].'</h4>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
'.$hesklang['no_device_information'].'
</div>
</div>
</div>
</div>';
}
?>
<?php
if ($modsForHesk_settings['request_location']) {
$hasLocation = true;
$has_location_or_user_agent = true;
if (strpos($ticket['latitude'], 'E') === false) {
$locationText = $hesklang['click_for_map'];
$iconColor = '';
} else {
$hasLocation = false;
$locationText = $hesklang['location_unavailable'];
$iconColor = 'class="grey"';
$locationText = $hesklang['users_location'];
}
$dropdown .= '<li><a href="javascript:;" data-toggle="modal" data-target=".map-modal" ' . $iconColor . '><i class="fa fa-map-marker fa-fw"></i> ' . $locationText . ' </a></li>';
?>
<div id="map-modal" class="modal fade map-modal" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4><?php echo $hesklang['users_location']; ?></h4>
</div>
<div class="modal-body">
<?php if ($hasLocation): ?>
<div id="map" style="height: 500px"></div><br>
<address id="friendly-location" style="font-size: 13px"></address>
<p id="save-for-address"
style="font-size: 13px;display:none"><?php echo $hesklang['save_to_see_updated_address']; ?></p>
<script>
getFriendlyLocation(<?php echo $ticket['latitude']; ?>,
<?php echo $ticket['longitude']; ?>);
</script>
<div class="row">
<form action="admin_ticket.php" method="post" role="form">
<input type="hidden" name="track"
value="<?php echo $trackingID; ?>">
<input type="hidden" name="token"
value="<?php hesk_token_echo(); ?>">
<input type="hidden" name="latitude" id="latitude"
value="<?php echo $ticket['latitude']; ?>">
<input type="hidden" name="longitude" id="longitude"
value="<?php echo $ticket['longitude']; ?>">
<div class="col-sm-12">
<div class="btn-group" style="display:none" id="save-group">
<input type="submit" class="btn btn-success"
value="<?php echo $hesklang['save_location']; ?>">
<button class="btn btn-default" data-dismiss="modal"
onclick="closeAndReset(<?php echo $ticket['latitude']; ?>, <?php echo $ticket['longitude']; ?>)">
<?php echo $hesklang['close_modal_without_saving']; ?>
</button>
</div>
<div class="btn-group">
<button id="close-button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal']; ?></button>
</div>
</div>
</form>
</div>
<?php
else:
$errorCode = explode('-', $ticket['latitude']);
$key = 'location_unavailable_' . $errorCode[1];
echo '<h5>' . $hesklang[$key] . '</h5>';
endif;
?>
</div>
</div>
</div>
</div>
<?php
// Only output JavaScript if we have coordinates
if (strpos($ticket['latitude'], 'E') === false):
?>
$dropdown .= '<div class="panel panel-default">
<div class="panel-heading">
<h4><i class="fa fa-map-marker fa-fw"></i> ' . $locationText . '</h4>
</div>';
if ($hasLocation):
$dropdown .= '<div id="map" style="height: 500px"></div><br><div class="panel-body">
<address id="friendly-location" style="font-size: 13px"></address>
<p id="save-for-address"
style="font-size: 13px;display:none">' . $hesklang['save_to_see_updated_address'] . '</p>
<script>
var latitude = '';
latitude = <?php echo $ticket['latitude'] != '' ? $ticket['latitude'] : -1; ?>;
var longitude = '';
longitude = <?php echo $ticket['longitude'] != '' ? $ticket['longitude'] : -1; ?>;
initializeMapForStaff(latitude, longitude, "<?php echo $hesklang['users_location']; ?>");
getFriendlyLocation(' . $ticket['latitude'] . ',
' . $ticket['longitude'] . ');
</script>
<?php
<div class="row">
<form action="admin_ticket.php" method="post" role="form">
<input type="hidden" name="track"
value="'. $trackingID . '">
<input type="hidden" name="token"
value="'. hesk_token_echo(0) . '">
<input type="hidden" name="latitude" id="latitude"
value="'. $ticket['latitude'] . '">
<input type="hidden" name="longitude" id="longitude"
value="'. $ticket['longitude'] . '">
<div class="col-sm-12">
<div class="btn-group" style="display: none" id="save-group">
<input type="submit" class="btn btn-success"
value="'. $hesklang['save_location'] . '">
<button type="button" class="btn btn-default" onclick="closeAndReset('. $ticket['latitude'] . ', '. $ticket['longitude'] . ')">' . $hesklang['reset'] . '</button>
</div>
</div>
</form>
</div>';
else:
$dropdown .= '<div class="panel-body">';
$errorCode = explode('-', $ticket['latitude']);
$key = 'location_unavailable_' . $errorCode[1];
$dropdown .= '<h5>' . $hesklang[$key] . '</h5>';
endif;
}
// If there is device info enabled or location, separate them from the rest of the items in the dropdown.
if ($has_location_or_user_agent) {
$dropdown .= '<li role="separator" class="divider"></li>';
$dropdown .= '</div></div>';
}
$dropdown .= '<div class="row">';
/* Lock ticket button */
if ($can_resolve) {
$template = '<li><a href="lock.php?track=' . $trackingID . '&amp;locked=%s&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-%s fa-fw"></i> %s</a></li>';
$template =
'<div class="col-md-6 col-sm-12"><a class="button-link" href="lock.php?track=' . $trackingID . '&amp;locked=%s&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '">
<div class="panel panel-default">
<div class="panel-body">
<h4>
<i class="fa fa-%s fa-fw"></i> %s
</h4>
</div>
</div>
</a></div>';
$dropdown .= $ticket['locked']
? sprintf($template, 0, 'unlock', $hesklang['tul'])
: sprintf($template, 1, 'lock', $hesklang['tlo']);
@ -1426,7 +1434,16 @@ function hesk_getAdminButtons($category_id)
/* Tag ticket button */
if ($can_archive) {
$template = '<li><a href="archive.php?track=' . $trackingID . '&amp;archived=%s&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-tag fa-fw"></i> %s</a></li>';
$template =
'<div class="col-md-6 col-sm-12"><a class="button-link" href="archive.php?track=' . $trackingID . '&amp;archived=%s&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '">
<div class="panel panel-default">
<div class="panel-body">
<h4>
<i class="fa fa-tag fa-fw"></i> %s
</h4>
</div>
</div>
</a></div>';
$dropdown .= $ticket['archive']
? sprintf($template, 0, $hesklang['remove_archive'])
@ -1435,7 +1452,16 @@ function hesk_getAdminButtons($category_id)
/* Import to knowledgebase button */
if ($hesk_settings['kb_enable'] && hesk_checkPermission('can_man_kb', 0)) {
$dropdown .= '<li><a href="manage_knowledgebase.php?a=import_article&amp;track=' . $trackingID . '"><i class="fa fa-lightbulb-o fa-fw"></i> ' . $hesklang['import_kb'] . '</a></li>';
$dropdown .=
'<div class="col-md-6 col-sm-12"><a href="manage_knowledgebase.php?a=import_article&amp;track=' . $trackingID . '" class="button-link">
<div class="panel panel-default">
<div class="panel-body">
<h4>
<i class="fa fa-lightbulb-o fa-fw"></i> ' . $hesklang['import_kb'] . '
</h4>
</div>
</div>
</a></div>';
}
/* Delete ticket */
@ -1449,9 +1475,18 @@ function hesk_getAdminButtons($category_id)
$tmp = 'delete_ticket=1';
$txt = $hesklang['dele'];
}
$dropdown .= '<li><a href="' . $url . '?track=' . $trackingID . '&amp;' . $tmp . '&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '" onclick="return hesk_confirmExecute(\'' . hesk_makeJsString($txt) . '?\');"><i class="fa fa-fw fa-times"></i> ' . $txt . '</a></li>';
$dropdown .=
'<div class="col-md-6 col-sm-12"><a class="button-link" href="' . $url . '?track=' . $trackingID . '&amp;' . $tmp . '&amp;Refresh=' . mt_rand(10000, 99999) . '&amp;token=' . hesk_token_echo(0) . '" onclick="return hesk_confirmExecute(\'' . hesk_makeJsString($txt) . '?\');">
<div class="panel panel-default">
<div class="panel-body danger">
<h4>
<i class="fa fa-fw fa-times"></i> ' . $txt . '
</h4>
</div>
</div>
</a></div>';
}
$dropdown .= '</ul></div> ';
$dropdown .= '</div></div></div></div></div> ';
$options .= $dropdown;
/* Return generated HTML */
@ -1609,15 +1644,22 @@ function mfh_print_message() {
?>
</div>
<div class="timeline-body">
<?php
if ($ticket['message'] != '') {
if ($ticket['html']) {
echo hesk_html_entity_decode($ticket['message']);
} else {
echo $ticket['message'];
}
}
?>
<div class="row">
<div class="col-md-3 text-right">
<strong><?php echo $hesklang['message_colon']; ?></strong>
</div>
<div class="col-md-9">
<?php
if ($ticket['message'] != '') {
if ($ticket['html']) {
echo hesk_html_entity_decode($ticket['message']);
} else {
echo $ticket['message'];
}
}
?>
</div>
</div>
</div>
<?php
$first = true;
@ -1713,12 +1755,19 @@ function hesk_printTicketReplies()
<span class="time"><i class="fa fa-clock-o"></i> <?php echo $reply['dt']; ?></span>
<h3 class="timeline-header"><?php echo $reply['name']; ?></h3>
<div class="timeline-body">
<?php
if ($reply['html']) {
echo hesk_html_entity_decode($reply['message']);
} else {
echo $reply['message'];
} ?>
<div class="row">
<div class="col-md-3 text-right">
<strong><?php echo $hesklang['message_colon']; ?></strong>
</div>
<div class="col-md-9">
<?php
if ($reply['html']) {
echo hesk_html_entity_decode($reply['message']);
} else {
echo $reply['message'];
} ?>
</div>
</div>
</div>
<?php
if ($hesk_settings['attachments']['use'] && strlen($reply['attachments'])):
@ -1788,6 +1837,7 @@ function hesk_printReplyForm()
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",
@ -2110,51 +2160,36 @@ function hesk_printCanned()
} // End hesk_printCanned()
function buildUserAgentModal($user_agent, $width, $height) {
function buildUserAgentBody($user_agent, $width, $height) {
global $hesklang;
echo '
<div id="user-agent-modal" class="modal fade" tabindex="-1" role="dialog"
aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4>' . $hesklang['device_information'] . '</h4>
</div>
<div class="modal-body">
<script>
var userAgent = platform.parse(\'' . addslashes($user_agent) . '\');
console.log(userAgent);
var screenResWidth = ' . intval($width) . ';
var screenResHeight = ' . intval($height) . ';
</script>
<table class="table table-striped">
<tbody>
<tr>
<td><strong>' . $hesklang['operating_system'] . '</strong>
</td>
<td id="operating-system">&nbsp;</td>
<script>$(\'#operating-system\').html(userAgent.os.toString());</script>
</tr>
<tr>
<td><strong>' . $hesklang['browser'] . '</strong></td>
<td id="browser">&nbsp;</td>
<script>$(\'#browser\').html(userAgent.name + \' \' + userAgent.version);</script>
</tr>
<tr>
<td><strong>' . $hesklang['screen_resolution'] . '</strong>
</td>
<td id="screen-resolution">&nbsp;</td>
<script>$(\'#screen-resolution\').html(screenResWidth + \' x \' + screenResHeight);</script>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>';
return '
<script>
var userAgent = platform.parse(\'' . addslashes($user_agent) . '\');
console.log(userAgent);
var screenResWidth = ' . intval($width) . ';
var screenResHeight = ' . intval($height) . ';
</script>
<table class="table table-striped">
<tbody>
<tr>
<td><strong>' . $hesklang['operating_system'] . '</strong>
</td>
<td id="operating-system">&nbsp;</td>
<script>$(\'#operating-system\').html(userAgent.os.toString());</script>
</tr>
<tr>
<td><strong>' . $hesklang['browser'] . '</strong></td>
<td id="browser">&nbsp;</td>
<script>$(\'#browser\').html(userAgent.name + \' \' + userAgent.version);</script>
</tr>
<tr>
<td><strong>' . $hesklang['screen_resolution'] . '</strong>
</td>
<td id="screen-resolution">&nbsp;</td>
<script>$(\'#screen-resolution\').html(screenResWidth + \' x \' + screenResHeight);</script>
</tr>
</tbody>
</table>';
}
?>

@ -92,8 +92,9 @@ if (!$row['isadmin']) {
// Make sure two people don't assign a ticket to a different user at the same time
if ($ticket['owner'] && $ticket['owner'] != $owner && hesk_REQUEST('unassigned') && hesk_GET('confirm') != 'Y') {
$new_owner = ($owner == $_SESSION['id']) ? $hesklang['scoy'] : sprintf($hesklang['scot'], $row['name']);
$originalOwner = intval($ticket['owner']);
$res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$ticket['owner']}' LIMIT 1");
$res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$originalOwner}' LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
$row = hesk_dbFetchAssoc($res);

@ -68,7 +68,7 @@ while ($row = hesk_dbFetchAssoc($rs)) {
continue;
}
$row['css_style'] = $row['color'] == null ? 'color: black; border: solid 1px #000;' : 'border: solid 1px ' . $row['color'] . '; background: ' . $row['color'];
$row['css_style'] = $row['color'] == null ? 'background: white; color: black; border: solid 1px #000;' : 'border: solid 1px ' . $row['color'] . '; background: ' . $row['color'];
$categories[] = $row;
}
@ -83,7 +83,6 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
<ul class="sidebar-menu">
<li class="header text-uppercase"><?php echo $hesklang['calendar_categories']; ?></li>
<?php foreach ($categories as $category): ?>
<!-- TODO Clean this up -->
<li>
<div class="ticket-info">
<div class="hide-on-overflow no-wrap event-category background-volatile"
@ -152,6 +151,16 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
</div>
</div>
<div class="box-body no-padding">
<?php if (hesk_checkPermission('can_man_calendar', 0)): ?>
<div class="row" style="padding-right: 10px">
<div class="col-xs-12 text-right">
<button class="btn btn-success" id="create-event-button">
<i class="fa fa-plus-circle"></i>
<?php echo $hesklang['new_event']; ?>
</button>
</div>
</div>
<?php endif; ?>
<div id="calendar"></div>
</div>
</div>

@ -88,7 +88,7 @@ if ($statusRow['IsClosed']) // Closed
// Log who marked the ticket resolved
$closedby_sql = ' , `closedat`=NOW(), `closedby`=' . intval($_SESSION['id']) . ' ';
} elseif ($statusRow['IsNewTicketStatus'] == '0') //Ticket is still open, but not new
} elseif ($statusRow['IsNewTicketStatus'] == 0) //Ticket is still open, but not new
{
$action = sprintf($hesklang['tsst'], $status_options[$status]);
$revision = sprintf($hesklang['thist9'], hesk_date(), $status_options[$status], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');

@ -222,7 +222,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
<?php echo $hesklang['custom_l']; ?>
</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="max_length"
<input type="text" class="form-control" name="readonly_max_length"
value="<?php echo isset($value['max_length']) ? intval($value['max_length']) : '255'; ?>" size="5">
</div>
</div>
@ -231,7 +231,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
<?php echo $hesklang['defw']; ?>
</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="default_value"
<input type="text" class="form-control" name="readonly_default_value"
value="<?php echo isset($value['default_value']) ? $value['default_value'] : ''; ?>" size="30">
</div>
</div>
@ -1202,8 +1202,8 @@ function cf_validate()
break;
case 'readonly':
$max_length = hesk_POST('max_length');
$value = hesk_POST('default_value');
$max_length = hesk_POST('readonly_max_length');
$value = hesk_POST('readonly_default_value');
$cf['value'] = array('default_value' => $value, 'max_length' => $max_length);
break;

@ -147,7 +147,7 @@ if (isset($_POST['save'])) {
if (isset($_POST[$k]) && is_array($_POST[$k])) {
foreach ($_POST[$k] as $myCB) {
$tmpvar[$k] .= ( is_array($myCB) ? '' : hesk_input($myCB) ) . '<br>';
$tmpvar[$k] .= ( is_array($myCB) ? '' : hesk_input($myCB) ) . '<br />';
}
$tmpvar[$k]=substr($tmpvar[$k],0,-6);
} else {
@ -354,7 +354,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
$k_value = $ticket[$k];
if ($v['type'] == 'checkbox') {
$k_value = explode('<br>', $k_value);
$k_value = explode('<br />', $k_value);
}
if ($v['req'] == 2) {
@ -580,6 +580,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -208,6 +208,7 @@ $num = hesk_dbNumRows($result);
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -46,6 +46,7 @@ if ($modsForHesk_settings['html_emails']) {
theme : "advanced",
convert_urls : false,
gecko_spellcheck: true,
plugins: "autolink",
theme_advanced_buttons1 : "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -358,6 +358,7 @@ if (!isset($_SESSION['hide']['new_article']))
theme : "advanced",
convert_urls : false,
gecko_spellcheck: true,
plugins: "autolink",
theme_advanced_buttons1 : "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",
@ -1459,6 +1460,7 @@ function edit_article()
theme : "advanced",
convert_urls : false,
gecko_spellcheck: true,
plugins: "autolink",
theme_advanced_buttons1 : "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -292,6 +292,7 @@ $num = hesk_dbNumRows($result);
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -199,6 +199,7 @@ $show_quick_help = $show['show'];
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -132,6 +132,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
theme: "advanced",
convert_urls: false,
gecko_spellcheck: true,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup,code",

@ -1,4 +1,4 @@
<?php
// Define the current build
define('MODS_FOR_HESK_BUILD', 37);
define('MODS_FOR_HESK_BUILD', 38);

@ -199,6 +199,15 @@ button.dropdown-submit {
background-color: #EEE;
}
.button-link .danger {
background-color: #ffe6e6;
color: #f00;
}
.button-link .danger:hover {
background-color: #ffcccc;
}
.timeline-header {
background: #ddd;
border-left: solid 1px #ddd;

@ -168,6 +168,11 @@ function hesk_suggestKB() {
var d = document.form1;
var s = d.subject.value;
var m = d.message.value;
if ($('textarea[name="message"]').data('rich-text-enabled') && tinyMCE.get('message') !== undefined) {
m = tinyMCE.get('message').getContent();
}
var element = document.getElementById('kb_suggestions');
if (s != '' && m != '' && (heskKBquery != s + " " + m || heskKBfailed == true)) {

@ -160,7 +160,7 @@ function hesk_mergeTickets($merge_these, $merge_into)
$this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']);
/* Get required ticket information */
$res = hesk_dbQuery("SELECT `id`,`trackid`,`category`,`name`,`message`,`dt`,`time_worked`,`attachments` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='" . intval($this_id) . "' LIMIT 1");
$res = hesk_dbQuery("SELECT `id`,`trackid`,`category`,`name`,`message`,`dt`,`time_worked`,`attachments`, `html` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='" . intval($this_id) . "' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
continue;
}
@ -172,7 +172,7 @@ function hesk_mergeTickets($merge_these, $merge_into)
}
/* Insert ticket message as a new reply to target ticket */
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`) VALUES ('" . intval($ticket['id']) . "','" . hesk_dbEscape($row['name']) . "','" . hesk_dbEscape($row['message']) . "','" . hesk_dbEscape($row['dt']) . "','" . hesk_dbEscape($row['attachments']) . "')");
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`, `html`) VALUES ('" . intval($ticket['id']) . "','" . hesk_dbEscape($row['name']) . "','" . hesk_dbEscape($row['message']) . "','" . hesk_dbEscape($row['dt']) . "','" . hesk_dbEscape($row['attachments']) . "', '" . intval($row['html']) . "')");
/* Update attachments */
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` SET `ticket_id`='" . hesk_dbEscape($ticket['trackid']) . "' WHERE `ticket_id`='" . hesk_dbEscape($row['trackid']) . "'");
@ -180,7 +180,7 @@ function hesk_mergeTickets($merge_these, $merge_into)
/* Get old ticket replies and insert them as new replies */
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` WHERE `replyto`='" . intval($row['id']) . "' ORDER BY `id` ASC");
while ($reply = hesk_dbFetchAssoc($res)) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`rating`,`read`) VALUES ('" . intval($ticket['id']) . "','" . hesk_dbEscape($reply['name']) . "','" . hesk_dbEscape($reply['message']) . "','" . hesk_dbEscape($reply['dt']) . "','" . hesk_dbEscape($reply['attachments']) . "','" . intval($reply['staffid']) . "','" . intval($reply['rating']) . "','" . intval($reply['read']) . "')");
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`rating`,`read`, `html`) VALUES ('" . intval($ticket['id']) . "','" . hesk_dbEscape($reply['name']) . "','" . hesk_dbEscape($reply['message']) . "','" . hesk_dbEscape($reply['dt']) . "','" . hesk_dbEscape($reply['attachments']) . "','" . intval($reply['staffid']) . "','" . intval($reply['rating']) . "','" . intval($reply['read']) . "', '" . intval($reply['html']) . "')");
}
/* Delete replies to the old ticket */

@ -652,9 +652,10 @@ function hesk_getEmailSubject($eml_file, $ticket = '', $is_ticket = 1, $strip =
}
/* Set status */
$statusRs = hesk_dbQuery("SELECT `Key` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . $ticket['status']);
$statusRs = hesk_dbQuery("SELECT `text` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref`
WHERE `status_id` = " . $ticket['status'] . " AND `language` = '". hesk_dbEscape($hesklang['LANGUAGE']) ."'");
$row = hesk_dbFetchAssoc($statusRs);
$ticket['status'] = $hesklang[$row['Key']];
$ticket['status'] = $row['text'];
/* Replace all special tags */
$msg = str_replace('%%SUBJECT%%', $ticket['subject'], $msg);
@ -815,9 +816,10 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message
$ticket['owner'] = hesk_msgToPlain(hesk_getOwnerName($ticket['owner']), 1);
/* Set status */
$statusRs = hesk_dbQuery("SELECT `Key` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . $ticket['status']);
$statusRs = hesk_dbQuery("SELECT `text` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref`
WHERE `status_id` = " . $ticket['status'] . " AND `language` = '". hesk_dbEscape($hesklang['LANGUAGE']) ."'");
$row = hesk_dbFetchAssoc($statusRs);
$ticket['status'] = $hesklang[$row['Key']];
$ticket['status'] = $row['text'];
/* Replace all special tags */
$msg = str_replace('%%NAME%%', $ticket['name'], $msg);

@ -0,0 +1 @@
(function(){tinymce.create("tinymce.plugins.AutolinkPlugin",{init:function(a,b){var c=this;a.onKeyDown.addToTop(function(d,f){if(f.keyCode==13){return c.handleEnter(d)}});if(tinyMCE.isIE){return}a.onKeyPress.add(function(d,f){if(f.which==41){return c.handleEclipse(d)}});a.onKeyUp.add(function(d,f){if(f.keyCode==32){return c.handleSpacebar(d)}})},handleEclipse:function(a){this.parseCurrentLine(a,-1,"(",true)},handleSpacebar:function(a){this.parseCurrentLine(a,0,"",true)},handleEnter:function(a){this.parseCurrentLine(a,-1,"",false)},parseCurrentLine:function(i,d,b,g){var a,f,c,n,k,m,h,e,j;a=i.selection.getRng(true).cloneRange();if(a.startOffset<5){e=a.endContainer.previousSibling;if(e==null){if(a.endContainer.firstChild==null||a.endContainer.firstChild.nextSibling==null){return}e=a.endContainer.firstChild.nextSibling}j=e.length;a.setStart(e,j);a.setEnd(e,j);if(a.endOffset<5){return}f=a.endOffset;n=e}else{n=a.endContainer;if(n.nodeType!=3&&n.firstChild){while(n.nodeType!=3&&n.firstChild){n=n.firstChild}if(n.nodeType==3){a.setStart(n,0);a.setEnd(n,n.nodeValue.length)}}if(a.endOffset==1){f=2}else{f=a.endOffset-1-d}}c=f;do{a.setStart(n,f>=2?f-2:0);a.setEnd(n,f>=1?f-1:0);f-=1}while(a.toString()!=" "&&a.toString()!=""&&a.toString().charCodeAt(0)!=160&&(f-2)>=0&&a.toString()!=b);if(a.toString()==b||a.toString().charCodeAt(0)==160){a.setStart(n,f);a.setEnd(n,c);f+=1}else{if(a.startOffset==0){a.setStart(n,0);a.setEnd(n,c)}else{a.setStart(n,f);a.setEnd(n,c)}}var m=a.toString();if(m.charAt(m.length-1)=="."){a.setEnd(n,c-1)}m=a.toString();h=m.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i);if(h){if(h[1]=="www."){h[1]="http://www."}else{if(/@$/.test(h[1])&&!/^mailto:/.test(h[1])){h[1]="mailto:"+h[1]}}k=i.selection.getBookmark();i.selection.setRng(a);tinyMCE.execCommand("createlink",false,h[1]+h[2]);i.selection.moveToBookmark(k);i.nodeChanged();if(tinyMCE.isWebKit){i.selection.collapse(false);var l=Math.min(n.length,c+1);a.setStart(n,l);a.setEnd(n,l);i.selection.setRng(a)}}},getInfo:function(){return{longname:"Autolink",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autolink",tinymce.plugins.AutolinkPlugin)})();

@ -0,0 +1,184 @@
/**
* editor_plugin_src.js
*
* Copyright 2011, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://tinymce.moxiecode.com/license
* Contributing: http://tinymce.moxiecode.com/contributing
*/
(function() {
tinymce.create('tinymce.plugins.AutolinkPlugin', {
/**
* Initializes the plugin, this will be executed after the plugin has been created.
* This call is done before the editor instance has finished it's initialization so use the onInit event
* of the editor instance to intercept that event.
*
* @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
* @param {string} url Absolute URL to where the plugin is located.
*/
init : function(ed, url) {
var t = this;
// Add a key down handler
ed.onKeyDown.addToTop(function(ed, e) {
if (e.keyCode == 13)
return t.handleEnter(ed);
});
// Internet Explorer has built-in automatic linking for most cases
if (tinyMCE.isIE)
return;
ed.onKeyPress.add(function(ed, e) {
if (e.which == 41)
return t.handleEclipse(ed);
});
// Add a key up handler
ed.onKeyUp.add(function(ed, e) {
if (e.keyCode == 32)
return t.handleSpacebar(ed);
});
},
handleEclipse : function(ed) {
this.parseCurrentLine(ed, -1, '(', true);
},
handleSpacebar : function(ed) {
this.parseCurrentLine(ed, 0, '', true);
},
handleEnter : function(ed) {
this.parseCurrentLine(ed, -1, '', false);
},
parseCurrentLine : function(ed, end_offset, delimiter, goback) {
var r, end, start, endContainer, bookmark, text, matches, prev, len;
// We need at least five characters to form a URL,
// hence, at minimum, five characters from the beginning of the line.
r = ed.selection.getRng(true).cloneRange();
if (r.startOffset < 5) {
// During testing, the caret is placed inbetween two text nodes.
// The previous text node contains the URL.
prev = r.endContainer.previousSibling;
if (prev == null) {
if (r.endContainer.firstChild == null || r.endContainer.firstChild.nextSibling == null)
return;
prev = r.endContainer.firstChild.nextSibling;
}
len = prev.length;
r.setStart(prev, len);
r.setEnd(prev, len);
if (r.endOffset < 5)
return;
end = r.endOffset;
endContainer = prev;
} else {
endContainer = r.endContainer;
// Get a text node
if (endContainer.nodeType != 3 && endContainer.firstChild) {
while (endContainer.nodeType != 3 && endContainer.firstChild)
endContainer = endContainer.firstChild;
// Move range to text node
if (endContainer.nodeType == 3) {
r.setStart(endContainer, 0);
r.setEnd(endContainer, endContainer.nodeValue.length);
}
}
if (r.endOffset == 1)
end = 2;
else
end = r.endOffset - 1 - end_offset;
}
start = end;
do
{
// Move the selection one character backwards.
r.setStart(endContainer, end >= 2 ? end - 2 : 0);
r.setEnd(endContainer, end >= 1 ? end - 1 : 0);
end -= 1;
// Loop until one of the following is found: a blank space, &nbsp;, delimeter, (end-2) >= 0
} while (r.toString() != ' ' && r.toString() != '' && r.toString().charCodeAt(0) != 160 && (end -2) >= 0 && r.toString() != delimiter);
if (r.toString() == delimiter || r.toString().charCodeAt(0) == 160) {
r.setStart(endContainer, end);
r.setEnd(endContainer, start);
end += 1;
} else if (r.startOffset == 0) {
r.setStart(endContainer, 0);
r.setEnd(endContainer, start);
}
else {
r.setStart(endContainer, end);
r.setEnd(endContainer, start);
}
// Exclude last . from word like "www.site.com."
var text = r.toString();
if (text.charAt(text.length - 1) == '.') {
r.setEnd(endContainer, start - 1);
}
text = r.toString();
matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i);
if (matches) {
if (matches[1] == 'www.') {
matches[1] = 'http://www.';
} else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) {
matches[1] = 'mailto:' + matches[1];
}
bookmark = ed.selection.getBookmark();
ed.selection.setRng(r);
tinyMCE.execCommand('createlink',false, matches[1] + matches[2]);
ed.selection.moveToBookmark(bookmark);
ed.nodeChanged();
// TODO: Determine if this is still needed.
if (tinyMCE.isWebKit) {
// move the caret to its original position
ed.selection.collapse(false);
var max = Math.min(endContainer.length, start + 1);
r.setStart(endContainer, max);
r.setEnd(endContainer, max);
ed.selection.setRng(r);
}
}
},
/**
* Returns information about the plugin as a name/value array.
* The current keys are longname, author, authorurl, infourl and version.
*
* @return {Object} Name/value array containing information about the plugin.
*/
getInfo : function() {
return {
longname : 'Autolink',
author : 'Moxiecode Systems AB',
authorurl : 'http://tinymce.moxiecode.com',
infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink',
version : tinymce.majorVersion + "." + tinymce.minorVersion
};
}
});
// Register plugin
tinymce.PluginManager.add('autolink', tinymce.plugins.AutolinkPlugin);
})();

@ -680,6 +680,7 @@ function print_add_ticket()
<div class="col-sm-9">
<textarea placeholder="<?php echo htmlspecialchars($hesklang['message']); ?>" name="message"
id="message" class="form-control htmlEditor" rows="12"
data-rich-text-enabled="<?php echo $modsForHesk_settings['rich_text_for_tickets_for_customers']; ?>"
cols="60" <?php if (in_array('message', $_SESSION['iserror'])) {
echo ' class="isError" ';
} ?> data-error="<?php echo htmlspecialchars($hesklang['enter_message']); ?>"
@ -697,6 +698,7 @@ function print_add_ticket()
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup",

@ -37,7 +37,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// We will be installing this HESK version:
define('HESK_NEW_VERSION','2.7.2');
define('MODS_FOR_HESK_NEW_VERSION','3.0.3');
define('MODS_FOR_HESK_NEW_VERSION','3.0.5');
define('REQUIRE_PHP_VERSION','5.3.0');
define('REQUIRE_MYSQL_VERSION','5.0.7');

@ -80,6 +80,10 @@ if ($version == 2) {
execute302Scripts();
} elseif ($version == 37) {
execute303Scripts();
} elseif ($version == 38) {
execute304Scripts();
} elseif ($version == 39) {
execute305Scripts();
} else {
$response = 'The version "' . $version . '" was not recognized. Check the value submitted and try again.';
print $response;

@ -46,6 +46,8 @@ $buildToVersionMap = array(
35 => '3.0.1',
36 => '3.0.2',
37 => '3.0.3',
38 => '3.0.4',
39 => '3.0.5',
);
function echoInitialVersionRows($version, $build_to_version_map)

@ -107,6 +107,12 @@ function processUpdates(startingVersion) {
} else if (startingVersion < 37) {
startVersionUpgrade('303');
executeUpdate(37, '303', '3.0.3');
} else if (startingVersion < 38) {
startVersionUpgrade('304');
executeUpdate(38, '304', '3.0.4');
} else if (startingVersion < 39) {
startVersionUpgrade('305');
executeUpdate(39, '305', '3.0.5');
} else {
installationFinished();
}

@ -118,6 +118,8 @@ hesk_dbConnect();
<select name="current-version" class="form-control">
<option disabled>Select One, or "No Previous Installation" Below</option>
<optgroup label="Mods for HESK 3">
<option value="38">3.0.4</option>
<option value="37">3.0.3</option>
<option value="36">3.0.2</option>
<option value="35">3.0.1</option>
<option value="34">3.0.0</option>

@ -960,6 +960,20 @@ function execute303Scripts() {
updateVersion('3.0.3');
}
function execute304Scripts() {
global $hesk_settings;
hesk_dbConnect();
updateVersion('3.0.4');
}
function execute305Scripts() {
global $hesk_settings;
hesk_dbConnect();
updateVersion('3.0.5');
}
function execute310Scripts() {
global $hesk_settings;
hesk_dbConnect();

@ -22,6 +22,7 @@ $(document).ready(function() {
events.push(buildEvent(this.id, this));
});
callback(events);
updateCategoryVisibility();
},
error: function(data) {
console.error(data);

@ -22,6 +22,7 @@ $(document).ready(function() {
events.push(buildEvent(this.id, this));
});
callback(events);
updateCategoryVisibility();
},
error: function(data) {
console.error(data);

@ -22,9 +22,9 @@ $(document).ready(function() {
events.push(buildEvent(this.id, this));
});
callback(events);
updateCategoryVisibility();
},
error: function(data) {
console.error(data);
$.jGrowl($('#lang_error_loading_events').text(), { theme: 'alert-danger', closeTemplate: '' });
}
});

@ -255,7 +255,7 @@ function initializeMapForStaff(latitude, longitude, usersLocationText) {
$('#save-for-address').show();
});
$('#map-modal').on('shown.bs.modal', function(){
$('#more-modal').on('shown.bs.modal', function(){
setTimeout(function() {
map.invalidateSize();
}, 10);

@ -2,9 +2,9 @@
<p>Your support ticket "%%SUBJECT%%" has been submitted.</p>
<p>We reply to all tickets as soon as possible, within 24 to 48 hours. If we expect your ticket will take additional time, we will update you by sending you an email.</p>
<p>Ticket tracking ID: %%TRACK_ID%%</p>
<p>You can view the status of your ticket here:
%%TRACK_URL%%</p>
<p>You can view the status of your ticket here: %%TRACK_URL%%</p>
<p>You will receive an email notification when our staff replies to your ticket.</p>
<p>Sincerely,</p>
%%SITE_TITLE%% <br>
%%SITE_URL%%
<p>%%SITE_TITLE%% <br /> %%SITE_URL%%</p>
<p>&nbsp;</p>
<p><strong>Ticket Status:</strong> %%STATUS%%</p>

@ -579,7 +579,7 @@ $hesklang['add_ticket_your_message']='Your Message';
// EMAIL SUBJECTS
$hesklang['new_ticket_staff'] = '[#%%TRACK_ID%%] New ticket: %%SUBJECT%%';
$hesklang['ticket_received'] = '[#%%TRACK_ID%%] Ticket received: %%SUBJECT%%';
$hesklang['ticket_received'] = '[#%%TRACK_ID%%] Ticket received: %%SUBJECT%%; Status: %%STATUS%%';
$hesklang['ticket_assigned_to_you'] = '[#%%TRACK_ID%%] Ticket assigned: %%SUBJECT%%';
$hesklang['new_reply_by_customer'] = '[#%%TRACK_ID%%] New reply to: %%SUBJECT%%';
$hesklang['new_reply_by_staff'] = '[#%%TRACK_ID%%] New reply to: %%SUBJECT%%';

@ -62,12 +62,14 @@ $message = hesk_input(hesk_POST('message'));
// If the message was entered, further parse it
$modsForHesk_settings = mfh_getSettings();
if (strlen($message) && !$modsForHesk_settings['rich_text_for_tickets_for_customers']) {
// Make links clickable
$message = hesk_makeURL($message);
if (strlen($message)) {
if (!$modsForHesk_settings['rich_text_for_tickets_for_customers']) {
// Make links clickable
$message = hesk_makeURL($message);
// Turn newlines into <br />
$message = nl2br($message);
// Turn newlines into <br />
$message = nl2br($message);
}
} else {
$hesk_error_buffer[] = $hesklang['enter_message'];
}

@ -23,7 +23,7 @@ hesk_load_database_functions();
header('Content-Type: text/html; charset=' . $hesklang['ENCODING']);
/* Get the search query composed of the subject and message */
$query = hesk_REQUEST('q') or die('');
$query = strip_tags(html_entity_decode(hesk_REQUEST('q'))) or die('');
hesk_dbConnect();

@ -319,7 +319,13 @@ if (!$show['show']) {
<div class="blankSpace"></div>
<!-- REPLIES -->
<?php
// Print "Submit a reply" form?
if ($ticket['locked'] != 1 && $ticket['status'] != 3 && $hesk_settings['reply_top'] == 1) {
hesk_printCustomerReplyForm();
}
if ($hesk_settings['new_top']) {
$i = hesk_printCustomerTicketReplies() ? 0 : 1;
} else {
@ -405,12 +411,6 @@ if (!$show['show']) {
}
?>
<!-- END REPLIES -->
<?php
// Print "Submit a reply" form?
if ($ticket['locked'] != 1 && $ticket['status'] != 3 && $hesk_settings['reply_top'] == 1) {
hesk_printCustomerReplyForm();
}
?>
<?php
/* Print "Submit a reply" form? */
@ -627,6 +627,7 @@ function hesk_printCustomerReplyForm($reopen = 0)
elements: "content",
theme: "advanced",
convert_urls: false,
plugins: "autolink",
theme_advanced_buttons1: "cut,copy,paste,|,undo,redo,|,formatselect,fontselect,fontsizeselect,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2: "sub,sup,|,charmap,|,bullist,numlist,|,outdent,indent,insertdate,inserttime,preview,|,forecolor,backcolor,|,hr,removeformat,visualaid,|,link,unlink,anchor,image,cleanup",

@ -48,7 +48,7 @@ require_once(HESK_PATH . 'inc/header.inc.php');
// Need to notify staff?
// --> From autoassign?
$getOwnerRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE ID = " . hesk_dbEscape($ticket['owner']));
$getOwnerRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE ID = " . intval($ticket['owner']));
$autoassign_owner = hesk_dbFetchAssoc($getOwnerRs);
if ($ticket['owner'] && $autoassign_owner['notify_assigned']) {
hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you', $modsForHesk_settings);

Loading…
Cancel
Save