Monotone-Parent: 7466bb5da0445e1513612a7c2b55fbe4ba52738b

Monotone-Revision: 1ae9c2331a84b076b01da922ab81cf098a6fff43

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2007-10-22T21:59:20
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2007-10-22 21:59:20 +00:00
parent 5f97744f45
commit 29e7136332
10 changed files with 374 additions and 20 deletions

View File

@ -1,5 +1,24 @@
2007-10-22 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* 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.

4
NEWS
View File

@ -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;

View File

@ -20,6 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import <NGObjWeb/WOContext.h>
@ -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

View File

@ -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 */

View File

@ -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";
};
};
};

View File

@ -56,14 +56,13 @@
</thead>
<tbody>
<var:foreach list="messages" item="message"
><tr var:class="messageRowStyleClass" var:id="msgRowID"
><tr var:class="messageRowStyleClass" var:id="msgRowID" var:labels="msgLabels"
><td class="messageFlagColumn"><var:entity name="nbsp"/></td
><td class="messageFlagColumn"
><var:if condition="hasMessageAttachment"
><img rsrc:src="title_attachment_14x14.png"
/></var:if
></td
><td
var:class="messageSubjectCellStyleClass"
var:id="msgDivID"

View File

@ -130,14 +130,14 @@
</div>
<div class="menu" id="label-menu">
<ul id="">
<ul id="" class="choiceMenu">
<li><var:string label:value="None" /></li>
<li><!-- separator --></li>
<li><var:string label:value="Important" /></li>
<li><var:string label:value="Work" /></li>
<li><var:string label:value="Personal" /></li>
<li><var:string label:value="To Do" /></li>
<li><var:string label:value="Later" /></li>
<li class="label1"><var:string label:value="Important" /></li>
<li class="label2"><var:string label:value="Work" /></li>
<li class="label3"><var:string label:value="Personal" /></li>
<li class="label4"><var:string label:value="To Do" /></li>
<li class="label5"><var:string label:value="Later" /></li>
</ul>
</div>

View File

@ -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
{

View File

@ -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;
}

View File

@ -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()