diff --git a/ChangeLog b/ChangeLog index cb8d4b76e..63b2fea8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2007-10-22 Wolfgang Sourdeau + * UI/MailerUI/UIxMailActions.m ([UIxMailActions + -removeAllLabelsAction]): new method that removes all label flags + from the associated message. + ([UIxMailActions -addLabel1Action] + [UIxMailActions -addLabel2Action] + [UIxMailActions -addLabel3Action + [UIxMailActions -addLabel4Action] + [UIxMailActions -addLabel5Action]): new methods that adds label + flags to the associated message. + ([UIxMailActions -removeLabel1Action] + [UIxMailActions -removeLabel2Action] + [UIxMailActions -removeLabel3Action + [UIxMailActions -removeLabel4Action] + [UIxMailActions -removeLabel5Action]): new methods that removes + label flags from the associated message. + + * UI/MailerUI/UIxMailListView.m ([UIxMailListView -msgLabels]): + new accessor that returns the labels associated with the message. + * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder -allFolderPaths]): new method that returns all the paths of all the subfolders of the folder object. diff --git a/NEWS b/NEWS index 95e1bff63..e563d7fb5 100644 --- a/NEWS +++ b/NEWS @@ -2,9 +2,7 @@ -------------- - the user can now configure his folders as drafts, trash or sent folder; - added the ability the move and copy message across mail folders; - -0.9.0-200709XX --------------- +- added the ability to label messages; - implemented cookie-based identification in the web interface; - fixed a bug where a false positive happening whenever a wrong user login was given during an indirect bind; diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index 7b6d9e13e..4e962e432 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -20,6 +20,7 @@ * Boston, MA 02111-1307, USA. */ +#import #import #import @@ -221,4 +222,111 @@ return response; } +- (WOResponse *) _addLabel: (unsigned int) number +{ + WOResponse *response; + SOGoMailObject *co; + NSException *error; + NSArray *flags; + + co = [self clientObject]; + flags = [NSArray arrayWithObject: + [NSString stringWithFormat: @"$Label%u", number]]; + error = [co addFlags: flags]; + if (error) + response = (WOResponse *) error; + else + response = [self responseWith204]; + + return response; +} + +- (WOResponse *) _removeLabel: (unsigned int) number +{ + WOResponse *response; + SOGoMailObject *co; + NSException *error; + NSArray *flags; + + co = [self clientObject]; + flags = [NSArray arrayWithObject: + [NSString stringWithFormat: @"$Label%u", number]]; + error = [co removeFlags: flags]; + if (error) + response = (WOResponse *) error; + else + response = [self responseWith204]; + + return response; +} + +- (WOResponse *) addLabel1Action +{ + return [self _addLabel: 1]; +} + +- (WOResponse *) addLabel2Action +{ + return [self _addLabel: 2]; +} + +- (WOResponse *) addLabel3Action +{ + return [self _addLabel: 3]; +} + +- (WOResponse *) addLabel4Action +{ + return [self _addLabel: 4]; +} + +- (WOResponse *) addLabel5Action +{ + return [self _addLabel: 5]; +} + +- (WOResponse *) removeLabel1Action +{ + return [self _removeLabel: 1]; +} + +- (WOResponse *) removeLabel2Action +{ + return [self _removeLabel: 2]; +} + +- (WOResponse *) removeLabel3Action +{ + return [self _removeLabel: 3]; +} + +- (WOResponse *) removeLabel4Action +{ + return [self _removeLabel: 4]; +} + +- (WOResponse *) removeLabel5Action +{ + return [self _removeLabel: 5]; +} + +- (WOResponse *) removeAllLabelsAction +{ + WOResponse *response; + SOGoMailObject *co; + NSException *error; + NSArray *flags; + + co = [self clientObject]; + flags = [NSArray arrayWithObjects: @"$Label1", @"$Label2", @"$Label3", + @"$Label4", @"$Label5", nil]; + error = [co removeFlags: flags]; + if (error) + response = (WOResponse *) error; + else + response = [self responseWith204]; + + return response; +} + @end diff --git a/UI/MailerUI/UIxMailListView.m b/UI/MailerUI/UIxMailListView.m index e004eae93..e2cb26daf 100644 --- a/UI/MailerUI/UIxMailListView.m +++ b/UI/MailerUI/UIxMailListView.m @@ -534,6 +534,23 @@ static int attachmentFlagSize = 8096; return [self redirectToLocation:@"view"]; } +- (NSString *) msgLabels +{ + NSMutableArray *labels; + NSEnumerator *flags; + NSString *currentFlag; + + labels = [NSMutableArray new]; + [labels autorelease]; + + flags = [[message objectForKey: @"flags"] objectEnumerator]; + while ((currentFlag = [flags nextObject])) + if ([currentFlag hasPrefix: @"$label"]) + [labels addObject: [currentFlag substringFromIndex: 1]]; + + return [labels componentsJoinedByString: @" "]; +} + @end /* UIxMailListView */ diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index 083bbe403..6f269fb35 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -255,6 +255,61 @@ actionClass = "UIxMailActions"; actionName = "markMessageRead"; }; + addLabel1 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "addLabel1"; + }; + addLabel2 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "addLabel2"; + }; + addLabel3 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "addLabel3"; + }; + addLabel4 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "addLabel4"; + }; + addLabel5 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "addLabel5"; + }; + removeLabel1 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeLabel1"; + }; + removeLabel2 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeLabel2"; + }; + removeLabel3 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeLabel3"; + }; + removeLabel4 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeLabel4"; + }; + removeLabel5 = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeLabel5"; + }; + removeAllLabels = { + protectedBy = "View"; + actionClass = "UIxMailActions"; + actionName = "removeAllLabels"; + }; }; }; diff --git a/UI/Templates/MailerUI/UIxMailListView.wox b/UI/Templates/MailerUI/UIxMailListView.wox index 09dbd6b6f..cae21ceb3 100644 --- a/UI/Templates/MailerUI/UIxMailListView.wox +++ b/UI/Templates/MailerUI/UIxMailListView.wox @@ -56,14 +56,13 @@ diff --git a/UI/WebServerResources/MailerUI.css b/UI/WebServerResources/MailerUI.css index 6cdf164f0..abd9a6ec1 100644 --- a/UI/WebServerResources/MailerUI.css +++ b/UI/WebServerResources/MailerUI.css @@ -90,6 +90,21 @@ DIV#folderTreeContent bottom: 0px; overflow: auto; } +#label-menu LI.label1 +{ color: #f00; } + +#label-menu LI.label2 +{ color: #ff9a00; } + +#label-menu LI.label3 +{ color: #009a00; } + +#label-menu LI.label4 +{ color: #3130ff; } + +#label-menu LI.label5 +{ color: #9c309c; } + .aptview_title { color: #000000; @@ -518,7 +533,7 @@ TABLE#messageList TD.tbtv_date_headercell TABLE#messageList TR._selected TD { - background: #4b6983; + background-color: #4b6983; color: #fff; } @@ -527,6 +542,41 @@ TABLE#messageList TR._deleted TD text-decoration: line-through; } +TABLE#messageList TR[labels~="label5"] TD +{ color: #9c309c; } + +TABLE#messageList TR[labels~="label5"]._selected TD +{ color: #fff; + background-color: #9c309c; } + +TABLE#messageList TR[labels~="label4"] TD +{ color: #3130ff; } + +TABLE#messageList TR[labels~="label4"]._selected TD +{ color: #fff; + background-color: #3130ff; } + +TABLE#messageList TR[labels~="label3"] TD +{ color: #009a00; } + +TABLE#messageList TR[labels~="label3"]._selected TD +{ color: #fff; + background-color: #009a00; } + +TABLE#messageList TR[labels~="label2"] TD +{ color: #ff9a00; } + +TABLE#messageList TR[labels~="label2"]._selected TD +{ color: #fff; + background-color: #ff9a00; } + +TABLE#messageList TR[labels~="label1"] TD +{ color: #f00; } + +TABLE#messageList TR[labels~="label1"]._selected TD +{ color: #fff; + background-color: #f00; } + /* drag handles */ DIV#verticalDragHandle { diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 105f96ba1..2e086b91f 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -988,8 +988,6 @@ var messageListData = function(type) { } /* a model for a futur refactoring of the sortable table headers mechanism */ - - function configureMessageListEvents(table) { if (table) { table.multiselect = true; @@ -1379,6 +1377,50 @@ function onMenuChangeToTrashFolder(event) { return _onMenuChangeToXXXFolder(event, "Trash"); } +function onMenuLabelNone() { + var rowId = document.menuTarget.getAttribute("id").substr(4); + var messageId = currentMailbox + "/" + rowId; + var urlstr = ApplicationBaseURL + messageId + "/removeAllLabels"; + triggerAjaxRequest(urlstr, messageFlagCallback, + { mailbox: currentMailbox, msg: rowId, label: null } ); +} + +function _onMenuLabelFlagX(flag) { + var flags = document.menuTarget.getAttribute("labels").split(" "); + + var rowId = document.menuTarget.getAttribute("id").substr(4); + var messageId = currentMailbox + "/" + rowId; + + var operation = "add"; + if (flags.indexOf("label" + flag) > -1) + operation = "remove"; + var urlstr = (ApplicationBaseURL + messageId + + "/" + operation + "Label" + flag); + triggerAjaxRequest(urlstr, messageFlagCallback, + { mailbox: currentMailbox, msg: rowId, + label: operation + flag } ); +} + +function onMenuLabelFlag1() { + _onMenuLabelFlagX(1); +} + +function onMenuLabelFlag2() { + _onMenuLabelFlagX(2); +} + +function onMenuLabelFlag3() { + _onMenuLabelFlagX(3); +} + +function onMenuLabelFlag4() { + _onMenuLabelFlagX(4); +} + +function onMenuLabelFlag5() { + _onMenuLabelFlagX(5); +} + function folderOperationCallback(http) { if (http.readyState == 4 && isHttpStatus204(http.status)) @@ -1398,6 +1440,65 @@ function folderRefreshCallback(http) { window.alert(labels["Operation failed"]); } +function messageFlagCallback(http) { + if (http.readyState == 4 + && isHttpStatus204(http.status)) { + var data = http.callbackData; + if (data["mailbox"] == currentMailbox) { + var row = $("row_" + data["msg"]); + var operation = data["label"]; + if (operation) { + var labels = row.getAttribute("labels"); + var flags; + if (labels.length > 0) + flags = labels.split(" "); + else + flags = new Array(); + if (operation.substr(0, 3) == "add") + flags.push("label" + operation.substr(3)); + else { + var flag = "label" + operation.substr(6); + var idx = flags.indexOf(flag); + flags.splice(idx, 1); + } + row.setAttribute("labels", flags.join(" ")); + } + else + row.setAttribute("labels", ""); + } + } +} + +function onLabelMenuPrepareVisibility() { + var messageList = $("messageList"); + var rows = messageList.getSelectedRows(); + + var flags = {}; + for (var i = 1; i < 6; i++) + flags["label" + i] = true; + for (var i = 0; i < rows.length; i++) { + var rowFlags = rows[i].getAttribute("labels").split(" "); + for (var flag in flags) + if (flags[flag] && rowFlags.indexOf(flag) == -1) + flags[flag] = false; + } + + var lis = this.childNodesWithTag("ul")[0].childNodesWithTag("li") + var isFlagged = false; + for (var i = 1; i < 6; i++) { + if (flags["label" + i]) { + isFlagged = true; + lis[1 + i].addClassName("_chosen"); + } + else + lis[1 + i].removeClassName("_chosen"); + } + if (isFlagged) + lis[0].removeClassName("_chosen"); + else + lis[0].addClassName("_chosen"); +} + function getMenus() { var menus = {} menus["accountIconMenu"] = new Array(null, null, onMenuCreateFolder, null, @@ -1441,14 +1542,16 @@ function getMenus() { menus["folderTypeMenu"] = new Array(onMenuChangeToSentFolder, onMenuChangeToDraftsFolder, onMenuChangeToTrashFolder); - - menus["label-menu"] = new Array(null, "-", null , null, null, null , null, - null); + + menus["label-menu"] = new Array(onMenuLabelNone, "-", onMenuLabelFlag1, + onMenuLabelFlag2, onMenuLabelFlag3, + onMenuLabelFlag4, onMenuLabelFlag5); menus["mark-menu"] = new Array(null, null, null, null, "-", null, "-", null, null, null); menus["searchMenu"] = new Array(setSearchCriteria, setSearchCriteria, setSearchCriteria, setSearchCriteria, setSearchCriteria); + $("label-menu").prepareVisibility = onLabelMenuPrepareVisibility; return menus; } diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index 4522d2d08..68a5d4914 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -585,9 +585,11 @@ function popupMenu(event, menuId, target) { if (leftDiff < 0) menuLeft -= popup.offsetWidth; + if (popup.prepareVisibility) + popup.prepareVisibility(); popup.setStyle({ top: menuTop + "px", - left: menuLeft + "px", - visibility: "visible" }); + left: menuLeft + "px", + visibility: "visible" }); document.currentPopupMenu = popup; @@ -614,7 +616,7 @@ function getParentMenu(node) { } function onBodyClickMenuHandler(event) { - document.body.menuTarget = null; + document.menuTarget = null; hideMenu(document.currentPopupMenu); Event.stopObserving(document.body, "click", onBodyClickMenuHandler); @@ -776,6 +778,9 @@ function popupSubmenu(event) { parentNode.submenuItem = this; parentNode.submenu = submenuNode; + if (submenuNode.prepareVisibility) + submenuNode.prepareVisibility(); + var menuTop = (parentNode.offsetTop - 1 + this.offsetTop); if (window.height()