@ -17,7 +17,7 @@ define('WYSIWYG', 1);
define('VALIDATOR', 1);
define('MFH_PAGE_LAYOUT', 'TOP_AND_SIDE');
define('EXTRA_JS', '< script src = "'.HESK_PATH.'internal-api/js/admin-ticket.js" > < / script > ');
define('EXTRA_JS', '< script src = "'.HESK_PATH.'internal-api/js/admin-ticket.js" > < / script > < script src = "'.HESK_PATH.'js/jquery.dirtyforms.min.js" > < / script > ');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
@ -50,6 +50,10 @@ $can_unban_emails = hesk_checkPermission('can_unban_emails', 0);
$can_ban_ips = hesk_checkPermission('can_ban_ips', 0);
$can_unban_ips = hesk_checkPermission('can_unban_ips', 0);
$can_resolve = hesk_checkPermission('can_resolve', 0);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0);
$can_privacy = hesk_checkPermission('can_privacy',0);
$can_export = hesk_checkPermission('can_export',0);
$can_change_due_date = hesk_checkPermission('can_change_due_date', 0);
// Get ticket ID
$trackingID = hesk_cleanID() or print_form();
@ -90,13 +94,47 @@ if (hesk_dbNumRows($res) != 1) {
/* Permission to view this ticket? */
if ($ticket['owner'] & & $ticket['owner'] != $_SESSION['id'] & & !hesk_checkPermission('can_view_ass_others', 0)) {
hesk_error($hesklang['ycvtao']);
// Maybe this user is allowed to view tickets he/she assigned?
if (!$can_view_ass_by || $ticket['assignedby'] != $_SESSION['id']) {
hesk_error($hesklang['ycvtao']);
}
}
if (!$ticket['owner'] & & !$can_view_unassigned) {
hesk_error($hesklang['ycovtay']);
}
// Get audit information
$audit_sort = $hesk_settings['new_top'] ? "ASC" : "DESC";
$auditRes = hesk_dbQuery("SELECT `audit`.`id`, `audit`.`language_key`, `audit`.`date`,
`values`.`replacement_index`, `values`.`replacement_value`
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` AS `audit`
LEFT JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail_to_replacement_values` AS `values`
ON `audit`.`id` = `values`.`audit_trail_id`
WHERE `entity_type` = 'TICKET' AND `entity_id` = " . intval($ticket['id']) . "
ORDER BY `audit`.`date` {$audit_sort}");
$audit_records = array();
$current_audit_record = null;
while ($row = hesk_dbFetchAssoc($auditRes)) {
if ($current_audit_record == null || $current_audit_record['id'] != $row['id']) {
if ($current_audit_record != null) {
$audit_records[] = $current_audit_record;
}
$current_audit_record['id'] = $row['id'];
$current_audit_record['language_key'] = $row['language_key'];
$current_audit_record['date'] = $row['date'];
$current_audit_record['replacement_values'] = array();
}
if ($row['replacement_index'] != null) {
$current_audit_record['replacement_values'][intval($row['replacement_index'])] = $row['replacement_value'];
}
}
if ($current_audit_record != null) {
$audit_records[] = $current_audit_record;
}
/* Set last replier name */
if ($ticket['lastreplier']) {
if (empty($ticket['repliername'])) {
@ -120,19 +158,23 @@ $managerRow = hesk_dbFetchAssoc($managerRS);
$isManager = $managerRow['id'] == $category['manager'];
if ($isManager) {
$can_del_notes =
$can_reply =
$can_delete =
$can_edit =
$can_archive =
$can_assign_self =
$can_view_unassigned =
$can_change_own_cat =
$can_change_cat =
$can_ban_emails =
$can_unban_emails =
$can_ban_ips =
$can_unban_ips =
$can_resolve = true;
$can_reply =
$can_delete =
$can_edit =
$can_archive =
$can_assign_self =
$can_view_unassigned =
$can_change_own_cat =
$can_change_cat =
$can_ban_emails =
$can_unban_emails =
$can_ban_ips =
$can_unban_ips =
$can_resolve =
$can_view_ass_by =
$can_privacy =
$can_export =
$can_change_due_date = true;
}
/* Is this user allowed to view tickets inside this category? */
@ -392,13 +434,14 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) {
'trackid' => $ticket['trackid'],
'status' => $ticket['status'],
'name' => $_SESSION['name'],
'lastreplier' => $ticket['lastreplier'],
'subject' => $ticket['subject'],
'message' => stripslashes($msg),
'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true),
'attachments' => $myattachments,
'id' => $ticket['id'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => $ticket['repliername'],
);
// 2. Add custom fields to the array
@ -439,8 +482,10 @@ if ($hesk_settings['time_worked'] && ($can_reply || $can_edit) && isset($_POST['
$time_worked = hesk_getTime($h . ':' . $m . ':' . $s);
/* Update database */
$revision = sprintf($hesklang['thist14'], hesk_date(), $time_worked, $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `time_worked`='" . hesk_dbEscape($time_worked) . "', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `time_worked`='" . hesk_dbEscape($time_worked) . "' WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'");
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_time_worked', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $time_worked));
/* Show ticket */
hesk_process_messages($hesklang['twu'], 'admin_ticket.php?track=' . $trackingID . '& Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
@ -476,13 +521,26 @@ if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) {
}
hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = ' . intval($ticket['id']) . ' WHERE `trackid` = \'' . hesk_dbEscape(hesk_POST('childTrackingId')) . '\'');
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_linked_ticket', hesk_date(),
array(
0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => hesk_POST('childTrackingId')
));
hesk_process_messages(sprintf($hesklang['link_added'], $_POST['childTrackingId']), 'admin_ticket.php?track=' . $trackingID . '& Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
}
/* Delete child action */
if (($can_reply || $can_edit) & & isset($_GET['deleteChild'])) {
//-- Delete the relationship
$innerTrackingRs = hesk_dbQuery("SELECT `trackid` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id` = " . hesk_dbEscape($_GET['deleteChild']));
$innerTrackingId = hesk_dbFetchAssoc($innerTrackingRs);
hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = NULL WHERE `ID` = ' . hesk_dbEscape($_GET['deleteChild']));
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_unlinked_ticket', hesk_date(),
array(
0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $innerTrackingId['trackid']
));
hesk_process_messages($hesklang['ticket_no_longer_linked'], 'admin_ticket.php?track=' . $trackingID . '& Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
} elseif (($can_reply || $can_edit) & & isset($_GET['deleteParent'])) {
@ -528,7 +586,6 @@ if (isset($_GET['delatt']) && hesk_token_check()) {
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` WHERE `att_id`='" . intval($att_id) . "'");
/* Update ticket or reply in the database */
$revision = sprintf($hesklang['thist12'], hesk_date(), $att['real_name'], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
if ($reply) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name'] . '#' . $att['saved_name']) . ",','') WHERE `id`='" . intval($reply) . "'");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `id`='" . intval($ticket['id']) . "'");
@ -539,6 +596,9 @@ if (isset($_GET['delatt']) && hesk_token_check()) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name'] . '#' . $att['saved_name']) . ",','') WHERE `id`='" . intval($ticket['id']) . "'");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name']) . ",',''), `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `id`='" . intval($ticket['id']) . "'");
}
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_attachment_deleted', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $att['real_name']));
hesk_process_messages($hesklang['kb_att_rem'], 'admin_ticket.php?track=' . $trackingID . '& Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
}
@ -699,9 +759,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
< / span >
< / b > < br >
<?php if ( $can_change_due_date ) : ?>
< button class = "btn btn-default btn-sm" id = "change-button" >
<?php echo $hesklang [ 'chg' ]; ?>
< / button >
<?php endif ; ?>
< / div >
< div id = "editable-due-date" style = "display: none" >
< span class = "form-group" >
@ -890,6 +952,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
/* This will handle error, success and notice messages */
hesk_handle_messages();
$service_messages = mfh_get_service_messages('STAFF_VIEW_TICKET');
foreach ($service_messages as $sm) {
hesk_service_message($sm);
}
// Prepare special custom fields
foreach ($hesk_settings['custom_fields'] as $k=>$v) {
if ($v['use'] & & hesk_is_custom_field_in_category($k, $ticket['category']) ) {
@ -948,25 +1015,42 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
);
$options = array();
for ($i = 0; $i < 4 ; $ i + + ) {
if ($ticket['priority'] == $i) {
if ($i === 0) {
$cssClass = 'critical-priority';
} elseif ($i === 1) {
$cssClass = 'high-priority';
} elseif ($i === 2) {
$cssClass = 'medium-priority';
} else {
$cssClass = 'low-priority';
}
}
$selected = $ticket['priority'] == $i ? 'selected' : '';
array_push($options, '< option value = "' . $i . '" ' . $ selected . ' > ' . $priorityLanguages[$i] . '< / option > ');
}
$content = "< i class = 'fa fa-fw fa-%s %s' style = 'font-size: 1em' > < / i > {$priorityLanguages[$i]}";
if ($i === 0) {
$content = sprintf($content, 'long-arrow-up', 'critical');
} elseif ($i === 1) {
$content = sprintf($content, 'angle-double-up', 'orange');
} elseif ($i === 2) {
$content = sprintf($content, 'angle-double-down', 'green');
} else {
$content = sprintf($content, 'long-arrow-down', 'blue');
}
echo '< div class = "ticket-cell-admin col-md-3 col-sm-12 ' ;
if ($ticket['priority'] == 0) {
echo 'critical-priority">';
} elseif ($ticket['priority'] == 1) {
echo 'high-priority">';
} else {
echo 'med-low-priority">';
array_push($options, '< option data-content = "' . $content . '" value = "' . $i . '" ' . $ selected . ' > ' . $priorityLanguages[$i] . '< / option > ');
}
echo '< div class = "ticket-cell-admin col-md-3 col-sm-12 ' . $cssClass . '" > ';
echo '< p class = "ticket-property-title" > ' . $hesklang['priority'] . '< / p > ';
echo '< form style = "margin-bottom:0;" id = "changePriorityForm" action = "priority.php" method = "post" >
< span style = "white-space:nowrap;" >
< select class = " form-control" name = "priority" onchange = "document.getElementById(\'changePriorityForm\').submit();" > ';
< select class = " selectpicker form-control" name = "priority" onchange = "document.getElementById(\'changePriorityForm\').submit();" > ';
echo implode('', $options);
echo '
< / select >
@ -987,13 +1071,13 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
$results = mfh_getAllStatuses();
foreach ($results as $row) {
$selected = $ticket['status'] == $row['ID'] ? 'selected' : '';
$status_options[$row['ID']] = '< option value= "' . $row['ID'] . '" ' . $ selected . ' > ' . mfh_getDisplayTextForStatusId($row['ID']) . '< / option > ';
$status_options[$row['ID']] = '< option style= "color: ' . $row['TextColor'] . '" value= "' . $row['ID'] . '" ' . $ selected . ' > ' . mfh_getDisplayTextForStatusId($row['ID']) . '< / option > ';
}
echo '
< form role = "form" id = "changeStatusForm" style = "margin-bottom:0;" action = "change_status.php" method = "post" >
< span style = "white-space:nowrap;" >
< select class = " form-control" onchange = "document.getElementById(\'changeStatusForm\').submit();" name = "s" >
< select class = " selectpicker form-control" onchange = "document.getElementById(\'changeStatusForm\').submit();" name = "s" >
' . implode('', $status_options) . '
< / select >
@ -1011,7 +1095,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
echo '
< form style = "margin-bottom:0;" id = "changeOwnerForm" action = "assign_owner.php" method = "post" >
< span style = "white-space:nowrap;" >
< select class = " form-control" name = "owner" onchange = "document.getElementById(\'changeOwnerForm\').submit();" > ';
< select class = " selectpicker form-control" name = "owner" onchange = "document.getElementById(\'changeOwnerForm\').submit();" > ';
$selectedForUnassign = 'selected';
foreach ($admins as $k => $v) {
$selected = '';
@ -1046,7 +1130,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
< form style = "margin-bottom:0;" id = "changeCategory" action = "move_category.php" method = "post" >
< span style = "white-space:nowrap;" >
< select name = "category" class = " form-control" onchange = "document.getElementById(\'changeCategory\').submit();" >
< select name = "category" class = " selectpicker form-control" onchange = "document.getElementById(\'changeCategory\').submit();" >
' . $categories_options . '
< / select >
@ -1122,9 +1206,9 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
echo '
< a href = "../download_attachment.php?att_id=' . $att_id . '&track=' . $trackingID . '" >
< i class = "fa fa-paperclip" style = "font-size:16px;" data-toggle = "tooltip" data-placement = "top" data-original-title = "' . $hesklang['dnl'] . ' ' . $att_name . ' "> < / i >
< i class = "fa fa-paperclip" style = "font-size:16px;" data-toggle = "tooltip" data-placement = "top" data-original-title = "' . $hesklang['dnl'] . ' "> < / i >
< / a >
< a href = "../download_attachment.php?att_id=' . $att_id . '&track=' . $trackingID . '" > ' . $att_name . '< / a > < br / >
< a href = "../download_attachment.php?att_id=' . $att_id . '&track=' . $trackingID . '" > ' . $att_name . ' (' . mfh_getAttachmentFileSize($att_id) . ')' . ' < / a > < br / >
';
}
}
@ -1167,7 +1251,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
<?php build_dropzone_markup ( true , 'notesFiledrop' ); ?>
< / div >
< / div >
<?php display_dropzone_field ( $hesk_settings [ 'hesk_url' ] . '/ internal-api/ticket/upload-attachment.php', 'notesFiledrop' ); ?>
<?php display_dropzone_field ( HESK_PATH . ' internal-api/ticket/upload-attachment.php', 'notesFiledrop' ); ?>
< div class = "text-right" >
< i > <?php echo $hesklang [ 'nhid' ]; ?> </ i >
< div class = "btn-group" >
@ -1250,7 +1334,7 @@ require_once(HESK_PATH . 'inc/footer.inc.php');
function hesk_getAdminButtons($category_id)
{
global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve, $isManager;
global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve, $can_privacy, $can_export, $ isManager;
$options = '';
@ -1258,12 +1342,12 @@ function hesk_getAdminButtons($category_id)
if ($can_edit) {
$tmp = $reply ? '& reply=' . $reply['id'] : '';
$mgr = $isManager ? '& isManager=true' : '';
$options .= '< a class= "btn btn-default" href = "edit_post.php?track=' . $trackingID . $tmp . $mgr . '" > < i class = "fa fa-pencil orange" > < / i > ' . $hesklang['edit'] . '< / a > ';
$options .= '< a id= "editticket" title = "'.$hesklang['edtt'].'" class= "btn btn-default" href = "edit_post.php?track=' . $trackingID . $tmp . $mgr . '" > < i class = "fa fa-pencil orange" > < / i > ' . $hesklang['btn_ edit'] . '< / a > ';
}
/* Print ticket button */
$options .= '< a class = "btn btn-default" href= "../print.php?track=' . $trackingID . '" > < i class = "fa fa-print" > < / i > ' . $hesklang['printer_friendly '] . '< / a > ';
$options .= '< a class = "btn btn-default" title= "'.$hesklang['printer_friendly'].'" href= "../print.php?track=' . $trackingID . '" > < i class = "fa fa-print" > < / i > ' . $hesklang['btn_ print'] . '< / a > ';
/* Copy ticket button */
$strippedName = strip_tags($ticket['name']);
@ -1418,7 +1502,7 @@ function hesk_getAdminButtons($category_id)
/* Lock ticket button */
if ($can_resolve) {
$template =
'< div class = "col-md-6 col-sm-12" > < a class= "button-link" href = "lock.php?track=' . $trackingID . '&locked=%s&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" >
'< div class = "col-md-6 col-sm-12" > < a id= "%s" title = "%s" class= "button-link" href = "lock.php?track=' . $trackingID . '&locked=%s&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" >
< div class = "panel panel-default" >
< div class = "panel-body" >
< h4 >
@ -1428,14 +1512,14 @@ function hesk_getAdminButtons($category_id)
< / div >
< / a > < / div > ';
$dropdown .= $ticket['locked']
? sprintf($template, 0, 'unlock', $hesklang['tul'])
: sprintf($template, 1, 'lock', $hesklang['tlo']);
? sprintf($template, 'unlock', $hesklang['tul'] . ' - ' . $hesklang['isloc'], 0, 'unlock', $hesklang['b tn_ un lock '])
: sprintf($template, 'lock', $hesklang['tlo'] . ' - ' . $hesklang['isloc'], 1, 'lock', $hesklang['b tn_ lock ']);
}
/* Tag ticket button */
if ($can_archive) {
$template =
'< div class = "col-md-6 col-sm-12" > < a class= "button-link" href = "archive.php?track=' . $trackingID . '&archived=%s&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" >
'< div class = "col-md-6 col-sm-12" > < a id= "%s" title = "%s" class= "button-link" href = "archive.php?track=' . $trackingID . '&archived=%s&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" >
< div class = "panel panel-default" >
< div class = "panel-body" >
< h4 >
@ -1446,18 +1530,51 @@ function hesk_getAdminButtons($category_id)
< / a > < / div > ';
$dropdown .= $ticket['archive']
? sprintf($template, 0, $hesklang['remove_archive '])
: sprintf($template, 1, $hesklang['add_archive ']);
? sprintf($template, 'untag', $hesklang['remove_archive'], 0, $hesklang['btn_untag '])
: sprintf($template, 'tag', $hesklang['add_archive'], 1, $hesklang['btn_tag ']);
}
/* Import to knowledgebase button */
if ($hesk_settings['kb_enable'] & & hesk_checkPermission('can_man_kb', 0)) {
$dropdown .=
'< div class = "col-md-6 col-sm-12" > < a href= "manage_knowledgebase.php?a=import_article&track=' . $trackingID . '" class = "button-link" >
'< div class = "col-md-6 col-sm-12" > < a id= "addtoknow" title = "'.$hesklang['import_kb'].'" href= "manage_knowledgebase.php?a=import_article&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'] . '
< i class = "fa fa-lightbulb-o fa-fw" > < / i > ' . $hesklang['btn_import_kb'] . '
< / h4 >
< / div >
< / div >
< / a > < / div > ';
}
// Export ticket
if ($can_export) {
$dropdown .=
'< div class = "col-md-6 col-sm-12" >
< a id = "exportticket" href = "export_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999).'&token='.hesk_token_echo(0).'"
title="'.$hesklang['btn_export'].'" class="button-link">
< div class = "panel panel-default" >
< div class = "panel-body" >
< h4 >
< i class = "fa fa-download fa-fw" > < / i > '.$hesklang['btn_export'].'
< / h4 >
< / div >
< / div >
< / a > < / div > ';
}
// Anonymize ticket
if ($can_privacy) {
$dropdown .=
'< div class = "col-md-6 col-sm-12" >
< a id = "exportticket" href = "anonymize_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999).'&token='.hesk_token_echo(0).'"
onclick="return hesk_confirmExecute(\''.hesk_makeJsString($hesklang['confirm_anony']).'?\\n\\n'.hesk_makeJsString($hesklang['privacy_anon_info']).'\');"
title="'.$hesklang['confirm_anony'].'" class="button-link">
< div class = "panel panel-default" >
< div class = "panel-body warning" >
< h4 >
< i class = "fa fa-shield fa-fw" > < / i > '.$hesklang['btn_anony'].'
< / h4 >
< / div >
< / div >
@ -1469,11 +1586,11 @@ function hesk_getAdminButtons($category_id)
if ($reply) {
$url = 'admin_ticket.php';
$tmp = 'delete_post=' . $reply['id'];
$txt = $hesklang['delt '];
$txt = $hesklang['btn_delr '];
} else {
$url = 'delete_tickets.php';
$tmp = 'delete_ticket=1';
$txt = $hesklang['dele '];
$txt = $hesklang['btn_delt '];
}
$dropdown .=
'< div class = "col-md-6 col-sm-12" > < a class = "button-link" href = "' . $url . '?track=' . $trackingID . '&' . $tmp . '&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" onclick = "return hesk_confirmExecute(\'' . hesk_makeJsString($txt) . '?\');" >
@ -1496,7 +1613,7 @@ function hesk_getAdminButtons($category_id)
function hesk_getAdminButtonsInTicket($reply = 0, $white = 1)
{
global $hesk_settings, $hesklang, $ticket, $reply, $ trackingID, $can_edit, $can_archive, $can_delete, $isManager;
global $hesk_settings, $hesklang, $ticket, $trackingID, $can_edit, $can_archive, $can_delete, $isManager;
$options = $reply ? '' : '< div class = "pull-right" > ';
@ -1506,19 +1623,21 @@ function hesk_getAdminButtonsInTicket($reply = 0, $white = 1)
$replyDataAttribute = 'data-reply-id="' . $reply['id'] . '"';
}
$options .= '
if ($ticket['email'] !== '') {
$options .= '
< button class = "btn btn-default" data-action = "resend-email-notification" ' . $ replyDataAttribute . ' data-ticket-id = "' . $ticket['id'] . '" >
< i class = "fa fa-envelope navy-blue" > < / i > ' . $hesklang['resend_email_notification'] . '
< / button >
< span id = "lang_email_notification_sent" style = "display: none" > ' . $hesklang['email_notification_sent'] . '< / span >
< span id = "lang_email_notification_resend_failed" style = "display: none" > ' . $hesklang['email_notification_resend_failed'] . '< / span >
';
}
/* Edit post */
if ($can_edit) {
$tmp = $reply ? '& reply=' . $reply['id'] : '';
$mgr = $isManager ? '& isManager=true' : '';
$options .= '< a class = "btn btn-default" href = "edit_post.php?track=' . $trackingID . $tmp . $mgr . '" > < i class = "fa fa-pencil orange" > < / i > ' . $hesklang['edt t'] . '< / a > ';
$options .= '< a class = "btn btn-default" href = "edit_post.php?track=' . $trackingID . $tmp . $mgr . '" > < i class = "fa fa-pencil orange" > < / i > ' . $hesklang['btn_edi t'] . '< / a > ';
}
@ -1527,13 +1646,13 @@ function hesk_getAdminButtonsInTicket($reply = 0, $white = 1)
if ($reply) {
$url = 'admin_ticket.php';
$tmp = 'delete_post=' . $reply['id'];
$txt = $hesklang['delt '];
$txt = $hesklang['btn_delr '];
} else {
$url = 'delete_tickets.php';
$tmp = 'delete_ticket=1';
$txt = $hesklang['dele '];
$txt = $hesklang['btn_delt '];
}
$options .= '< a class= "btn btn-default" href = "' . $url . '?track=' . $trackingID . '&' . $tmp . '&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" onclick = "return hesk_confirmExecute(\'' . $txt . '?\');" > < i class = "fa fa-times red" > < / i > ' . $txt . '< / a > ';
$options .= '< a id= "deleteticket" class= "btn btn-default" href = "' . $url . '?track=' . $trackingID . '&' . $tmp . '&Refresh=' . mt_rand(10000, 99999) . '&token=' . hesk_token_echo(0) . '" onclick = "return hesk_confirmExecute(\'' . $txt . '?\');" > < i class = "fa fa-times red" > < / i > ' . $txt . '< / a > ';
}
/* Return generated HTML */
@ -1586,7 +1705,7 @@ function print_form()
} // End print_form()
function mfh_print_message() {
global $ticket, $hesklang, $hesk_settings, $can_ban_emails, $can_ban_ips, $trackingID, $modsForHesk_settings;
global $ticket, $hesklang, $hesk_settings, $can_ban_emails, $can_ban_ips, $can_unban_emails, $can_unban_ips, $ trackingID, $modsForHesk_settings;
?>
< li >< i class = "fa fa-comment bg-red" data-toggle = "tooltip" title = " <?php echo $hesklang [ 'original_message' ]; ?> " ></ i >
< div class = "timeline-item" >
@ -1747,7 +1866,46 @@ function mfh_print_message() {
function hesk_printTicketReplies()
{
global $hesklang, $hesk_settings, $result, $reply;
global $hesklang, $hesk_settings, $result, $reply, $audit_records;
// Sort replies and audit messages. They'll be in the proper order already
$combined_records = array();
foreach ($audit_records as $audit_record) {
$audit_record['SORT_TYPE'] = 'AUDIT_RECORD';
$combined_records[] = $audit_record;
}
while ($reply = hesk_dbFetchAssoc($result)) {
$reply['SORT_TYPE'] = 'REPLY';
$combined_records[] = $reply;
}
// Re-sort them so they're in order by date
usort($combined_records, function ($a, $b) use (& $hesk_settings) {
$a_date = null;
$b_date = null;
if ($a['SORT_TYPE'] == 'REPLY') {
$a_date = strtotime($a['dt']);
} else {
$a_date = strtotime($a['date']);
}
if ($b['SORT_TYPE'] == 'REPLY') {
$b_date = strtotime($b['dt']);
} else {
$b_date = strtotime($b['date']);
}
if ($a_date === $b_date & & $a['SORT_TYPE'] != $b['SORT_TYPE']) {
if ($hesk_settings['new_top']) {
return $a['SORT_TYPE'] == 'REPLY' ? 1 : -1;
}
return $a['SORT_TYPE'] == 'REPLY' ? -1 : 1;
}
return $hesk_settings['new_top'] ? $b_date - $a_date : $a_date - $b_date;
});
echo '< ul class = "timeline" > ';
if (!$hesk_settings['new_top']) {
@ -1756,83 +1914,198 @@ function hesk_printTicketReplies()
echo '< li class = "today-top" > < i class = "fa fa-clock-o bg-gray" data-toggle = "tooltip" title = "' . $hesklang['timeline_today'] . '" > < / i > < / li > ';
}
while ($reply = hesk_dbFetchAssoc($result)) {
$reply['dt'] = hesk_date($reply['dt'], true);
?>
< li >
<?php if ( $reply [ 'staffid' ]) : ?>
< i class = "fa fa-reply bg-orange" data-toggle = "tooltip" title = " <?php echo $hesklang [ 'reply_by_staff' ]; ?> " ></ i >
<?php else : ?>
< i class = "fa fa-share bg-blue" data-toggle = "tooltip" title = " <?php echo $hesklang [ 'reply_by_customer' ]; ?> " ></ i >
<?php endif ; ?>
< div class = "timeline-item" >
< 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" >
< 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 >
foreach ($combined_records as $record) {
if ($record['SORT_TYPE'] == 'REPLY') {
mfh_print_reply($record);
} else {
mfh_print_audit_record($record);
}
}
if ($hesk_settings['new_top']) {
mfh_print_message();
} else {
echo '< li > < i class = "fa fa-clock-o bg-gray" data-toggle = "tooltip" title = "' . $hesklang['timeline_today'] . '" > < / i > < / li > ';
}
echo '< / ul > ';
return;
} // End hesk_printTicketReplies()
function mfh_print_reply($reply) {
global $hesklang, $hesk_settings;
$reply['dt'] = hesk_date($reply['dt'], true);
?>
< li >
<?php if ( $reply [ 'staffid' ]) : ?>
< i class = "fa fa-reply bg-orange" data-toggle = "tooltip" title = " <?php echo $hesklang [ 'reply_by_staff' ]; ?> " ></ i >
<?php else : ?>
< i class = "fa fa-share bg-blue" data-toggle = "tooltip" title = " <?php echo $hesklang [ 'reply_by_customer' ]; ?> " ></ i >
<?php endif ; ?>
< div class = "timeline-item" >
< 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" >
< 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 >
<?php
if ($hesk_settings['attachments']['use'] & & strlen($reply['attachments'])):
< / div >
<?php
if ($hesk_settings['attachments']['use'] & & strlen($reply['attachments'])):
?>
< div class = "timeline-footer" >
<?php mfh_listAttachments ( $reply [ 'attachments' ], $reply [ 'id' ], true ); ?>
< / div >
<?php endif ; ?>
< div class = "timeline-footer" >
< div class = "row" >
< div class = "col-md-6" >
<?php
/* Staff rating */
if ($hesk_settings['rating'] & & $reply['staffid']) {
if ($reply['rating'] == 1) {
echo '< p class = "rate" > ' . $hesklang['rnh'] . '< / p > ';
} elseif ($reply['rating'] == 5) {
echo '< p class = "rate" > ' . $hesklang['rh'] . '< / p > ';
}
}
/* Show "unread reply" message? */
if ($reply['staffid'] & & !$reply['read']) {
echo '< p class = "rate" > ' . $hesklang['unread'] . '< / p > ';
<?php endif ; ?>
< div class = "timeline-footer" >
< div class = "row" >
< div class = "col-md-6" >
<?php
/* Staff rating */
if ($hesk_settings['rating'] & & $reply['staffid']) {
if ($reply['rating'] == 1) {
echo '< p class = "rate" > ' . $hesklang['rnh'] . '< / p > ';
} elseif ($reply['rating'] == 5) {
echo '< p class = "rate" > ' . $hesklang['rh'] . '< / p > ';
}
?>
< / div >
< div class = "col-md-6 text-right" >
<?php echo hesk_getAdminButtonsInTicket (); ?>
< / div >
}
/* Show "unread reply" message? */
if ($reply['staffid'] & & !$reply['read']) {
echo '< p class = "rate" > ' . $hesklang['unread'] . '< / p > ';
}
?>
< / div >
< div class = "col-md-6 text-right" >
<?php echo hesk_getAdminButtonsInTicket ( $reply ); ?>
< / div >
< / div >
< / div >
< / li >
<?php
}
< / div >
< / li >
<?php
}
if ($hesk_settings['new_top']) {
mfh_print_message();
} else {
echo '< li > < i class = "fa fa-clock-o bg-gray" data-toggle = "tooltip" title = "' . $hesklang['timeline_today'] . '" > < / i > < / li > ';
}
echo '< / ul > ';
function mfh_print_audit_record($record) {
global $hesklang;
return;
$record['date'] = hesk_date($record['date'], true);
$font_icon = null;
switch ($record['language_key']) {
case 'audit_moved_category':
$font_icon = 'fa-pie-chart';
break;
case 'audit_assigned':
case 'audit_assigned_self':
$font_icon = 'fa-user-plus';
break;
case 'audit_unassigned':
$font_icon = 'fa-user-times';
break;
case 'audit_autoassigned':
$font_icon = 'fa-bolt';
break;
case 'audit_closed':
case 'audit_automatically_closed':
$font_icon = 'fa-check-circle';
break;
case 'audit_opened':
$font_icon = 'fa-circle-o';
break;
case 'audit_locked':
case 'audit_automatically_locked':
$font_icon = 'fa-lock';
break;
case 'audit_unlocked':
$font_icon = 'fa-unlock-alt';
break;
case 'audit_created':
case 'audit_submitted_by':
$font_icon = 'fa-user';
break;
case 'audit_priority':
// The new priority is in arg[1]
$priority = $record['replacement_values'][1];
if ($priority === 'critical') {
$font_icon = 'fa-long-arrow-up';
} elseif ($priority === 'high') {
$font_icon = 'fa-angle-double-up';
} elseif ($priority === 'medium') {
$font_icon = 'fa-angle-double-down';
} else {
$font_icon = 'fa-long-arrow-down';
}
} // End hesk_printTicketReplies()
// Now localize the text for display
$record['replacement_values'][1] = $hesklang[$priority];
break;
case 'audit_status':
$font_icon = 'fa-exchange';
break;
case 'audit_submitted_via_piping':
case 'audit_submitted_via_pop':
case 'audit_submitted_via_imap':
$font_icon = 'fa-envelope-o';
break;
case 'audit_attachment_deleted':
$font_icon = 'fa-paperclip';
break;
case 'audit_merged':
$font_icon = 'fa-code-fork';
break;
case 'audit_time_worked':
$font_icon = 'fa fa-clock-o';
break;
case 'audit_due_date_removed':
$font_icon = 'fa fa-calendar-minus-o';
break;
case 'audit_due_date_changed':
$font_icon = 'fa fa-calendar';
//-- Format the date
$record['replacement_values'][1] = date('Y-m-d', strtotime($record['replacement_values'][1]));
break;
case 'audit_linked_ticket':
$font_icon = 'fa fa-link';
break;
case 'audit_unlinked_ticket':
$font_icon = 'fa fa-chain-broken';
break;
case 'audit_anonymized':
$font_icon = 'fa fa-shield';
break;
default:
$font_icon = 'fa-question-circle';
break;
}
?>
< li >
< i class = "fa <?php echo $font_icon ; ?> bg-gray" ></ i >
< div class = "timeline-item" >
< span class = "time" >< i class = "fa fa-clock-o" ></ i > <?php echo $record [ 'date' ]; ?> </ span >
< h3 class = "timeline-header audit-record" >
<?php echo vsprintf ( $hesklang [ $record [ 'language_key' ]], $record [ 'replacement_values' ]); ?>
< / h3 >
< / div >
< / li >
<?php
}
function hesk_printReplyForm()
{
global $hesklang, $hesk_settings, $ticket, $admins, $can_options, $can_resolve, $options, $can_assign_self, $isManager, $modsForHesk_settings;
global $hesklang, $hesk_settings, $ticket, $admins, $can_options, $can_resolve, $options, $can_assign_self, $modsForHesk_settings, $isManager ;
// Force assigning a ticket before allowing to reply?
if ($hesk_settings['require_owner'] & & ! $ticket['owner'])
@ -1845,22 +2118,15 @@ function hesk_printReplyForm()
<?php if ( $modsForHesk_settings [ 'rich_text_for_tickets' ]) : ?>
< script type = "text/javascript" >
/* < ![CDATA[ */
tinyMCE.init({
mode: "textareas",
editor_selector: "htmlEditor",
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",
theme_advanced_buttons3: "",
theme_advanced_toolbar_location: "top",
theme_advanced_toolbar_align: "left",
theme_advanced_statusbar_location: "bottom",
theme_advanced_resizing: true
$(document).ready(function() {
$('.htmlEditor').summernote({
height: 200,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['para', ['ul', 'ol']]
]
});
});
/* ]]> */
< / script >
@ -1884,7 +2150,7 @@ function hesk_printReplyForm()
$onsubmit = 'onsubmit="force_stop();return validateRichText(\'message-help-block\', \'message-group\', \'message\', \''.htmlspecialchars($hesklang['this_field_is_required']).'\')"';
}
?>
< form role= "form" data-toggle = "validator" class = "form-horizontal" method = "post" action = "admin_reply_ticket.php"
< form id= "reply-form" role= "form" data-toggle = "validator" class = "form-horizontal" method = "post" action = "admin_reply_ticket.php"
enctype="multipart/form-data" name="form1" <?php echo $onsubmit ; ?> >
<?php
@ -1963,7 +2229,6 @@ function hesk_printReplyForm()
?>< / textarea >
< div class = "help-block with-errors" id = "message-help-block" > < / div > < / span >
< p id = "lang_ticket_message_contents_exist" style = "display: none" > <?php echo $hesklang [ 'ticket_message_contents_exist' ]; ?> </ p >
< / div >
< / div >
<?php
@ -1978,7 +2243,7 @@ function hesk_printReplyForm()
< / div >
< / div >
<?php
display_dropzone_field($hesk_settings['hesk_url'] . '/ internal-api/ticket/upload-attachment.php');
display_dropzone_field(HESK_PATH . ' internal-api/ticket/upload-attachment.php');
}
?>
< div class = "form-group" >
@ -2061,6 +2326,7 @@ function hesk_printReplyForm()
< / div >
< / div >
< / form >
< script > $ ( 'form#reply-form' ) . dirtyForms ( ) ; < / script >
< / div >
< / div >
<!-- END REPLY FORM -->
@ -2124,6 +2390,7 @@ function hesk_printCanned()
myMsg = myMsg.replace(/%%HESK_TRACKID%%/g, '<?php echo hesk_jsString ( $ticket [ 'trackid' ]); ?> ');
myMsg = myMsg.replace(/%%HESK_TRACK_ID%%/g, '<?php echo hesk_jsString ( $ticket [ 'trackid' ]); ?> ');
myMsg = myMsg.replace(/%%HESK_NAME%%/g, '<?php echo hesk_jsString ( $ticket [ 'name' ]); ?> ');
myMsg = myMsg.replace(/%%HESK_FIRST_NAME%%/g, '<?php echo hesk_jsString ( hesk_full_name_to_first_name ( $ticket [ 'name' ])); ?> ');
myMsg = myMsg.replace(/%%HESK_EMAIL%%/g, '<?php echo hesk_jsString ( $ticket [ 'email' ]); ?> ');
myMsg = myMsg.replace(/%%HESK_OWNER%%/g, '<?php echo hesk_jsString ( isset ( $admins [ $ticket [ 'owner' ]]) ? $admins [ $ticket [ 'owner' ]] : '' ); ?> ');
@ -2136,8 +2403,8 @@ function hesk_printCanned()
if (document.getElementById) {
if (document.getElementById('moderep').checked) {
if (isHtml) {
tinymce.get("message").setContent(' ');
tinymce.get("message").execCommand('mceInsertRawHTML', false, myMsg );
$("#message").summernote('reset ');
$("#message").summernote('editor.insertText', myMsg) );
} else {
myMsg = $('< textarea / > ').html(myMsg).text();
$('#message').val(myMsg).trigger('input');
@ -2145,9 +2412,9 @@ function hesk_printCanned()
}
else {
if (isHtml) {
var oldMsg = tinymce.get("message").getContent ();
tinymce.get("message").setContent(' ');
tinymce.get("message").execCommand('mceInsertRawHTML', false, oldMsg + myMsg );
var oldMsg = $("#message").val ();
$("#message").summernote('reset ');
$("#message").summernote('editor.insertText', oldMsg + myMsg) );
} else {
var oldMsg = $('#message').val();
var newMsg = $('< textarea / > ').html(oldMsg + '\n' + myMsg).text();