diff --git a/modules/system/assets/ui/js/input.monitor.js b/modules/system/assets/ui/js/input.monitor.js index e6bd1704e..a374b7999 100644 --- a/modules/system/assets/ui/js/input.monitor.js +++ b/modules/system/assets/ui/js/input.monitor.js @@ -27,6 +27,7 @@ * Triggered events: * - changed.oc.changeMonitor - triggered when the form data changes. * - unchanged.oc.changeMonitor - triggered when the form data unchanges. + * - ready.oc.changeMonitor - triggered when the change monitor instance finishes initialization. * * JavaScript API: * $('#form').changeMonitor() @@ -67,6 +68,7 @@ $(window).on('beforeunload', this.proxy(this.onBeforeUnload)) this.$el.one('dispose-control', this.proxy(this.dispose)) + this.$el.trigger('ready.oc.changeMonitor') } ChangeMonitor.prototype.dispose = function() { diff --git a/modules/system/assets/ui/js/tab.js b/modules/system/assets/ui/js/tab.js index d1a22c9cf..31642e698 100644 --- a/modules/system/assets/ui/js/tab.js +++ b/modules/system/assets/ui/js/tab.js @@ -211,7 +211,7 @@ if ($('> li > a', this.$tabsContainer).length == 0) this.$el.trigger('afterAllClosed.oc.tab') - this.$el.trigger('closed.oc.tab', [$tab]) + this.$el.trigger('closed.oc.tab', [$tab, $pane]) $(window).trigger('resize') this.updateClasses() @@ -263,6 +263,13 @@ return tab } + Tab.prototype.findPaneFromTab = function(tab) { + var id = $(tab).find('> a').data('target'), + pane = this.$pagesContainer.find(id) + + return pane + } + Tab.prototype.goTo = function(identifier) { var $tab = $('[data-tab-id="'+identifier+'" ]', this.$tabsContainer) diff --git a/modules/system/assets/ui/less/popup.base.less b/modules/system/assets/ui/less/popup.base.less index 2c6ead27b..86442bc0c 100644 --- a/modules/system/assets/ui/less/popup.base.less +++ b/modules/system/assets/ui/less/popup.base.less @@ -124,7 +124,7 @@ // Automatically set modal's width for larger viewports .modal-dialog { width: @modal-md; - margin: 30px auto; + margin: 80px auto 30px auto; // The top margin is increased to avoid overlapping with flash messages } .modal-content { .box-shadow(0 5px 15px rgba(0,0,0,.5)); diff --git a/modules/system/assets/ui/storm-min.js b/modules/system/assets/ui/storm-min.js index 6976f7cad..44e88a4e6 100644 --- a/modules/system/assets/ui/storm-min.js +++ b/modules/system/assets/ui/storm-min.js @@ -2713,7 +2713,8 @@ this.$el.on('keyup input paste','input, textarea:not(.ace_text-input)',this.prox $('input:not([type=hidden]), textarea:not(.ace_text-input)',this.$el).each(function(){$(this).data('oldval.oc.changeMonitor',$(this).val());}) if(this.options.windowCloseConfirm) $(window).on('beforeunload',this.proxy(this.onBeforeUnload)) -this.$el.one('dispose-control',this.proxy(this.dispose))} +this.$el.one('dispose-control',this.proxy(this.dispose)) +this.$el.trigger('ready.oc.changeMonitor')} ChangeMonitor.prototype.dispose=function(){if(this.$el===null) return this.unregisterHandlers() @@ -3244,7 +3245,7 @@ if(isActive) $('> li > a',this.$tabsContainer).eq(tabIndex-1).tab('show') if($('> li > a',this.$tabsContainer).length==0) this.$el.trigger('afterAllClosed.oc.tab') -this.$el.trigger('closed.oc.tab',[$tab]) +this.$el.trigger('closed.oc.tab',[$tab,$pane]) $(window).trigger('resize') this.updateClasses()} Tab.prototype.updateClasses=function(){if(this.$tabsContainer.children().length>0) @@ -3270,6 +3271,8 @@ tabParent=this.$tabsContainer return tabParent.children().index($(tabToFind))} Tab.prototype.findTabFromPane=function(pane){var id='#'+$(pane).attr('id'),tab=$('[data-target="'+id+'"]',this.$tabsContainer) return tab} +Tab.prototype.findPaneFromTab=function(tab){var id=$(tab).find('> a').data('target'),pane=this.$pagesContainer.find(id) +return pane} Tab.prototype.goTo=function(identifier){var $tab=$('[data-tab-id="'+identifier+'" ]',this.$tabsContainer) if($tab.length==0) return false diff --git a/modules/system/assets/ui/storm.css b/modules/system/assets/ui/storm.css index 298398d7a..3339a330c 100644 --- a/modules/system/assets/ui/storm.css +++ b/modules/system/assets/ui/storm.css @@ -2604,7 +2604,7 @@ div.inspector-dictionary-container table.inspector-dictionary-table tbody tr:las .modal-footer .btn + .btn{margin-left:5px;margin-bottom:0} .modal-footer .btn-group .btn + .btn{margin-left:-1px} .modal-footer .btn-block + .btn-block{margin-left:0} -@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto} +@media (min-width:768px){.modal-dialog{width:600px;margin:80px auto 30px auto} .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)} .modal-sm{width:300px} } diff --git a/modules/system/classes/VersionManager.php b/modules/system/classes/VersionManager.php index ea124598a..05576e27e 100644 --- a/modules/system/classes/VersionManager.php +++ b/modules/system/classes/VersionManager.php @@ -69,8 +69,10 @@ class VersionManager /** * Updates a single plugin by its code or object with it's latest changes. + * If the $stopOnVersion parameter is specified, the process stops after + * the specified version is applied. */ - public function updatePlugin($plugin) + public function updatePlugin($plugin, $stopOnVersion = null) { $code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin); @@ -90,11 +92,30 @@ class VersionManager $newUpdates = $this->getNewFileVersions($code, $databaseVersion); foreach ($newUpdates as $version => $details) { $this->applyPluginUpdate($code, $version, $details); + + if ($stopOnVersion === $version) { + return true; + } } return true; } + /** + * Returns a list of unapplied plugin versions. + */ + public function listNewVersions($plugin) + { + $code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin); + + if (!$this->hasVersionFile($code)) { + return []; + } + + $databaseVersion = $this->getDatabaseVersion($code); + return $this->getNewFileVersions($code, $databaseVersion); + } + /** * Applies a single version update to a plugin. */ @@ -134,8 +155,10 @@ class VersionManager /** * Removes and packs down a plugin from the system. Files are left intact. + * If the $stopOnVersion parameter is specified, the process stops after + * the specified version is rolled back. */ - public function removePlugin($plugin) + public function removePlugin($plugin, $stopOnVersion = null) { $code = (is_string($plugin)) ? $plugin : $this->pluginManager->getIdentifier($plugin); @@ -146,16 +169,31 @@ class VersionManager $pluginHistory = $this->getDatabaseHistory($code); $pluginHistory = array_reverse($pluginHistory); + $stopOnNextVersion = false; + $newPluginVersion = null; + foreach ($pluginHistory as $history) { + if ($stopOnNextVersion && $history->version !== $stopOnVersion) { + // Stop if the $stopOnVersion value was found and + // this is a new version. The history could contain + // multiple items for a single version (comments and scripts). + $newPluginVersion = $history->version; + break; + } + if ($history->type == self::HISTORY_TYPE_COMMENT) { $this->removeDatabaseComment($code, $history->version); } elseif ($history->type == self::HISTORY_TYPE_SCRIPT) { $this->removeDatabaseScript($code, $history->version, $history->detail); } + + if ($stopOnVersion === $history->version) { + $stopOnNextVersion = true; + } } - $this->setDatabaseVersion($code); + $this->setDatabaseVersion($code, $newPluginVersion); if (isset($this->fileVersions[$code])) { unset($this->fileVersions[$code]);