mirror of https://github.com/itflow-org/itflow
Show who else is viewing the same open ticket as you
This commit is contained in:
parent
5db7ab3d73
commit
fb4da53026
32
ajax.php
32
ajax.php
|
|
@ -154,3 +154,35 @@ if(isset($_POST['client_set_notes'])){
|
||||||
mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Client', log_action = 'Modify', log_description = '$session_name modified client notes', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_created_at = NOW(), log_client_id = $client_id, log_user_id = $session_user_id, company_id = $session_company_id");
|
mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Client', log_action = 'Modify', log_description = '$session_name modified client notes', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_created_at = NOW(), log_client_id = $client_id, log_user_id = $session_user_id, company_id = $session_company_id");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isset($_GET['ticket_add_view'])){
|
||||||
|
$ticket_id = intval($_GET['ticket_id']);
|
||||||
|
|
||||||
|
$a = mysqli_query($mysqli, "INSERT INTO ticket_views SET view_ticket_id = '$ticket_id', view_user_id = '$session_user_id', view_timestamp = NOW()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($_GET['ticket_query_views'])){
|
||||||
|
$ticket_id = intval($_GET['ticket_id']);
|
||||||
|
|
||||||
|
$query = mysqli_query($mysqli, "SELECT user_name FROM ticket_views LEFT JOIN users ON view_user_id = user_id WHERE view_ticket_id = '$ticket_id' AND view_user_id != '$session_user_id' AND view_timestamp > DATE_SUB(NOW(), INTERVAL 2 MINUTE)");
|
||||||
|
while($row = mysqli_fetch_array($query)){
|
||||||
|
$users[] = $row['user_name'];
|
||||||
|
}
|
||||||
|
if(!empty($users)){
|
||||||
|
$users = array_unique($users);
|
||||||
|
if(count($users) > 1){
|
||||||
|
// Multiple viewers
|
||||||
|
$response['message'] = implode(", ", $users) . " are viewing this ticket.";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Single viewer
|
||||||
|
$response['message'] = implode("", $users) . " is viewing this ticket.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// No viewers
|
||||||
|
$response['message'] = "";
|
||||||
|
}
|
||||||
|
echo json_encode($response);
|
||||||
|
|
||||||
|
}
|
||||||
3
cron.php
3
cron.php
|
|
@ -257,6 +257,9 @@ while($row = mysqli_fetch_array($sql_companies)){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean-up ticket views table used for collision detection
|
||||||
|
mysqli_query($mysqli, "TRUNCATE TABLE ticket_views");
|
||||||
|
|
||||||
// PAST DUE INVOICE Notifications
|
// PAST DUE INVOICE Notifications
|
||||||
//$invoiceAlertArray = [$config_invoice_overdue_reminders];
|
//$invoiceAlertArray = [$config_invoice_overdue_reminders];
|
||||||
$invoiceAlertArray = [30,60,90,120,150,180,210,240,270,300,330,360,390,420,450,480,510,540,570,590,620];
|
$invoiceAlertArray = [30,60,90,120,150,180,210,240,270,300,330,360,390,420,450,480,510,540,570,590,620];
|
||||||
|
|
|
||||||
16
db.sql
16
db.sql
|
|
@ -1274,6 +1274,22 @@ CREATE TABLE `ticket_replies` (
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `ticket_views`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `ticket_views`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `ticket_views` (
|
||||||
|
`view_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`view_ticket_id` int(11) NOT NULL,
|
||||||
|
`view_user_id` int(11) NOT NULL,
|
||||||
|
`view_timestamp` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (`view_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `tickets`
|
-- Table structure for table `tickets`
|
||||||
--
|
--
|
||||||
|
|
|
||||||
136
ticket.php
136
ticket.php
|
|
@ -216,7 +216,7 @@ if(isset($_GET['ticket_id'])){
|
||||||
<!-- Only show ticket reply modal if status is not closed -->
|
<!-- Only show ticket reply modal if status is not closed -->
|
||||||
<?php if($ticket_status != "Closed"){ ?>
|
<?php if($ticket_status != "Closed"){ ?>
|
||||||
<form class="mb-3" action="post.php" method="post" autocomplete="off">
|
<form class="mb-3" action="post.php" method="post" autocomplete="off">
|
||||||
<input type="hidden" name="ticket_id" value="<?php echo $ticket_id; ?>">
|
<input type="hidden" name="ticket_id" id="ticket_id" value="<?php echo $ticket_id; ?>">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<textarea class="form-control summernote" name="ticket_reply" required></textarea>
|
<textarea class="form-control summernote" name="ticket_reply" required></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -262,6 +262,8 @@ if(isset($_GET['ticket_id'])){
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p class="font-weight-light" id="ticket_collision_viewing"></p>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<!-- End IF for reply modal -->
|
<!-- End IF for reply modal -->
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
@ -605,59 +607,95 @@ if(isset($_GET['ticket_id'])){
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if($ticket_status !== "Closed"){
|
if($ticket_status !== "Closed"){ ?>
|
||||||
?>
|
<!-- Ticket Time Tracking JS -->
|
||||||
<!-- Ticket Time Tracking JS -->
|
<script type="text/javascript">
|
||||||
<script type="text/javascript">
|
// Default values
|
||||||
// Default values
|
var hours = 0;
|
||||||
var hours = 0;
|
var minutes = 0;
|
||||||
var minutes = 0;
|
var seconds = 0;
|
||||||
var seconds = 0;
|
setInterval(countTime, 1000);
|
||||||
setInterval(countTime, 1000);
|
|
||||||
|
|
||||||
// Counter
|
// Counter
|
||||||
function countTime()
|
function countTime()
|
||||||
{
|
{
|
||||||
++seconds;
|
++seconds;
|
||||||
if(seconds == 60) {
|
if(seconds == 60) {
|
||||||
seconds = 0;
|
seconds = 0;
|
||||||
minutes++;
|
minutes++;
|
||||||
}
|
}
|
||||||
if(minutes == 60) {
|
if(minutes == 60) {
|
||||||
minutes = 0;
|
minutes = 0;
|
||||||
hours++;
|
hours++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total timeworked
|
// Total timeworked
|
||||||
var time_worked = pad(hours) + ":" + pad(minutes) + ":" + pad(seconds);
|
var time_worked = pad(hours) + ":" + pad(minutes) + ":" + pad(seconds);
|
||||||
document.getElementById("time_worked").value = time_worked;
|
document.getElementById("time_worked").value = time_worked;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows manually adjusting the timer
|
// Allows manually adjusting the timer
|
||||||
function setTime()
|
function setTime()
|
||||||
{
|
{
|
||||||
var time_as_text = document.getElementById("time_worked").value;
|
var time_as_text = document.getElementById("time_worked").value;
|
||||||
const time_text_array = time_as_text.split(":");
|
const time_text_array = time_as_text.split(":");
|
||||||
hours = parseInt(time_text_array[0]);
|
hours = parseInt(time_text_array[0]);
|
||||||
minutes = parseInt(time_text_array[1]);
|
minutes = parseInt(time_text_array[1]);
|
||||||
seconds = parseInt(time_text_array[2]);
|
seconds = parseInt(time_text_array[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function "pads" out the values, adding zeros if they are required
|
// This function "pads" out the values, adding zeros if they are required
|
||||||
function pad(val)
|
function pad(val)
|
||||||
{
|
{
|
||||||
var valString = val + "";
|
var valString = val + "";
|
||||||
if(valString.length < 2)
|
if(valString.length < 2)
|
||||||
{
|
{
|
||||||
return "0" + valString;
|
return "0" + valString;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return valString;
|
return valString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<?php include("footer.php");
|
<?php include("footer.php");
|
||||||
|
|
||||||
|
// jQuery is called in footer, so this must be below it
|
||||||
|
if($ticket_status !== "Closed"){ ?>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
// Collision detection
|
||||||
|
// Adds a "view" record of the current ticket every 3 mins into the database
|
||||||
|
// Updates the currently viewing <p> element with anyone that's looked at this ticket recently
|
||||||
|
function ticket_collision_detection() {
|
||||||
|
|
||||||
|
// Get the page ticket id
|
||||||
|
var ticket_id = document.getElementById("ticket_id").value;
|
||||||
|
|
||||||
|
//Send a GET request to ajax.php as ajax.php?ticket_add_view=true&ticket_id=NUMBER
|
||||||
|
jQuery.get(
|
||||||
|
"ajax.php",
|
||||||
|
{ticket_add_view: 'true', ticket_id: ticket_id},
|
||||||
|
function(data){
|
||||||
|
// We don't care about a response
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
//Send a GET request to ajax.php as ajax.php?ticket_query_views=true&ticket_id=NUMBER
|
||||||
|
jQuery.get(
|
||||||
|
"ajax.php",
|
||||||
|
{ticket_query_views: 'true', ticket_id: ticket_id},
|
||||||
|
function(data){
|
||||||
|
//If we get a response from ajax.php, parse it as JSON
|
||||||
|
const ticket_view_data = JSON.parse(data);
|
||||||
|
document.getElementById("ticket_collision_viewing").innerText = ticket_view_data.message;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ticket_collision_detection();
|
||||||
|
setInterval(ticket_collision_detection, 120*1000);
|
||||||
|
</script>
|
||||||
|
<?php } ?>
|
||||||
Loading…
Reference in New Issue