From fa014edca0399ed15d6103a0b266ae1a3916ba72 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Tue, 10 Feb 2015 23:03:35 +0000 Subject: [PATCH 01/23] Special handling when printing for splitter --- etemplate/js/et2_widget_split.js | 26 ++++++++++++++++++++-- etemplate/templates/default/etemplate2.css | 13 +++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/etemplate/js/et2_widget_split.js b/etemplate/js/et2_widget_split.js index c99c107138..3dc542b324 100644 --- a/etemplate/js/et2_widget_split.js +++ b/etemplate/js/et2_widget_split.js @@ -28,7 +28,7 @@ * @see http://methvin.com/splitter/ Uses Splitter * @augments et2_DOMWidget */ -var et2_split = et2_DOMWidget.extend([et2_IResizeable], +var et2_split = et2_DOMWidget.extend([et2_IResizeable,et2_IPrint], { attributes: { "orientation": { @@ -85,6 +85,9 @@ var et2_split = et2_DOMWidget.extend([et2_IResizeable], // Deferred object so we can wait for children this.loading = jQuery.Deferred(); + + // Flag to temporarily ignore resizing + this.stop_resize = false; }, destroy: function() { @@ -274,7 +277,7 @@ var et2_split = et2_DOMWidget.extend([et2_IResizeable], { this._init_splitter(); } - if(this.dynheight) + if(this.dynheight && !this.stop_resize ) { var old = {w: this.div.width(), h: this.div.height()}; this.dynheight.update(function(w,h) { @@ -376,6 +379,25 @@ var et2_split = et2_DOMWidget.extend([et2_IResizeable], */ toggleDock: function() { this.div.trigger("toggleDock"); + }, + + // Printing + /** + * Prepare for printing by stopping all the fuss + * + */ + beforePrint: function() { + // Resizing causes preference changes & relayouts. Don't do it. + this.stop_resize = true; + + // Add the class, if needed + this.div.addClass('print'); + + // Don't return anything, just work normally + }, + afterPrint: function() { + this.div.removeClass('print'); + this.stop_resize = false; } }); diff --git a/etemplate/templates/default/etemplate2.css b/etemplate/templates/default/etemplate2.css index fbfca886f5..33096e51cb 100644 --- a/etemplate/templates/default/etemplate2.css +++ b/etemplate/templates/default/etemplate2.css @@ -131,6 +131,15 @@ div.et2_hbox > div { * > .et2_split { overflow: hidden; } +/* These need to be applied to tame the sizing before printing */ +.et2_split.print, .et2_split.print > .splitter-pane { + height: auto !important; + width: auto !important; +} +.et2_split.print > * { + position: relative !important; +} + /** * Label widget, and labels for other widgets */ @@ -1160,6 +1169,10 @@ div.message.floating { display: none; border:none; } + .et2_split, .et2_split > .splitter-pane { + height: auto !important; + width: auto !important; + } } /** * Grid / nextmatch Hierarchy From dfb81fc050a80728add6ef97d27891a6869e9e9a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 11 Feb 2015 08:33:03 +0000 Subject: [PATCH 02/23] position list-/tile-view icon absolute from right, so it does not depened on existence of file upload (only there for writable shares) --- filemanager/templates/default/sharing.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/filemanager/templates/default/sharing.css b/filemanager/templates/default/sharing.css index 1af1afcb3e..364950211a 100644 --- a/filemanager/templates/default/sharing.css +++ b/filemanager/templates/default/sharing.css @@ -24,9 +24,9 @@ div.header_row_right, span.header_count, select#filemanager-index_filter, span.s } div#filemanager-index_buttons img#filemanager-index_button\[change_view\] { display: inline-block !important; - position: relative; - left: -230px; - top: 3px; + position: absolute; + right: 418px; + top: 10px; } div.filemanager_navigation label { From a9522e71cd4c5311462f4d9f8305b900bf622293 Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Wed, 11 Feb 2015 09:40:01 +0000 Subject: [PATCH 03/23] Fix user can not delete its own categories from nextmatch context menu --- admin/inc/class.admin_categories.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/inc/class.admin_categories.inc.php b/admin/inc/class.admin_categories.inc.php index 3f3af1c684..a5db725894 100644 --- a/admin/inc/class.admin_categories.inc.php +++ b/admin/inc/class.admin_categories.inc.php @@ -365,7 +365,7 @@ class admin_categories $row['subs'] = count($row['children']); $row['class'] = 'level'.$row['level']; - if($row['owner'] > 0 && !$GLOBALS['egw_info']['user']['apps']['admin'] && $row['owner'] != $GLOBALS['egw_info']['user']['account_id']) + if($row['owner'][0] > 0 && !$GLOBALS['egw_info']['user']['apps']['admin'] && $row['owner'][0] != $GLOBALS['egw_info']['user']['account_id']) { $row['class'] .= ' rowNoEdit rowNoDelete '; } From d0afb453a08cd45ef41a9bbb3f545f8134149f7a Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 11 Feb 2015 09:43:29 +0000 Subject: [PATCH 04/23] * ImportExport: links supposed to open in admin did not show admin sidebox with tree --- phpgwapi/js/jsapi/egw_open.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/phpgwapi/js/jsapi/egw_open.js b/phpgwapi/js/jsapi/egw_open.js index 680aae8591..8df4560654 100644 --- a/phpgwapi/js/jsapi/egw_open.js +++ b/phpgwapi/js/jsapi/egw_open.js @@ -365,6 +365,12 @@ egw.extend('open', egw.MODULE_WND_LOCAL, function(_egw, _wnd) */ link_handler: function(_url, _target) { + // if url is supposed to open in admin, use admins loader to open it in it's own iframe + // (otherwise there's no tree and sidebox!) + if (_target === 'admin' && !_url.match(/menuaction=admin\.admin_ui\.index/)) + { + _url = _url.replace(/menuaction=([^&]+)/, 'menuaction=admin.admin_ui.index&load=$1'); + } if (_wnd.framework) { _wnd.framework.linkHandler(_url, _target); From 8f4c4237ed10da1044a4e2191ab26e1542941786 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 11 Feb 2015 11:06:01 +0000 Subject: [PATCH 05/23] cache based on vfs-url of image not its path which could be a sharing url --- etemplate/thumbnail.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etemplate/thumbnail.php b/etemplate/thumbnail.php index 987ad6ef8f..9065eb8436 100644 --- a/etemplate/thumbnail.php +++ b/etemplate/thumbnail.php @@ -134,7 +134,8 @@ function read_thumbnail($src) // Generate the destination filename and check whether the destination directory // had been successfully created (the cache class used in gen_dstfile does that). - $dst = gen_dstfile($src, $maxsize, $height, $width, $minsize); + $stat = egw_vfs::stat(egw_vfs::parse_url($src, PHP_URL_PATH)); + $dst = gen_dstfile($stat && !empty($stat['url']) ? $stat['url'] : $src, $maxsize, $height, $width, $minsize); $dst_dir = dirname($dst); if(file_exists($dst_dir)) { From dd097695ac61564f1e1d1c64577485239bd831a1 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 11 Feb 2015 11:16:33 +0000 Subject: [PATCH 06/23] * Filemanager/Mail: fixed not created thumbnails for readable shares --- api/src/Vfs/StreamWrapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/Vfs/StreamWrapper.php b/api/src/Vfs/StreamWrapper.php index f4864904f8..53995e7b30 100644 --- a/api/src/Vfs/StreamWrapper.php +++ b/api/src/Vfs/StreamWrapper.php @@ -301,7 +301,7 @@ class StreamWrapper implements StreamWrapperIface { return false; } - if ($mode != 'r' && self::url_is_readonly($url)) + if (str_replace('b', '', $mode) != 'r' && self::url_is_readonly($url)) { return false; } From 905bbc9c161e7669bb1972eb444875eb3ff17a7a Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Wed, 11 Feb 2015 11:21:40 +0000 Subject: [PATCH 07/23] Fix mousewheel handler on indicators in expose view causes problem, and not working in FF --- etemplate/js/expose.js | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/etemplate/js/expose.js b/etemplate/js/expose.js index 136f3ec0af..1fb3353311 100644 --- a/etemplate/js/expose.js +++ b/etemplate/js/expose.js @@ -440,23 +440,9 @@ function expose (widget) var total_count = nm.controller._grid.getTotalCount(); if(total_count >= gallery.num) { - gallery.container.find('.indicator').off() + var $indicator = gallery.container.find('.indicator'); + $indicator.off() .addClass('paginating') - .mousewheel(function(event, delta) { - if(delta > 0 && parseInt($j(this).css('left')) > gallery.container.width() / 2) return; - - //Reload next pictures into the gallery by scrolling on thumbnails - if (delta<0 && $j(this).width() + parseInt($j(this).css('left')) < gallery.container.width()) - { - var nextIndex = gallery.indicatorContainer.find('[title="loading"]')[0]; - if (nextIndex) self.expose_onslideend(gallery,nextIndex.dataset.index -1); - return; - } - // Move it about 5 indicators - $j(this).css('left',parseInt($j(this).css('left'))-(-delta*gallery.activeIndicator.width()*5)+'px'); - - event.preventDefault(); - }) .swipe(function(event, direction, distance) { if(direction == jQuery.fn.swipe.directions.LEFT) { @@ -472,6 +458,23 @@ function expose (widget) } $j(this).css('left',min(0,parseInt($j(this).css('left'))-(distance*30))+'px'); }); + // Bind the mousewheel handler for FF (DOMMousewheel), and other browsers (mousewheel) + $indicator.bind('mousewheel DOMMousewheel',function(event, _delta) { + var delta = _delta || event.originalEvent.wheelDelta / 120; + if(delta > 0 && parseInt($j(this).css('left')) > gallery.container.width() / 2) return; + + //Reload next pictures into the gallery by scrolling on thumbnails + if (delta<0 && $j(this).width() + parseInt($j(this).css('left')) < gallery.container.width()) + { + var nextIndex = gallery.indicatorContainer.find('[title="loading"]')[0]; + if (nextIndex) self.expose_onslideend(gallery,nextIndex.dataset.index -1); + return; + } + // Move it about 5 indicators + $j(this).css('left',parseInt($j(this).css('left'))-(-delta*gallery.activeIndicator.width()*5)+'px'); + + event.preventDefault(); + }); } } }, From 2edc2d831bde89abcea4393062292f4c6df6544a Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Wed, 11 Feb 2015 15:17:10 +0000 Subject: [PATCH 08/23] Implement Document Type Definition (DTD) generator - DTD generator is integrated to eTemplate2 Reference (widget browser) --- etemplate/js/widget_browser.js | 202 +++++++++++++++++- etemplate/templates/default/dtd.xet | 17 ++ .../templates/default/widget_browser.css | 9 + 3 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 etemplate/templates/default/dtd.xet diff --git a/etemplate/js/widget_browser.js b/etemplate/js/widget_browser.js index 5227708470..703aa818e4 100644 --- a/etemplate/js/widget_browser.js +++ b/etemplate/js/widget_browser.js @@ -4,6 +4,7 @@ * * @link http://www.egroupware.org * @author Nathan Gray + * @author Hadi Nategh * @copyright 2013 Nathan Gray * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate @@ -41,6 +42,8 @@ function widget_browser(list_div, widget_div) // Create and popuplate the widget list this._init_list(); + // Build DTD + this._init_dtd(); } /** @@ -62,7 +65,7 @@ widget_browser.prototype._init_list = function() for(var type in et2_registry) { types.push(type); - } + } types.sort(); for(var i = 0; i < types.length; i++) { @@ -160,8 +163,8 @@ widget_browser.prototype.select_widget = function(e,f) if(this.widget.attributes[attr].ignore) continue; this.create_attribute(attr, this.widget.attributes[attr]) .appendTo(this.attribute_list); - } - } + } + } }; @@ -227,9 +230,200 @@ widget_browser.prototype.create_attribute = function(name, settings) return row; }; +/** + * Initialise the DTD generator + */ +widget_browser.prototype._init_dtd = function () +{ + //Contains all widgets + this.widgets = []; + + //Contains not readonly widgets + this.dtd_widgets = []; + + //Contians readonly widgets + this.dtd_widgets_ro = []; + + // Contains the whole DTD string + this.dtd = ""; + + var self = this; + + // Create DTD Generator button and bind click handler on it + var dtd_btn = $j(document.createElement('button')) + .attr({id:'dtd_btn', title:'Generates Document Type Definition (DTD) for all widgets'}) + .click(function(){ + self._dtd_builder(); + }) + .addClass('dtd_btn') + .appendTo('body'); + dtd_btn.text('DTD Generator'); +} + +/** + * Iterates over all et2_widget to build DTD tags + * and display them as string + * + */ +widget_browser.prototype._dtd_builder = function() +{ + var dtdContentW = ""; + var i = 0; + for (var widget_type in et2_registry) + { + var attrs = {}; + + // creating a dialog popups an empty dialog, + // which we don't want therefore + // we eliminate dialog tag from dtd ATM. + if (widget_type.match(/dialog/,'i')) continue; + + if (!widget_type.match(/nextmatch/,'i')) + { + + this.widgets[i] = et2_createWidget(widget_type ,attrs, this.et2.widgetContainer) + if (widget_type.match(/_ro/,'i')) + { + this.dtd_widgets_ro.push( widget_type.replace('_ro','')); + } + else + { + this.dtd_widgets.push(widget_type); + dtdContentW += this._dtd_widgets(widget_type, this.widgets[i]) + } + i++; + } + } + // DTD Final Content + this.dtd = this._dtd_header() + dtdContentW; + + //Display DTD resault and UI to copy/download them + et2_createWidget("dialog", { + callback: function() {}, + title: egw.lang('DTD Result'), + buttons:et2_dialog.BUTTONS_OK, + value: { + content: { + value: this.dtd, + message: egw.lang('DTD Content') + } + }, + template: egw.webserverUrl+'/etemplate/templates/default/dtd.xet', + modal:true, + resizable:false + }); +} + +/** + * Builds some specific header DTD tags (e.g. ENTITY) + * + * @returns {String} returns dtd header tags as string + */ +widget_browser.prototype._dtd_header = function () +{ + var dtd = ''; + dtd = '\r\n'; + dtd += '\r\n'; + return dtd; +} + +/** + * Builds DTD ELEMENTS and teir ATTRLIST for given widget + * + * @param {string} _type widget type + * @param {object} _widget widget object + * @returns {String} returns generated dtd tags in string + */ +widget_browser.prototype._dtd_widgets = function (_type, _widget) +{ + var dtd = ''; + switch (_type) + { + // Special handling for menulist widget as it has a complicated structure + case 'menulist': + dtd = '\r\n'; + break; + + // Special handling for grid widget as it has a complicated structure + case 'grid': + dtd += '\r\n'; + dtd += '\r\n\ + \n\ + \n\ + \n\ + \r\n'; + break; + + // Special handling for tabbox widget as it has a complicated structure + case 'tabbox': + dtd += '\r\n'; + dtd += '\r\n'; + dtd += '\r\n'; + break; + + // Widget which can be a parent + case 'vbox': + case 'hbox': + case 'box': + case 'groupbox': + case 'template': + dtd = '\r\n'; + break; + + // Other widgets which only can be used as child + default: + dtd = '\r\n'; + } + + dtd +='\r\n'; + return dtd; +} + egw_LAB.wait(function() { var wb = new widget_browser( document.getElementById("widget_list"), document.getElementById("widget_container") ); -}); \ No newline at end of file +}); diff --git a/etemplate/templates/default/dtd.xet b/etemplate/templates/default/dtd.xet new file mode 100644 index 0000000000..c0d35c9062 --- /dev/null +++ b/etemplate/templates/default/dtd.xet @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/etemplate/templates/default/widget_browser.css b/etemplate/templates/default/widget_browser.css index 753629c203..392895f90f 100644 --- a/etemplate/templates/default/widget_browser.css +++ b/etemplate/templates/default/widget_browser.css @@ -43,3 +43,12 @@ font-size: 1.4em; height: 16px; } +/* DTD Generator Button*/ +.dtd_btn{ + width: 100px; + height: 35px; + float: right; + box-shadow: 1px 1px 1px 1px gray; + border: white solid 1px; + border-radius: 10px; +} From 82f36e6de4e905a13ed902e7c6624e855ffc9520 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Wed, 11 Feb 2015 18:05:14 +0000 Subject: [PATCH 09/23] Extend printing support to work with multiple etemplates on the printed tab --- etemplate/js/et2_extension_nextmatch.js | 4 ++ etemplate/js/etemplate2.js | 64 +++++++------------------ phpgwapi/js/framework/fw_base.js | 43 ++++++++++++++++- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index 5104f50247..491c10ff8b 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -1978,6 +1978,10 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin ); return defer; } + else + { + this.dynheight.innerNode.css('height', 'auto'); + } // Don't return anything, just work normally }, afterPrint: function() { diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index f7e599e31d..50a0f30fa7 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -909,66 +909,34 @@ etemplate2.app_refresh = function(_msg, _app, _id, _type) }; /** - * "Intelligently" print a given app + * "Intelligently" print a given etemplate * * Mostly, we let the nextmatch change how many rows it's showing, so you don't * get just one printed page. + * + * @return {Deferred[]} A list of Deferred objects that must complete before + * actual printing can begin. */ -etemplate2.print = function(_app) +etemplate2.prototype.print = function() { - // Allow any widget to change for printing - var et2 = etemplate2.getByApplication(_app); - // Sometimes changes take time var deferred = []; - for(var i = 0; i < et2.length; i++) - { - // Skip hidden templates - if(!jQuery(et2[i].DOMContainer).filter(':visible').length) continue; - et2[i].widgetContainer.iterateOver(function(_widget) { - // Skip widgets from a different etemplate (home) - if(_widget.getInstanceManager() != et2[i]) return; - var result = _widget.beforePrint(); - if (typeof result == "object" && result.done) - { - deferred.push(result); - } - },et2,et2_IPrint); - } + // Skip hidden etemplates + if(!jQuery(this.DOMContainer).filter(':visible').length) return []; - // Try to clean up after - not guaranteed - var afterPrint = function() { - for(var i = 0; i < et2.length; i++) + // Allow any widget to change for printing + this.widgetContainer.iterateOver(function(_widget) { + // Skip widgets from a different etemplate (home) + if(_widget.getInstanceManager() != this) return; + var result = _widget.beforePrint(); + if (typeof result == "object" && result.done) { - // Skip hidden templates - if(!jQuery(et2[i].DOMContainer).filter(':visible')) continue; - et2[i].widgetContainer.iterateOver(function(_widget) { - _widget.afterPrint(); - },et2,et2_IPrint); + deferred.push(result); } - var mediaQueryList = window.matchMedia('print'); - mediaQueryList - }; - if(egw.window.matchMedia) { - var mediaQueryList = window.matchMedia('print'); - var listener = function(mql) { - if (!mql.matches) { - afterPrint(); - mediaQueryList.removeListener(listener); - } - }; - mediaQueryList.addListener(listener); - } + },this,et2_IPrint); - egw.window.onafterprint = afterPrint; - - // Wait for everything to be loaded, then send it off - jQuery.when.apply(jQuery, deferred).done(function() { - egw.window.print(); - }).fail(function() { - afterPrint(); - }); + return deferred; } // Some static things to make getting into widget context a little easier // diff --git a/phpgwapi/js/framework/fw_base.js b/phpgwapi/js/framework/fw_base.js index dd88d0d5d8..faef5dcac6 100644 --- a/phpgwapi/js/framework/fw_base.js +++ b/phpgwapi/js/framework/fw_base.js @@ -960,9 +960,48 @@ var fw_base = Class.extend({ appWindow.focus(); // et2 available, let its widgets prepare - if(typeof etemplate2 == "function" && etemplate2.print) + var deferred = [] + var et2_list = []; + $j('.et2_container',this.activeApp.tab.contDiv).each(function() { + var et2 = etemplate2.getById(this.id); + if(et2 && jQuery(et2.DOMContainer).filter(':visible')) + { + deferred = deferred.concat(et2.print()); + et2_list.push(et2); + } + }); + + if(et2_list.length) { - etemplate2.print(this.activeApp.appName); + // Try to clean up after - not guaranteed + var afterPrint = function() { + for(var i = 0; i < et2_list.length; i++) + { + et2_list[i].widgetContainer.iterateOver(function(_widget) { + _widget.afterPrint(); + },et2_list[i],et2_IPrint); + } + appWindow.onafterprint = null; + }; + if(appWindow.matchMedia) { + var mediaQueryList = appWindow.matchMedia('print'); + var listener = function(mql) { + if (!mql.matches) { + afterPrint(); + mediaQueryList.removeListener(listener); + } + }; + mediaQueryList.addListener(listener); + } + + appWindow.onafterprint = afterPrint; + + // Wait for everything to be loaded, then send it off + jQuery.when.apply(jQuery, deferred).done(function() { + appWindow.print(); + }).fail(function() { + afterPrint(); + }); } else { From 92c26d156dacdda477cf2e794b266368714ff7d5 Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Wed, 11 Feb 2015 20:00:22 +0000 Subject: [PATCH 10/23] Better handling of printing of various row quantities: - print < loaded row count - print > loaded row count - print all rows --- etemplate/js/et2_extension_nextmatch.js | 33 ++++++++++++++++++++-- etemplate/templates/default/etemplate2.css | 1 - mail/templates/default/app.css | 1 - mail/templates/pixelegg/app.css | 1 - mail/templates/pixelegg/app.less | 1 - 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/etemplate/js/et2_extension_nextmatch.js b/etemplate/js/et2_extension_nextmatch.js index 491c10ff8b..bc5c81dbbc 100644 --- a/etemplate/js/et2_extension_nextmatch.js +++ b/etemplate/js/et2_extension_nextmatch.js @@ -1867,6 +1867,8 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin // Trigger resize, so we can fit on a page this.dynheight.outerNode.css('max-width',this.div.css('max-width')); this.resize(); + // Reset height to auto (after width resize) so there's no restrictions + this.dynheight.innerNode.css('height', 'auto'); // Check for rows that aren't loaded yet, or lots of rows var range = this.controller._grid.getIndexRange(); @@ -1898,6 +1900,8 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin button = 'dialog[all]'; // Add the class, gives more reliable sizing this.div.addClass('print'); + // Show it all + $j('.egwGridView_scrollarea',this.div).css('height','auto'); } // We need more rows if(button == 'dialog[all]' || value > loaded_count) @@ -1943,10 +1947,30 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin defer.reject(); return; } - nm.controller._grid.setScrollHeight(nm.controller._grid.getAverageHeight() * (value+1)); + if(value < total) + { + // Set height to the requested number of rows, using the average height. + // We add one, in case there's some larger rows we + // try to get most of it but that's pretty hacky + nm.controller._grid.setScrollHeight(nm.controller._grid.getAverageHeight() * (value+1)); + } + // Grid needs to redraw before it can be printed, so wait window.setTimeout(jQuery.proxy(function() { dialog.destroy(); + + if(value < total) + { + // Show requested number, based on average height + nm.controller._grid.setScrollHeight(nm.controller._grid.getAverageHeight() * (value)); + // No scrollbar in print view + $j('.egwGridView_scrollarea',this.div).css('overflow-y','hidden'); + } + else + { + // Show it all + $j('.egwGridView_scrollarea',this.div).css('height','auto'); + } // Should be OK to print now defer.resolve(); },nm),ET2_GRID_INVALIDATE_TIMEOUT); @@ -1961,11 +1985,12 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin else { // Don't need more rows, limit to requested and finish - this.controller._grid.setScrollHeight(this.controller._grid.getAverageHeight() * (value+1)); + this.controller._grid.setScrollHeight(this.controller._grid.getAverageHeight() * (value)); + // No scrollbar in print view + $j('.egwGridView_scrollarea',this.div).css('overflow-y','hidden'); // Give dialog a chance to close, or it will be in the print window.setTimeout(function() {defer.resolve();}, 0); } - //this.controller._gridCallback(0, button == et2_dialog.OK_BUTTON ? value : this.controller._grid.getTotalCount()); },this), egw.lang('How many rows to print'), egw.lang('Print'), Math.min(100, total), @@ -1980,7 +2005,9 @@ var et2_nextmatch = et2_DOMWidget.extend([et2_IResizeable, et2_IInput, et2_IPrin } else { + // Show all rows this.dynheight.innerNode.css('height', 'auto'); + $j('.egwGridView_scrollarea',this.div).css('height','auto'); } // Don't return anything, just work normally }, diff --git a/etemplate/templates/default/etemplate2.css b/etemplate/templates/default/etemplate2.css index 33096e51cb..53f03d20f3 100644 --- a/etemplate/templates/default/etemplate2.css +++ b/etemplate/templates/default/etemplate2.css @@ -477,7 +477,6 @@ These are set via javascript before printing to help tame nextmatch's layout for printing */ .et2_nextmatch.print .egwGridView_scrollarea { - height: auto !important; width: auto !important; } .et2_nextmatch.print > div { diff --git a/mail/templates/default/app.css b/mail/templates/default/app.css index cbe4869e10..e39cb40c52 100644 --- a/mail/templates/default/app.css +++ b/mail/templates/default/app.css @@ -752,7 +752,6 @@ blockquote blockquote blockquote blockquote blockquote blockquote{ height: auto !important; } html *, .td_display { - font-size: 12pt !important; border-right: none !important; border-left: none !important; } diff --git a/mail/templates/pixelegg/app.css b/mail/templates/pixelegg/app.css index 9c7158105d..46eb38a766 100755 --- a/mail/templates/pixelegg/app.css +++ b/mail/templates/pixelegg/app.css @@ -748,7 +748,6 @@ blockquote blockquote blockquote blockquote blockquote blockquote { } html *, .td_display { - font-size: 12pt !important; border-right: none !important; border-left: none !important; } diff --git a/mail/templates/pixelegg/app.less b/mail/templates/pixelegg/app.less index c78b0b07f6..aa477d9899 100755 --- a/mail/templates/pixelegg/app.less +++ b/mail/templates/pixelegg/app.less @@ -12,7 +12,6 @@ * @version $Id$ */ - @import (reference) "../../../pixelegg/less/layout_definitions.less"; @import (reference) "../../../pixelegg/less/definitions.less"; @import (less) "../default/app.css"; From 8926574a3541b72f5f437d5bad2677c51ea8ffaa Mon Sep 17 00:00:00 2001 From: Nathan Gray Date: Wed, 11 Feb 2015 21:08:53 +0000 Subject: [PATCH 11/23] Change media logic to also support mime=false --- etemplate/js/expose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etemplate/js/expose.js b/etemplate/js/expose.js index 1fb3353311..331d21af3a 100644 --- a/etemplate/js/expose.js +++ b/etemplate/js/expose.js @@ -381,7 +381,7 @@ function expose (widget) var self=this; // If the media type is not supported do not bind the click handler - if (_value && typeof _value.mime != 'undefined' && !_value.mime.match(mime_regex,'ig')) + if (!_value || typeof _value.mime != 'string' || !_value.mime.match(mime_regex,'ig')) { return; } From dd1a2cc80121f15230b749f84fd267b9b3437c60 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 11 Feb 2015 21:51:59 +0000 Subject: [PATCH 12/23] fixed share links were reused, event if attributes were different (password, expires, writable) --- phpgwapi/inc/class.egw_sharing.inc.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/phpgwapi/inc/class.egw_sharing.inc.php b/phpgwapi/inc/class.egw_sharing.inc.php index 668f749e30..037b6bbb3d 100644 --- a/phpgwapi/inc/class.egw_sharing.inc.php +++ b/phpgwapi/inc/class.egw_sharing.inc.php @@ -377,12 +377,15 @@ class egw_sharing { throw new egw_exception_not_found("'$path' NOT found!"); } - // check if file has been shared before + // check if file has been shared before, with identical attributes if (($mode != self::LINK || isset($path2tmp[$path])) && - ($share = self::$db->select(self::TABLE, '*', array( + ($share = self::$db->select(self::TABLE, '*', $extra+array( 'share_path' => $mode == 'link' ? $path2tmp[$path] : $vfs_path, 'share_owner' => $GLOBALS['egw_info']['user']['account_id'], - )+$extra, __LINE__, __FILE__)->fetch())) + 'share_expires' => null, + 'share_passwd' => null, + 'share_writable'=> false, + ), __LINE__, __FILE__)->fetch())) { // if yes, just add additional recipients $share['share_with'] = $share['share_with'] ? explode(',', $share['share_with']) : array(); From 8a5ab38c36ead94fea14cbae2519b79523a6e1cf Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 12 Feb 2015 08:34:02 +0000 Subject: [PATCH 13/23] set font size for printing of text mail body and all headers, attachments --- mail/templates/default/app.css | 4 ++++ mail/templates/pixelegg/app.css | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/mail/templates/default/app.css b/mail/templates/default/app.css index e39cb40c52..2790fc8c8d 100644 --- a/mail/templates/default/app.css +++ b/mail/templates/default/app.css @@ -755,6 +755,10 @@ blockquote blockquote blockquote blockquote blockquote blockquote{ border-right: none !important; border-left: none !important; } + /* set font size for printing of text mail body and all headers, attachments */ + .td_display pre, .mailDisplayHeaders, .mailDisplayAttachments * { + font-size: 12pt !important; + } .mailDisplayHeaders { border-bottom: 0.1em solid #d7d7d7; padding-top: 4px; diff --git a/mail/templates/pixelegg/app.css b/mail/templates/pixelegg/app.css index 46eb38a766..cb7f51aa56 100755 --- a/mail/templates/pixelegg/app.css +++ b/mail/templates/pixelegg/app.css @@ -751,6 +751,12 @@ blockquote blockquote blockquote blockquote blockquote blockquote { border-right: none !important; border-left: none !important; } + /* set font size for printing of text mail body and all headers, attachments */ + .td_display pre, + .mailDisplayHeaders, + .mailDisplayAttachments * { + font-size: 12pt !important; + } .mailDisplayHeaders { border-bottom: 0.1em solid #d7d7d7; padding-top: 4px; From 32f3a52280a30ea4e03e7ae0054b8c76ad412c52 Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Thu, 12 Feb 2015 09:02:56 +0000 Subject: [PATCH 14/23] Prepare mail display iframe for printing --- mail/js/app.js | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/mail/js/app.js b/mail/js/app.js index 83bf8d38d9..7a6a762f68 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -38,7 +38,7 @@ app.classes.mail = AppJS.extend( nm_index: 'nm', // nm name of index mail_fileSelectorWindow: null, mail_isMainWindow: true, - + // Some state variables to track preview pre-loading preview_preload: { timeout: null, @@ -57,7 +57,7 @@ app.classes.mail = AppJS.extend( * */ aclRights:['l','r','s','w','i','p','c','d','a'], - + /** * In order to store Intervals assigned to window * @array of setted intervals @@ -172,6 +172,12 @@ app.classes.mail = AppJS.extend( this.mail_callRefreshVacationNotice(); break; case 'mail.display': + var self = this; + // Prepare display dialog for printing + // copies iframe content to a DIV, as iframe causes + // trouble for multipage printing + jQuery('#mail-display_mailDisplayBodySrc').on('load', function(){self.mail_prepare_print()}); + this.mail_isMainWindow = false; this.mail_display(); @@ -3940,10 +3946,13 @@ app.classes.mail = AppJS.extend( }, /** - * Print a mail from Display + * Prepare display dialog for printing + * copies iframe content to a DIV, as iframe causes + * trouble for multipage printing * + * @returns {undefined} */ - mail_display_print: function () + mail_prepare_print: function() { var mainIframe = jQuery('#mail-display_mailDisplayBodySrc'); var tmpPrintDiv = jQuery('#tempPrintDiv'); @@ -3964,6 +3973,13 @@ app.classes.mail = AppJS.extend( if (notAttached) jQuery('#mail-display_mailDisplayBodySrc').after(tmpPrintDiv); tmpPrintDiv.find('#divAppboxHeader').remove(); + }, + + /** + * Print a mail from Display + */ + mail_display_print: function () + { this.egw.message('Printing....'); // Make sure the print happens after the content is loaded. Seems Firefox and IE can't handle timing for print command correctly @@ -4073,7 +4089,7 @@ app.classes.mail = AppJS.extend( //Make used email-tag list widgets in mail compose droppable emailTags.droppable({ accept:'.ms-sel-item', - + /** * Run after a draggable email item dropped over one of the email-taglists * -Set the dropped item to the dropped current target widget @@ -4187,7 +4203,7 @@ app.classes.mail = AppJS.extend( document.title = _widget.get_value(); } }, - + /** * Clear intervals stored in W_INTERVALS which assigned to window */ @@ -4199,10 +4215,10 @@ app.classes.mail = AppJS.extend( delete this.W_INTERVALS[i]; } }, - + /** * Window title getter function in order to set the window title - * + * * @returns {string} window title */ getWindowTitle: function () @@ -4220,7 +4236,7 @@ app.classes.mail = AppJS.extend( break; } }, - + /** * Set the relevant widget to toolbar actions and submit * @param {type} _action toolbar action @@ -4229,10 +4245,10 @@ app.classes.mail = AppJS.extend( { this.et2._inst.submit(null,null,true); }, - + /** * Set the selected checkbox action - * + * * @param {type} _action selected toolbar action with checkbox * @returns {undefined} */ @@ -4244,7 +4260,7 @@ app.classes.mail = AppJS.extend( widget.set_value(_action.checked?"on":"off"); } }, - + /** * Set the selected priority value * @param {type} _action selected action @@ -4258,7 +4274,7 @@ app.classes.mail = AppJS.extend( widget.set_value(_action.id); } }, - + /** * Triger relative widget via its toolbar identical action * @param {type} _action toolbar action @@ -4278,7 +4294,7 @@ app.classes.mail = AppJS.extend( } } }, - + /** * Save drafted compose as eml file into VFS * @param {type} _action action From 0df9400f465686cb7ed7182fb9910c5313974f83 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 12 Feb 2015 09:05:44 +0000 Subject: [PATCH 15/23] Changelog for 14.2.20150212 --- doc/rpm-build/debian.changes | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/rpm-build/debian.changes b/doc/rpm-build/debian.changes index 85d3408240..59c1bf26d5 100644 --- a/doc/rpm-build/debian.changes +++ b/doc/rpm-build/debian.changes @@ -1,3 +1,15 @@ +egroupware-epl (14.2.20150212-1) hardy; urgency=low + + * 14.2 final release + * All apps: improved printing: CRM view and given number or rows + * All apps: drag & drop files only worked on input nodes, eg. files draged in from desktop + * Filemanager/Mail: fixed not created thumbnails for readable shares + * ImportExport: links supposed to open in admin did not show admin sidebox with tree + * ProjectManager: add new role with rights limited only to add timesheets + * Home: fixed placing of portlets for FireFox and missing context menu after re-opening home tab + + -- Ralf Becker Thu, 12 Feb 2015 10:05:47 +0100 + egroupware-epl (14.2.20150210-1) hardy; urgency=low * 3. release candidate for upcomming 14.2 release From d15d01a8b4eb63d65a0503c3639ff9e62e0b92ef Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Thu, 12 Feb 2015 15:19:24 +0000 Subject: [PATCH 16/23] fix problem(s) with display of attachments on forward when either forwarding inline with several attachments to the forwarded message or forwarding multiple messages as attachment --- mail/inc/class.mail_ui.inc.php | 2 +- mail/js/app.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index a235c3aca2..11417cc653 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -1967,7 +1967,7 @@ class mail_ui $preventRedirect=false; if(isset($_requesteddata['id'])) $rowID = $_requesteddata['id']; - if(isset($_requesteddata['part'])) $partID = $_requesteddata['part']; + if(isset($_requesteddata['part'])) $partID = $_requesteddata['part']!='null'?$_requesteddata['part']:null; if(isset($_requesteddata['mode'])) $preventRedirect = (($_requesteddata['mode']=='display' || $_requesteddata['mode'] == 'print')?true:false); $hA = self::splitRowID($rowID); diff --git a/mail/js/app.js b/mail/js/app.js index 7a6a762f68..12333abfa3 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -2239,7 +2239,8 @@ app.classes.mail = AppJS.extend( attgrid = this.et2.getArrayMgr("content").getEntry('attachments')[widget.id.replace(/\[name\]/,'')]; var mailids = this.et2.getArrayMgr("content").getEntry('processedmail_id'); var mailida = mailids.split(','); - mailid = mailida[widget.id.replace(/\[name\]/,'')]; + // either several attachments of one email, or multiple emlfiles + mailid = mailida.length==1 ? mailida[0] : mailida[widget.id.replace(/\[name\]/,'')]; if (typeof attgrid.uid != 'undefined' && attgrid.uid && mailid.indexOf(attgrid.uid)==-1) { for (var i=0; i Date: Thu, 12 Feb 2015 15:48:49 +0000 Subject: [PATCH 17/23] Fix up button does nothing if you have a filemanager favorite on home --- filemanager/templates/default/index.xet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filemanager/templates/default/index.xet b/filemanager/templates/default/index.xet index f2462599c4..833f91dd8c 100644 --- a/filemanager/templates/default/index.xet +++ b/filemanager/templates/default/index.xet @@ -45,7 +45,7 @@