diff --git a/ChangeLog b/ChangeLog index c0718c7aa..20e6efa37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-05-28 Francis Lachapelle + + * UI/MailerUI/UIxMailMainFrame.m (-saveColumnsStateAction): new + method to save the relative sizes of the columns widths. It will + also save the columns order when the web interface supports it. + + * UI/WebServerResources/SOGoResizableTable.js (saveColumnsState): idem. + 2010-05-28 Wolfgang Sourdeau * UI/WebServerResources/UIxComponentEditor.js: diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index e24fa51ab..c7b8e414e 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -321,12 +321,12 @@ return keys; } -- (NSString *) defaultSortKey +- (NSString *) defaultSortKey { return @"ARRIVAL"; } -- (NSString *) imap4SortKey +- (NSString *) imap4SortKey { NSString *sort; @@ -341,11 +341,37 @@ - (NSString *) imap4SortOrdering { NSString *sort, *ascending; + NSString *module; //*login + NSMutableDictionary *moduleSettings; + BOOL asc; + SOGoUser *activeUser; + SOGoUserSettings *us; + SOGoMailAccounts *clientObject; sort = [self imap4SortKey]; - ascending = [[context request] formValueForKey: @"asc"]; - if (![ascending boolValue]) + asc = [ascending boolValue]; + + if (![sort isEqualToString: [self defaultSortKey]]) + { + // Save the sorting state in the user settings + activeUser = [context activeUser]; + clientObject = [self clientObject]; + module = [[[clientObject container] container] nameInContainer]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; + if (!moduleSettings) + { + moduleSettings = [NSMutableDictionary dictionary]; + [us setObject: moduleSettings forKey: module]; + } + [moduleSettings setObject: [NSArray arrayWithObjects: [sort lowercaseString], [NSString stringWithFormat: @"%d", (asc?1:0)], nil] + forKey: @"SortingState"]; + [us synchronize]; + } + + // Construct and return the final IMAP ordering constraint + if (!asc) sort = [@"REVERSE " stringByAppendingString: sort]; return sort; diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index 5c3e33ced..87e6bf9b3 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -65,14 +65,23 @@ @implementation UIxMailMainFrame +- (id) init +{ + if ((self = [super init])) + { + folderType = 0; + } + + return self; +} + - (void) _setupContext { SOGoUser *activeUser; - NSString *login, *module; + NSString *module; SOGoMailAccounts *clientObject; activeUser = [context activeUser]; - login = [activeUser login]; clientObject = [self clientObject]; module = [clientObject nameInContainer]; @@ -386,6 +395,42 @@ return [self responseWithStatus: 204]; } +- (NSString *) columnsState +{ + NSDictionary *columns; + + [self _setupContext]; + columns = [moduleSettings objectForKey: @"ColumnsState"]; + + return [columns jsonRepresentation]; +} + +- (WOResponse *) saveColumnsStateAction +{ + WORequest *request; + NSDictionary *columns; + NSArray *columnsIds, *widths; + + [self _setupContext]; + request = [context request]; + + columnsIds = [[request formValueForKey: @"columns"] componentsSeparatedByString: @","]; + widths = [[request formValueForKey: @"widths"] componentsSeparatedByString: @","]; + if (columnsIds != nil && widths != nil && [columnsIds count] == [widths count]) + { + columns = [NSDictionary dictionaryWithObjects: widths + forKeys: columnsIds]; + [moduleSettings setObject: columns + forKey: @"ColumnsState"]; + } + else + return [self responseWithStatus: 400]; + + [us synchronize]; + + return [self responseWithStatus: 204]; +} + - (id) defaultAction { SOGoUserDefaults *ud; @@ -400,20 +445,6 @@ return [super defaultAction]; } -/** - * - * methods from UIxMailListView - */ - -- (id) init -{ - if ((self = [super init])) - { - folderType = 0; - } - - return self; -} - (BOOL) showToAddress { SOGoMailFolder *co; diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 21a9a4e66..5429ca2bc 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -352,6 +352,11 @@ pageName = "UIxMailMainFrame"; actionName = "saveFoldersState"; }; + saveColumnsState = { + protectedBy = "View"; + pageName = "UIxMailMainFrame"; + actionName = "saveColumnsState"; + }; }; }; diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 9314a36b4..3784a2e86 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -245,7 +245,7 @@ diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 2d581c6d9..7416257c9 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -479,7 +479,6 @@ function onMailboxTreeItemClick(event) { topNode.selectedEntry = this; search = {}; - sorting = {}; $("searchValue").value = ""; initCriteria(); @@ -518,6 +517,8 @@ function toggleAddressColumn(search, replace) { if (i >= 0) UserDefaults["SOGoMailListViewColumnsOrder"][i] = replace.capitalize(); } + if (sorting["attribute"] == search) + sorting["attribute"] = replace; } function onMailboxMenuMove(event) { @@ -627,7 +628,7 @@ function openMailbox(mailbox, reload, updateStatus) { if (!reload) { var messageContent = $("messageContent"); messageContent.update(); - $("messageCountHeader").down().update(); + $("messageCountHeader").down().update(' '); lastClickedRow = -1; // from generic.js } @@ -695,10 +696,6 @@ function messageListCallback(row, data, isNew) { row.writeAttribute('labels', (data['labels']?data['labels']:"")); var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"]; -// if (typeof columnsOrder == "undefined") { -// columnsOrder = defaultColumnsOrder; -// } - var cells; if (Prototype.Browser.IE) cells = row.childNodes; @@ -1510,6 +1507,7 @@ function onHeaderClick(event) { sorting["attribute"] = newSortAttribute; sorting["ascending"] = true; } + refreshCurrentFolder(); Event.stop(event); @@ -1605,9 +1603,16 @@ function openInbox(node) { } function initMailer(event) { - // Default sort options - sorting["attribute"] = "date"; - sorting["ascending"] = false; + // Restore sorting from user settings + if (UserSettings["Mail"] && UserSettings["Mail"]["SortingState"]) { + sorting["attribute"] = UserSettings["Mail"]["SortingState"][0]; + sorting["ascending"] = parseInt(UserSettings["Mail"]["SortingState"][1]) > 0; + if (sorting["attribute"] == 'to') sorting["attribute"] = 'from'; // initial mailbox is always the inbox + } + else { + sorting["attribute"] = "date"; + sorting["ascending"] = false; + } // Define columns order if (typeof UserDefaults["SOGoMailListViewColumnsOrder"] == "undefined") { @@ -1631,7 +1636,10 @@ function initMailer(event) { var messageListHeader = $("messageListHeader"); messageListHeader.addInterface(SOGoResizableTableInterface); - + if (UserSettings["Mail"] && UserSettings["Mail"]["ColumnsState"]) { + messageListHeader.restore($H(UserSettings["Mail"]["ColumnsState"])); + } + configureMessageListEvents($("messageListHeader"), $("messageListBody")); initMailboxTree(); diff --git a/UI/WebServerResources/SOGoDataTable.js b/UI/WebServerResources/SOGoDataTable.js index 862e9ca16..9068e9301 100644 --- a/UI/WebServerResources/SOGoDataTable.js +++ b/UI/WebServerResources/SOGoDataTable.js @@ -62,6 +62,7 @@ var SOGoDataTableInterface = { if (this.dataSource) this.dataSource.destroy(); this._emptyTable(); this.dataSource = new window[dataSourceClass](this, url); + this.scrollTop = 0; this.load(params); }, diff --git a/UI/WebServerResources/SOGoMailDataSource.js b/UI/WebServerResources/SOGoMailDataSource.js index 182dfc232..5b04f51fc 100644 --- a/UI/WebServerResources/SOGoMailDataSource.js +++ b/UI/WebServerResources/SOGoMailDataSource.js @@ -45,7 +45,7 @@ SOGoMailDataSource = Class.create({ else params = ""; -// log ("MailDataSource.load() " + params); + log ("MailDataSource.load() " + params); triggerAjaxRequest(this.url + "/uids", this._loadCallback.bind(this), null, diff --git a/UI/WebServerResources/SOGoResizableTable.js b/UI/WebServerResources/SOGoResizableTable.js index 580f45fde..86becd48a 100644 --- a/UI/WebServerResources/SOGoResizableTable.js +++ b/UI/WebServerResources/SOGoResizableTable.js @@ -9,6 +9,7 @@ var SOGoResizableTableInterface = { delayedResize: null, + ratios: null, bind: function() { var i; @@ -23,17 +24,17 @@ var SOGoResizableTableInterface = { } SOGoResizableTable._resize(this, $(cell), i, null, cell.getWidth()); } - Event.observe(window, "resize", this.restore.bind(this)); + Event.observe(window, "resize", this.resize.bind(this)); }, - restore: function(e) { + resize: function(e) { // Only resize the columns after a certain delay, otherwise it slow // down the interface. if (this.delayedResize) window.clearTimeout(this.delayedResize); - this.delayedResize = this._restore.bind(this).delay(0.2); + this.delayedResize = this._resize.bind(this).delay(0.2); }, - _restore: function() { + _resize: function() { if (Prototype.Browser.IE) while (SOGoResizableTable._stylesheet.styleSheet.rules.length) SOGoResizableTable._stylesheet.styleSheet.removeRule(); @@ -41,13 +42,58 @@ var SOGoResizableTableInterface = { while (SOGoResizableTable._stylesheet.firstChild) SOGoResizableTable._stylesheet.removeChild(SOGoResizableTable._stylesheet.firstChild); - // TODO : widths ratios should be computed and columns restored accordingly. + var tableWidth = this.getWidth()/100; var cells = $(this).down('tr').childElements(); for (i = 0; i < cells.length; i++) { var cell = cells[i]; - SOGoResizableTable._resize(this, $(cell), i, null, cell.getWidth()); + var ratio = this.ratios.get(cell.id); + SOGoResizableTable._resize(this, $(cell), i, null, ratio*tableWidth); + } + }, + + restore: function(relativeWidths) { + var tableWidth = this.getWidth()/100; + var cells = $(this).down('tr').childElements(); + for (i = 0; i < cells.length; i++) { + var cell = cells[i]; + var ratio = relativeWidths.get(cell.id); + SOGoResizableTable._resize(this, $(cell), i, null, ratio*tableWidth); + } + this.ratios = relativeWidths; + }, + + saveColumnsState: function() { + this.ratios = new Hash(); + var tableWidth = 100/this.getWidth(); + var cells = $(this).down('tr').childElements(); + for (i = 0; i < cells.length; i++) { + var cell = cells[i]; + if (cell.hasClassName('resizable')) + this.ratios.set(cell.id, Math.round(cell.getWidth()*tableWidth)); + } + if (!$(document.body).hasClassName("popup")) { + var url = ApplicationBaseURL + "saveColumnsState"; + var data = this.ratios; + var columns = data.keys(); + var params = "columns=" + columns.join(",") + + "&widths=" + columns.collect(function(c) { return data.get(c); }).join(","); + triggerAjaxRequest(url, + this.saveColumnsStateCallback, + null, + params, + { "Content-type": "application/x-www-form-urlencoded" }); + } + }, + + saveColumnsStateCallback: function(http) { + if (isHttpStatus204(http.status)) { + log ("ResizableTable.saveColumnsStateCallback() Columns state saved"); + } + else if (http.readyState == 4) { + log ("ResizableTable.saveColumnsStateCallback() Can't save columns state"); } } + }; SOGoResizableTable = { @@ -89,6 +135,8 @@ SOGoResizableTable = { var w = nextResizableCell.getWidth() - delta; SOGoResizableTable._resize(table, nextResizableCell, i, null, w, true); } + + table.saveColumnsState(); }, _resize: function(table, cell, index, nextResizableCell, w, isAdjustment) {