Merge pull request #247 from mkoch227/location-support

Location support. Closes #204
merge-requests/2/head
Mike Koch 9 years ago
commit 836aa910e4

@ -902,6 +902,26 @@ if ( defined('HESK_DEMO') )
?>
</div>
</div>
<div class="form-group">
<label for="request_location" class="col-sm-6 control-label">
<span class="label label-primary"
data-toggle="tooltip"
title="<?php echo $hesklang['added_in_mods_for_hesk']; ?>"><?php echo $hesklang['mods_for_hesk_acronym']; ?></span>
<?php echo $hesklang['request_user_location']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
title="<?php echo $hesklang['request_user_location']; ?>"
data-content="<?php echo $hesklang['request_user_location_help']; ?>"></i>
</label>
<div class="col-sm-6 form-inline">
<?php
$on = $modsForHesk_settings['request_location'] ? 'checked' : '';
$off = $modsForHesk_settings['request_location'] ? '' : 'checked';
echo '
<div class="radio"><label><input type="radio" name="request_location" value="0" '.$off.' /> '.$hesklang['off'].'</label></div>&nbsp;&nbsp;&nbsp;
<div class="radio"><label><input type="radio" name="request_location" value="1" '.$on.' /> '.$hesklang['on'].'</label></div>';
?>
</div>
</div>
<div class="form-group">
<label class="col-sm-6 control-label"><?php echo $hesklang['select']; ?> <a href="Javascript:void(0)" onclick="Javascript:hesk_window('<?php echo $help_folder; ?>helpdesk.html#65','400','500')"><i class="fa fa-question-circle settingsquestionmark"></i></a></label>
<div class="col-sm-6">

@ -506,6 +506,7 @@ $set['use_bootstrap_theme'] = empty($_POST['use_bootstrap_theme']) ? 0 : 1;
$set['new_kb_article_visibility'] = hesk_checkMinMax( intval( hesk_POST('new_kb_article_visibility') ) , 0, 2, 2);
$set['mfh_attachments'] = empty($_POST['email_attachments']) ? 0 : 1;
$set['show_number_merged'] = empty($_POST['show_number_merged']) ? 0 : 1;
$set['request_location'] = empty($_POST['request_location']) ? 0 : 1;
if ($set['customer-email-verification-required'])
{
@ -568,7 +569,10 @@ $modsForHesk_settings[\'new_kb_article_visibility\'] = '.$set['new_kb_article_vi
$modsForHesk_settings[\'attachments\'] = '.$set['mfh_attachments'].';
//-- Setting for showing number of merged tickets in the ticket search screen. 0 = Disable, 1 = Enable
$modsForHesk_settings[\'show_number_merged\'] = '.$set['show_number_merged'].';';
$modsForHesk_settings[\'show_number_merged\'] = '.$set['show_number_merged'].';
//-- Setting for requesting user\'s location. 0 = Disable, 1 = Enable
$modsForHesk_settings[\'request_location\'] = '.$set['request_location'].';';
// Write the file
if ( ! file_put_contents(HESK_PATH . 'modsForHesk_settings.inc.php', $modsForHesk_file_content) )

@ -588,6 +588,15 @@ if (isset($_GET['delatt']) && hesk_token_check())
hesk_process_messages($hesklang['kb_att_rem'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS');
}
//-- Update location action
if (isset($_POST['latitude']) && isset($_POST['longitude'])) {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `latitude` = '".hesk_dbEscape($_POST['latitude'])."',
`longitude` = '".hesk_dbEscape($_POST['longitude'])."' WHERE `ID` = ".intval($ticket['id']));
//redirect
hesk_process_messages($hesklang['ticket_location_updated'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS');
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
@ -861,6 +870,89 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
{
echo '<span class="fa fa-lock"></span>&nbsp;';
}
if ($modsForHesk_settings['request_location'])
{
$locationText = '';
$iconColor = '';
$hasLocation = true;
if (strpos($ticket['latitude'], 'E') === false)
{
$locationText = $hesklang['click_for_map'];
$iconColor = 'inherit';
}
else
{
$hasLocation = false;
$locationText = $hesklang['location_unavailable'];
$iconColor = '#ccc';
}
?>
<span data-toggle="modal" data-target=".map-modal" style="cursor: pointer">
<i class="fa fa-map-marker" data-toggle="tooltip" title="<?php echo $locationText; ?>"
style="color: <?php echo $iconColor; ?>"></i>
</span>
<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="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>
<button id="close-button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal']; ?></button>
</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):
?>
<script>
var latitude = '';
latitude = <?php echo $ticket['latitude']; ?>;
var longitude = '';
longitude = <?php echo $ticket['longitude']; ?>;
initializeMapForStaff(latitude, longitude, "<?php echo $hesklang['users_location']; ?>");
</script>
<?php
endif;
}
echo $ticket['subject'];
?></h3>
</div>

@ -60,6 +60,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php');
<link href="<?php echo HESK_PATH; ?>css/bootstrap-iconpicker.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/octicons.css" type="text/css">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="<?php echo HESK_PATH; ?>js/jquery-1.10.2.min.js"></script>
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>hesk_javascript.js"></script>
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap.min.js"></script>
@ -68,6 +69,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php');
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-fontawesome-4.3.0.js"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-octicon-2.1.2.js"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-iconpicker.js"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<?php

@ -60,6 +60,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php');
<link href="<?php echo HESK_PATH; ?>css/bootstrap-iconpicker.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="<?php echo HESK_PATH; ?>css/octicons.css" type="text/css">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="<?php echo HESK_PATH; ?>js/jquery-1.10.2.min.js"></script>
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>hesk_javascript.js"></script>
<script language="Javascript" type="text/javascript" src="<?php echo HESK_PATH; ?>js/modsForHesk-javascript.js"></script>
@ -68,6 +69,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php');
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-fontawesome-4.3.0.js"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/iconset-octicon-2.1.2.js"></script>
<script type="text/javascript" src="<?php echo HESK_PATH; ?>js/bootstrap-iconpicker.js"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<?php
/* Prepare Javascript that browser should load on page load */

@ -95,7 +95,9 @@ function hesk_newTicket($ticket, $isVerified = true)
`custom18`,
`custom19`,
`custom20`,
`status`
`status`,
`latitude`,
`longitude`
)
VALUES
(
@ -136,7 +138,9 @@ function hesk_newTicket($ticket, $isVerified = true)
'".hesk_dbEscape($ticket['custom18'])."',
'".hesk_dbEscape($ticket['custom19'])."',
'".hesk_dbEscape($ticket['custom20'])."',
'".intval($ticket['status'])."'
'".intval($ticket['status'])."',
'".hesk_dbEscape($ticket['latitude'])."',
'".hesk_dbEscape($ticket['longitude'])."'
)
");

@ -961,10 +961,23 @@ if ( ! isset($_SESSION['c_category']) && ! $hesk_settings['select_cat'])
<?php
}
if ($modsForHesk_settings['request_location']):
?>
<div class="form-group">
<label for="location" class="col-md-3 control-label"><?php echo $hesklang['location_colon']; ?></label>
<div class="col-sm-9">
<p id="console"><?php echo $hesklang['requesting_location_ellipsis']; ?></p>
<div id="map" style="height: 300px">
</div>
</div>
</div>
<!-- Submit -->
<?php
endif;
if ($hesk_settings['submit_notice'])
{
?>
@ -1002,6 +1015,8 @@ if ( ! isset($_SESSION['c_category']) && ! $hesk_settings['select_cat'])
?>
<div class="row">
<div class="col-md-9 col-md-offset-3">
<input type="hidden" id="latitude" name="latitude" value="E-0">
<input type="hidden" id="longitude" name="longitude" value="E-0">
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>">
<input class="btn btn-default" type="submit" value="<?php echo $hesklang['sub_ticket']; ?>">
</div>
@ -1025,6 +1040,16 @@ if ( ! isset($_SESSION['c_category']) && ! $hesk_settings['select_cat'])
<?php
// Request for the users location if enabled
if ($modsForHesk_settings['request_location'])
{
echo '
<script>
requestUserLocation("'.$hesklang['your_current_location'].'", "'.$hesklang['unable_to_determine_location'].'");
</script>
';
}
hesk_cleanSessionVars('iserror');
hesk_cleanSessionVars('isnotice');

@ -31,6 +31,8 @@ if ($task == 'status-change') {
removeTicketsPendingVerificationTable();
} elseif ($task == 'service-message-icon') {
removeServiceMessageCustomIcon();
} elseif ($task == 'location') {
removeTicketLocation();
} elseif ($task == 'miscellaneous') {
executeMiscellaneousSql();
} else {

@ -1,7 +1,8 @@
function getTasks() {
return ['status-change', 'autorefresh', 'parent-child', 'settings-access', 'activate-user',
'notify-note-unassigned', 'user-manage-notification-settings', 'settings-table', 'verified-emails-table',
'pending-verification-emails-table', 'pending-verification-tickets-table', 'service-message-icon', 'miscellaneous'];
'pending-verification-emails-table', 'pending-verification-tickets-table', 'service-message-icon', 'location',
'miscellaneous'];
}
function processUninstallation() {

@ -448,6 +448,10 @@ function execute230Scripts() {
executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `Key` = `ShortNameContentKey`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` DROP COLUMN `ShortNameContentKey`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` DROP COLUMN `TicketViewContentKey`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `latitude` VARCHAR(100) NOT NULL DEFAULT 'E-0'");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `longitude` VARCHAR(100) NOT NULL DEFAULT 'E-0'");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."stage_tickets` ADD COLUMN `latitude` VARCHAR(100) NOT NULL DEFAULT 'E-0'");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."stage_tickets` ADD COLUMN `longitude` VARCHAR(100) NOT NULL DEFAULT 'E-0'");
executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` SET `Value` = '2.3.0' WHERE `Key` = 'modsForHeskVersion'");
}
@ -463,6 +467,13 @@ function execute230FileUpdate() {
//-- Setting for showing number of merged tickets in the ticket search screen. 0 = Disable, 1 = Enable
$modsForHesk_settings[\'show_number_merged\'] = 1;';
}
if (strpos($file, '$modsForHesk_settings[\'request_location\']') === false)
{
$file .= '
//-- Setting for requesting user\'s location. 0 = Disable, 1 = Enable
$modsForHesk_settings[\'request_location\'] = 0';
}
return file_put_contents(HESK_PATH.'modsForHesk_settings.inc.php', $file);
}

@ -136,6 +136,16 @@ function removeServiceMessageCustomIcon() {
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."service_messages` DROP COLUMN `icon`");
}
function removeTicketLocation() {
global $hesk_settings;
hesk_dbConnect();
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` DROP COLUMN `latitude`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` DROP COLUMN `longitude`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."stage_tickets` DROP COLUMN `latitude`");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."stage_tickets` DROP COLUMN `longitude`");
}
function executeMiscellaneousSql() {
global $hesk_settings;

@ -17,6 +17,7 @@ function echoTaskRows() {
printUninstallRow('Remove pending verification emails table', 'pending-verification-emails-table');
printUninstallRow('Remove tickets pending verification table', 'pending-verification-tickets-table');
printUninstallRow('Remove custom service messages icon', 'service-message-icon');
printUninstallRow('Remove ticket location', 'location');
printUninstallRow('Miscellaneous database cleanup changes', 'miscellaneous');
}

@ -106,4 +106,102 @@ function changeText(id, checkedValue, uncheckedValue, object) {
}
}
function requestUserLocation(yourLocationText, unableToDetermineText) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
setLatLon(latitude, longitude);
$('#console').hide();
initializeMapForCustomer(latitude, longitude, yourLocationText);
}, function(error) {
$('#map').hide();
$('#console').text(unableToDetermineText).show();
switch(error.code) {
case error.PERMISSION_DENIED:
setLatLon('E-1','E-1');
break;
case error.POSITION_UNAVAILABLE:
setLatLon('E-2','E-2');
break;
case error.TIMEOUT:
setLatLon('E-3','E-3');
break;
case error.UNKNOWN_ERROR:
setLatLon('E-4','E-4');
break;
}
});
} else {
$('#map').hide();
$('#console').text(unableToDetermineText).show();
setLatLon('E-5','E-5');
}
}
function setLatLon(lat, lon) {
$('#latitude').val(lat);
$('#longitude').val(lon);
}
var marker;
var map;
function resetLatLon(lat, lon) {
map.setView([lat, lon], 15);
marker.setLatLng(L.latLng(lat, lon));
}
function closeAndReset(lat, lon) {
$('#save-group').hide();
$('#close-button').show();
$('#friendly-location').show();
$('#save-for-address').hide();
resetLatLon(lat, lon);
}
function initializeMapForCustomer(latitude, longitude, yourLocationText) {
map = L.map('map').setView([latitude, longitude], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
marker = L.marker([latitude, longitude], {draggable: true})
.addTo(map)
.bindPopup(yourLocationText);
marker.on('dragend', function(event) {
setLatLon(event.target.getLatLng().lat, event.target.getLatLng().lng);
});
}
function initializeMapForStaff(latitude, longitude, usersLocationText) {
map = L.map('map').setView([latitude, longitude], 15);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
marker = L.marker([latitude, longitude], {draggable: true})
.addTo(map)
.bindPopup(usersLocationText);
marker.on('dragend', function(event) {
setLatLon(event.target.getLatLng().lat, event.target.getLatLng().lng);
$('#save-group').show();
$('#close-button').hide();
$('#friendly-location').hide();
$('#save-for-address').show();
});
$('#map-modal').on('shown.bs.modal', function(){
setTimeout(function() {
map.invalidateSize();
}, 10);
});
}
function getFriendlyLocation(latitude, longitude) {
var URL = 'http://nominatim.openstreetmap.org/reverse?format=json&lat='+ latitude +'&lon='+ longitude +'&zoom=15&addressdetails=1';
$.getJSON(URL, function(data) {
$('#friendly-location').text(data.display_name);
});
}
jQuery(document).ready(loadJquery);

@ -44,6 +44,28 @@ $hesklang['show_number_merged_help'] = 'If enabled, the user will be able to see
$hesklang['latest_top_on_home'] = 'Latest/Top articles on home page';
$hesklang['latest_top_on_home_help'] = 'Select YES to display the top and latest knowledgebase articles on the home page.
Otherwise, a link to the knowledgebase will appear on the home page.';
$hesklang['location_unavailable'] = "Location unavailable. Click for more information.";
$hesklang['click_for_map'] = "View map of user's location";
$hesklang['request_user_location'] = "Request Location";
$hesklang['request_user_location_help'] = "If enabled, the help desk will ask for the customer's location, allowing staff to
see a map of the customer's location when they created the ticket.";
$hesklang['users_location'] = "User's Location";
$hesklang['location_unavailable_0'] = "User's location is not available because the ticket was created before location tracking was enabled.";
$hesklang['location_unavailable_1'] = "User's location is not available because the user refused to share it.";
$hesklang['location_unavailable_2'] = "User's location is not available because the help desk was unable to determine the user's position.";
$hesklang['location_unavailable_3'] = "User's location is not available because the help desk was not able to determine the user's position in
a reasonable amount of time.";
$hesklang['location_unavailable_4'] = "An unknown error occurred when trying to obtain the user's location.";
$hesklang['location_unavailable_5'] = "User's location is not available because the user's browser did not meet the minimum
requirements for tracking their location when the ticket was submitted.";
$hesklang['save_location'] = 'Save Location';
$hesklang['close_modal_without_saving'] = 'Close without saving';
$hesklang['ticket_location_updated'] = 'Ticket location has been updated!';
$hesklang['location_colon'] = 'Location:';
$hesklang['your_current_location'] = 'Your location';
$hesklang['requesting_location_ellipsis'] = 'Requesting location...';
$hesklang['unable_to_determine_location'] = 'Unable to determine your location, or you declined to share it.';
$hesklang['save_to_see_updated_address'] = 'Save the new location to see the updated address';
// ADDED OR MODIFIED IN Mods for HESK 2.2.1
$hesklang['popart_no_colon']='Top Knowledgebase Articles'; // same as $hesklang['popart'] but without a colon (:)

@ -43,4 +43,7 @@ $modsForHesk_settings['new_kb_article_visibility'] = 0;
$modsForHesk_settings['attachments'] = 0;
//-- Setting for showing number of merged tickets in the ticket search screen. 0 = Disable, 1 = Enable
$modsForHesk_settings['show_number_merged'] = 1;
$modsForHesk_settings['show_number_merged'] = 1;
//-- Setting for requesting user's location. 0 = Disable, 1 = Enable
$modsForHesk_settings['request_location'] = 0;

@ -427,6 +427,10 @@ if ($hesk_settings['attachments']['use'] && ! empty($attachments) )
}
}
// Set latitude and longitude
$tmpvar['latitude'] = hesk_POST('latitude');
$tmpvar['longitude'] = hesk_POST('longitude');
// Should the helpdesk validate emails?
$createTicket = true;
if ($modsForHesk_settings['customer_email_verification_required'])

Loading…
Cancel
Save