diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index e13128529cc4fa4ba26d8b3cc0f1d03c4d7bb489..721da44032dd29c96893016f5733564157732528 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -122,7 +122,10 @@ class TicketsAjaxAPI extends AjaxController { return $this->json_encode(array('id'=>0, 'retry'=>true)); } - return $this->json_encode(array('id'=>$lock->getId(), 'time'=>$lock->getTime())); + return $this->json_encode(array( + 'id'=>$lock->getId(), 'time'=>$lock->getTime(), + 'code' => $lock->getCode() + )); } function renewLock($tid, $id) { diff --git a/include/class.lock.php b/include/class.lock.php index e4870d4652801659d68e6c77bc6d231991f378ea..acbe1365e2c3f8fa2dbb64c4f4f39b227c418890 100644 --- a/include/class.lock.php +++ b/include/class.lock.php @@ -38,13 +38,6 @@ class Lock extends VerySimpleModel { ), ); - var $expiretime; - - function __onload() { - if (isset($this->expire)) - $this->expiretime = strtotime($this->expire); - } - function getId() { return $this->lock_id; } @@ -62,16 +55,16 @@ class Lock extends VerySimpleModel { } function getExpireTime() { - return $this->expire; + return strtotime($this->expire); } //Get remaiming time before the lock expires function getTime() { - return $this->isExpired()?0:($this->expiretime-time()); + return $this->isExpired()?0:($this->getExpireTime()-time()); } //Should we be doing realtime check here? (Ans: not really....expiretime is local & based on loadtime) function isExpired() { - return (time()>$this->expiretime); + return (time()>$this->getExpireTime()); } function getCode() { @@ -89,7 +82,7 @@ class Lock extends VerySimpleModel { SqlFunction::NOW(), SqlInterval::MINUTE($lockTime) ); - return $this->save(); + return $this->save(true); } //release aka delete a lock. diff --git a/include/staff/footer.inc.php b/include/staff/footer.inc.php index 5abc0997369e1e00e9e3d79bc98ae92b671438ca..778fbd045397566bdfe42d5d293c8f32ec1d1683 100644 --- a/include/staff/footer.inc.php +++ b/include/staff/footer.inc.php @@ -34,7 +34,7 @@ if(is_object($thisstaff) && $thisstaff->isStaff()) { ?> <hr style="margin-top:3em"/> <p class="full-width"> <span class="buttons pull-right"> - <input type="button" value="<?php echo __('OK');?>" class="close"> + <input type="button" value="<?php echo __('OK');?>" class="close ok"> </span> </p> <div class="clear"></div> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index 0560eaf00ce70eacee1048f45dd9903a13368843..572fc90c6ae09e77c624dbdaf973d10ffa3bc5a9 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -701,7 +701,7 @@ $tcount = $ticket->getThreadEntries($types)->count(); echo $ticket->getId(); ?>#note" name="note" method="post" enctype="multipart/form-data"> <?php csrf_token(); ?> <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>"> - <input type="hidden" name="locktime" value="<?php echo $cfg->getLockTime(); ?>"> + <input type="hidden" name="locktime" value="<?php echo $cfg->getLockTime() * 60; ?>"> <input type="hidden" name="a" value="postnote"> <input type="hidden" name="lockCode" value="<?php echo $ticket->getLock()->getCode(); ?>"> <table width="100%" border="0" cellspacing="0" cellpadding="3"> @@ -1065,7 +1065,7 @@ $(function() { clearInterval(setLock); autoLock.setLock({ id:<?php echo $lock->getId(); ?>, - time: <?php echo $cfg->getLockTime(); ?>}, 'acquire'); + time: <?php echo $cfg->getLockTime() * 60; ?>}, 'acquire'); }, 50); }(); <?php } ?> diff --git a/js/redactor-osticket.js b/js/redactor-osticket.js index 39ffaad3051debd0098e3c67400ebe5a8e405222..ac1ca3bef84c791b631143f1cf1e4d395bd16a6b 100644 --- a/js/redactor-osticket.js +++ b/js/redactor-osticket.js @@ -209,6 +209,16 @@ RedactorPlugins.signature = function() { } }; +RedactorPlugins.autolock = function() { + return { + init: function() { + var code = this.$box.closest('form').find('[name=lockCode]'); + if ($.autoLock && code.length) + this.opts.keydownCallback = $.autoLock.handleEvent; + } + }; +} + /* Redactor richtext init */ $(function() { var captureImageSizes = function(html) { @@ -245,7 +255,7 @@ $(function() { 'focus': false, 'plugins': el.hasClass('no-bar') ? ['imagepaste','imagemanager','definedlinks'] - : ['imagepaste','imagemanager','imageannotate','table','video','definedlinks'], + : ['imagepaste','imagemanager','imageannotate','table','video','definedlinks','autolock'], 'imageUpload': 'tbd', 'imageManagerJson': 'ajax.php/draft/images/browse', 'syncBeforeCallback': captureImageSizes, diff --git a/scp/js/scp.js b/scp/js/scp.js index edb2cf0c0ccf6750c3a9b58584ab3b0a1dbd1687..44a99523514927c5b32076477b1ce350b7ab94a3 100644 --- a/scp/js/scp.js +++ b/scp/js/scp.js @@ -617,6 +617,8 @@ $.sysAlert = function (title, msg, cb) { $('#title', $dialog).html(title); $('#body', $dialog).html(msg); $dialog.show(); + if (cb) + $dialog.find('input.ok.close').click(cb); } else { alert(msg); } diff --git a/scp/js/ticket.js b/scp/js/ticket.js index 37b828a172974f4b0bcb9265c9cd358bbd4361ad..7082679962d08b54af60a24b6b85645812613e55 100644 --- a/scp/js/ticket.js +++ b/scp/js/ticket.js @@ -17,12 +17,14 @@ var autoLock = { // Defaults lockId: 0, + lockCode: '', timerId: 0, lasteventTime: 0, + lastcheckTime: 0, lastattemptTime: 0, acquireTime: 0, renewTime: 0, - renewFreq: 0, //renewal frequency in seconds...based on returned lock time. + renewFreq: 10000, //renewal frequency in seconds...based on returned lock time. time: 0, lockAttempts: 0, //Consecutive lock attempt errors maxattempts: 2, //Maximum failed lock attempts before giving up. @@ -53,16 +55,6 @@ var autoLock = { //Incoming event... handleEvent: function(e) { - if(!autoLock.lockId) { - var now = new Date().getTime(); - //Retry every 5 seconds?? - if(autoLock.retry && (!autoLock.lastattemptTime || (now-autoLock.lastattemptTime)>5000)) { - autoLock.acquireLock(e,autoLock.warn); - autoLock.lastattemptTime=new Date().getTime(); - } - }else{ - autoLock.renewLock(e); - } if(!autoLock.lasteventTime) { //I hate nav away warnings..but $(document).on('pjax:beforeSend.changed', function(e) { @@ -72,8 +64,23 @@ var autoLock = { return __("Any changes or info you've entered will be discarded!"); }); } + // Handle events only every few seconds + var now = new Date().getTime(), + renewFreq = autoLock.renewFreq; + + if (autoLock.lasteventTime && now - autoLock.lasteventTime < renewFreq) + return; + + autoLock.lasteventTime = now; + + if (!autoLock.lockId) { + // Retry every 5 seconds?? + if (autoLock.retry) + autoLock.acquireLock(e,autoLock.warn); + } else { + autoLock.renewLock(e); + } - autoLock.lasteventTime=new Date().getTime(); }, //Watch activity on individual form. @@ -126,7 +133,6 @@ var autoLock = { void(autoLock.lockTime=parseInt($(':input[name=locktime]',fObj).val())); autoLock.watchDocument(); - autoLock.resetTimer(); autoLock.addEvent(window,'unload',autoLock.releaseLock,true); //Release lock regardless of any activity. }, @@ -168,9 +174,7 @@ var autoLock = { success: function(lock){ autoLock.setLock(lock,'acquire',warn); } - }) - .done(function() { }) - .fail(function() { }); + }); } return autoLock.lockId; @@ -179,22 +183,25 @@ var autoLock = { //Renewal only happens on form activity.. renewLock: function(e) { - if(!autoLock.lockId) { return false; } + if (!autoLock.lockId) + return false; - var now= new Date().getTime(); - if(!autoLock.lastcheckTime || (now-autoLock.lastcheckTime)>=(autoLock.renewFreq*1000)){ - $.ajax({ - type: 'POST', - url: 'ajax.php/tickets/'+autoLock.tid+'/lock/'+autoLock.lockId+'/renew', - dataType: 'json', - cache: false, - success: function(lock){ - autoLock.setLock(lock,'renew',autoLock.warn); - } - }) - .done(function() { }) - .fail(function() { }); - } + var now = new Date().getTime(), + renewFreq = autoLock.renewFreq; + + if (autoLock.lastcheckTime && now - autoLock.lastcheckTime < renewFreq) + return; + + autoLock.lastcheckTime = now; + $.ajax({ + type: 'POST', + url: 'ajax.php/tickets/'+autoLock.tid+'/lock/'+autoLock.lockId+'/renew', + dataType: 'json', + cache: false, + success: function(lock){ + autoLock.setLock(lock,'renew',autoLock.warn); + } + }); }, releaseLock: function(e) { @@ -209,22 +216,23 @@ var autoLock = { success: function() { autoLock.lockId = 0; } - }) - .done(function() { }) - .fail(function() { }); + }); }, setLock: function(lock, action, warn) { var warn = warn || false; - if(!lock) return false; + if (!lock) + return false; - if(lock.id) { - autoLock.renewFreq=lock.time?(lock.time/2):30; - autoLock.lastcheckTime=new Date().getTime(); - } autoLock.lockId=lock.id; //override the lockid. + if (lock.code) { + autoLock.lockCode = lock.code; + // Update the lock code for the upcoming POST + var el = $('input[name=lockCode]').val(lock.code); + } + switch(action){ case 'renew': if(!lock.id && lock.retry) { @@ -242,6 +250,10 @@ var autoLock = { } break; } + + if (lock.id && lock.time) { + autoLock.resetTimer((lock.time - 10) * 1000); + } }, discardWarning: function(e) { @@ -250,17 +262,25 @@ var autoLock = { //TODO: Monitor events and elapsed time and warn user when the lock is about to expire. monitorEvents: function() { - // warn user when lock is about to expire??; - //autoLock.resetTimer(); + $.sysAlert( + __('Your lock is expiring soon'), + __('The lock you hold on this ticket will expire soon. Would you like to renew the lock?'), + function() { + autoLock.renewLock(); + } + ); }, clearTimer: function() { clearTimeout(autoLock.timerId); }, - resetTimer: function() { + resetTimer: function(time) { clearTimeout(autoLock.timerId); - autoLock.timerId=setTimeout(function () { autoLock.monitorEvents() },30000); + autoLock.timerId = setTimeout( + function () { autoLock.monitorEvents(); }, + time || 30000 + ); } }; $.autoLock = autoLock; diff --git a/scp/tickets.php b/scp/tickets.php index 0a57e94c53c053b377504484ca5f80c98fa8a355..620f8cfc47facd0375e695076fd0f1e5dd653429 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -76,7 +76,10 @@ if($_POST && !$errors): elseif ($lock->getStaffId()!=$thisstaff->getId()) { $errors['err'] = __('Action Denied. Ticket is locked by someone else!'); } - elseif ($lock->getCode() != $_POST['lockCode']) { + // Attempt to renew the lock if possible + elseif (($lock->isExpired() && !$lock->renew()) + ||($lock->getCode() != $_POST['lockCode']) + ) { $errors['err'] = __('Your lock has expired. Please try again'); }