Added support for dynamic mail labels/tags management.

The CSS in the UIxPreferences remains to be done.
pull/15/merge
Ludovic Marcotte 2013-11-11 10:49:58 -05:00
parent 6a9bcfda68
commit 37d3234b60
24 changed files with 625 additions and 230 deletions

View File

@ -16,6 +16,7 @@ Mailer_OBJC_FILES += \
SOGoMailAccounts.m \
SOGoMailAccount.m \
SOGoMailFolder.m \
SOGoMailLabel.m \
SOGoMailNamespace.m \
SOGoMailObject.m \
SOGoMailObject+Draft.m \

View File

@ -0,0 +1,50 @@
/*
Copyright (C) 2013 Inverse inc.
This file is part of SOGo.
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#ifndef SOGOMAILLABEL_H
#define SOGOMAILLABEL_H
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import "../../UI/SOGoUI/UIxComponent.h";
@interface SOGoMailLabel : NSObject
{
NSString *_name;
NSString *_label;
NSString *_color;
}
- (id) initWithName: (NSString *) theName
label: (NSString *) theLabel
color: (NSString *) theColor;
- (NSString *) name;
- (NSString *) label;
- (NSString *) color;
+ (NSArray *) labelsFromDefaults: (NSDictionary *) theDefaults
component: (UIxComponent *) theComponent;
@end
#endif // SOGOMAILLABEL_H

View File

@ -0,0 +1,96 @@
/*
Copyright (C) 2007-2013 Inverse inc.
This file is part of SOGo.
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with OGo; see the file COPYING. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#import "SOGoMailLabel.h"
#import <Foundation/NSDictionary.h>
@implementation SOGoMailLabel
- (id) initWithName: (NSString *) theName
label: (NSString *) theLabel
color: (NSString *) theColor
{
self = [super init];
if (self)
{
ASSIGN(_name, theName);
ASSIGN(_label, theLabel);
ASSIGN(_color, theColor);
}
return self;
}
- (void) dealloc
{
RELEASE(_name);
RELEASE(_label);
RELEASE(_color);
[super dealloc];
}
- (NSString *) name
{
return _name;
}
- (NSString *) label
{
return _label;
}
- (NSString *) color
{
return _color;
}
+ (NSArray *) labelsFromDefaults: (NSDictionary *) theDefaults
component: (UIxComponent *) theComponent
{
NSMutableArray *allLabels, *allKeys;
NSDictionary *mailLabelsColors;
NSString *key, *name;
SOGoMailLabel *label;
NSArray *values;
int i;
allLabels = [NSMutableArray array];
allKeys = [[theDefaults allKeys] sortedArrayUsingSelector: @selector (caseInsensitiveCompare:)];
for (i = 0; i < [allKeys count]; i++)
{
key = [allKeys objectAtIndex: i];
values = [theDefaults objectForKey: key];
name = [theComponent labelForKey: [values objectAtIndex: 0]];
label = [[self alloc] initWithName: key
label: name
color: [values objectAtIndex: 1]];
[allLabels addObject: label];
RELEASE(label);
}
return allLabels;
}
@end

View File

@ -76,4 +76,12 @@
SOGoRemindWithASound = YES;
SOGoSearchMinimumWordLength = 2;
SOGoMailLabelsColors = {
label1 = ("Important", "#f00");
label2 = ("Work", "#ff9a00");
label3 = ("Personal", "#009a00");
label4 = ("To Do", "#3130ff");
label5 = ("Later", "#9c309c");
};
}

View File

@ -1,8 +1,6 @@
/* SOGoUserDefaults.h - this file is part of SOGo
*
* Copyright (C) 2011-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2011-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -166,6 +164,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
- (void) setForwardOptions: (NSDictionary *) newValue;
- (NSDictionary *) forwardOptions;
- (void) setMailLabelsColors: (NSDictionary *) newValues;
- (NSDictionary *) mailLabelsColors;
/* calendar */
- (void) setCalendarCategories: (NSArray *) newValues;
- (NSArray *) calendarCategories;

View File

@ -1,8 +1,6 @@
/* SOGoUserDefaults.m - this file is part of SOGo
*
* Copyright (C) 2009-2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2009-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -733,6 +731,26 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
return [self boolForKey: @"SOGoRemindWithASound"];
}
//
// Dictionary of arrays. Example:
//
// {
// label1 => ("Important", "#FF0000");
// label2 => ("Work" "#00FF00");
// foo_bar => ("Foo Bar", "#0000FF");
// }
//
- (void) setMailLabelsColors: (NSDictionary *) newValues
{
[self setObject: newValues forKey: @"SOGoMailLabelsColors"];
}
- (NSDictionary *) mailLabelsColors
{
return [self objectForKey: @"SOGoMailLabelsColors"];
}
- (void) setSieveFilters: (NSArray *) newValue
{
[self setObject: newValue forKey: @"SOGoSieveFilters"];

View File

@ -1,8 +1,6 @@
/* UIxMailActions.h - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,8 +1,6 @@
/* UIxMailActions.m - this file is part of SOGo
*
* Copyright (C) 2007 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,6 +19,7 @@
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <NGObjWeb/WOContext.h>
@ -32,6 +31,8 @@
#import <SoObjects/Mailer/SOGoDraftsFolder.h>
#import <SoObjects/Mailer/SOGoMailAccount.h>
#import <SoObjects/Mailer/SOGoMailObject.h>
#import <SoObjects/SOGo/SOGoUserDefaults.h>
#import "../Common/WODirectAction+SOGo.h"
@ -194,16 +195,18 @@
return response;
}
- (WOResponse *) _addLabel: (unsigned int) number
- (WOResponse *) addLabelAction
{
WOResponse *response;
SOGoMailObject *co;
NSException *error;
NSArray *flags;
NSString *flag;
flag = [[[self->context request] formValueForKey: @"flag"] fromCSSIdentifier];
co = [self clientObject];
flags = [NSArray arrayWithObject:
[NSString stringWithFormat: @"$Label%u", number]];
flags = [NSArray arrayWithObject: flag];
error = [co addFlags: flags];
if (error)
response = (WOResponse *) error;
@ -213,16 +216,18 @@
return response;
}
- (WOResponse *) _removeLabel: (unsigned int) number
- (WOResponse *) removeLabelAction
{
WOResponse *response;
SOGoMailObject *co;
NSException *error;
NSArray *flags;
NSString *flag;
flag = [[[self->context request] formValueForKey: @"flag"] fromCSSIdentifier];
co = [self clientObject];
flags = [NSArray arrayWithObject:
[NSString stringWithFormat: @"$Label%u", number]];
flags = [NSArray arrayWithObject: flag];
error = [co removeFlags: flags];
if (error)
response = (WOResponse *) error;
@ -232,66 +237,25 @@
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
{
NSMutableArray *flags;
WOResponse *response;
SOGoMailObject *co;
NSException *error;
NSArray *flags;
NSDictionary *v;
co = [self clientObject];
flags = [NSArray arrayWithObjects: @"$Label1", @"$Label2", @"$Label3",
@"$Label4", @"$Label5", nil];
v = [[[context activeUser] userDefaults] mailLabelsColors];
// We always unconditionally remove the Mozilla tags
flags = [NSMutableArray arrayWithObjects: @"$Label1", @"$Label2", @"$Label3",
@"$Label4", @"$Label5", nil];
[flags addObjectsFromArray: [v allKeys]];
error = [co removeFlags: flags];
if (error)
response = (WOResponse *) error;

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2006-2011 Inverse inc.
Copyright (C) 2006-2013 Inverse inc.
This file is part of SOGo
@ -861,8 +861,9 @@
flags = [[message objectForKey: @"flags"] objectEnumerator];
while ((currentFlag = [flags nextObject]))
if ([currentFlag hasPrefix: @"$label"])
[labels addObject: [currentFlag substringFromIndex: 1]];
{
[labels addObject: currentFlag];
}
return [labels componentsJoinedByString: @" "];
}

View File

@ -1,8 +1,6 @@
/* UIxMailMainFrame.h - this file is part of SOGo
*
* Copyright (C) 2006-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2006-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,6 +23,8 @@
#import "../SOGoUI/UIxComponent.h"
@class SOGoMailLabel;
@interface UIxMailMainFrame : UIxComponent
{
SOGoUserSettings *us;
@ -33,6 +33,7 @@
NSArray *columnsOrder;
int folderType;
NSDictionary *currentColumn;
SOGoMailLabel *_currentLabel;
}
- (WOResponse *) getFoldersStateAction;

View File

@ -1,9 +1,5 @@
/*
Copyright (C) 2007-2011 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
Ludovic Marcotte <lmarcotte@inverse.ca>
Copyright (C) 2007-2013 Inverse inc.
This file is part of SOGo.
@ -48,6 +44,7 @@
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h>
#import <Mailer/SOGoMailFolder.h>
#import <Mailer/SOGoMailLabel.h>
#import <Mailer/SOGoMailObject.h>
#import <Mailer/SOGoSentFolder.h>
#import <SOGo/NSDictionary+URL.h>
@ -84,6 +81,12 @@
return self;
}
- (void) dealloc
{
RELEASE(_currentLabel);
[super dealloc];
}
- (void) _setupContext
{
SOGoUser *activeUser;
@ -687,4 +690,32 @@
return [folders jsonRepresentation];
}
//
// Standard mapping done by Thunderbird:
//
// label1 => Important
// label2 => Work
// label3 => Personal
// label4 => To Do
// label5 => Later
//
- (NSArray *) availableLabels
{
NSDictionary *v;
v = [[[context activeUser] userDefaults] mailLabelsColors];
return [SOGoMailLabel labelsFromDefaults: v component: self];
}
- (void) setCurrentLabel: (SOGoMailLabel *) theCurrentLabel
{
ASSIGN(_currentLabel, theCurrentLabel);
}
- (SOGoMailLabel *) currentLabel
{
return _currentLabel;
}
@end /* UIxMailMainFrame */

View File

@ -272,55 +272,15 @@
actionClass = "UIxMailActions";
actionName = "markMessageRead";
};
addLabel1 = {
addLabel = {
protectedBy = "View";
actionClass = "UIxMailActions";
actionName = "addLabel1";
actionName = "addLabel";
};
addLabel2 = {
removeLabel = {
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";
actionName = "removeLabel";
};
removeAllLabels = {
protectedBy = "View";

View File

@ -288,12 +288,13 @@
"Flagged" = "Flagged";
"Junk" = "Junk";
"Not Junk" = "Not Junk";
"Label 1" = "Label 1";
"Label 2" = "Label 2";
"Label 3" = "Label 3";
"Label 4" = "Label 4";
"Label 5" = "Label 5";
"Important" = "Important";
"Work" = "Work";
"Personal" = "Personal";
"To Do" = "To Do";
"Later" = "Later";
/* Password policy */
"The password was changed successfully." = "The password was changed successfully.";
"Password must not be empty." = "Password must not be empty.";
"The passwords do not match. Please try again." = "The passwords do not match. Please try again.";
@ -306,4 +307,4 @@
"Unhandled policy error: %{0}" = "Unhandled policy error: %{0}";
"Unhandled error response" = "Unhandled error response";
"Password change is not supported." = "Password change is not supported.";
"Unhandled HTTP error code: %{0}" = "Unhandled HTTP error code: %{0}";
"Unhandled HTTP error code: %{0}" = "Unhandled HTTP error code: %{0}";

View File

@ -1,8 +1,6 @@
/* UIxFilterEditor.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,20 +24,44 @@
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGoUI/UIxComponent.h>
@interface UIxFilterEditor : UIxComponent
{
NSString *filterId;
NSDictionary *labels;
}
@end
@implementation UIxFilterEditor
- (id) init
{
self = [super init];
if (self)
{
filterId = nil;
labels = nil;
}
return self;
}
- (void) dealloc
{
RELEASE(filterId);
RELEASE(labels);
[super dealloc];
}
/* convert and save */
- (BOOL) _validateFilterId
{
@ -80,4 +102,14 @@
return filterId;
}
- (NSString *) labels
{
if (!labels)
{
ASSIGN(labels, [[[context activeUser] userDefaults] mailLabelsColors]);
}
return [labels jsonRepresentation];
}
@end

View File

@ -1,8 +1,6 @@
/* UIxPreferences.h - this file is part of SOGo
*
* Copyright (C) 2007-2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2007-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -27,23 +25,36 @@
@class NSString;
@class SOGoMailLabel;
@class SOGoUser;
@interface UIxPreferences : UIxComponent
{
id item;
SOGoUser *user;
// Calendar categories
NSString *category;
NSArray *calendarCategories;
NSDictionary *calendarCategoriesColors;
NSArray *contactsCategories;
NSString *defaultCategoryColor;
NSCalendarDate *today;
// Mail labels/tags
SOGoMailLabel *label;
NSArray *mailLabels;
// Sieve filtering
NSArray *daysOfWeek, *daysBetweenResponsesList;
NSArray *sieveFilters;
NSMutableDictionary *vacationOptions, *forwardOptions;
BOOL mailCustomFromEnabled;
BOOL hasChanged;
}
- (NSString *) userLongDateFormat;

View File

@ -1,9 +1,6 @@
/* UIxPreferences.m - this file is part of SOGo
*
* Copyright (C) 2007-2011 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
* Copyright (C) 2007-2013 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,6 +28,8 @@
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WORequest.h>
#import <NGImap4/NSString+Imap4.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGCards/iCalTimeZone.h>
@ -47,6 +46,7 @@
#import <SOGo/WOResourceManager+SOGo.h>
#import <Mailer/SOGoMailAccount.h>
#import <Mailer/SOGoMailAccounts.h>
#import <Mailer/SOGoMailLabel.h>
#import "UIxPreferences.h"
@ -77,6 +77,9 @@
defaultCategoryColor = nil;
category = nil;
label = nil;
mailLabels = nil;
ASSIGN (daysOfWeek, [locale objectForKey: NSWeekDayNameArray]);
dd = [user domainDefaults];
@ -120,6 +123,8 @@
[calendarCategoriesColors release];
[defaultCategoryColor release];
[category release];
[label release];
[mailLabels release];
[contactsCategories release];
[forwardOptions release];
[daysOfWeek release];
@ -1175,6 +1180,67 @@
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
}
- (SOGoMailLabel *) label
{
return label;
}
- (void) setLabel: (SOGoMailLabel *) newLabel
{
ASSIGN(label, newLabel);
}
- (NSArray *) mailLabelList
{
if (!mailLabels)
{
NSDictionary *v;
v = [[[context activeUser] userDefaults] mailLabelsColors];
ASSIGN(mailLabels, [SOGoMailLabel labelsFromDefaults: v component: self]);
}
return mailLabels;
}
- (NSString *) mailLabelsValue
{
return @"";
}
- (void) setMailLabelsValue: (NSString *) value
{
NSMutableDictionary *sanitizedLabels;
NSDictionary *newLabels;
NSArray *allKeys;
NSString *name;
int i;
newLabels = [value objectFromJSONString];
if (newLabels && [newLabels isKindOfClass: [NSDictionary class]])
{
// We encode correctly our keys
sanitizedLabels = [NSMutableDictionary dictionary];
allKeys = [newLabels allKeys];
for (i = 0; i < [allKeys count]; i++)
{
name = [allKeys objectAtIndex: i];
if (![name is7bitSafe])
name = [name stringByEncodingImap4FolderName];
name = [name lowercaseString];
[sanitizedLabels setObject: [newLabels objectForKey: [allKeys objectAtIndex: i]]
forKey: name];
}
[userDefaults setMailLabelsColors: sanitizedLabels];
}
}
- (void) setCategory: (NSString *) newCategory
{
ASSIGN (category, newCategory);

View File

@ -16,6 +16,10 @@
var unseenCountFolders = <var:string value="unseenCountFolders" const:escapeHTML="NO"/>;
</script>
<style type="text/css">
<var:foreach list="availableLabels" item="currentLabel">
#label-menu LI.<var:string value="currentLabel.name"/>
{ color: <var:string value="currentLabel.color"/>; }
</var:foreach>
<var:if condition="horizontalDragHandleStyle">
DIV#verticalDragHandle, DIV#rightPanel
{ left: <var:string value="horizontalDragHandleStyle" />; }
@ -170,11 +174,9 @@
<ul id="" class="choiceMenu">
<li><var:string label:value="None" /></li>
<li><!-- separator --></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>
<var:foreach list="availableLabels" item="currentLabel">
<li var:class="currentLabel.name" var:data-name="currentLabel.name"> <var:string value="currentLabel.label"/></li>
</var:foreach>
</ul>
</div>

View File

@ -13,6 +13,7 @@
>
<script type="text/javascript">
var filterId = '<var:string value="filterId"/>';
var labels = <var:string value="labels"/>;
</script>
<form id="mainForm" var:href="ownPath">
<div id="filterNameContainer" class="container">

View File

@ -283,6 +283,41 @@
</span></a>
</div>
</var:if>
<label><var:string label:value="Labels"/></label>
<div id="mailLabelsListWrapper" class="listWrapper"
><table class="labelsList" cellspacing="0">
<thead>
<tr class="tableview"
><th const:class="tbtv_headercell" const:id="labelTableHeader"
><var:string label:value="Label"/></th
><th const:class="tbtv_headercell" const:id="colorTableHeader"
><var:string label:value="Color"/></th
></tr
></thead>
<tbody>
<var:foreach list="mailLabelList" item="label">
<tr var:data-name="label.name" const:class="labelListRow"
><td const:class="labelListCell"
><var:string var:value="label.label"/></td
><td const:class="labelListCell"
><div const:class="colorBox"><var:string var:value="label.color"
/></div></td
></tr>
</var:foreach>
</tbody>
</table>
</div>
<div class="bottomToolbar">
<a const:id="mailLabelAdd" class="bottomButton" href="#">
<span><img rsrc:src="add-icon.png" label:title="Add" />
</span></a>
<a const:id="mailLabelDelete" class="bottomButton" href="#">
<span><img rsrc:src="remove-icon.png" label:title="Delete" />
</span></a>
</div>
<input type="hidden" const:id="mailLabelsValue"
const:name="mailLabelsValue" var:value="mailLabelsValue"/>
</div>
<div id="mailAccountsView" class="tab">

View File

@ -1,14 +1,15 @@
/*
Copyright (C) 2005-2013 Inverse inc.
Copyright (C) 2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
This file is part of SOGo.
OGo is free software; you can redistribute it and/or modify it under
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
@ -93,21 +94,6 @@ DIV#folderTreeContent
right: 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;

View File

@ -2488,9 +2488,11 @@ function onMenuLabelNone() {
});
}
function _onMenuLabelFlagX(flag) {
function onMenuLabelFlag() {
var messages = new Hash();
var flag = this.readAttribute("data-name");
if (document.menuTarget.tagName == "DIV")
// Menu called from message content view
messages.set(Mailer.currentMessages[Mailer.currentMailbox],
@ -2502,45 +2504,25 @@ function _onMenuLabelFlagX(flag) {
if (row)
messages.set(rowID.substr(4),
row.getAttribute("labels"));
});
});
else
// Menu called from one selection in messages list view
messages.set(document.menuTarget.getAttribute("id").substr(4),
document.menuTarget.getAttribute("labels"));
var url = ApplicationBaseURL + encodeURI(Mailer.currentMailbox) + "/";
messages.keys().each(function(id) {
var flags = messages.get(id).split(" ");
var operation = "add";
if (flags.indexOf("label" + flag) > -1)
operation = "remove";
triggerAjaxRequest(url + id + "/" + operation + "Label" + flag,
messageFlagCallback,
{ mailbox: Mailer.currentMailbox, msg: id,
label: operation + flag } );
});
}
function onMenuLabelFlag1() {
_onMenuLabelFlagX(1);
}
function onMenuLabelFlag2() {
_onMenuLabelFlagX(2);
}
function onMenuLabelFlag3() {
_onMenuLabelFlagX(3);
}
function onMenuLabelFlag4() {
_onMenuLabelFlagX(4);
}
function onMenuLabelFlag5() {
_onMenuLabelFlagX(5);
var flags = messages.get(id).split(" ");
var operation = "add";
if (flags.indexOf(flag) > -1)
operation = "remove";
triggerAjaxRequest(url + id + "/" + operation + "Label?flag=" + flag.asCSSIdentifier(),
messageFlagCallback,
{ mailbox: Mailer.currentMailbox, msg: id,
label: operation + flag } );
});
}
function onMenuToggleMessageFlag(event) {
@ -2707,14 +2689,33 @@ function onLabelMenuPrepareVisibility() {
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");
// lis is our array of labels, ex:
// li
// li.seperator
// li.label1
// li.broccoli
// ...
for (var i = 2; i < lis.length; i++) {
// We bind the event handlers if we need to
if (lis[i].menuCallback == null) {
lis[i].menuCallback = onMenuLabelFlag;
lis[i].on("mousedown", onMenuClickHandler);
lis[i].removeClassName("disabled");
}
var flag = lis[i].readAttribute("data-name");
if (flags[flag]) {
isFlagged = true;
lis[i].addClassName("_chosen");
}
else {
lis[i].removeClassName("_chosen");
}
else
lis[1 + i].removeClassName("_chosen");
}
if (isFlagged)
lis[0].removeClassName("_chosen");
else
@ -2834,12 +2835,9 @@ function getMenus() {
onMenuChangeToDraftsFolder,
onMenuChangeToTrashFolder ],
"label-menu": [ onMenuLabelNone, "-", onMenuLabelFlag1,
onMenuLabelFlag2, onMenuLabelFlag3,
onMenuLabelFlag4, onMenuLabelFlag5 ],
"label-menu": [ onMenuLabelNone, "-" ],
"mark-menu": [ onMenuToggleMessageRead, null, null, null, "-", onMenuToggleMessageFlag ],
// , "-",
// null, null, null ],
searchMenu: [ setSearchCriteria, setSearchCriteria,
setSearchCriteria, setSearchCriteria,

View File

@ -1,11 +1,13 @@
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
var type;
function onLoadColorPicker(event) {
showColorPicker();
}
function onChooseColor(newColor) {
window.opener.onColorPickerChoice(newColor);
window.opener.onColorPickerChoice(newColor, type);
window.close();
}

View File

@ -90,9 +90,10 @@ function setupConstants() {
"flagged": _("Flagged"),
"junk": _("Junk"),
"not_junk": _("Not Junk") };
for (var i = 1; i < 6; i++) {
var key = "label" + i;
flagLabels[key] = _("Label " + i);
for (var name in labels) {
flagLabels[name] = _( labels[name][0] );
}
}

View File

@ -17,6 +17,10 @@ function savePreferences(sender) {
serializeContactsCategories();
}
if ($("mailLabelsListWrapper")) {
serializeMailLabels();
}
if (typeof mailCustomFromEnabled !== "undefined" && !emailRE.test($("email").value)) {
showAlertDialog(_("Please specify a valid sender address."));
sendForm = false;
@ -182,6 +186,7 @@ function initPreferences() {
if (typeof (initAdditionalPreferences) != "undefined")
initAdditionalPreferences();
// Calender categories
var wrapper = $("calendarCategoriesListWrapper");
if (wrapper) {
var table = wrapper.childNodesWithTag("table")[0];
@ -195,6 +200,22 @@ function initPreferences() {
$("calendarCategoryDelete").observe("click", onCalendarCategoryDelete);
}
// Mail labels/tags
var wrapper = $("mailLabelsListWrapper");
if (wrapper) {
var table = wrapper.childNodesWithTag("table")[0];
resetMailLabelsColors(null);
var r = $$("#mailLabelsListWrapper tbody tr");
for (var i= 0; i < r.length; i++)
r[i].identify();
table.multiselect = true;
resetMailTableActions();
$("mailLabelAdd").observe("click", onMailLabelAdd);
$("mailLabelDelete").observe("click", onMailLabelDelete);
}
// Contact categories
wrapper = $("contactsCategoriesListWrapper");
if (wrapper) {
var table = wrapper.childNodesWithTag("table")[0];
@ -855,21 +876,15 @@ function compactMailAccounts() {
}
}
/* calendar categories */
function resetCalendarTableActions() {
var r = $$("#calendarCategoriesListWrapper tbody tr");
for (var i = 0; i < r.length; i++) {
var row = $(r[i]);
row.observe("mousedown", onRowClick);
var tds = row.childElements();
var editionCtlr = new RowEditionController();
editionCtlr.attachToRowElement(tds[0]);
tds[1].childElements()[0].observe("dblclick", onColorEdit);
}
}
/* common function between calendar categories and mail labels */
function onColorEdit (e, type) {
var r;
function onColorEdit (e) {
var r = $$("#calendarCategoriesListWrapper div.colorEditing");
if (type == "calendar")
r = $$("#calendarCategoriesListWrapper div.colorEditing");
else
r = $$("#mailLabelsListWrapper div.colorEditing");
for (var i=0; i<r.length; i++)
r[i].removeClassName("colorEditing");
@ -881,12 +896,19 @@ function onColorEdit (e) {
+ "menubar=0,copyhistory=0", "test"
);
cPicker.focus();
cPicker.type = type;
preventDefault(e);
}
function onColorPickerChoice (newColor) {
var div = $$("#calendarCategoriesListWrapper div.colorEditing").first ();
function onColorPickerChoice (newColor, type) {
var div;
if (type == "calendar")
div = $$("#calendarCategoriesListWrapper div.colorEditing").first ();
else
div = $$("#mailLabelsListWrapper div.colorEditing").first ();
// div.removeClassName ("colorEditing");
div.showColor = newColor;
div.style.background = newColor;
@ -895,6 +917,26 @@ function onColorPickerChoice (newColor) {
hasChanged.value = "1";
}
}
/* /common function between calendar categories and mail labels */
/* calendar categories */
function resetCalendarTableActions() {
var r = $$("#calendarCategoriesListWrapper tbody tr");
for (var i = 0; i < r.length; i++) {
var row = $(r[i]);
row.observe("mousedown", onRowClick);
var tds = row.childElements();
var editionCtlr = new RowEditionController();
editionCtlr.attachToRowElement(tds[0]);
tds[1].childElements()[0].observe("dblclick", onCalendarColorEdit);
}
}
function onCalendarColorEdit (e) {
var onCCE = onColorEdit.bind(this);
onCCE(e, "calendar");
}
function onCalendarCategoryAdd (e) {
var row = new Element ("tr");
@ -959,6 +1001,95 @@ function resetCalendarCategoriesColors (e) {
/* /calendar categories */
/* mail label/tags */
function resetMailTableActions() {
var r = $$("#mailLabelsListWrapper tbody tr");
for (var i = 0; i < r.length; i++) {
var row = $(r[i]);
row.observe("mousedown", onRowClick);
var tds = row.childElements();
var editionCtlr = new RowEditionController();
editionCtlr.attachToRowElement(tds[0]);
tds[1].childElements()[0].observe("dblclick", onMailColorEdit);
}
}
function onMailColorEdit (e) {
var onMCE = onColorEdit.bind(this);
onMCE(e, "mail");
}
function onMailLabelAdd (e) {
var row = new Element ("tr");
var nametd = new Element ("td").update ("");
var colortd = new Element ("td");
var colordiv = new Element ("div", {"class": "colorBox"});
row.identify ();
row.addClassName ("labelListRow");
nametd.addClassName ("labelListCell");
colortd.addClassName ("labelListCell");
colordiv.innerHTML = "&nbsp;";
colordiv.showColor = "#F0F0F0";
colordiv.style.background = colordiv.showColor;
colortd.appendChild (colordiv);
row.appendChild (nametd);
row.appendChild (colortd);
$("mailLabelsListWrapper").childNodesWithTag("table")[0].tBodies[0].appendChild (row);
resetMailTableActions ();
nametd.editionController.startEditing();
}
function onMailLabelDelete (e) {
var list = $('mailLabelsListWrapper').down("TABLE").down("TBODY");
var rows = list.getSelectedNodes();
var count = rows.length;
for (var i=0; i < count; i++) {
rows[i].editionController = null;
rows[i].remove ();
}
}
function resetMailLabelsColors (e) {
var divs = $$("#mailLabelsListWrapper DIV.colorBox");
for (var i = 0; i < divs.length; i++) {
var d = divs[i];
var color = d.innerHTML;
d.showColor = color;
if (color != "undefined")
d.setStyle({ backgroundColor: color });
d.update("&nbsp;");
}
}
function serializeMailLabels() {
var r = $$("#mailLabelsListWrapper TBODY TR");
var values = [];
for (var i = 0; i < r.length; i++) {
var tds = r[i].childElements ();
var name = r[i].readAttribute("data-name");
var label = $(tds.first ()).innerHTML;
var color = $(tds.last ().childElements ().first ()).showColor;
/* if name is null, that's because we've just added a new tag */
if (!name) {
name = label.replace(/ /g,"_");
}
values.push("\"" + name + "\": [\"" + label + "\", \"" + color + "\"]");
}
$("mailLabelsValue").value = "{ " + values.join(",\n") + "}";
}
/* /mail label/tags */
/* contacts categories */
function resetContactsTableActions() {
var r = $$("#contactsCategoriesListWrapper tbody tr");