diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index d29ce39bd..1086821e5 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1035,6 +1035,32 @@ HTML */ public function DisplayDetails(WebPage $oPage, $bEditMode = false, $sMode = self::ENUM_OBJECT_MODE_VIEW) { + // N°3786: As this can now be call recursively from the self::ReloadAndDisplay(), we need to make sure we don't fall into an infinite loop + static $bBlockReentrance = false; + + $sClass = get_class($this); + $iKey = $this->GetKey(); + + if ($sMode === static::ENUM_OBJECT_MODE_VIEW) + { + // The concurrent access lock makes sense only for already existing objects + $LockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled'); + if ($LockEnabled) + { + $aLockInfo = iTopOwnershipLock::IsLocked($sClass, $iKey); + if ($aLockInfo['locked'] === true && $aLockInfo['owner']->GetKey() == UserRights::GetUserId() && $bBlockReentrance === false) + { + // If the object is locked by the current user, it's worth trying again, since + // the lock may be released by 'onunload' which is called AFTER loading the current page. + //$bTryAgain = $oOwner->GetKey() == UserRights::GetUserId(); + $bBlockReentrance = true; + self::ReloadAndDisplay($oPage, $this, array('operation' => 'details')); + + return; + } + } + } + // Object's details $oObjectDetails = ObjectFactory::MakeDetails($this); diff --git a/js/layouts/activity-panel/activity-panel.js b/js/layouts/activity-panel/activity-panel.js index 03d7c494e..72b27dec2 100644 --- a/js/layouts/activity-panel/activity-panel.js +++ b/js/layouts/activity-panel/activity-panel.js @@ -234,12 +234,18 @@ $(function() }); // Page exit - // - Show confirm dialog if draft entries (IMPORTANT: Lock is NOT released, see N°3786) - window.onbeforeunload = function (oEvent) { - if (true === me._HasDraftEntries()) { - return true; - } - }; + // - Show confirm dialog if draft entries + if (window.onbeforeunload === null) { + window.onbeforeunload = function (oEvent) { + if (true === me._HasDraftEntries()) { + return true; + } + }; + } + // - Processing / cleanup when the leaving page + $(window).on('unload', function() { + return me._onUnload(); + }); // Mostly for outside clicks that should close elements oBodyElem.on('click', function (oEvent) { @@ -404,8 +410,14 @@ $(function() _onDraftEntryForm: function (sCaseLogAttCode) { // Put draft indicator this.element.find(this.js_selectors.tab_toggler+'[data-tab-type="'+this.enums.tab_types.caselog+'"][data-caselog-attribute-code="'+sCaseLogAttCode+'"]').addClass(this.css_classes.is_draft); - // Request lock - this._RequestLock(); + + if (this.options.lock_enabled === true) { + // Request lock + this._RequestLock(); + } else { + // Only enable buttons + this.element.find(this.js_selectors.caselog_entry_form + '[data-attribute-code="' + sCaseLogAttCode + '"]').trigger('enable_submission.caselog_entry_form.itop'); + } }, /** * Remove indication of a draft entry and will cancel the lock (acquired or pending) if no draft entry left @@ -416,9 +428,15 @@ $(function() _onEmptyEntryForm: function (sCaseLogAttCode) { // Remove draft indicator this.element.find(this.js_selectors.tab_toggler+'[data-tab-type="'+this.enums.tab_types.caselog+'"][data-caselog-attribute-code="'+sCaseLogAttCode+'"]').removeClass(this.css_classes.is_draft); - // Cancel lock if all forms empty - if (false === this._HasDraftEntries()) { - this._CancelLock(); + + if (this.options.lock_enabled === true) { + // Cancel lock if all forms empty + if (false === this._HasDraftEntries()) { + this._CancelLock(); + } + } else { + // Only disable buttons + this.element.find(this.js_selectors.caselog_entry_form + '[data-attribute-code="' + sCaseLogAttCode + '"]').trigger('disable_submission.caselog_entry_form.itop'); } }, _onCancelledEntryForm: function () { @@ -432,7 +450,7 @@ $(function() */ _onRequestSubmission: function (oEvent, oData) { // Check lock state - if (this.enums.lock_status.locked_by_myself !== this.options.lock_status) { + if ((this.options.lock_enabled === true) && (this.enums.lock_status.locked_by_myself !== this.options.lock_status)) { CombodoJSConsole.Debug('ActivityPanel: Could not submit entries, current user does not have the lock on the object'); return; } @@ -483,6 +501,13 @@ $(function() this._HideAllFiltersOptions(); } }, + /** + * Called when the user leave the page, will remove the current lock if any draft entries + * @private + */ + _onUnload: function() { + return OnUnload(this.options.transaction_id, this.element.attr('data-object-class'), this.element.attr('data-object-id'), this.options.lock_token); + }, // Methods // - Helpers on host object