Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dd4d870e0 |
No files matched your search
@@ -7,7 +7,6 @@ Bug fixes
|
||||
- Fixed several sync issues on environments with multiple users (Zentyal)
|
||||
- Folders from other users will no longer appear on your Outlook (Zentyal)
|
||||
- Use right auth in multidomain environments in contacts and calendar from Outlook (Zentyal)
|
||||
- Session fix when SOGoEnableDomainBasedUID is enabled but logins are domain-less
|
||||
|
||||
2.3.1 (2015-07-23)
|
||||
------------------
|
||||
|
||||
@@ -1493,9 +1493,8 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent
|
||||
// the database. We do this ONLY when using SOGo from the
|
||||
// Web interface or over ActiveSync.
|
||||
// Over DAV, it'll be handled directly in PUTAction:
|
||||
if (![context request] ||
|
||||
[[context request] handledByDefaultHandler] ||
|
||||
[[[context request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
|
||||
if (![context request] || [[context request] handledByDefaultHandler]
|
||||
|| [[[context request] requestHandlerKey] isEqualToString: @"Microsoft-Server-ActiveSync"])
|
||||
{
|
||||
// If an alarm was specified, let's use it. This would happen if an attendee accepts/declines/etc. an
|
||||
// event invitation and also sets an alarm along the way. This would happen ONLY from the web interface.
|
||||
|
||||
@@ -84,30 +84,17 @@
|
||||
*/
|
||||
- (NSDictionary *) attributesInContext: (WOContext *) context
|
||||
{
|
||||
NSArray *allEvents, *rules;
|
||||
NSArray *rules;
|
||||
NSCalendarDate *untilDate;
|
||||
NSMutableDictionary *data, *repeat;
|
||||
NSString *frequency;
|
||||
NSTimeZone *timeZone;
|
||||
SOGoUserDefaults *ud;
|
||||
iCalEvent *masterComponent;
|
||||
iCalRecurrenceRule *rule;
|
||||
|
||||
data = [NSMutableDictionary dictionaryWithDictionary: [super attributesInContext: context]];
|
||||
|
||||
if ([self recurrenceId])
|
||||
{
|
||||
// If the component is an occurrence of a recurrent component,
|
||||
// consider the recurrence rules of the master component.
|
||||
allEvents = [[self parent] events];
|
||||
masterComponent = [allEvents objectAtIndex: 0];
|
||||
rules = [masterComponent recurrenceRules];
|
||||
}
|
||||
else
|
||||
{
|
||||
rules = [self recurrenceRules];
|
||||
}
|
||||
|
||||
rules = [self recurrenceRules];
|
||||
if ([rules count] > 0)
|
||||
{
|
||||
rule = [rules objectAtIndex: 0];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* NGVCard+SOGo.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009-2015 Inverse inc.
|
||||
* Copyright (C) 2009-2014 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,10 +31,6 @@
|
||||
- (CardElement *) elementWithTag: (NSString *) elementTag
|
||||
ofType: (NSString *) type;
|
||||
|
||||
- (void) addElementWithTag: (NSString *) elementTag
|
||||
ofType: (NSString *) type
|
||||
withValue: (id) value;
|
||||
|
||||
- (void) updateFromLDIFRecord: (NSDictionary *) ldifRecord;
|
||||
- (NSMutableDictionary *) asLDIFRecord;
|
||||
|
||||
|
||||
@@ -188,8 +188,8 @@ convention:
|
||||
}
|
||||
|
||||
- (void) addElementWithTag: (NSString *) elementTag
|
||||
ofType: (NSString *) type
|
||||
withValue: (id) value
|
||||
ofType: (NSString *) type
|
||||
withValue: (id) value
|
||||
{
|
||||
NSArray *allValues;
|
||||
NSEnumerator *list;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2006-2015 Inverse inc.
|
||||
Copyright (C) 2006-2014 Inverse inc.
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
@@ -31,13 +32,9 @@
|
||||
@class NSString;
|
||||
|
||||
@interface SOGoContactGCSFolder : SOGoGCSFolder <SOGoContactFolder>
|
||||
{
|
||||
NSString *baseCardDAVURL, *basePublicCardDAVURL;
|
||||
}
|
||||
|
||||
- (void) fixupContactRecord: (NSMutableDictionary *) contactRecord;
|
||||
- (NSDictionary *) lookupContactWithName: (NSString *) aName;
|
||||
- (NSString *) cardDavURL;
|
||||
- (NSString *) publicCardDavURL;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (C) 2006-2013-2015 Inverse inc.
|
||||
Copyright (C) 2006-2013 Inverse inc.
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
@@ -66,24 +67,6 @@ static NSArray *folderListingFields = nil;
|
||||
@"c_component", nil];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
baseCardDAVURL = nil;
|
||||
basePublicCardDAVURL = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[baseCardDAVURL release];
|
||||
[basePublicCardDAVURL release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (Class) objectClassForContent: (NSString *) content
|
||||
{
|
||||
CardGroup *cardEntry;
|
||||
@@ -453,48 +436,4 @@ static NSArray *folderListingFields = nil;
|
||||
return [NSString stringWithFormat: @"%@:%@", nsRep, nodeName];
|
||||
}
|
||||
|
||||
- (NSString *) _baseCardDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!baseCardDAVURL)
|
||||
{
|
||||
davURL = [[self realDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
baseCardDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
baseCardDAVURL = davURL;
|
||||
[baseCardDAVURL retain];
|
||||
}
|
||||
|
||||
return baseCardDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) cardDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _baseCardDAVURL]];
|
||||
}
|
||||
|
||||
- (NSString *) _basePublicCardDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!basePublicCardDAVURL)
|
||||
{
|
||||
davURL = [[self publicDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
basePublicCardDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
basePublicCardDAVURL = davURL;
|
||||
[basePublicCardDAVURL retain];
|
||||
}
|
||||
|
||||
return basePublicCardDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) publicCardDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _basePublicCardDAVURL]];
|
||||
}
|
||||
|
||||
@end /* SOGoContactGCSFolder */
|
||||
@@ -1,6 +1,8 @@
|
||||
/* NSArray+Utilities.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2006-2015 Inverse inc.
|
||||
* Copyright (C) 2006 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* NSArray+Utilities.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2006-2015 Inverse inc.
|
||||
* Copyright (C) 2006-2011 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* NSObject+Utilities.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2007-2015 Inverse inc.
|
||||
* Copyright (C) 2007 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* NSObject+Utilities.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2007-2015 Inverse inc.
|
||||
* Copyright (C) 2007 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -778,10 +778,7 @@ static Class NSNullK;
|
||||
NSRange r;
|
||||
|
||||
r = [theUID rangeOfString: [NSString stringWithFormat: @"@%@", theDomain]];
|
||||
|
||||
// We check if the range is ok here since we could be using DomainLessLogin
|
||||
if (r.location != NSNotFound)
|
||||
theUID = [theUID substringToIndex: r.location];
|
||||
theUID = [theUID substringToIndex: r.location];
|
||||
}
|
||||
|
||||
sogoSources = [[self authenticationSourceIDsInDomain: theDomain] objectEnumerator];
|
||||
|
||||
@@ -70,11 +70,7 @@ class Carddav:
|
||||
if not self.cards:
|
||||
url = "/SOGo/so/%s/Contacts/personal/view" % (self.login)
|
||||
content = self._get(url)
|
||||
#print "\nCONTENT:", content
|
||||
if 'cards' in content:
|
||||
self.cards = content['cards']
|
||||
else:
|
||||
self.cards = []
|
||||
self.cards = content['cards']
|
||||
return self.cards
|
||||
|
||||
def get_cards(self, pattern):
|
||||
|
||||
@@ -89,9 +89,9 @@ class preferences:
|
||||
get = HTTPPreferencesGET(url)
|
||||
get.cookie = self.cookie
|
||||
self.client.execute(get)
|
||||
if DEBUG: print "DEBUG (url):", url
|
||||
if DEBUG: print "DEBUG (status):", get.response["status"]
|
||||
if DEBUG: print "DEBUG (body):", get.response['body']
|
||||
if DEBUG: print "LUC (url):", url
|
||||
if DEBUG: print "LUC (status):", get.response["status"]
|
||||
if DEBUG: print "LUC (body):", get.response['body']
|
||||
content = simplejson.loads(get.response['body'])
|
||||
result = None
|
||||
try:
|
||||
@@ -117,7 +117,7 @@ class preferences:
|
||||
# Get the right sub-dict and change the key/value
|
||||
subdict = self.find_key(self.preferences, preference)
|
||||
if not subdict:
|
||||
raise AttributeError("ERROR(nosubdict): looking for %s in: %s" %(preference, str(self.preferences)))
|
||||
print "LUC(nosubdict):", preference, self.preferences
|
||||
subdict[preference] = value
|
||||
|
||||
def set(self, preference, value=None):
|
||||
|
||||
@@ -85,13 +85,6 @@ class JsonDavPhoneTests(unittest.TestCase):
|
||||
self.allphones = list(self.newphone)
|
||||
self.allphones.extend(self.newphones_difftype)
|
||||
self.allphones.extend(self.newphones_sametype)
|
||||
#- In case there are no cards for this user
|
||||
try:
|
||||
self._get_card()
|
||||
except IndexError:
|
||||
path = 'Contacts/personal'
|
||||
(card, path, gid) = self._create_new_card(path)
|
||||
self._save_card(card)
|
||||
|
||||
def tearDown(self):
|
||||
self._connect_as_user()
|
||||
@@ -109,23 +102,6 @@ class JsonDavPhoneTests(unittest.TestCase):
|
||||
def _connect_as_user(self, newuser=username, newpassword=password):
|
||||
self.dv = carddav.Carddav(newuser, newpassword)
|
||||
|
||||
def _create_new_card(self, path):
|
||||
gid = self.dv.newguid(path)
|
||||
card = {'c_categories': None,
|
||||
'c_cn': 'John Doe',
|
||||
'c_component': 'vcard',
|
||||
'c_givenname': 'John Doe',
|
||||
'c_mail': 'johndoe@nothere.com',
|
||||
'c_name': gid,
|
||||
'c_o': '',
|
||||
'c_screenname': '',
|
||||
'c_sn': '',
|
||||
'c_telephonenumber': '123.456.7890',
|
||||
'emails': [{'type': 'pref', 'value': 'johndoe@nothere.com'}],
|
||||
'phones': [{'type': 'home', 'value': '111.222.3333'}],
|
||||
'id': gid}
|
||||
return (card, path, gid)
|
||||
|
||||
def _get_card(self, name="John Doe"):
|
||||
tmp_card = self.dv.get_cards(name)[0]
|
||||
self.card = self.dv.get_card(tmp_card['c_name'])
|
||||
|
||||
@@ -28,14 +28,12 @@ class preventInvitationsTest(unittest.TestCase):
|
||||
self.caldav = CalDAVSchedulingTest(self)
|
||||
cal = self.prefs.get("Calendar")
|
||||
if "PreventInvitationsWhitelist" not in cal:
|
||||
#print "LUC (cal):", cal
|
||||
cal["PreventInvitationsWhitelist"] = None
|
||||
self.prefs.set("PreventInvitationsWhitelist", None)
|
||||
if "PreventInvitations" not in cal:
|
||||
cal["PreventInvitations"] = 0
|
||||
self.prefs.set("PreventInvitations", 0)
|
||||
|
||||
def tearDown(self):
|
||||
#self.prefs.set("autoReplyText", "")
|
||||
self.prefs.set("autoReplyText", "")
|
||||
self.prefs.set('PreventInvitations', 0)
|
||||
self.prefs.set("PreventInvitationsWhitelist", None)
|
||||
#- Manual Cleanup, not called because classs is not derived from unittest
|
||||
|
||||
@@ -21,8 +21,8 @@ class UIPostsTests(unittest.TestCase):
|
||||
self.cookie = sogoLogin.getAuthCookie(hostname, port, username, password)
|
||||
|
||||
def _urlPostData(self, client, url, data, exp_status=200):
|
||||
post = webdavlib.HTTPPOST(url, simplejson.dumps(data))
|
||||
post.content_type = "application/json"
|
||||
post = webdavlib.HTTPPOST(url, data)
|
||||
post.content_type = "application/x-www-form-urlencoded"
|
||||
post.cookie = self.cookie
|
||||
|
||||
client.execute(post)
|
||||
@@ -43,14 +43,16 @@ class UIPostsTests(unittest.TestCase):
|
||||
""" Add Web Calendar """
|
||||
|
||||
ret=True
|
||||
data = {"url":"%s" % webCalendarURL}
|
||||
data = "url=%s" % webCalendarURL
|
||||
calendarBaseURL="/SOGo/so/%s/Calendar" % username
|
||||
addWebCalendarURL = "%s/addWebCalendar" % calendarBaseURL
|
||||
response = self._urlPostData(self.client, addWebCalendarURL, data)
|
||||
|
||||
respJSON = simplejson.loads(response['body'])
|
||||
calID = respJSON['id']
|
||||
folderID = respJSON['folderID']
|
||||
|
||||
#sogo1:Calendar/C07-5006F300-1-370E2480
|
||||
(_, calID) = folderID.split('/', 1)
|
||||
self.assertNotEqual(calID, None)
|
||||
|
||||
# reload the cal
|
||||
|
||||
@@ -408,17 +408,16 @@
|
||||
|
||||
- (id <WOActionResults>) copyAction
|
||||
{
|
||||
WORequest *request;
|
||||
id <WOActionResults> response;
|
||||
NSString *destinationFolderId;
|
||||
NSArray *contactsId;
|
||||
NSDictionary *data;
|
||||
NSException *ex;
|
||||
|
||||
data = [[[context request] contentAsString] objectFromJSONString];
|
||||
contactsId = [data objectForKey: @"uids"];
|
||||
destinationFolderId = [data objectForKey: @"folder"];
|
||||
request = [context request];
|
||||
|
||||
if (destinationFolderId && [contactsId count])
|
||||
if ((destinationFolderId = [request formValueForKey: @"folder"]) &&
|
||||
(contactsId = [request formValuesForKey: @"uid"]))
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
andKeepCopy: YES];
|
||||
@@ -437,17 +436,16 @@
|
||||
|
||||
- (id <WOActionResults>) moveAction
|
||||
{
|
||||
WORequest *request;
|
||||
id <WOActionResults> response;
|
||||
NSString *destinationFolderId;
|
||||
NSDictionary *data;
|
||||
NSArray *contactsId;
|
||||
NSException *ex;
|
||||
|
||||
data = [[[context request] contentAsString] objectFromJSONString];
|
||||
contactsId = [data objectForKey: @"uids"];
|
||||
destinationFolderId = [data objectForKey: @"folder"];
|
||||
request = [context request];
|
||||
|
||||
if (destinationFolderId && [contactsId count])
|
||||
if ((destinationFolderId = [request formValueForKey: @"folder"])
|
||||
&& (contactsId = [request formValuesForKey: @"uid"]))
|
||||
ex = [self _moveContacts: contactsId
|
||||
toFolder: destinationFolderId
|
||||
andKeepCopy: NO];
|
||||
|
||||
@@ -440,6 +440,40 @@
|
||||
return ([[self productCSSURL] length] > 0);
|
||||
}
|
||||
|
||||
- (BOOL) _moduleIs: (NSString *) moduleName
|
||||
{
|
||||
NSString *frameworkName;
|
||||
|
||||
frameworkName = [[context page] frameworkName];
|
||||
|
||||
return [frameworkName isEqualToString: moduleName];
|
||||
}
|
||||
|
||||
- (BOOL) isCalendar
|
||||
{
|
||||
return [self _moduleIs: @"SchedulerUI"];
|
||||
}
|
||||
|
||||
- (BOOL) isContacts
|
||||
{
|
||||
return [self _moduleIs: @"ContactsUI"];
|
||||
}
|
||||
|
||||
- (BOOL) isMail
|
||||
{
|
||||
return [self _moduleIs: @"MailerUI"];
|
||||
}
|
||||
|
||||
- (BOOL) isPreferences
|
||||
{
|
||||
return [self _moduleIs: @"PreferencesUI"];
|
||||
}
|
||||
|
||||
- (BOOL) isAdministration
|
||||
{
|
||||
return [self _moduleIs: @"AdministrationUI"];
|
||||
}
|
||||
|
||||
- (void) setToolbar: (NSString *) newToolbar
|
||||
{
|
||||
ASSIGN (toolbar, newToolbar);
|
||||
@@ -475,12 +509,6 @@
|
||||
return [[context activeUser] cn];
|
||||
}
|
||||
|
||||
- (NSString *) userEmail
|
||||
{
|
||||
return [[context activeUser] systemEmail];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) canLogoff
|
||||
{
|
||||
BOOL canLogoff;
|
||||
|
||||
@@ -43,12 +43,6 @@
|
||||
"Copy To" = "Copy To";
|
||||
"Add to:" = "Add to:";
|
||||
|
||||
/* Number of selected contacts in list */
|
||||
"selected" = "selected";
|
||||
|
||||
/* Empty right pane */
|
||||
"No contact selected" = "No contact selected";
|
||||
|
||||
/* Tooltips */
|
||||
|
||||
"Create a new address book card" = "Create a new address book card";
|
||||
|
||||
@@ -367,8 +367,6 @@ static Class SOGoContactGCSEntryK = Nil;
|
||||
day = [date dayOfMonth];
|
||||
[card setBday: [NSString stringWithFormat: @"%.4d%.2d%.2d", year, month, day]];
|
||||
}
|
||||
else
|
||||
[card setBday: nil];
|
||||
|
||||
if ([[attributes objectForKey: @"addresses"] isKindOfClass: [NSArray class]])
|
||||
{
|
||||
@@ -432,9 +430,8 @@ static Class SOGoContactGCSEntryK = Nil;
|
||||
{
|
||||
if ([attrs isKindOfClass: [NSDictionary class]])
|
||||
{
|
||||
[card addElementWithTag: @"tel"
|
||||
ofType: [attrs objectForKey: @"type"]
|
||||
withValue: [attrs objectForKey: @"value"]];
|
||||
element = [card elementWithTag: @"tel" ofType: [attrs objectForKey: @"type"]];
|
||||
[element setSingleValue: [attrs objectForKey: @"value"] forKey: @""];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,9 +448,8 @@ static Class SOGoContactGCSEntryK = Nil;
|
||||
{
|
||||
if ([o isKindOfClass: [NSDictionary class]])
|
||||
{
|
||||
[card addElementWithTag: @"email"
|
||||
ofType: [o objectForKey: @"type"]
|
||||
withValue: [o objectForKey: @"value"]];
|
||||
element = [card elementWithTag: @"email" ofType: [o objectForKey: @"type"]];
|
||||
[element setSingleValue: [o objectForKey: @"value"] forKey: @""];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,9 +466,8 @@ static Class SOGoContactGCSEntryK = Nil;
|
||||
{
|
||||
if ([attrs isKindOfClass: [NSDictionary class]])
|
||||
{
|
||||
[card addElementWithTag: @"url"
|
||||
ofType: [attrs objectForKey: @"type"]
|
||||
withValue: [attrs objectForKey: @"value"]];
|
||||
element = [card elementWithTag: @"url" ofType: [attrs objectForKey: @"type"]];
|
||||
[element setSingleValue: [attrs objectForKey: @"value"] forKey: @""];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +112,15 @@
|
||||
|
||||
request = [context request];
|
||||
rc = [NSMutableDictionary dictionary];
|
||||
data = [[[[[request httpRequest] body] parts] lastObject] body];
|
||||
|
||||
fileContent = [[NSString alloc] initWithData: (NSData *) data
|
||||
encoding: NSUTF8StringEncoding];
|
||||
[fileContent autorelease];
|
||||
data = [request formValueForKey: @"contactsFile"];
|
||||
if ([data respondsToSelector: @selector(isEqualToString:)])
|
||||
fileContent = (NSString *) data;
|
||||
else
|
||||
{
|
||||
fileContent = [[NSString alloc] initWithData: (NSData *) data
|
||||
encoding: NSUTF8StringEncoding];
|
||||
[fileContent autorelease];
|
||||
}
|
||||
|
||||
if (fileContent && [fileContent length])
|
||||
{
|
||||
@@ -128,10 +132,12 @@
|
||||
imported = 0;
|
||||
}
|
||||
|
||||
[rc setObject: [NSNumber numberWithInt: imported] forKey: @"imported"];
|
||||
[rc setObject: [NSNumber numberWithInt: imported]
|
||||
forKey: @"imported"];
|
||||
|
||||
response = [self responseWithStatus: 200];
|
||||
[response setHeader: @"text/html" forKey: @"content-type"];
|
||||
[response setHeader: @"text/html"
|
||||
forKey: @"content-type"];
|
||||
[(WOResponse*)response appendContentString: [rc jsonRepresentation]];
|
||||
|
||||
return response;
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@class SOGoContactGCSFolder;
|
||||
|
||||
@interface UIxContactFolderLinksTemplate : UIxComponent
|
||||
{
|
||||
SOGoContactGCSFolder *addressBook;
|
||||
NSString *baseCardDAVURL, *basePublicCardDAVURL;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -24,6 +24,69 @@
|
||||
|
||||
@implementation UIxContactFolderLinksTemplate
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
addressBook = [self clientObject];
|
||||
baseCardDAVURL = nil;
|
||||
basePublicCardDAVURL = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[baseCardDAVURL release];
|
||||
[basePublicCardDAVURL release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) _baseCardDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!baseCardDAVURL)
|
||||
{
|
||||
davURL = [[addressBook realDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
baseCardDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
baseCardDAVURL = davURL;
|
||||
[baseCardDAVURL retain];
|
||||
}
|
||||
|
||||
return baseCardDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) cardDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _baseCardDAVURL]];
|
||||
}
|
||||
|
||||
- (NSString *) _basePublicCardDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!basePublicCardDAVURL)
|
||||
{
|
||||
davURL = [[addressBook publicDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
basePublicCardDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
basePublicCardDAVURL = davURL;
|
||||
[basePublicCardDAVURL retain];
|
||||
}
|
||||
|
||||
return basePublicCardDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) publicCardDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _basePublicCardDAVURL]];
|
||||
}
|
||||
|
||||
- (BOOL) isPublicAccessEnabled
|
||||
{
|
||||
// NOTE: This method is the same found in Common/UIxAclEditor.m
|
||||
|
||||
@@ -275,70 +275,32 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
|
||||
return [[self queryParameterForKey: @"popup"] boolValue];
|
||||
}
|
||||
|
||||
- (BOOL) isPublicAccessEnabled
|
||||
{
|
||||
// NOTE: This method is the same found in Common/UIxAclEditor.m
|
||||
return [[SOGoSystemDefaults sharedSystemDefaults] enablePublicAccess];
|
||||
}
|
||||
|
||||
- (NSString *) contactFolders
|
||||
{
|
||||
SOGoContactFolders *folderContainer;
|
||||
NSMutableDictionary *urls, *acls;
|
||||
NSArray *folders;
|
||||
NSMutableArray *foldersAttrs;
|
||||
NSString *userLogin, *owner;
|
||||
NSArray *folders, *allACLs;
|
||||
NSDictionary *folderAttrs;
|
||||
id currentFolder;
|
||||
|
||||
BOOL objectCreator, objectEditor, objectEraser;
|
||||
int max, i;
|
||||
|
||||
userLogin = [[context activeUser] login];
|
||||
folderContainer = [self clientObject];
|
||||
folders = [folderContainer subFolders];
|
||||
|
||||
// return [folderContainer subFolders];
|
||||
|
||||
folders = [folderContainer subFolders];
|
||||
max = [folders count];
|
||||
foldersAttrs = [NSMutableArray arrayWithCapacity: max];
|
||||
urls = nil;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
currentFolder = [folders objectAtIndex: i];
|
||||
owner = [currentFolder ownerInContext: context];
|
||||
|
||||
// We extract URLs for this address book
|
||||
if ([currentFolder respondsToSelector: @selector(cardDavURL)])
|
||||
{
|
||||
urls = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||
[currentFolder cardDavURL], @"cardDavURL",
|
||||
nil];
|
||||
if ([self isPublicAccessEnabled])
|
||||
{
|
||||
[urls setObject: [currentFolder publicCardDavURL] forKey: @"publicCardDavURL"];
|
||||
}
|
||||
}
|
||||
|
||||
// We extract ACLs for this address book
|
||||
allACLs = ([owner isEqualToString: userLogin] ? nil : [currentFolder aclsForUser: userLogin]);
|
||||
objectCreator = ([owner isEqualToString: userLogin] || [allACLs containsObject: SOGoRole_ObjectCreator]);
|
||||
objectEditor = ([owner isEqualToString: userLogin] || [allACLs containsObject: SOGoRole_ObjectEditor]);
|
||||
objectEraser = ([owner isEqualToString: userLogin] || [allACLs containsObject: SOGoRole_ObjectEraser]);
|
||||
acls = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: objectCreator], @"objectCreator",
|
||||
[NSNumber numberWithBool: objectEditor], @"objectEditor",
|
||||
[NSNumber numberWithBool: objectEraser], @"objectEraser", nil];
|
||||
|
||||
// NOTE: keep urls as the last key/value here, to avoid chopping the dictionary
|
||||
// if it is not a GCS folder
|
||||
folderAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
[NSString stringWithFormat: @"%@", [currentFolder nameInContainer]], @"id",
|
||||
[currentFolder displayName], @"name",
|
||||
owner, @"owner",
|
||||
[currentFolder ownerInContext: context], @"owner",
|
||||
[NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoGCSFolderK]], @"isEditable",
|
||||
[NSNumber numberWithBool: [currentFolder isKindOfClass: SOGoContactSourceFolderK]
|
||||
&& ![currentFolder isPersonalSource]], @"isRemote",
|
||||
acls, @"acls",
|
||||
urls, @"urls",
|
||||
nil];
|
||||
[foldersAttrs addObject: folderAttrs];
|
||||
}
|
||||
@@ -457,6 +419,12 @@ Class SOGoContactSourceFolderK, SOGoGCSFolderK;
|
||||
return [super defaultAction];
|
||||
}
|
||||
|
||||
- (BOOL) isPublicAccessEnabled
|
||||
{
|
||||
// NOTE: This method is the same found in Common/UIxAclEditor.m
|
||||
return [[SOGoSystemDefaults sharedSystemDefaults] enablePublicAccess];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface UIxContactViewTemplate : UIxComponent
|
||||
|
||||
@@ -838,10 +838,11 @@
|
||||
o = [card birthday];
|
||||
if (o)
|
||||
{
|
||||
[data setObject: [NSNumber numberWithInt: [o timeIntervalSince1970]]
|
||||
forKey: @"birthday"];
|
||||
NSNumber *time = [NSNumber numberWithInt: [o timeIntervalSince1970]];
|
||||
[data setObject: time forKey: @"birthday"];
|
||||
}
|
||||
|
||||
// o = [card source];
|
||||
// if (o) [data setObject: o forKey: @"source"];
|
||||
o = [card tz];
|
||||
if (o) [data setObject: o forKey: @"tz"];
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2006-2015 Inverse inc.
|
||||
Copyright (C) 2006-2014 Inverse inc.
|
||||
|
||||
This file is part of SOGo.
|
||||
|
||||
@@ -39,9 +39,6 @@
|
||||
#import <Contacts/SOGoContactFolder.h>
|
||||
#import <Contacts/SOGoContactFolders.h>
|
||||
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserSettings.h>
|
||||
|
||||
#import <NGCards/NGVCard.h>
|
||||
#import <NGCards/NGVList.h>
|
||||
#import <SoObjects/Contacts/SOGoContactGCSEntry.h>
|
||||
@@ -88,31 +85,6 @@
|
||||
return s;
|
||||
}
|
||||
|
||||
- (void) saveSortValue
|
||||
{
|
||||
NSMutableDictionary *contactSettings;
|
||||
NSString *ascending, *sort;
|
||||
SOGoUserSettings *us;
|
||||
|
||||
sort = [[context request] formValueForKey: @"sort"];
|
||||
ascending = [[context request] formValueForKey: @"asc"];
|
||||
|
||||
if ([sort length])
|
||||
{
|
||||
us = [[context activeUser] userSettings];
|
||||
contactSettings = [us objectForKey: @"Contact"];
|
||||
// Must create if it doesn't exist
|
||||
if (!contactSettings)
|
||||
{
|
||||
contactSettings = [NSMutableDictionary dictionary];
|
||||
[us setObject: contactSettings forKey: @"Contact"];
|
||||
}
|
||||
[contactSettings setObject: [NSArray arrayWithObjects: [sort lowercaseString], [NSString stringWithFormat: @"%d", [ascending intValue]], nil]
|
||||
forKey: @"SortingState"];
|
||||
[us synchronize];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) contactInfos
|
||||
{
|
||||
id <SOGoContactFolder> folder;
|
||||
@@ -125,8 +97,6 @@
|
||||
WORequest *rq;
|
||||
unsigned int i;
|
||||
|
||||
[self saveSortValue];
|
||||
|
||||
if (!contactInfos)
|
||||
{
|
||||
folder = [self clientObject];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* UIxMailPartTextViewer.h - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006-2015 Inverse inc.
|
||||
* Copyright (C) 2006 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* 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
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
/* UIxMailPartTextViewer.m - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006-2015 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
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of OpenGroupware.org.
|
||||
|
||||
OGo 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
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
UIxMailPartTextViewer
|
||||
|
||||
@@ -65,9 +65,6 @@
|
||||
"Account: " = "Account: ";
|
||||
"Shared Account: " = "Shared Account: ";
|
||||
|
||||
/* Empty right pane */
|
||||
"No message selected" = "No message selected";
|
||||
|
||||
/* acls */
|
||||
"Access rights to" = "Access rights to";
|
||||
"For user" = "For user";
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
errorFormat = [self labelForKey: @"The folder with name \"%@\" could not be created." inContext: context];
|
||||
errorFormat = [self labelForKey: @"The folder with name \"%@\" could not be created."];
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [NSString stringWithFormat: errorFormat, folderName]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
@@ -101,7 +101,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'name' parameter." inContext: context]
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'name' parameter."]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
andJSONRepresentation: jsonResponse];
|
||||
@@ -149,7 +149,7 @@
|
||||
|
||||
if (!newFolderName || [newFolderName length] == 0)
|
||||
{
|
||||
message = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing name parameter" inContext: context]
|
||||
message = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing name parameter"]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
andString: [message jsonRepresentation]];
|
||||
@@ -160,7 +160,7 @@
|
||||
error = [co renameTo: newFolderName];
|
||||
if (error)
|
||||
{
|
||||
message = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to rename folder." inContext: context]
|
||||
message = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to rename folder."]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
andString: [message jsonRepresentation]];
|
||||
@@ -251,7 +251,7 @@
|
||||
error = [connection moveMailboxAtURL: srcURL toURL: destURL];
|
||||
if (error)
|
||||
{
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder." inContext: context]
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder."]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
andString: [jsonResponse jsonRepresentation]];
|
||||
@@ -283,7 +283,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder." inContext: context]
|
||||
jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Unable to move folder."]
|
||||
forKey: @"error"];
|
||||
response = [self responseWithStatus: 500
|
||||
andString: [jsonResponse jsonRepresentation]];
|
||||
@@ -374,7 +374,7 @@
|
||||
{
|
||||
uids = [value componentsSeparatedByString: @","];
|
||||
response = [co archiveUIDs: uids
|
||||
inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
|
||||
inArchiveNamed: [self labelForKey: @"Saved Messages.zip"]
|
||||
inContext: context];
|
||||
if (!response)
|
||||
response = [self responseWith204];
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
#import <Mailer/SOGoSentFolder.h>
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/NSDictionary+Utilities.h>
|
||||
#import <SOGo/NSObject+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoDateFormatter.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
@@ -132,7 +131,7 @@
|
||||
else if ([now dayOfCommonEra] - [messageDate dayOfCommonEra] == 1)
|
||||
{
|
||||
// Yesterday
|
||||
return [self labelForKey: @"Yesterday" inContext: context];
|
||||
return [self labelForKey: @"Yesterday"];
|
||||
}
|
||||
else if ([now dayOfCommonEra] - [messageDate dayOfCommonEra] < 7)
|
||||
{
|
||||
@@ -191,10 +190,10 @@
|
||||
s = [[s substringFromIndex: r.location+1]
|
||||
stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
|
||||
if ([s hasPrefix: @"1"]) result = [self labelForKey: @"highest" inContext: context];
|
||||
else if ([s hasPrefix: @"2"]) result = [self labelForKey: @"high" inContext: context];
|
||||
else if ([s hasPrefix: @"4"]) result = [self labelForKey: @"low" inContext: context];
|
||||
else if ([s hasPrefix: @"5"]) result = [self labelForKey: @"lowest" inContext: context];
|
||||
if ([s hasPrefix: @"1"]) result = [self labelForKey: @"highest"];
|
||||
else if ([s hasPrefix: @"2"]) result = [self labelForKey: @"high"];
|
||||
else if ([s hasPrefix: @"4"]) result = [self labelForKey: @"low"];
|
||||
else if ([s hasPrefix: @"5"]) result = [self labelForKey: @"lowest"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +242,7 @@
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self labelForKey:@"View Mail Folder" inContext: context];
|
||||
s = [self labelForKey:@"View Mail Folder"];
|
||||
s = [s stringByAppendingString:@": "];
|
||||
s = [s stringByAppendingString:[self objectTitle]];
|
||||
return s;
|
||||
@@ -623,12 +622,11 @@
|
||||
- (NSDictionary *) getUIDsInFolder: (SOGoMailFolder *) folder
|
||||
withHeaders: (BOOL) includeHeaders
|
||||
{
|
||||
NSArray *uids, *threadedUids, *headers;
|
||||
NSMutableDictionary *data;
|
||||
NSArray *uids, *threadedUids, *headers;
|
||||
NSRange r;
|
||||
SOGoMailAccount *account;
|
||||
id quota;
|
||||
|
||||
NSRange r;
|
||||
int count;
|
||||
|
||||
data = [NSMutableDictionary dictionary];
|
||||
@@ -646,14 +644,10 @@
|
||||
if (includeHeaders)
|
||||
{
|
||||
// Also retrieve the first headers, up to 'headersPrefetchMaxSize'
|
||||
NSArray *a;
|
||||
|
||||
a = [uids flattenedArray];
|
||||
count = [a count];
|
||||
if (count > headersPrefetchMaxSize)
|
||||
count = headersPrefetchMaxSize;
|
||||
count = [[uids flattenedArray] count];
|
||||
if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize;
|
||||
r = NSMakeRange(0, count);
|
||||
headers = [self getHeadersForUIDs: [a subarrayWithRange: r]
|
||||
headers = [self getHeadersForUIDs: [[uids flattenedArray] subarrayWithRange: r]
|
||||
inFolder: folder];
|
||||
|
||||
[data setObject: headers forKey: @"headers"];
|
||||
@@ -750,6 +744,7 @@
|
||||
noHeaders = [[[requestContent objectForKey: @"sortingAttributes"] objectForKey:@"noHeaders"] boolValue];
|
||||
data = [self getUIDsInFolder: folder
|
||||
withHeaders: !noHeaders];
|
||||
|
||||
[response appendContentString: [data jsonRepresentation]];
|
||||
|
||||
return response;
|
||||
@@ -883,7 +878,7 @@
|
||||
data = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
@"No UID specified", @"error", nil];
|
||||
return [self responseWithStatus: 404 /* Not Found */
|
||||
andString: [data jsonRepresentation]];
|
||||
andString: [data jsonRepresentation]];
|
||||
}
|
||||
|
||||
uids = [data objectForKey: @"uids"];
|
||||
|
||||
@@ -118,18 +118,6 @@
|
||||
return [accounts jsonRepresentation];
|
||||
}
|
||||
|
||||
- (WOResponse *) mailAccountsAction
|
||||
{
|
||||
WOResponse *response;
|
||||
NSString *s;
|
||||
|
||||
s = [self mailAccounts];
|
||||
response = [self responseWithStatus: 200
|
||||
andString: s];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
- (NSString *) userNames
|
||||
{
|
||||
NSArray *accounts, *userNames;
|
||||
|
||||
@@ -342,11 +342,6 @@
|
||||
actionClass = "UIxMailMainFrame";
|
||||
actionName = "unseenCount";
|
||||
};
|
||||
mailAccounts = {
|
||||
protectedBy = "View";
|
||||
actionClass = "UIxMailMainFrame";
|
||||
actionName = "mailAccounts";
|
||||
};
|
||||
// viewerTemplate = {
|
||||
// protectedBy = "View";
|
||||
// pageName = "UIxMailViewTemplate";
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
"Connect" = "Connect";
|
||||
|
||||
"Authentication Failed" = "Authentication Failed";
|
||||
"Wrong username or password." = "Wrong username or password.";
|
||||
"cookiesNotEnabled" = "You cannot login because your browser's cookies are disabled. Please enable cookies in your browser's settings and try again.";
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@
|
||||
SOGoWebAuthenticator *auth;
|
||||
SOGoAppointmentFolders *calendars;
|
||||
SOGoUserDefaults *ud;
|
||||
SOGoSystemDefaults *sd;
|
||||
SOGoUser *loggedInUser;
|
||||
NSDictionary *params;
|
||||
NSString *username, *password, *language, *domain, *remoteHost;
|
||||
@@ -225,15 +226,13 @@
|
||||
|
||||
response = [self responseWithStatus: 200
|
||||
andJSONRepresentation: json];
|
||||
|
||||
// We get the proper username for cookie creation. If we are using a multidomain
|
||||
// environment with SOGoEnableDomainBasedUID, we could have to append the domain
|
||||
// to the username. Also when SOGoEnableDomainBasedUID is enabled, we could be in
|
||||
// the DomainLessLogin situation, so we would NOT add the domain. -getUIDForEmail
|
||||
// has all the logic for this, so lets use it.
|
||||
|
||||
if ([domain isNotNull])
|
||||
{
|
||||
username = [[SOGoUserManager sharedUserManager] getUIDForEmail: username];
|
||||
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||
if ([sd enableDomainBasedUID] &&
|
||||
[username rangeOfString: @"@"].location == NSNotFound)
|
||||
username = [NSString stringWithFormat: @"%@@%@", username, domain];
|
||||
}
|
||||
|
||||
authCookie = [auth cookieWithUsername: username
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* toolbar */
|
||||
"Save and Close" = "Save and Close";
|
||||
"Close" = "Close";
|
||||
"Preferences saved" = "Preferences saved";
|
||||
|
||||
/* tabs */
|
||||
"General" = "General";
|
||||
|
||||
@@ -61,8 +61,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
SOGoUserDefaults *defaults;
|
||||
NSMutableArray *accounts;
|
||||
NSArray *categoryLabels;
|
||||
NSDictionary *locale;
|
||||
|
||||
|
||||
if (!preferencesProduct)
|
||||
{
|
||||
preferencesProduct = [[SoProduct alloc] initWithBundle:
|
||||
@@ -79,7 +78,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoTimeZone"])
|
||||
[[defaults source] setObject: [defaults timeZoneName] forKey: @"SOGoTimeZone"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoShortDateFormat"])
|
||||
[[defaults source] setObject: [defaults shortDateFormat] forKey: @"SOGoShortDateFormat"];
|
||||
|
||||
@@ -91,7 +90,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoLoginModule"])
|
||||
[[defaults source] setObject: [defaults loginModule] forKey: @"SOGoLoginModule"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoRefreshViewCheck"])
|
||||
[[defaults source] setObject: [defaults refreshViewCheck] forKey: @"SOGoRefreshViewCheck"];
|
||||
|
||||
@@ -100,13 +99,13 @@ static SoProduct *preferencesProduct = nil;
|
||||
//
|
||||
if (![[defaults source] objectForKey: @"SOGoFirstDayOfWeek"])
|
||||
[[defaults source] setObject: [NSNumber numberWithInt: [defaults firstDayOfWeek]] forKey: @"SOGoFirstDayOfWeek"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoDayStartTime"])
|
||||
[[defaults source] setObject: [NSString stringWithFormat: @"%02d:00", [defaults dayStartHour]] forKey: @"SOGoDayStartTime"];
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoDayEndTime"])
|
||||
[[defaults source] setObject: [NSString stringWithFormat: @"%02d:00", [defaults dayEndHour]] forKey: @"SOGoDayEndTime"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoFirstWeekOfYear"])
|
||||
[[defaults source] setObject: [defaults firstWeekOfYear] forKey: @"SOGoFirstWeekOfYear"];
|
||||
|
||||
@@ -115,20 +114,20 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoCalendarEventsDefaultClassification"])
|
||||
[[defaults source] setObject: [defaults calendarEventsDefaultClassification] forKey: @"SOGoCalendarEventsDefaultClassification"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoCalendarTasksDefaultClassification"])
|
||||
[[defaults source] setObject: [defaults calendarTasksDefaultClassification] forKey: @"SOGoCalendarTasksDefaultClassification"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoCalendarDefaultReminder"])
|
||||
[[defaults source] setObject: [defaults calendarDefaultReminder] forKey: @"SOGoCalendarDefaultReminder"];
|
||||
|
||||
|
||||
// Populate default calendar categories, based on the user's preferred language
|
||||
if (![defaults calendarCategories])
|
||||
{
|
||||
categoryLabels = [[[self labelForKey: @"calendar_category_labels" withResourceManager: [preferencesProduct resourceManager]]
|
||||
componentsSeparatedByString: @","]
|
||||
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
|
||||
|
||||
|
||||
[defaults setCalendarCategories: categoryLabels];
|
||||
}
|
||||
if (![defaults calendarCategoriesColors])
|
||||
@@ -144,7 +143,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
[defaults setCalendarCategoriesColors: colors];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Default Contacts preferences
|
||||
//
|
||||
@@ -155,10 +154,10 @@ static SoProduct *preferencesProduct = nil;
|
||||
categoryLabels = [[[self labelForKey: @"contacts_category_labels" withResourceManager: [preferencesProduct resourceManager]]
|
||||
componentsSeparatedByString: @","]
|
||||
sortedArrayUsingSelector: @selector (localizedCaseInsensitiveCompare:)];
|
||||
|
||||
|
||||
if (!categoryLabels)
|
||||
categoryLabels = [NSArray array];
|
||||
|
||||
|
||||
[defaults setContactsCategories: categoryLabels];
|
||||
}
|
||||
|
||||
@@ -173,27 +172,27 @@ static SoProduct *preferencesProduct = nil;
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoMailReplyPlacement"])
|
||||
[[defaults source] setObject: [defaults mailReplyPlacement] forKey: @"SOGoMailReplyPlacement"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoMailSignaturePlacement"])
|
||||
[[defaults source] setObject: [defaults mailSignaturePlacement] forKey: @"SOGoMailSignaturePlacement"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoMailComposeMessageType"])
|
||||
[[defaults source] setObject: [defaults mailComposeMessageType] forKey: @"SOGoMailComposeMessageType"];
|
||||
|
||||
|
||||
if (![[defaults source] objectForKey: @"SOGoMailDisplayRemoteInlineImages"])
|
||||
[[defaults source] setObject: [defaults mailDisplayRemoteInlineImages] forKey: @"SOGoMailDisplayRemoteInlineImages"];
|
||||
|
||||
|
||||
// Populate default mail lablels, based on the user's preferred language
|
||||
if (![[defaults source] objectForKey: @"SOGoMailLabelsColors"])
|
||||
{
|
||||
SOGoMailLabel *label;
|
||||
NSArray *labels;
|
||||
id v;
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
v = [defaults mailLabelsColors];
|
||||
|
||||
|
||||
labels = [SOGoMailLabel labelsFromDefaults: v component: self];
|
||||
v = [NSMutableDictionary dictionary];
|
||||
for (i = 0; i < [labels count]; i++)
|
||||
@@ -202,7 +201,7 @@ static SoProduct *preferencesProduct = nil;
|
||||
[v setObject: [NSArray arrayWithObjects: [label label], [label color], nil]
|
||||
forKey: [label name]];
|
||||
}
|
||||
|
||||
|
||||
[defaults setMailLabelsColors: v];
|
||||
}
|
||||
|
||||
@@ -215,10 +214,6 @@ static SoProduct *preferencesProduct = nil;
|
||||
//
|
||||
values = [[[[defaults source] values] mutableCopy] autorelease];
|
||||
|
||||
// Add locale code (used by CK Editor)
|
||||
locale = [[preferencesProduct resourceManager] localeForLanguageNamed: [defaults language]];
|
||||
[values setObject: [locale objectForKey: @"NSLocaleCode"] forKey: @"LocaleCode"];
|
||||
|
||||
accounts = [NSMutableArray arrayWithArray: [values objectForKey: @"AuxiliaryMailAccounts"]];
|
||||
account = [[[context activeUser] mailAccounts] objectAtIndex: 0];
|
||||
if (![account objectForKey: @"receipts"])
|
||||
@@ -255,16 +250,6 @@ static SoProduct *preferencesProduct = nil;
|
||||
forKey: @"PreventInvitationsWhitelist"];
|
||||
}
|
||||
|
||||
// Initialize some default values
|
||||
if (![settings objectForKey: @"Calendar"])
|
||||
[settings setObject: [NSMutableDictionary dictionary] forKey: @"Calendar"];
|
||||
|
||||
if (![settings objectForKey: @"Contact"])
|
||||
[settings setObject: [NSMutableDictionary dictionary] forKey: @"Contact"];
|
||||
|
||||
if (![settings objectForKey: @"Mail"])
|
||||
[settings setObject: [NSMutableDictionary dictionary] forKey: @"Mail"];
|
||||
|
||||
return [self _makeResponse: [[settings source] values]];
|
||||
}
|
||||
|
||||
|
||||
@@ -1064,7 +1064,7 @@ static NSArray *reminderValues = nil;
|
||||
|
||||
if (!capabilities)
|
||||
{
|
||||
if ([self isSieveScriptsEnabled] && [self _sieveClient])
|
||||
if ([self _sieveClient])
|
||||
capabilities = [[self _sieveClient] capabilities];
|
||||
else
|
||||
capabilities = [NSArray array];
|
||||
|
||||
@@ -94,7 +94,7 @@ static NSArray *tasksFields = nil;
|
||||
@"c_classification", @"c_category",
|
||||
@"c_partmails", @"c_partstates", @"c_owner",
|
||||
@"c_iscycle", @"c_nextalarm",
|
||||
@"c_recurrence_id", @"isException", @"viewable", @"editable",
|
||||
@"c_recurrence_id", @"isException", @"editable",
|
||||
@"erasable", @"ownerIsOrganizer", @"c_description", nil];
|
||||
[eventsFields retain];
|
||||
}
|
||||
@@ -104,7 +104,7 @@ static NSArray *tasksFields = nil;
|
||||
@"calendarName",
|
||||
@"c_status", @"c_title", @"c_enddate",
|
||||
@"c_classification", @"c_location", @"c_category",
|
||||
@"viewable", @"editable", @"erasable",
|
||||
@"editable", @"erasable",
|
||||
@"c_priority", @"c_owner",
|
||||
@"c_iscycle", @"c_nextalarm",
|
||||
@"c_recurrence_id", @"isException", @"c_description", nil];
|
||||
@@ -258,7 +258,7 @@ static NSArray *tasksFields = nil;
|
||||
|
||||
labelKey = [NSString stringWithFormat: @"%@_class%@",
|
||||
type, [component objectForKey: @"c_classification"]];
|
||||
[component setObject: [self labelForKey: labelKey inContext: context]
|
||||
[component setObject: [self labelForKey: labelKey]
|
||||
forKey: @"c_title"];
|
||||
}
|
||||
|
||||
@@ -441,35 +441,21 @@ static NSArray *tasksFields = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentInfos = [[currentFolder fetchCoreInfosFrom: startDate
|
||||
id foo;
|
||||
|
||||
foo = [currentFolder fetchCoreInfosFrom: startDate
|
||||
to: endDate
|
||||
title: value
|
||||
component: component]
|
||||
objectEnumerator];
|
||||
component: component];
|
||||
currentInfos = [foo objectEnumerator];
|
||||
}
|
||||
|
||||
owner = [currentFolder ownerInContext: context];
|
||||
ownerUser = [SOGoUser userWithLogin: owner];
|
||||
isErasable = ([owner isEqualToString: userLogin] || [[currentFolder aclsForUser: userLogin] containsObject: SOGoRole_ObjectEraser]);
|
||||
|
||||
|
||||
while ((newInfo = [currentInfos nextObject]))
|
||||
{
|
||||
if ([fields containsObject: @"viewable"])
|
||||
{
|
||||
if ([owner isEqualToString: userLogin])
|
||||
[newInfo setObject: [NSNumber numberWithInt: 1] forKey: @"viewable"];
|
||||
else
|
||||
{
|
||||
role = [currentFolder roleForComponentsWithAccessClass: [[newInfo objectForKey: @"c_classification"] intValue]
|
||||
forUser : userLogin];
|
||||
|
||||
if ([role isEqualToString: @"ComponentViewer"])
|
||||
[newInfo setObject: [NSNumber numberWithInt: 1] forKey: @"viewable"];
|
||||
else
|
||||
[newInfo setObject: [NSNumber numberWithInt: 0] forKey: @"viewable"];
|
||||
}
|
||||
}
|
||||
|
||||
if ([fields containsObject: @"editable"])
|
||||
{
|
||||
if (folderIsRemote)
|
||||
@@ -562,19 +548,19 @@ static NSArray *tasksFields = nil;
|
||||
{
|
||||
// Same day
|
||||
if (forAllDay)
|
||||
return [self labelForKey: @"Today" inContext: context];
|
||||
return [self labelForKey: @"Today"];
|
||||
else
|
||||
return [dateFormatter formattedTime: date];
|
||||
}
|
||||
else if ([now dayOfCommonEra] - [date dayOfCommonEra] == 1)
|
||||
{
|
||||
// Yesterday
|
||||
return [self labelForKey: @"Yesterday" inContext: context];
|
||||
return [self labelForKey: @"Yesterday"];
|
||||
}
|
||||
else if ([date dayOfCommonEra] - [now dayOfCommonEra] == 1)
|
||||
{
|
||||
// Tomorrow
|
||||
return [self labelForKey: @"Tomorrow" inContext: context];
|
||||
return [self labelForKey: @"Tomorrow"];
|
||||
}
|
||||
else if (abs(delta = [date dayOfCommonEra] - [now dayOfCommonEra]) < 7)
|
||||
{
|
||||
@@ -587,7 +573,7 @@ static NSArray *tasksFields = nil;
|
||||
return dayOfWeek;
|
||||
else
|
||||
// With the past 7 days
|
||||
return [NSString stringWithFormat: [self labelForKey: @"last %@" inContext: context], dayOfWeek];
|
||||
return [NSString stringWithFormat: [self labelForKey: @"last %@"], dayOfWeek];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -666,11 +652,10 @@ static NSArray *tasksFields = nil;
|
||||
return [self _responseWithData: data];
|
||||
}
|
||||
|
||||
- (void) saveFilterValue: (NSString *) submodule
|
||||
- (void) saveFilterValue
|
||||
{
|
||||
NSString *filter;
|
||||
SOGoUserSettings *us;
|
||||
NSMutableDictionary *calendarSettings;
|
||||
|
||||
filter = [[context request] formValueForKey: @"filterpopup"];
|
||||
if ([filter length]
|
||||
@@ -678,20 +663,12 @@ static NSArray *tasksFields = nil;
|
||||
&& ![filter isEqualToString: @"view_future"])
|
||||
{
|
||||
us = [[context activeUser] userSettings];
|
||||
calendarSettings = [us objectForKey: @"Calendar"];
|
||||
// Must create if it doesn't exist
|
||||
if (!calendarSettings)
|
||||
{
|
||||
calendarSettings = [NSMutableDictionary dictionary];
|
||||
[us setObject: calendarSettings forKey: @"Calendar"];
|
||||
}
|
||||
//[us setObject: filter forKey: submodule];
|
||||
[calendarSettings setObject: filter forKey: submodule];
|
||||
[us setObject: filter forKey: @"CalendarDefaultFilter"];
|
||||
[us synchronize];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) saveSortValue: (NSString *) submodule
|
||||
- (void) saveSortValue
|
||||
{
|
||||
NSString *sort, *ascending;
|
||||
SOGoUserSettings *us;
|
||||
@@ -709,8 +686,7 @@ static NSArray *tasksFields = nil;
|
||||
calendarSettings = [NSMutableDictionary dictionary];
|
||||
[us setObject: calendarSettings forKey: @"Calendar"];
|
||||
}
|
||||
[calendarSettings setObject: [NSArray arrayWithObjects: [sort lowercaseString], [NSString stringWithFormat: @"%d", [ascending intValue]], nil]
|
||||
forKey: submodule];
|
||||
[calendarSettings setObject: [NSArray arrayWithObjects: [sort lowercaseString], [NSString stringWithFormat: @"%d", (ascending?1:0)], nil] forKey: @"EventsSortingState"];
|
||||
[us synchronize];
|
||||
}
|
||||
}
|
||||
@@ -746,11 +722,10 @@ static NSArray *tasksFields = nil;
|
||||
* @apiSuccess (Success 200) {String[]} events.c_partmails Participants email addresses
|
||||
* @apiSuccess (Success 200) {String[]} events.c_partstates Participants states
|
||||
* @apiSuccess (Success 200) {String} events.c_owner Event's owner
|
||||
* @apiSuccess (Success 200) {Number} events.c_iscycle 1 if the event is cyclic/recurring
|
||||
* @apiSuccess (Success 200) {Number} events.c_iscycle 1 if the event is cyclic
|
||||
* @apiSuccess (Success 200) {Number} events.c_nextalarm Epoch time of next alarm
|
||||
* @apiSuccess (Success 200) {String} [events.c_recurrence_id] Recurrence ID if event is cyclic
|
||||
* @apiSuccess (Success 200) {Number} events.isException 1 if recurrence is an exception
|
||||
* @apiSuccess (Success 200) {Number} events.viewable 1 if active user can view the event
|
||||
* @apiSuccess (Success 200) {Number} events.editable 1 if active user can edit the event
|
||||
* @apiSuccess (Success 200) {Number} events.erasable 1 if active user can erase the event
|
||||
* @apiSuccess (Success 200) {Number} events.ownerIsOrganizer 1 if owner is also the organizer
|
||||
@@ -768,8 +743,8 @@ static NSArray *tasksFields = nil;
|
||||
NSString *sort, *ascending;
|
||||
|
||||
[self _setupContext];
|
||||
[self saveFilterValue: @"EventsFilterState"];
|
||||
[self saveSortValue: @"EventsSortingState"];
|
||||
[self saveFilterValue];
|
||||
[self saveSortValue];
|
||||
|
||||
newEvents = [NSMutableArray array];
|
||||
events = [[self _fetchFields: eventsFields
|
||||
@@ -1269,7 +1244,6 @@ _computeBlocksPosition (NSArray *blocks)
|
||||
* @apiSuccess (Success 200) {Number} events.c_nextalarm Epoch time of next alarm
|
||||
* @apiSuccess (Success 200) {String} [events.c_recurrence_id] Recurrence ID if event is cyclic
|
||||
* @apiSuccess (Success 200) {Number} events.isException 1 if recurrence is an exception
|
||||
* @apiSuccess (Success 200) {Number} events.viewable 1 if active user can view the event
|
||||
* @apiSuccess (Success 200) {Number} events.editable 1 if active user can edit the event
|
||||
* @apiSuccess (Success 200) {Number} events.erasable 1 if active user can erase the event
|
||||
* @apiSuccess (Success 200) {Number} events.ownerIsOrganizer 1 if owner is also the organizer
|
||||
@@ -1434,7 +1408,6 @@ _computeBlocksPosition (NSArray *blocks)
|
||||
* @apiSuccess (Success 200) {Number} tasks.c_classification 0: Public, 1: Private, 2: Confidential
|
||||
* @apiSuccess (Success 200) {String} tasks.c_location Location
|
||||
* @apiSuccess (Success 200) {String} tasks.c_category Category
|
||||
* @apiSuccess (Success 200) {Number} tasks.viewable 1 if task is viewable by the active user
|
||||
* @apiSuccess (Success 200) {Number} tasks.editable 1 if task is editable by the active user
|
||||
* @apiSuccess (Success 200) {Number} tasks.erasable 1 if task is erasable by the active user
|
||||
* @apiSuccess (Success 200) {String} tasks.c_priority Priority (0-9)
|
||||
@@ -1463,8 +1436,6 @@ _computeBlocksPosition (NSArray *blocks)
|
||||
filteredTasks = [NSMutableArray array];
|
||||
|
||||
[self _setupContext];
|
||||
[self saveFilterValue: @"TasksFilterState"];
|
||||
[self saveSortValue: @"TasksSortingState"];
|
||||
|
||||
startSecs = (unsigned int) [startDate timeIntervalSince1970];
|
||||
endsSecs = (unsigned int) [endDate timeIntervalSince1970];
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#import <NGCards/iCalPerson.h>
|
||||
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
#import <SOGo/SOGoUserDefaults.h>
|
||||
@@ -262,14 +261,12 @@
|
||||
- (WOResponse *) saveSelectedListAction
|
||||
{
|
||||
WORequest *request;
|
||||
NSDictionary *params;
|
||||
NSString *selectedList;
|
||||
|
||||
[self _setupContext];
|
||||
request = [context request];
|
||||
params = [[request contentAsString] objectFromJSONString];
|
||||
|
||||
selectedList = [params objectForKey: @"list"];
|
||||
selectedList = [request formValueForKey: @"list"];
|
||||
[moduleSettings setObject: selectedList
|
||||
forKey: @"SelectedList"];
|
||||
[us synchronize];
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@class SOGoAppointmentFolder;
|
||||
|
||||
@interface UIxCalendarFolderLinksTemplate : UIxComponent
|
||||
{
|
||||
SOGoAppointmentFolder *calendar;
|
||||
NSString *baseCalDAVURL, *basePublicCalDAVURL;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -28,6 +28,89 @@
|
||||
|
||||
@implementation UIxCalendarFolderLinksTemplate
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
calendar = [self clientObject];
|
||||
baseCalDAVURL = nil;
|
||||
basePublicCalDAVURL = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[baseCalDAVURL release];
|
||||
[basePublicCalDAVURL release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) _baseCalDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!baseCalDAVURL)
|
||||
{
|
||||
davURL = [[calendar realDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
baseCalDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
baseCalDAVURL = davURL;
|
||||
[baseCalDAVURL retain];
|
||||
}
|
||||
|
||||
return baseCalDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) calDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _baseCalDAVURL]];
|
||||
}
|
||||
|
||||
- (NSString *) webDavICSURL
|
||||
{
|
||||
return [calendar webDavICSURL];
|
||||
}
|
||||
|
||||
- (NSString *) webDavXMLURL
|
||||
{
|
||||
return [calendar webDavXMLURL];
|
||||
}
|
||||
|
||||
- (NSString *) _basePublicCalDAVURL
|
||||
{
|
||||
NSString *davURL;
|
||||
|
||||
if (!basePublicCalDAVURL)
|
||||
{
|
||||
davURL = [[calendar publicDavURL] absoluteString];
|
||||
if ([davURL hasSuffix: @"/"])
|
||||
basePublicCalDAVURL = [davURL substringToIndex: [davURL length] - 1];
|
||||
else
|
||||
basePublicCalDAVURL = davURL;
|
||||
[basePublicCalDAVURL retain];
|
||||
}
|
||||
|
||||
return basePublicCalDAVURL;
|
||||
}
|
||||
|
||||
- (NSString *) publicCalDavURL
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/", [self _basePublicCalDAVURL]];
|
||||
}
|
||||
|
||||
- (NSString *) publicWebDavICSURL
|
||||
{
|
||||
return [calendar publicWebDavICSURL];
|
||||
}
|
||||
|
||||
- (NSString *) publicWebDavXMLURL
|
||||
{
|
||||
return [calendar publicWebDavXMLURL];
|
||||
}
|
||||
|
||||
- (BOOL) isPublicAccessEnabled
|
||||
{
|
||||
// NOTE: This method is the same found in Common/UIxAclEditor.m
|
||||
@@ -35,4 +118,14 @@
|
||||
enablePublicAccess];
|
||||
}
|
||||
|
||||
- (BOOL) isWebCalendar
|
||||
{
|
||||
return ([calendar isKindOfClass: [SOGoWebAppointmentFolder class]]);
|
||||
}
|
||||
|
||||
- (NSString *) webCalendarURL
|
||||
{
|
||||
return [calendar folderPropertyValueInCategory: @"WebCalendars"];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -842,7 +842,7 @@ static NSArray *reminderValues = nil;
|
||||
|
||||
clientObject = [self clientObject];
|
||||
ownerUser = [SOGoUser userWithLogin: [clientObject ownerInContext: context]];
|
||||
if ([[clientObject container] isKindOfClass: [SOGoWebAppointmentFolder class]])
|
||||
if ([clientObject isKindOfClass: [SOGoWebAppointmentFolder class]])
|
||||
rc = componentReadableOnly;
|
||||
else
|
||||
{
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
actionName = "saveUserRights";
|
||||
};
|
||||
links = {
|
||||
protectedBy = "Access Contents Information";
|
||||
protectedBy = "View";
|
||||
pageName = "UIxCalendarFolderLinksTemplate";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
<md-content md-scroll-y="md-scroll-y" class="viewer md-padding md-whiteframe-z1 bg-sogoPaper-50">
|
||||
<!-- <div class="editor md-padding">-->
|
||||
<md-content md-scroll-y="true" class="md-padding md-whiteframe-z1 bg-sogoPaper-50">
|
||||
<div class="editor md-padding">
|
||||
<hgroup class="header">
|
||||
<h1 class="sg-md-display-2--light" ng-bind-html="editor.card.$fullname()"><!-- fullname --></h1>
|
||||
<h6 class="sg-md-display-2-subheader">{{editor.card.$description()}}</h6>
|
||||
@@ -115,6 +115,7 @@
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="md-layout-margin" layout="row" layout-align="start center">
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.addEmail()">
|
||||
@@ -127,25 +128,12 @@
|
||||
</div>
|
||||
|
||||
<!-- birthday -->
|
||||
<div class="section">
|
||||
<div layout="row" layout-align="space-between end" ng-show="editor.card.birthday">
|
||||
<label>
|
||||
<var:string label:value="Birthday"/>
|
||||
</label>
|
||||
<md-datepicker ng-model="editor.card.birthday"><!-- birthday --></md-datepicker>
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.card.$delete('birthday', -1)">
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
<div class="md-layout-margin" layout="row" layout-align="start center" ng-hide="editor.card.birthday">
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.addBirthday()">
|
||||
<md-icon>add_circle</md-icon>
|
||||
</md-button>
|
||||
<label class="button-label">
|
||||
<var:string label:value="Add Birthday"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<md-input-container>
|
||||
<label>
|
||||
<var:string label:value="Birthday"/>
|
||||
</label>
|
||||
<input type="date" ng-model="editor.card.birthday"/>
|
||||
</md-input-container>
|
||||
|
||||
<!-- phones -->
|
||||
<div class="section">
|
||||
@@ -354,7 +342,7 @@
|
||||
</var:if>
|
||||
</div>
|
||||
</form>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</md-content>
|
||||
|
||||
</container>
|
||||
@@ -6,15 +6,14 @@
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<md-dialog flex="60" flex-sm="100">
|
||||
<md-dialog flex="40">
|
||||
<md-toolbar class="sg-padded">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">link</md-icon>
|
||||
<div class="md-toolbar-tools">
|
||||
<div class="pseudo-input-container md-flex">
|
||||
<label class="pseudo-input-label"><var:string label:value="Links to this Address Book"/></label>
|
||||
<div class="pseudo-input-field sg-md-title">{{links.addressbook.name}}</div>
|
||||
<div class="pseudo-input-field sg-md-title"><var:string value="addressBook.displayName"/></div>
|
||||
</div>
|
||||
<md-button class="md-icon-button" ng-click="links.close()">
|
||||
<md-button class="md-icon-button" ng-click="close()">
|
||||
<md-icon aria-label="Close dialog">close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
@@ -25,7 +24,7 @@
|
||||
<div class="sg-md-title"><var:string label:value="Authenticated User Access"/></div>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="CardDAV URL"/></label>
|
||||
<input type="text" ng-model="links.addressbook.urls.cardDavURL" ng-readonly="true"/>
|
||||
<input var:value="cardDavURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<var:if condition="isPublicAccessEnabled">
|
||||
@@ -33,7 +32,7 @@
|
||||
<div class="sg-md-title"><var:string label:value="Public Access"/></div>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="CardDAV URL"/></label>
|
||||
<input type="text" ng-model="links.addressbook.urls.publicCardDavURL" ng-readonly="true"/>
|
||||
<input var:value="publicCardDavURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
</var:if>
|
||||
|
||||
@@ -9,16 +9,94 @@
|
||||
className="UIxPageFrame"
|
||||
title="title"
|
||||
const:userDefaultsKeys="SOGoContactsCategories"
|
||||
const:jsFiles="vendor/ckeditor/ckeditor.js, vendor/ckeditor/ck.js, Common.js, Preferences.services.js, Mailer.services.js, Contacts.js, Contacts.services.js, vendor/angular-file-upload.min.js">
|
||||
const:jsFiles="Common.js, Preferences.services.js, Contacts.js, Contacts.services.js">
|
||||
<script type="text/javascript">
|
||||
var contactFolders = <var:string value="contactFolders" const:escapeHTML="NO" />;
|
||||
</script>
|
||||
|
||||
<main class="view layout-fill" ui-view="addressbooks" layout="row" ng-controller="navController"><!-- addressbooks list --></main>
|
||||
<!--
|
||||
<div id="uploadDialog" style="display: none" class="dialog left">
|
||||
<div>
|
||||
<h3><var:string label:value="Import Cards"/></h3>
|
||||
<p class="prompt"><var:string label:value="Select a vCard or LDIF file."/></p>
|
||||
<form const:href="" name="uploadForm" id="uploadForm" method="post"
|
||||
enctype="multipart/form-data"
|
||||
onsubmit="return AIM.submit(this, {'onStart' : validateUploadForm,
|
||||
'onComplete' : uploadCompleted})">
|
||||
<p class="prompt"><input type="file" name="contactsFile" id="contactsFile" class="textField" required="required" />
|
||||
<a href="#" class="button actionButton" id="uploadSubmit"
|
||||
onclick="if($('uploadForm').onsubmit()) $('uploadForm').submit()">
|
||||
<span><var:string label:value="Upload" /></span></a>
|
||||
<a href="#" class="button" const:id="uploadCancel">
|
||||
<span><var:string label:value="Cancel" /></span></a></p>
|
||||
</form>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="uploadResults" dropdown-content="dropdown-content" class="f-dropdown">
|
||||
<div>
|
||||
<h3><var:string label:value="Import Cards"/></h3>
|
||||
<p id="uploadResultsContent">!- empty -</p>
|
||||
<p><a href="#" class="button" const:id="uploadOK">
|
||||
<span><var:string label:value="Done" /></span></a></p>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="f-dropdown" dropdown-content="dropdown-content" id="contactMenu">
|
||||
<li><var:string label:value="Properties" /></li>
|
||||
<li><var:string label:value="Categories" /></li>
|
||||
<li>!- separator -</li>
|
||||
<li><var:string label:value="Write" /></li>
|
||||
<li><var:string label:value="Instant Message" /></li>
|
||||
<li>!- separator -</li>
|
||||
<li><var:string label:value="Delete" /></li>
|
||||
<li>!- separator -</li>
|
||||
<li><var:string label:value="Move To" /></li>
|
||||
<li><var:string label:value="Copy To" /></li>
|
||||
<li><var:string label:value="Export" /></li>
|
||||
<li><var:string label:value="View Raw Source" /></li>
|
||||
</ul>
|
||||
-->
|
||||
<!--
|
||||
MAIN CONTENT ROW
|
||||
Content of the application view injected injected in the element bellow
|
||||
MUST be the first html element after body
|
||||
SHOULD be a main tag (with role="main")
|
||||
|
||||
Templates script tag wrappers goes next
|
||||
-->
|
||||
<main class="view md-layout-fill" ui-view="addressbooks" layout="row" ng-controller="navController"><!-- addressbooks list --></main>
|
||||
|
||||
<!-- TEMPLATE SCRIPT WRAPPER -->
|
||||
<script type="text/ng-template" id="UIxContactFoldersView">
|
||||
|
||||
<!-- dropdown menu for addressbook options button -->
|
||||
<div id="addressbookProperties" class="f-dropdown icons-dropdown" ng-hide="true">
|
||||
<ul class="button-group">
|
||||
<li label:tooltip="Links to this Address Book"
|
||||
tooltip-popup-delay="500">
|
||||
<span class="button"
|
||||
sg-dropdown-content-toggle="#addressbookLinks">
|
||||
<i class="icon-hyperlink"><!-- links --></i>
|
||||
</span>
|
||||
</li>
|
||||
<li label:tooltip="Rename"
|
||||
tooltip-popup-delay="500">
|
||||
<span class="button" ng-click="edit()">
|
||||
<i class="icon-pencil"><!-- rename --></i>
|
||||
</span>
|
||||
</li>
|
||||
<li label:tooltip="Import Cards"
|
||||
tooltip-popup-delay="500">
|
||||
<span class="button" ng-click="importCards()">
|
||||
<i class="icon-file"><!-- import --></i>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Sidenav -->
|
||||
<md-sidenav id="left-sidenav" class="md-sidenav-left md-whiteframe-z1" md-component-id="left" md-is-locked-open="isGtMedium" layout="column">
|
||||
<var:component className="UIxSidenavToolbarTemplate" />
|
||||
@@ -28,7 +106,7 @@
|
||||
<section>
|
||||
<md-subheader class="sg-md-subheader">
|
||||
<div layout="row" layout-align="space-between center">
|
||||
<span><var:string label:value="Address Books"/></span>
|
||||
<span><var:string label:value="AddressBooks"/></span>
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="New Addressbook..."
|
||||
ng-click="app.newAddressbook()">
|
||||
@@ -62,22 +140,11 @@
|
||||
ng-click="$mdOpenMenu()"
|
||||
md-menu-origin="md-menu-origin">more_vert</md-icon>
|
||||
<md-menu-content width="2">
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.edit(folder)">
|
||||
<var:string label:value="Rename"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.confirmDelete()">
|
||||
<var:string label:value="Delete"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider><!-- divider --></md-menu-divider>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.importCards($event, folder)">
|
||||
<var:string label:value="Import"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.exportCards()">
|
||||
<var:string label:value="Export"/>
|
||||
@@ -138,11 +205,6 @@
|
||||
ng-click="$mdOpenMenu()"
|
||||
md-menu-origin="md-menu-origin">more_vert</md-icon>
|
||||
<md-menu-content width="2">
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.edit(folder)">
|
||||
<var:string label:value="Rename"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.confirmDelete(folder)">
|
||||
<var:string label:value="Delete"/>
|
||||
@@ -172,16 +234,17 @@
|
||||
<!-- </div> -->
|
||||
</md-sidenav>
|
||||
|
||||
<section layout="column" class="sg-app-content layout-fill" ui-view="addressbook"><!-- contacts list --></section>
|
||||
<section layout="column" class="sg-app-content md-layout-fill" ui-view="addressbook"><!-- contacts list --></section>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="addressbook">
|
||||
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top" layout="row" layout-align="space-between start">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top sg-padded" layout="row" layout-align="space-between start">
|
||||
<var:component className="UIxTopnavToolbarTemplate" />
|
||||
</div>
|
||||
<div class="md-toolbar-tools" layout="row" layout-align="space-between center"
|
||||
ng-show="addressbook.selectedFolder.$selectedCount() == 0">
|
||||
|
||||
<div class="view-list" layout="row" layout-align="space-between center"
|
||||
ng-hide="addressbook.mode.search">
|
||||
<div class="sg-toolbar-group">
|
||||
@@ -232,10 +295,9 @@
|
||||
</md-menu-item>
|
||||
<md-menu-divider> <!-- divider --></md-menu-divider>
|
||||
<md-menu-item >
|
||||
<md-button ng-href="#">
|
||||
<md-button ng-click="addressbook.sort()">
|
||||
<md-checkbox
|
||||
ng-change="addressbook.sort(addressbook.selectedFolder.constructor.$query.sort)"
|
||||
ng-model="addressbook.selectedFolder.constructor.$query.asc"
|
||||
ng-model="addressbook.selectedFolder.$query.asc"
|
||||
ng-true-value="0"
|
||||
ng-false-value="1"><var:string label:value="Descending Order"/></md-checkbox>
|
||||
</md-button>
|
||||
@@ -268,51 +330,26 @@
|
||||
</md-input-container>
|
||||
</div>
|
||||
</div>
|
||||
<!-- multiple selection mode -->
|
||||
<div class="md-toolbar-tools" layout="row" layout-align="space-between center"
|
||||
ng-show="addressbook.selectedFolder.$selectedCount() > 0">
|
||||
<div class="view-list" layout="row" layout-align="space-between center">
|
||||
<div class="sg-toolbar-group">
|
||||
<md-button class="sg-icon-button" ng-click="addressbook.unselectCards()">
|
||||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<label>{{addressbook.selectedFolder.$selectedCount()}} <var:string label:value="selected"/></label>
|
||||
</div>
|
||||
<div class="sg-toolbar-group-last">
|
||||
|
||||
<div layout="row" layout-align="start center" ng-show="addressbook.selectedFolder.$selectedCount() > 0">
|
||||
<md-button class="sg-icon-button" ng-click="addressbook.unselectCards()">
|
||||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<label>{{addressbook.selectedFolder.$selectedCount()}} selected</label>
|
||||
<md-button class="sg-icon-button" ng-click="addressbook.selectAll()">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Select All"/></md-tooltip>
|
||||
<md-icon>select_all</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-show="addressbook.selectedFolder.acls.objectEraser"
|
||||
ng-click="addressbook.confirmDeleteSelectedCards()">
|
||||
<md-button class="sg-icon-button" ng-click="addressbook.confirmDeleteSelectedCards()">
|
||||
<md-icon>delete</md-icon>
|
||||
</md-button>
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="Copy contacts" ng-click="$mdOpenMenu()">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Copy To"/></md-tooltip>
|
||||
<md-icon>content_copy</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<md-menu-item>
|
||||
<md-button class="md-primary" ng-disabled="true"><var:string label:value="Address Books"/></md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-repeat="folder in app.service.$addressbooks track by folder.id"
|
||||
ng-hide="addressbook.selectedFolder.id == folder.id">
|
||||
<md-button ng-click="addressbook.copySelectedCards(folder.id)">
|
||||
<span ng-class="'sg-child-level-' + folder.level">{{folder.name}}</span>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
<md-menu>
|
||||
<md-button class="sg-icon-button" label:aria-label="More messages options" ng-click="$mdOpenMenu()">
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content width="2">
|
||||
<md-menu-item>
|
||||
<md-button ng-click="addressbook.newMessageWithSelectedCards($event)">
|
||||
<md-button>
|
||||
<var:string label:value="Write"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
@@ -323,11 +360,9 @@
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<div layout="row" class="md-flex">
|
||||
<div layout="row" class="md-flex" layout-align="space-between">
|
||||
<div class="view-list" layout="column">
|
||||
<md-content id="contactsList" layout="column" class="md-flex">
|
||||
<header class="sg-md-subheader sg-md-subheader--fixed">
|
||||
@@ -336,59 +371,62 @@
|
||||
<span ng-show="addressbook.selectedFolder.cards.length == 0"><var:string label:value="No contact"/></span>
|
||||
</h2>
|
||||
</header>
|
||||
<!-- Search field & special results
|
||||
<input type="text" placeholder="Search" ng-model="search.filter" ng-keyup="doSearch($event)" />
|
||||
<div ng-switch="search.status">
|
||||
<div ng-switch-when="min-char" class="alert-bg">
|
||||
<i class="icon-warning"></i><var:string label:value="Please enter at least three characters"/>
|
||||
</div>
|
||||
<div ng-switch-when="no-result" class="alert-bg">
|
||||
<i class="icon-ion-search"></i><var:string label:value="No matching card"/>
|
||||
</div>
|
||||
<div ng-switch-when="remote-addressbook" ng-show="addressbook.cards.length == 0" class="alert-bg">
|
||||
<i class="icon-ion-search"></i><var:string label:value="Initiate a search"/>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<md-virtual-repeat-container class="md-flex">
|
||||
<md-list class="sg-section-list">
|
||||
<div md-virtual-repeat="currentCard in addressbook.selectedFolder.cards" md-item-size="72">
|
||||
<md-list>
|
||||
<div md-virtual-repeat="currentCard in addressbook.selectedFolder.cards">
|
||||
<md-list-item
|
||||
ng-class="{'sg-active': currentCard.id == addressbook.selectedFolder.selectedCard}"
|
||||
ng-click="addressbook.selectCard(currentCard)"
|
||||
ui-sref="app.addressbook.card.view({addressbookId: addressbook.selectedFolder.id, cardId: currentCard.id})">
|
||||
<div class="sg-selected-avatar" ng-show="currentCard.selected"
|
||||
ng-click="currentCard.selected = !currentCard.selected">
|
||||
<!-- selected avatar -->
|
||||
</div>
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
ng-show="addressbook.notSelectedComponent(currentCard, 'vcard')"
|
||||
ng-click="currentCard.selected = !currentCard.selected"
|
||||
sg-email="currentCard.$preferredEmail(addressbook.selectedFolder.constructor.$query)"
|
||||
size="40">
|
||||
<!-- contact avatar -->
|
||||
</sg-avatar-image>
|
||||
<div class="sg-list-avatar"
|
||||
ng-show="addressbook.notSelectedComponent(currentCard, 'vlist')"
|
||||
ng-click="currentCard.selected = !currentCard.selected">
|
||||
<!-- list avatar -->
|
||||
</div>
|
||||
<!-- ui-sref-active="sg-active" -->
|
||||
<div class="sg-selected-avatar" ng-show="currentCard.selected"
|
||||
ng-click="currentCard.selected = !currentCard.selected">
|
||||
<!-- selected avatar -->
|
||||
</div>
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
ng-show="addressbook.notSelectedComponent(currentCard, 'vcard')"
|
||||
ng-click="currentCard.selected = !currentCard.selected"
|
||||
sg-email="currentCard.$preferredEmail(addressbook.selectedFolder.$query)"
|
||||
size="48">
|
||||
<!-- contact avatar -->
|
||||
</sg-avatar-image>
|
||||
<div class="sg-list-avatar"
|
||||
ng-show="addressbook.notSelectedComponent(currentCard, 'vlist')"
|
||||
ng-click="currentCard.selected = !currentCard.selected">
|
||||
<!-- list avatar -->
|
||||
</div>
|
||||
<div class="sg-tile-content">
|
||||
<div class="sg-md-subhead-multi" ng-bind-html="currentCard.$fullname()"><!-- cn --></div>
|
||||
<div class="sg-md-body-multi">{{currentCard.$preferredEmail(addressbook.selectedFolder.constructor.$query)}}</div>
|
||||
<div class="sg-md-body-multi">{{currentCard.$preferredEmail(addressbook.selectedFolder.$query)}}</div>
|
||||
</div>
|
||||
</md-list-item>
|
||||
</div>
|
||||
</md-list>
|
||||
</md-virtual-repeat-container>
|
||||
<div class="sg-progress-circular-floating"
|
||||
ng-show="addressbook.selectedFolder.$isLoading">
|
||||
<md-progress-circular class="md-accent"
|
||||
md-mode="indeterminate"
|
||||
md-diameter="32"><!-- progress --></md-progress-circular>
|
||||
</div>
|
||||
<md-button class="md-fab md-fab-bottom-right md-accent"
|
||||
label:aria-label="New Contact"
|
||||
ng-show="addressbook.selectedFolder.acls.objectCreator"
|
||||
ng-click="addressbook.newComponent($event)">
|
||||
<md-icon>add</md-icon>
|
||||
</md-button>
|
||||
</md-content>
|
||||
</div>
|
||||
|
||||
<md-content id="detailView" class="view-detail md-hue-1" layout="column" layout-align="center center"
|
||||
ng-class="{ 'sg-close': !addressbook.selectedFolder.selectedCard }"
|
||||
ui-view="card">
|
||||
<md-input-container class="hide-sm md-hue-1" style="flex-grow: 0">
|
||||
<label class="sg-md-title"><var:string label:value="No contact selected"/></label>
|
||||
</md-input-container>
|
||||
</md-content>
|
||||
<div id="detailView" class="view-detail ng-cloak" layout="column" ui-view="card"
|
||||
ng-show="addressbook.selectedFolder.selectedCard"><!-- card view --></div>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<md-card class="viewer flex-sm">
|
||||
<md-card class="viewer md-flex">
|
||||
<md-card-content>
|
||||
<header class="msg-header">
|
||||
<div ng-show="editor.card.tag == 'vcard'">
|
||||
@@ -30,19 +30,18 @@
|
||||
<div class="sg-icon-bar--vertical">
|
||||
<md-button class="sg-icon-button show-sm"
|
||||
label:aria-label="Close"
|
||||
ng-click="editor.close()">
|
||||
ng-click="toggleDetailView()">
|
||||
<md-icon>close</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="Edit"
|
||||
ng-show="editor.currentFolder.acls.objectEditor"
|
||||
ng-show="editor.currentFolder.isEditable"
|
||||
ui-sref="app.addressbook.card.editor({addressbookId: editor.currentFolder.id, cardId: editor.card.id})">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Edit"/></md-tooltip>
|
||||
<md-icon>mode_edit</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="Delete"
|
||||
ng-show="editor.currentFolder.acls.objectEraser"
|
||||
ng-click="editor.confirmDelete(editor.card)">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Delete"/></md-tooltip>
|
||||
<md-icon>delete</md-icon>
|
||||
@@ -54,13 +53,7 @@
|
||||
</md-button>
|
||||
<md-menu-content>
|
||||
<md-menu-item>
|
||||
<md-button label:aria-label="Export"
|
||||
ng-click="editor.exportCard()">
|
||||
<var:string label:value="Export"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button label:aria-label="View Raw Source"
|
||||
<md-button aria-label="View Raw Source"
|
||||
ng-click="editor.viewRawSource($event)">
|
||||
<var:string label:value="View Raw Source"/>
|
||||
</md-button>
|
||||
@@ -72,14 +65,14 @@
|
||||
</header>
|
||||
<section class="msg-body">
|
||||
|
||||
<div class="pseudo-input-container" ng-show="editor.card.$birthday().length">
|
||||
<div class="pseudo-input-container" ng-show="editor.card.birthday">
|
||||
<div class="key">
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="Birthday"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="pseudo-input-field">
|
||||
<span>{{editor.card.$birthday()}}</span>
|
||||
<span>{{editor.card.$birthday() | date}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -118,8 +111,7 @@
|
||||
</div>
|
||||
|
||||
<div class="pseudo-input-field">
|
||||
<a href="#" ng-bind="email.value"
|
||||
ng-click="addressbook.newMessageWithRecipient($event, email.value, editor.card.$fullname())"><!-- recipient --></a>
|
||||
<a href="mailto:{{email.value}}">{{email.value}}</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -173,4 +165,5 @@
|
||||
</section>
|
||||
</md-card-content>
|
||||
</md-card>
|
||||
|
||||
</container>
|
||||
@@ -7,7 +7,6 @@
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label">
|
||||
<var:string value="cssContent" const:escapeHTML="NO" />
|
||||
<div class="SOGoHTMLMail-CSS-Delimiter mailer_htmlcontent">
|
||||
<var:string value="flatContentAsString" const:escapeHTML="NO" />
|
||||
</div>
|
||||
<div class="SOGoHTMLMail-CSS-Delimiter mailer_htmlcontent"
|
||||
><var:string value="flatContentAsString" const:escapeHTML="NO" /></div>
|
||||
</container>
|
||||
@@ -250,7 +250,7 @@
|
||||
<label class="pseudo-input-label"><var:string label:value="Attendees"/></label>
|
||||
<!-- md-contact-chips don't support "readonly", so we build them using md-chips
|
||||
in readonly mode and a template similar to the one of md-contact-chips -->
|
||||
<md-chips class="md-contact-chips sg-readonly"
|
||||
<md-chips class="md-contact-chips"
|
||||
ng-model="part.participants"
|
||||
readonly="true">
|
||||
<md-chip-template>
|
||||
|
||||
@@ -11,14 +11,13 @@
|
||||
var:title="filenameForDisplay"
|
||||
class="md-card-image"></img>
|
||||
<md-card-content>
|
||||
<p class="md-caption">
|
||||
<p>
|
||||
<var:string value="filenameForDisplay" /><br/>
|
||||
<var:string value="bodyInfo.size" formatter="sizeFormatter"/>
|
||||
</p>
|
||||
</md-card-content>
|
||||
<div class="md-actions" layout="row" layout-align="end center">
|
||||
<md-button class="sg-icon-button" var:href="pathForDownload">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Save Attachment"/></md-tooltip>
|
||||
<md-icon>save</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
@@ -4,16 +4,24 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<md-card>
|
||||
<md-card-content>
|
||||
<md-whiteframe class="md-whiteframe-z1" layout="row" layout-align="space-between center">
|
||||
<div layout="row">
|
||||
<div>
|
||||
<img var:src="mimeImageURL"/>
|
||||
<p class="md-caption">
|
||||
<var:string value="filenameForDisplay"/><br/>
|
||||
</div>
|
||||
|
||||
<div layout="column" layout-align="start start" layout-padding="layout-padding">
|
||||
<div>
|
||||
<var:string value="filenameForDisplay"/>
|
||||
</div>
|
||||
<div class="md-caption">
|
||||
<var:string value="bodyInfo.size" formatter="sizeFormatter"/>
|
||||
</p>
|
||||
</md-card-content>
|
||||
<div class="md-actions" layout="row" layout-align="end center">
|
||||
<md-button class="sg-icon-button" var:href="pathToAttachment" target="_blank">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div layout="row" layout-align="end end">
|
||||
<md-button class="sg-icon-button" var:href="pathToAttachment">
|
||||
<md-tooltip md-direction="left"><var:string label:value="View Attachment"/></md-tooltip>
|
||||
<md-icon>open_in_browser</md-icon>
|
||||
</md-button>
|
||||
@@ -42,5 +50,5 @@
|
||||
PartPath: <var:string value="partPath" /><br />
|
||||
-->
|
||||
|
||||
</md-card>
|
||||
</md-whiteframe>
|
||||
</div>
|
||||
@@ -6,238 +6,180 @@
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
<md-dialog flex="80" flex-sm="100">
|
||||
<md-toolbar class="sg-padded--right">
|
||||
<md-toolbar class="md-padding">
|
||||
<!-- TOOLBAR TO SHOW CC/BCC/ATTACHMENT FIELDS -->
|
||||
|
||||
<div class="md-toolbar-tools">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">edit</md-icon>
|
||||
<!-- from -->
|
||||
<sg-avatar-image class="md-tile-left" hide-sm="hide-sm"
|
||||
sg-email="editor.message.editable.from"
|
||||
size="32"><!-- avatar --></sg-avatar-image>
|
||||
<md-input-container flex="flex">
|
||||
<label><var:string label:value="From"/></label>
|
||||
<md-select name="from"
|
||||
ng-model="editor.message.editable.from">
|
||||
<md-option ng-value="identity" ng-repeat="identity in editor.identities">{{identity}}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
<div flex-gt-sm="flex-gt-sm"><!-- spacer --></div>
|
||||
<md-button class="sg-icon-button" ng-click="editor.send()">
|
||||
<md-icon>send</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-click="editor.message.$save()">
|
||||
<md-icon>save</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-click="editor.cancel()">
|
||||
<md-icon>close</md-icon>
|
||||
<md-button ng-show="editor.hideCc" ng-click="editor.hideCc = false">Cc</md-button>
|
||||
<md-button ng-show="editor.hideBcc" ng-click="editor.hideBcc = false">Bcc</md-button>
|
||||
|
||||
<md-button>
|
||||
<label for="file-input">
|
||||
Add files
|
||||
</label>
|
||||
</md-button>
|
||||
<input id="file-input" type="file"
|
||||
nv-file-select="nv-file-select"
|
||||
multiple="multiple"
|
||||
uploader="editor.uploader"
|
||||
ng-show="false"/>
|
||||
|
||||
<md-menu>
|
||||
<md-button label:aria-label="More mail options" class="iconBtton" ng-click="$mdOpenMenu($event)">
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<md-menu-item>
|
||||
<md-button>
|
||||
<md-checkbox ng-model="editor.message.editable.receipt">
|
||||
<var:string label:value="Receipt"/>
|
||||
</md-checkbox>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<div layout="row" layout-align="center center">
|
||||
<span>
|
||||
<var:string label:value="Priority"/>
|
||||
</span>
|
||||
<md-slider flex="flex"
|
||||
md-discrete="md-discrete"
|
||||
ng-model="editor.message.editable.priority"
|
||||
step="1"
|
||||
min="1"
|
||||
max="5"
|
||||
label:aria-label="Priority">
|
||||
</md-slider>
|
||||
</div>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
|
||||
</div>
|
||||
</md-toolbar>
|
||||
|
||||
<md-dialog-content>
|
||||
<form>
|
||||
<header>
|
||||
<div class="msg-header-content">
|
||||
|
||||
<!-- to -->
|
||||
<!-- FROM / TO / CC/ BCC / SUBJECT / ATTACHMENTS -->
|
||||
<div class="msg-header-content">
|
||||
<md-input-container>
|
||||
<label> <var:string label:value="From"/></label>
|
||||
<md-select name="from"
|
||||
ng-model="editor.message.editable.from">
|
||||
<md-option ng-value="identity" ng-repeat="identity in editor.identities">{{identity}}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<div class="pseudo-input-container">
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="To"/>
|
||||
</label>
|
||||
<md-chips ng-model="editor.message.editable.to"
|
||||
md-on-append="editor.addRecipient($chip)">
|
||||
<md-chips ng-model="editor.message.editable.to">
|
||||
<md-autocomplete
|
||||
class="sg-chips-autocomplete"
|
||||
md-search-text="editor.autocomplete.to.searchText"
|
||||
md-selected-item="editor.autocomplete.to.selected"
|
||||
md-search-text="editor.autocomplete.to.searchText"
|
||||
md-items="user in editor.contactFilter(editor.autocomplete.to.searchText)"
|
||||
md-min-length="3"
|
||||
md-delay="300"
|
||||
md-no-cache="true"
|
||||
label:placeholder="Add a recipient">
|
||||
<md-item-template>
|
||||
<span class="md-contact-suggestion">
|
||||
<span class="md-contact-name"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$fullname}}</span>
|
||||
<span class="md-contact-email"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$email}}</span>
|
||||
</span>
|
||||
</md-item-template>
|
||||
<span md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user}}</span>
|
||||
</md-autocomplete>
|
||||
<md-chip-template>{{$chip}}</md-chip-template>
|
||||
</md-chips>
|
||||
</div>
|
||||
|
||||
<!-- cc -->
|
||||
<div class="pseudo-input-container" ng-hide="editor.hideCc">
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="Cc"/>
|
||||
</label>
|
||||
<md-chips ng-model="editor.message.editable.cc"
|
||||
md-on-append="editor.addRecipient($chip)">
|
||||
<md-chips ng-model="editor.message.editable.cc">
|
||||
<md-autocomplete
|
||||
class="sg-chips-autocomplete"
|
||||
md-search-text="editor.autocomplete.cc.searchText"
|
||||
md-selected-item="editor.autocomplete.cc.selected"
|
||||
md-search-text="editor.autocomplete.cc.searchText"
|
||||
md-items="user in editor.contactFilter(editor.autocomplete.cc.searchText)"
|
||||
label:placeholder="Add a recipient">
|
||||
<md-item-template>
|
||||
<span class="md-contact-suggestion">
|
||||
<span class="md-contact-name"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$fullname}}</span>
|
||||
<span class="md-contact-email"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$email}}</span>
|
||||
</span>
|
||||
</md-item-template>
|
||||
<span md-highlight-text="editor.autocomplete.cc.searchText"
|
||||
md-highlight-flags="^i">{{user}}</span>
|
||||
</md-autocomplete>
|
||||
<md-chip-template>{{$chip}}</md-chip-template>
|
||||
</md-chips>
|
||||
</div>
|
||||
|
||||
<!-- bcc -->
|
||||
<div class="pseudo-input-container" ng-hide="editor.hideBcc">
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="Bcc"/>
|
||||
</label>
|
||||
<md-chips ng-model="editor.message.editable.bcc"
|
||||
md-on-append="editor.addRecipient($chip)">
|
||||
<md-chips ng-model="editor.message.editable.bcc">
|
||||
<md-autocomplete
|
||||
class="sg-chips-autocomplete"
|
||||
md-selected-item="editor.autocomplete.bcc.selected"
|
||||
md-search-text="editor.autocomplete.bcc.searchText"
|
||||
md-items="user in editor.contactFilter(editor.autocomplete.bcc.searchText)"
|
||||
label:placeholder="Add a recipient">
|
||||
<md-item-template>
|
||||
<span class="md-contact-suggestion">
|
||||
<span class="md-contact-name"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$fullname}}</span>
|
||||
<span class="md-contact-email"
|
||||
md-highlight-text="editor.autocomplete.to.searchText"
|
||||
md-highlight-flags="^i">{{user.$$email}}</span>
|
||||
</span>
|
||||
</md-item-template>
|
||||
<span md-highlight-text="editor.autocomplete.bcc.searchText"
|
||||
md-highlight-flags="^i">{{user}}</span>
|
||||
</md-autocomplete>
|
||||
<md-chip-template>{{$chip}}</md-chip-template>
|
||||
</md-chips>
|
||||
</div>
|
||||
|
||||
<!-- subject -->
|
||||
<md-input-container>
|
||||
<label>
|
||||
<var:string label:value="Subject"/>
|
||||
</label>
|
||||
<input type="text" name="subject" ng-model="editor.message.editable.subject"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-list>
|
||||
<!-- FILES ALREADY UPLOADED, FOR EXAMPLE WHEN WE FORWARD A
|
||||
MAIL WITH ATTACHMENTS -->
|
||||
<md-list-item ng-repeat="item in editor.message.editable.attachmentAttrs">
|
||||
<div layout="row" layout-align="space-between center">
|
||||
<span ng-bind="item.filename"><!-- filename --></span>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-click="editor.message.$deleteAttachment(item.filename);">
|
||||
<md-icon>remove_circle_outline</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-list-item>
|
||||
<!-- FILE BEING ATTACHED TO A MAIL -->
|
||||
<md-list-item ng-repeat="item in editor.uploader.queue">
|
||||
<div layout="row" layout-align="space-between center">
|
||||
<span ng-bind="item.file.name"><!-- filename --></span>
|
||||
<md-progress-linear md-mode="determinate"
|
||||
value="{{item.progress}}"
|
||||
ng-show="item.isUploading" ><!-- progress--></md-progress-linear>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-click="editor.uploader.cancelItem(item)"
|
||||
ng-show="item.isUploading">
|
||||
<md-icon>cancel</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-click="editor.message.$deleteAttachment(item.file.name); item.remove();"
|
||||
ng-show="!item.isUploading">
|
||||
<md-icon>remove_circle_outline</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</div>
|
||||
|
||||
<!-- toolbar to show cc/bcc/attachment fields -->
|
||||
<div layout="column" layout-align="start end">
|
||||
<md-button class="sg-icon-button " ng-show="editor.hideCc" ng-click="editor.hideCc = false">Cc</md-button>
|
||||
<md-button class="sg-icon-button " ng-show="editor.hideBcc" ng-click="editor.hideBcc = false">Bcc</md-button>
|
||||
<md-menu>
|
||||
<md-button label:aria-label="More mail options" class="sg-icon-button" ng-click="$mdOpenMenu($event)">
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content width="4">
|
||||
<md-menu-item>
|
||||
<md-button ng-href="#">
|
||||
<md-checkbox ng-model="editor.message.editable.receipt">
|
||||
<var:string label:value="Return Receipt"/>
|
||||
</md-checkbox>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button class="md-primary" ng-disabled="true"><var:string label:value="Priority"/></md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="editor.message.editable.priority = 1">
|
||||
<md-icon ng-class="{ 'icon-check': editor.message.editable.priority == 1}"><!-- highest --></md-icon>
|
||||
<var:string label:value="highest"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="editor.message.editable.priority = 2">
|
||||
<md-icon ng-class="{ 'icon-check': editor.message.editable.priority == 2}"><!-- high --></md-icon>
|
||||
<var:string label:value="high"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="editor.message.editable.priority = 3">
|
||||
<md-icon ng-class="{ 'icon-check':
|
||||
!editor.message.editable.priority
|
||||
|| editor.message.editable.priority == 3}"><!-- normal --></md-icon>
|
||||
<var:string label:value="normal"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="editor.message.editable.priority = 4">
|
||||
<md-icon ng-class="{ 'icon-check': editor.message.editable.priority == 4}"><!-- low --></md-icon>
|
||||
<var:string label:value="low"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="editor.message.editable.priority = 5">
|
||||
<md-icon ng-class="{ 'icon-check': editor.message.editable.priority == 5}"><!-- lowest --></md-icon>
|
||||
<var:string label:value="lowest"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- MESSAGE CONTENT -->
|
||||
<textarea name="content" var:class="editorClass"
|
||||
ck-locale="editor.localeCode"
|
||||
ng-model="editor.message.editable.text"/>
|
||||
</md-dialog-content>
|
||||
|
||||
<!-- TOOLBAR BUTTONS -->
|
||||
<div class="md-actions">
|
||||
<div layout="row" layout-align="space-between center" layout-fill="layout-fill">
|
||||
<div>
|
||||
<!-- md-icon does not play well with Firefox - makes the
|
||||
file input never appear. This should eventually be
|
||||
fixed in Angular Material -->
|
||||
<label class="md-button" for="file-input">
|
||||
<span><var:string label:value="Attach"/></span>
|
||||
</label>
|
||||
<input id="file-input" type="file"
|
||||
nv-file-select="nv-file-select"
|
||||
multiple="multiple"
|
||||
uploader="editor.uploader"
|
||||
ng-show="false"/>
|
||||
<!-- TOOLBAR BUTTONS -->
|
||||
<div class="buttonsToolbar">
|
||||
<div layout="row" layout-align="end center">
|
||||
<md-button ng-click="editor.cancel()"><var:string label:value="Cancel"/></md-button>
|
||||
<md-button ng-click="editor.message.$save()"><var:string label:value="Save"/></md-button>
|
||||
<md-button class="fg-sogoBlue-700 md-primary md-hue-3"
|
||||
ng-click="editor.send()"><var:string label:value="Send"/></md-button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- FILES ALREADY UPLOADED, FOR EXAMPLE WHEN WE FORWARD A
|
||||
MAIL WITH ATTACHMENTS -->
|
||||
<md-chips ng-model="editor.message.editable.attachmentAttrs"
|
||||
class="sg-readonly" readonly="true">
|
||||
<md-chip-template>
|
||||
<span>{{$chip.filename}}</span>
|
||||
<md-icon ng-click="editor.message.$deleteAttachment($chip.filename);">close</md-icon>
|
||||
</md-chip-template>
|
||||
</md-chips>
|
||||
<!-- FILE BEING ATTACHED TO A MAIL -->
|
||||
<md-chips ng-model="editor.uploader.queue"
|
||||
class="sg-readonly" readonly="true">
|
||||
<md-chip-template>
|
||||
<span>{{$chip.file.name}}</span>
|
||||
<md-icon ng-show="!$chip.isUploading"
|
||||
ng-click="editor.message.$deleteAttachment($chip.file.name);
|
||||
$chip.remove();">close</md-icon>
|
||||
<md-icon ng-show="$chip.isUploading"
|
||||
ng-click="editor.uploader.cancelItem($chip)"
|
||||
ng-style="{ 'color': '#F00' }">cancel</md-icon>
|
||||
<span ng-show="$chip.isUploading">{{$chip.progress}} %</span>
|
||||
</md-chip-template>
|
||||
</md-chips>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</md-dialog>
|
||||
</form>
|
||||
</md-dialog-content>
|
||||
</md-dialog>
|
||||
</container>
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:label="OGo:label">
|
||||
<div class="view-list" layout="column">
|
||||
<md-content id="messagesList" layout="column" class="md-flex">
|
||||
<md-progress-linear ng-show="mailbox.selectedFolder.$isLoading" md-mode="indeterminate"><!-- progress --></md-progress-linear>
|
||||
<header class="sg-md-subheader sg-md-subheader--fixed">
|
||||
<h2 class="md-default-theme sg-md-subhead-solo fg-sogoBlue-700">
|
||||
<span ng-show="mailbox.selectedFolder.$messages.length > 0">{{mailbox.selectedFolder.$messages.length}} <var:string label:value="messages"/></span>
|
||||
@@ -12,44 +13,39 @@
|
||||
</h2>
|
||||
</header>
|
||||
<md-virtual-repeat-container class="md-flex">
|
||||
<md-list class="sg-section-list">
|
||||
<md-list-item
|
||||
md-virtual-repeat="currentMessage in mailbox.selectedFolder"
|
||||
md-on-demand="md-on-demand"
|
||||
ng-class="{'sg-active': currentMessage.uid == mailbox.selectedFolder.selectedMessage, unread: !currentMessage.isread}"
|
||||
ng-click="mailbox.selectMessage(currentMessage)"
|
||||
ui-sref="mail.account.mailbox.message({accountId: mailbox.account.id, mailboxId: (mailbox.selectedFolder.path | encodeUri), messageId: currentMessage.uid})">
|
||||
<!-- ui-sref-active="sg-active"> -->
|
||||
<div class="sg-selected-avatar"
|
||||
ng-show="currentMessage.selected"
|
||||
ng-click="currentMessage.selected = !currentMessage.selected"><!-- selected avatar --></div>
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
ng-show="!currentMessage.selected"
|
||||
ng-click="currentMessage.selected = !currentMessage.selected"
|
||||
sg-email="::currentMessage.from[0].email"
|
||||
size="48"><!-- avatar --></sg-avatar-image>
|
||||
<div class="sg-tile-content">
|
||||
<span class="msg-date"
|
||||
ng-bind-html="currentMessage.relativedate"><!-- date --></span>
|
||||
<div class="sg-md-subhead-multi">{{currentMessage.$shortAddress('from')}}</div>
|
||||
<div class="sg-md-body-multi">{{currentMessage.subject}}</div>
|
||||
</div>
|
||||
<div class="sg-tile-icons">
|
||||
<md-icon ng-show="currentMessage.priority == 'highest' || currentMessage.priority == 'high'">warning</md-icon>
|
||||
<md-icon ng-show="currentMessage.isflagged">star</md-icon>
|
||||
<md-icon ng-show="currentMessage.isanswered">reply</md-icon>
|
||||
<md-icon ng-show="currentMessage.isforwarded">forward</md-icon>
|
||||
<md-icon ng-show="currentMessage.hasattachment">attach_file</md-icon>
|
||||
</div>
|
||||
</md-list-item>
|
||||
<md-list>
|
||||
<div md-virtual-repeat="currentMessage in mailbox.selectedFolder.$messages">
|
||||
<md-list-item
|
||||
ng-class="{'sg-active': currentMessage.uid == mailbox.selectedFolder.selectedMessage, unread: !currentMessage.isread}"
|
||||
ng-click="mailbox.selectMessage(currentMessage)"
|
||||
ui-sref="mail.account.mailbox.message({accountId: mailbox.account.id, mailboxId: (mailbox.selectedFolder.path | encodeUri), messageId: currentMessage.uid})">
|
||||
<!-- ui-sref-active="sg-active"> -->
|
||||
<div class="sg-selected-avatar"
|
||||
ng-show="currentMessage.selected"
|
||||
ng-click="currentMessage.selected = !currentMessage.selected"><!-- selected avatar --></div>
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
ng-show="!currentMessage.selected"
|
||||
ng-click="currentMessage.selected = !currentMessage.selected"
|
||||
sg-email="currentMessage['from'][0].email"
|
||||
size="48"><!-- avatar --></sg-avatar-image>
|
||||
<div class="sg-tile-content">
|
||||
<span class="msg-date"
|
||||
ng-bind-html="currentMessage.relativedate"><!-- date --></span>
|
||||
<div class="sg-md-subhead-multi">{{currentMessage.$shortAddress('from')}}</div>
|
||||
<div class="sg-md-body-multi">{{currentMessage.subject}}</div>
|
||||
<i class="icon-ion-refresh"
|
||||
ng-hide="mailbox.selectedFolder.$loadMessage(currentMessage.uid)"><!-- loading --></i>
|
||||
</div>
|
||||
<div class="sg-tile-icons">
|
||||
<md-icon ng-show="currentMessage.isflagged">star</md-icon>
|
||||
<md-icon ng-show="currentMessage.isanswered">reply</md-icon>
|
||||
<md-icon ng-show="currentMessage.isforwarded">forward</md-icon>
|
||||
<md-icon ng-show="currentMessage.hasattachment">attach_file</md-icon>
|
||||
</div>
|
||||
</md-list-item>
|
||||
</div>
|
||||
</md-list>
|
||||
</md-virtual-repeat-container>
|
||||
<div class="sg-progress-circular-floating"
|
||||
ng-show="mailbox.selectedFolder.$isLoading">
|
||||
<md-progress-circular class="md-accent"
|
||||
md-mode="indeterminate"
|
||||
md-diameter="32"><!-- progress --></md-progress-circular>
|
||||
</div>
|
||||
<md-button class="md-fab md-fab-bottom-right md-accent"
|
||||
label:aria-label="Write a new message"
|
||||
ng-click="mailbox.newMessage($event)">
|
||||
@@ -58,12 +54,7 @@
|
||||
</md-content>
|
||||
</div>
|
||||
|
||||
<md-content id="detailView" class="view-detail md-hue-1" layout="column" layout-align="center center"
|
||||
ng-class="{ 'sg-close': !mailbox.selectedFolder.selectedMessage }"
|
||||
ui-view="message">
|
||||
<md-input-container class="hide-sm md-hue-1" style="flex-grow: 0">
|
||||
<label class="sg-md-title"><var:string label:value="No message selected"/></label>
|
||||
</md-input-container>
|
||||
</md-content>
|
||||
<div id="detailView" class="view-detail ng-cloak" layout="column" ui-view="message"
|
||||
ng-show="mailbox.selectedFolder.selectedMessage"><!-- message view --></div>
|
||||
|
||||
</container>
|
||||
@@ -221,13 +221,13 @@
|
||||
|
||||
Templates script tag wrappers go next
|
||||
-->
|
||||
<main class="view layout-fill" ui-view="mailboxes" layout="row" ng-controller="navController"><!-- mailboxes list --></main>
|
||||
<main class="view md-layout-fill" ui-view="mailboxes" layout="row" ng-controller="navController"><!-- mailboxes list --></main>
|
||||
|
||||
<!-- TEMPLATE SCRIPT WRAPPER -->
|
||||
<script type="text/ng-template" id="UIxMailMainFrame">
|
||||
|
||||
<!-- Sidenav -->
|
||||
<md-sidenav id="left-sidenav" class="md-sidenav-left md-whiteframe-z1 layout-fill" md-component-id="left" md-is-locked-open="isGtMedium" layout="column">
|
||||
<md-sidenav id="left-sidenav" class="md-sidenav-left md-whiteframe-z1 md-layout-fill" md-component-id="left" md-is-locked-open="isGtMedium" layout="column">
|
||||
<var:component className="UIxSidenavToolbarTemplate" />
|
||||
<md-content md-scroll-y="md-scroll-y" class="md-flex">
|
||||
<section ng-repeat="account in app.accounts track by account.id">
|
||||
@@ -235,17 +235,17 @@
|
||||
<div layout="row" layout-align="space-between center">
|
||||
<span>{{account.name}}</span>
|
||||
<div>
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="New Folder..."
|
||||
ng-click="app.newFolder(account)">
|
||||
<md-icon>add_circle_outline</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-show="account.id == 0"
|
||||
label:aria-label="Delegation..."
|
||||
ng-click="app.delegate(account)">
|
||||
<md-icon>people</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="New Folder..."
|
||||
ng-click="app.newFolder(account)">
|
||||
<md-icon>add_circle_outline</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-show="account.id == 0"
|
||||
label:aria-label="Delegation..."
|
||||
ng-click="app.delegate(account)">
|
||||
<md-icon>people</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</div>
|
||||
</md-subheader>
|
||||
@@ -287,17 +287,12 @@
|
||||
<var:string label:value="New Subfolder..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$isEditable">
|
||||
<md-button type="button" ng-click="app.editFolder(folder)">
|
||||
<var:string label:value="Rename"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button type="button" ng-click="app.compactFolder(folder)">
|
||||
<var:string label:value="Compact"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-show="folder.$isEditable">
|
||||
<md-menu-item ng-show="folder.$isEditable">
|
||||
<md-button type="button" ng-click="app.confirmDelete(folder)">
|
||||
<var:string label:value="Delete"/>
|
||||
</md-button>
|
||||
@@ -342,14 +337,18 @@
|
||||
</md-content>
|
||||
</md-sidenav>
|
||||
|
||||
<section layout="column" class="sg-app-content layout-fill" ui-view="mailbox"><!-- messages list --></section>
|
||||
<section layout="column" class="sg-app-content md-layout-fill" ui-view="mailbox"><!-- messages list --></section>
|
||||
</script>
|
||||
|
||||
<script type="text/ng-template" id="UIxMailFolderTemplate">
|
||||
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main" >
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top"
|
||||
layout="row" layout-align="space-between start">
|
||||
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top sg-padded" layout="row" layout-align="space-between start">
|
||||
<var:component className="UIxTopnavToolbarTemplate" />
|
||||
<div class="sg-toolbar-group-last">
|
||||
<md-button class="sg-icon-button" label:aria-label="More">
|
||||
<md-icon>more_vert</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-toolbar-tools" layout="row" layout-align="space-between center"
|
||||
ng-show="mailbox.selectedFolder.$selectedCount() == 0">
|
||||
@@ -394,10 +393,9 @@
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-divider> <!-- divider --></md-menu-divider>
|
||||
<md-menu-item>
|
||||
<md-button ng-href="#">
|
||||
<md-menu-item >
|
||||
<md-button ng-click="mailbox.selectedFolder.$filter()">
|
||||
<md-checkbox
|
||||
ng-change="mailbox.selectedFolder.$filter()"
|
||||
ng-model="mailbox.service.$query.asc"
|
||||
ng-true-value="0"
|
||||
ng-false-value="1"><var:string label:value="Descending Order"/></md-checkbox>
|
||||
@@ -474,12 +472,12 @@
|
||||
</md-button>
|
||||
<md-menu-content width="2">
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.markSelectedMessagesAsFlagged()">
|
||||
<md-button>
|
||||
<var:string label:value="Flag"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button ng-click="mailbox.markSelectedMessagesAsUnread()">
|
||||
<md-button>
|
||||
<var:string label:value="Mark as Unread"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
|
||||
@@ -20,18 +20,8 @@
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="From"/>
|
||||
</label>
|
||||
<div layout="row" layout-align="start center">
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
sg-email="viewer.message.from[0].email"
|
||||
size="48">
|
||||
<!-- contact avatar -->
|
||||
</sg-avatar-image>
|
||||
<div class="md-list-item-text">
|
||||
<span>{{ viewer.message.from[0].name }}</span><br/>
|
||||
<a class="md-caption" href="#"
|
||||
ng-bind="viewer.message.from[0].email"
|
||||
ng-click="viewer.newMessage($event, viewer.message.from[0])"><!-- from --></a>
|
||||
</div>
|
||||
<div class="pseudo-input-field">
|
||||
<a ng-href="mailto:{{viewer.message.from[0].email}}" ng-bind="viewer.message.from[0].full"><!-- from --></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,26 +29,8 @@
|
||||
<label class="pseudo-input-label">
|
||||
<var:string label:value="To"/>
|
||||
</label>
|
||||
<div class="pseudo-input-field" ng-hide="viewer.message.$showDetailedRecipients">
|
||||
<a href="#" ng-click="viewer.message.showDetailedRecipients()">{{viewer.message.$shortRecipients()}}</a>
|
||||
</div>
|
||||
<div class="pseudo-input-field" ng-show="viewer.message.$showDetailedRecipients">
|
||||
<span ng-repeat="recipient in viewer.message.to">
|
||||
<a href="#" ng-bind="recipient.full"
|
||||
ng-click="viewer.newMessage($event, recipient)"><!-- recipient --></a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pseudo-input-container--compact" ng-show="viewer.message.$showDetailedRecipients">
|
||||
<label class="pseudo-input-label" ng-show="viewer.message.cc.length > 0">
|
||||
<var:string label:value="Cc"/>
|
||||
</label>
|
||||
<div class="pseudo-input-field">
|
||||
<span ng-repeat="recipient in viewer.message.cc">
|
||||
<a href="#" ng-bind="recipient.full"
|
||||
ng-click="viewer.newMessage($event, recipient)"><!-- recipient --></a>
|
||||
</span>
|
||||
<a ng-href="mailto:{{viewer.message.to[0].email}}" ng-bind="viewer.message.to[0].full"><!-- to --></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +57,7 @@
|
||||
<div class="sg-icon-bar--vertical">
|
||||
<md-button class="sg-icon-button show-sm"
|
||||
label:aria-label="Close"
|
||||
ng-click="viewer.close()">
|
||||
ng-click="toggleDetailView()">
|
||||
<md-icon>close</md-icon>
|
||||
</md-button>
|
||||
<!-- todo: Replace md-tooltip values by localizable string variable -->
|
||||
@@ -130,12 +102,6 @@
|
||||
<var:string label:value="Load Images"/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button label:aria-label="Save As..."
|
||||
ng-click="viewer.saveMessage()">
|
||||
<var:string label:value="Save As..."/>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item>
|
||||
<md-button label:aria-label="View Message Source"
|
||||
ng-click="viewer.viewRawSource($event)">
|
||||
@@ -170,11 +136,9 @@
|
||||
<div class="msg-date sg-md-body-multi">
|
||||
<time datetime="viewer.message.date" ng-bind="viewer.message.date"><!-- date --></time>
|
||||
</div>
|
||||
<div layout="row" layout-wrap="layout-wrap">
|
||||
<div ng-class="part.msgclass" layout="row" layout-wrap="layout-wrap" class="mailer_mailcontent" ng-repeat="part in viewer.message.$content()">
|
||||
<div ng-if="part.html" ng-bind-html="part.content"><!-- msg --></div>
|
||||
<div ng-if="part.compile" sg-compile="part.content"><!-- msg --></div>
|
||||
</div>
|
||||
<div class="mailer_mailcontent" ng-repeat="part in viewer.message.$content()">
|
||||
<div ng-if="part.html" ng-bind-html="part.content"><!-- msg --></div>
|
||||
<div ng-if="part.compile" sg-compile="part.content"><!-- msg --></div>
|
||||
</div>
|
||||
</div>
|
||||
</md-content>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label"
|
||||
const:jsFiles="Main.js, Common.js"
|
||||
const:jsFiles="Main.app.js, Common.js"
|
||||
>
|
||||
<!--
|
||||
MAIN CONTENT ROW
|
||||
@@ -15,13 +15,32 @@
|
||||
MUST be the first html element after body
|
||||
SHOULD be a main tag (with role="main")
|
||||
-->
|
||||
<main class="view layout-fill layout-padding" ui-view="login" layout="row" layout-align="center start">
|
||||
<main class="view md-layout-fill md-layout-padding" ui-view="login" layout="row" layout-align="center start">
|
||||
<md-content class="md-padding" md-scroll-y="true">
|
||||
<div class="sg-login" ng-controller="LoginController as app">
|
||||
<div ng-controller="loginController">
|
||||
|
||||
<script type="text/javascript">
|
||||
var cookieUsername = '<var:string var:value="cookieUsername" const:escapeHTML="NO"/>';
|
||||
</script>
|
||||
<!-- <div id="aboutBox" style="display:none;">
|
||||
<div>
|
||||
<p class="logo"><img const:alt="SOGo" rsrc:src="img/sogo-logo.png"/></p>
|
||||
<p>Version <var:string value="version"/> <span class="buildDate">(<var:string value="buildDate" />)</span></p>
|
||||
<p class="scroll"><var:string label:value="AboutBox" const:escapeHTML="NO"/></p>
|
||||
<img const:alt="Inverse" rsrc:src="img/inverse.png"/>
|
||||
<p class="links"><a href="http://sogo.nu/" target="_new">sogo.nu</a> /
|
||||
<a href="http://inverse.ca/" target="_new">inverse.ca</a></p>
|
||||
<p><a id="aboutClose" href="#" class="button">
|
||||
<span><var:string label:value="OK" /></span></a></p>
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- <nav class="top-bar">
|
||||
<section class="top-bar-section">
|
||||
<ul class="right">
|
||||
<li><a href="#"><var:string label:value="About" /></a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</nav> -->
|
||||
<div id="login">
|
||||
<div id="logo">
|
||||
<img const:alt="*" id="splash" rsrc:src="img/sogo-full.svg"/>
|
||||
@@ -29,22 +48,28 @@
|
||||
|
||||
<form name="loginForm" layout="column"
|
||||
ng-cloak="ng-cloak"
|
||||
ng-submit="app.login()">
|
||||
ng-controller="loginController"
|
||||
ng-submit="login(creds)">
|
||||
<var:if condition="hasLoginSuffix">
|
||||
<input type="hidden" ng-model="app.creds.loginSuffix" var:value="loginSuffix"/>
|
||||
<input type="hidden" ng-model="creds.loginSuffix" var:value="loginSuffix"/>
|
||||
</var:if>
|
||||
<div ng-show="warning" ng-cloak="ng-cloak" alert="alert" class="alert-box radius warning">{{warning}}</div>
|
||||
<md-input-container>
|
||||
<md-icon>person</md-icon>
|
||||
<input autocapitalize="off" type="text" ng-model="app.creds.username" ng-required="true" label:placeholder="Username"/>
|
||||
<label>
|
||||
<var:string label:value="Username"/>
|
||||
</label>
|
||||
<input autocapitalize="off" type="text" ng-model="creds.username" required="required" />
|
||||
</md-input-container>
|
||||
<md-input-container md-no-float="md-no-float">
|
||||
<md-icon>email</md-icon>
|
||||
<input type="password" ng-model="app.creds.password" ng-required="true" label:placeholder="Password"/>
|
||||
<md-input-container>
|
||||
<label>
|
||||
<var:string label:value="Password"/>
|
||||
</label>
|
||||
<input type="password" ng-model="creds.password" required="required" />
|
||||
</md-input-container>
|
||||
|
||||
<!-- CONNECT BUTTON -->
|
||||
<div layout="row" layout-align="end center">
|
||||
<md-button class="md-raised" type="submit" ng-disabled='app.loginForm.$invalid'>
|
||||
<md-button class="md-raised" type="submit" ng-disabled='!loginForm.$valid'>
|
||||
<span>
|
||||
<var:string label:value="Connect"/>
|
||||
</span>
|
||||
@@ -53,32 +78,38 @@
|
||||
|
||||
<!-- LANGUAGES SELECT -->
|
||||
<div layout="row" layout-align="start end">
|
||||
<md-icon>language</md-icon>
|
||||
<md-select flex="true" ng-model="app.creds.language" label:placeholder="choose">
|
||||
<var:foreach list="languages" item="item">
|
||||
<md-option var:value="item">
|
||||
<var:string value="languageText"/>
|
||||
</md-option>
|
||||
</var:foreach>
|
||||
<md-input-container>
|
||||
<label class="login-lang">
|
||||
<var:string label:value="Language"/>
|
||||
</label>
|
||||
<md-select flex="true" ng-model="creds.language">
|
||||
<var:foreach list="languages" item="item">
|
||||
<md-option var:value="item">
|
||||
<var:string value="languageText"/>
|
||||
</md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
</div>
|
||||
|
||||
<!-- DOMAINS SELECT -->
|
||||
<var:if condition="hasLoginDomains">
|
||||
<div layout="row" layout-align="start end">
|
||||
<md-icon>domain</md-icon>
|
||||
<md-select class="md-flex" ng-model="app.creds.domain" label:placeholder="choose">
|
||||
<var:foreach list="loginDomains" item="item">
|
||||
<md-option var:value="item">
|
||||
<var:string value="item"/>
|
||||
</md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
<label>
|
||||
<var:string label:value="Domain"/>
|
||||
</label>
|
||||
<md-select flex="true" ng-model="creds.domain" label:placeholder="choose">
|
||||
<var:foreach list="loginDomains" item="item">
|
||||
<md-option var:value="item">
|
||||
<var:string value="item"/>
|
||||
</md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
</div>
|
||||
</var:if>
|
||||
|
||||
<div layout="row" layout-align="center center">
|
||||
<md-switch ng-model="app.creds.rememberLogin" label:arial-label="Remember username">
|
||||
<md-switch ng-model="creds.rememberLogin" label:arial-label="Remember username">
|
||||
<var:string label:value="Remember username"/>
|
||||
</md-switch>
|
||||
</div>
|
||||
@@ -86,7 +117,7 @@
|
||||
<div layout="row" layout-align="end end" ng-cloak="ng-cloak">
|
||||
<md-button class="sg-icon-button fg-sogoPaper-500"
|
||||
label:aria-label="About"
|
||||
ng-click="app.showAbout()">
|
||||
ng-click="showAbout()">
|
||||
<md-icon class="material-icons fg-sogoPaper-500">info</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
@@ -105,7 +136,7 @@
|
||||
<!--<img class="full-image" const:alt="Inverse" rsrc:src="img/inverse.png"/>-->
|
||||
</md-dialog-content>
|
||||
<div class="md-actions">
|
||||
<md-button ng-click="about.closeDialog()"><var:string label:value="Close"/></md-button>
|
||||
<md-button ng-click="closeDialog()"><var:string label:value="Close"/></md-button>
|
||||
</div>
|
||||
</md-dialog>
|
||||
</script>
|
||||
|
||||
@@ -9,98 +9,74 @@
|
||||
xmlns:label="OGo:label"
|
||||
className="UIxPageFrame"
|
||||
>
|
||||
<md-dialog flex="50" flex-sm="100">
|
||||
<md-toolbar class="md-padding">
|
||||
<div class="md-toolbar-tools">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">account_box</md-icon>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Account Name"/></label>
|
||||
<input type="text" required="required"
|
||||
ng-readonly="$AccountDialogController.accountId == 0"
|
||||
ng-model="$AccountDialogController.account.name"/>
|
||||
</md-input-container>
|
||||
<md-button type="button" class="sg-icon-button " ng-click="$AccountDialogController.cancel()">
|
||||
<md-icon>close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<md-dialog>
|
||||
<md-dialog-content>
|
||||
|
||||
<form id="mainForm" name="accountForm" var:href="ownPath">
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Account Name"/></label>
|
||||
<input type="text" required="required"
|
||||
ng-readonly="accountId == 0" ng-model="account.name"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Server Name"/></label>
|
||||
<input type="text" required="required"
|
||||
ng-readonly="$AccountDialogController.accountId == 0"
|
||||
ng-model="$AccountDialogController.account.serverName"/>
|
||||
ng-readonly="accountId == 0" ng-model="account.serverName"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Port"/></label>
|
||||
<input type="number" required="required" min="1" max="65535"
|
||||
ng-readonly="$AccountDialogController.accountId == 0"
|
||||
ng-model="$AccountDialogController.account.port"/>
|
||||
ng-readonly="accountId == 0" ng-model="account.port"/>
|
||||
</md-input-container>
|
||||
|
||||
<label><var:string label:value="Encryption"/></label>
|
||||
<md-radio-group ng-model="$AccountDialogController.account.encryption">
|
||||
<md-radio-button ng-disabled="$AccountDialogController.accountId == 0" value="none" class="md-primary"><var:string label:value="None"/></md-radio-button>
|
||||
<md-radio-button ng-disabled="$AccountDialogController.accountId == 0" value="ssl"><var:string label:value="SSL"/></md-radio-button>
|
||||
<md-radio-button ng-disabled="$AccountDialogController.accountId == 0" value="tls"><var:string label:value="TLS"/></md-radio-button>
|
||||
<md-radio-group ng-model="account.encryption">
|
||||
<md-radio-button ng-disabled="accountId == 0" value="none" class="md-primary"><var:string label:value="None"/></md-radio-button>
|
||||
<md-radio-button ng-disabled="accountId == 0" value="ssl"><var:string label:value="SSL"/></md-radio-button>
|
||||
<md-radio-button ng-disabled="accountId == 0" value="tls"><var:string label:value="TLS"/></md-radio-button>
|
||||
</md-radio-group>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="User Name"/></label>
|
||||
<input type="text" required="required"
|
||||
ng-readonly="$AccountDialogController.accountId == 0"
|
||||
ng-model="$AccountDialogController.account.userName"/>
|
||||
ng-readonly="accountId == 0" ng-model="account.userName"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Password"/></label>
|
||||
<input type="password"
|
||||
ng-readonly="$AccountDialogController.accountId == 0"
|
||||
ng-model="$AccountDialogController.account.password"/>
|
||||
<input type="password" ng-readonly="accountId == 0"
|
||||
ng-model="account.password"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Full Name"/></label>
|
||||
<input type="text" required="required"
|
||||
ng-readonly="$AccountDialogController.customFromIsReadonly()"
|
||||
ng-model="$AccountDialogController.account.identities[0].fullName"/>
|
||||
ng-readonly="customFromIsReadonly()"
|
||||
ng-model="account.identities[0].fullName"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Email"/></label>
|
||||
<input type="email" required="required"
|
||||
ng-readonly="$AccountDialogController.customFromIsReadonly()"
|
||||
ng-model="$AccountDialogController.account.identities[0].email"/>
|
||||
ng-readonly="customFromIsReadonly()"
|
||||
ng-model="account.identities[0].email"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Reply To Email"/></label>
|
||||
<input type="email" ng-model="$AccountDialogController.account.identities[0].replyTo"/>
|
||||
<input type="email" ng-model="account.identities[0].replyTo"/>
|
||||
</md-input-container>
|
||||
|
||||
<!-- To switch between a simple text editor and the CK/HTML editor, we use a ng-if and not
|
||||
a ng-class as it doesn't get initialized by the ckEditor class directive -->
|
||||
<md-input-container ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'text'">
|
||||
<label><var:string label:value="Signature"/> {{$AccountDialogController.defaults.SOGoMailComposeMessageType}}</label>
|
||||
<textarea ng-model="$AccountDialogController.account.identities[0].signature"><!-- signature --></textarea>
|
||||
</md-input-container>
|
||||
<div class="pseudo-input-container"
|
||||
ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'html'">
|
||||
<label class="pseudo-input-label"><var:string label:value="Signature"/> {{$AccountDialogController.defaults.LocaleCode}}</label>
|
||||
<textarea class="ck-editor"
|
||||
ck-locale="$AccountDialogController.defaults.LocaleCode"
|
||||
ck-options="{ 'height': '70px',
|
||||
'toolbar': [['Bold', 'Italic', '-', 'Link',
|
||||
'Font','FontSize','-','TextColor',
|
||||
'BGColor']] }"
|
||||
ng-model="$AccountDialogController.account.identities[0].signature"><!-- signature --></textarea>
|
||||
</div>
|
||||
<!-- FIXME -->
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Signature"/></label>
|
||||
<input type="text" ng-model="account.identities[0].signature" />
|
||||
</md-input-container>
|
||||
|
||||
<md-radio-group ng-model="$AccountDialogController.account.receipts.receiptAction">
|
||||
<md-radio-group ng-model="account.receipts.receiptAction">
|
||||
<label><var:string label:value="When I receive a request for a return receipt"/></label>
|
||||
<md-radio-button value="ignore"><var:string label:value="Never send a return receipt"/></md-radio-button>
|
||||
<md-radio-button value="allow"><var:string label:value="Allow return receipts for some messages"/></md-radio-button>
|
||||
@@ -108,7 +84,7 @@
|
||||
|
||||
<label>
|
||||
<var:string label:value="If I'm not in the To or Cc of the message"/>
|
||||
<md-select ng-model="$AccountDialogController.account.receipts.receiptNonRecipientAction">
|
||||
<md-select ng-model="account.receipts.receiptNonRecipientAction">
|
||||
<md-option const:value="ignore"><var:string label:value="Never send"/></md-option>
|
||||
<md-option const:value="send"><var:string label:value="Always send"/></md-option>
|
||||
<md-option const:value="ask"><var:string label:value="Ask me"/></md-option>
|
||||
@@ -117,7 +93,7 @@
|
||||
|
||||
<label>
|
||||
<var:string label:value="If the sender is outside my domain"/>
|
||||
<md-select ng-model="$AccountDialogController.account.receipts.receiptOutsideDomainAction">
|
||||
<md-select ng-model="account.receipts.receiptOutsideDomainAction">
|
||||
<md-option const:value="ignore"><var:string label:value="Never send"/></md-option>
|
||||
<md-option const:value="send"><var:string label:value="Always send"/></md-option>
|
||||
<md-option const:value="ask"><var:string label:value="Ask me"/></md-option>
|
||||
@@ -126,18 +102,20 @@
|
||||
|
||||
<label>
|
||||
<var:string label:value="In all other cases"/>
|
||||
<md-select ng-model="$AccountDialogController.account.receipts.receiptAnyAction">
|
||||
<md-select ng-model="account.receipts.receiptAnyAction">
|
||||
<md-option const:value="ignore"><var:string label:value="Never send"/></md-option>
|
||||
<md-option const:value="send"><var:string label:value="Always send"/></md-option>
|
||||
<md-option const:value="ask"><var:string label:value="Ask me"/></md-option>
|
||||
</md-select>
|
||||
</label>
|
||||
|
||||
<div class="md-actions" layout="row">
|
||||
<md-button type="button" ng-click="cancel()">Cancel</md-button>
|
||||
<md-button type="button" class="md-primary"
|
||||
ng-disabled="accountForm.$invalid" ng-click="save()">Save</md-button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</md-dialog-content>
|
||||
<div class="md-actions">
|
||||
<md-button ng-disabled="$AccountDialogController.accountForm.$invalid" ng-click="$AccountDialogController.save()"><var:string label:value="Save"/></md-button>
|
||||
</div>
|
||||
</md-dialog>
|
||||
</var:component>
|
||||
@@ -7,31 +7,23 @@
|
||||
xmlns:label="OGo:label"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:uix="OGo:uix"><var:string var:value="doctype" const:escapeHTML="NO" />
|
||||
<md-dialog flex="50" flex-sm="100">
|
||||
<form id="mainForm" var:href="ownPath">
|
||||
<md-toolbar class="md-padding">
|
||||
<div class="md-toolbar-tools">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">filter_list</md-icon>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Filter name:"/></label>
|
||||
<input class="md-title" type="text" ng-model="filter.name" required="required"/>
|
||||
</md-input-container>
|
||||
<md-button type="button" class="sg-icon-button " ng-click="cancel()">
|
||||
<md-icon>close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<md-dialog flex="50">
|
||||
<md-dialog-content>
|
||||
<script type="text/javascript">
|
||||
var filterId = '<var:string value="filterId"/>';
|
||||
var sieveFolderEncoding = '<var:string value="sieveFolderEncoding"/>';
|
||||
var mailTags = <var:string value="labels" const:escapeHTML="NO"/>;
|
||||
</script>
|
||||
|
||||
<div layout="row" layout-align="start center">
|
||||
<div><var:string label:value="For incoming messages that"/></div>
|
||||
<md-input-container class="md-flex">
|
||||
<md-select ng-model="filter.match" required="required">
|
||||
<form id="mainForm" var:href="ownPath">
|
||||
<div id="filterNameContainer" class="container">
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Filter name:"/></label>
|
||||
<input const:name="filterName" type="text" ng-model="filter.name"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<div id="filterMatchContainer" class="container">
|
||||
<var:string label:value="For incoming messages that"/>
|
||||
<md-select const:name="matchType" const:id="matchType" ng-model="filter.match">
|
||||
<md-option const:value="all">
|
||||
<var:string label:value="match all of the following rules:"/>
|
||||
</md-option>
|
||||
@@ -42,135 +34,107 @@
|
||||
<var:string label:value="match all messages"/>
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CONDITIONS -->
|
||||
<div layout="column">
|
||||
<div id="filterRules"><!-- empty -->
|
||||
<md-list>
|
||||
<md-list-item ng-repeat="rule in filter.rules">
|
||||
<md-input-container flex="25">
|
||||
<!-- CONDITIONS -->
|
||||
<div id="filterRulesContainer" class="container">
|
||||
<div id="filterRules"><!-- empty -->
|
||||
<md-list>
|
||||
<md-list-item ng-repeat="rule in filter.rules">
|
||||
<md-select ng-model="rule.field">
|
||||
<md-option ng-value="key" ng-repeat="(key, value) in fieldLabels">{{ value }}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container flex="25" ng-show="rule.field == 'header'">
|
||||
<input type="text" ng-model="rule.custom_header"/>
|
||||
</md-input-container>
|
||||
<input type="text" ng-show="rule.field ==
|
||||
'header'" ng-model="rule.custom_header"/>
|
||||
|
||||
<md-input-container flex="25" ng-show="rule.field == 'size'">
|
||||
<md-select ng-model="rule.operator">
|
||||
<md-select ng-show="rule.field =='size'" ng-model="rule.operator">
|
||||
<md-option ng-value="key" ng-repeat="(key, value) in numberOperatorLabels">
|
||||
{{ value }}
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container flex="25" ng-show="rule.field != 'size'">
|
||||
<md-select ng-model="rule.operator">
|
||||
<md-select ng-show="rule.field !='size'" ng-model="rule.operator">
|
||||
<md-option ng-value="key" ng-repeat="(key, value) in textOperatorLabels">
|
||||
{{ value }}
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<md-input-container class="md-flex">
|
||||
<input type="text" ng-model="rule.value"/>
|
||||
</md-input-container>
|
||||
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="removeMailFilterRule($index)">
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="removeMailFilterRule($index)">
|
||||
<md-icon>remove</md-icon>
|
||||
</md-button>
|
||||
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</div>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</div>
|
||||
|
||||
<div layout="row" layout-align="end center">
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="addMailFilterRule($event)">
|
||||
<md-icon>add_circle</md-icon>
|
||||
<md-icon>add</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ACTIONS -->
|
||||
<div layout="column">
|
||||
<var:string label:value="Perform these actions:"/>
|
||||
<div id="filterActions"><!-- empty --></div>
|
||||
<!-- ACTIONS -->
|
||||
<div id="filterActionsContainer" class="container">
|
||||
<var:string label:value="Perform these actions:"/><br/>
|
||||
<div id="filterActions"><!-- empty --></div>
|
||||
|
||||
<md-list>
|
||||
<md-list-item layout="row" layout-align="space-between center"
|
||||
ng-repeat="action in filter.actions">
|
||||
<md-input-container>
|
||||
<md-list>
|
||||
<md-list-item ng-repeat="action in filter.actions">
|
||||
<md-select ng-model="action.method">
|
||||
<md-option ng-value="key" ng-repeat="(key, value) in methodLabels">{{ value }}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<!-- FORWARD MESSAGE TO -->
|
||||
<md-input-container ng-show="action.method == 'redirect'" >
|
||||
<input type="text" ng-model="action.argument"/>
|
||||
</md-input-container>
|
||||
<!-- FORWARD MESSAGE TO -->
|
||||
<input type="text" ng-show="action.method == 'redirect'" ng-model="action.argument"/>
|
||||
|
||||
<!-- DISCARD -->
|
||||
<!-- nada -->
|
||||
<!-- DISCARD -->
|
||||
<!-- nada -->
|
||||
|
||||
<!-- KEEP -->
|
||||
<!-- nada -->
|
||||
<!-- KEEP -->
|
||||
<!-- nada -->
|
||||
|
||||
<!-- SEND REJECT MESSAGE -->
|
||||
<md-input-container ng-show="action.method == 'reject'">
|
||||
<input type="text" ng-model="action.argument"/>
|
||||
</md-input-container>
|
||||
<!-- SEND REJECT MESSAGE -->
|
||||
<input type="text" ng-show="action.method == 'reject'" ng-model="action.argument"/>
|
||||
|
||||
<!-- FILE INTO -->
|
||||
<md-input-container ng-show="action.method == 'fileinto'" >
|
||||
<md-select ng-model="action.argument">
|
||||
<!-- FILE INTO -->
|
||||
<md-select ng-show="action.method == 'fileinto'" ng-model="action.argument">
|
||||
<md-option ng-value="item.path" ng-repeat="item in mailboxes">
|
||||
{{ item.name }}
|
||||
</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<!-- FLAG WITH -->
|
||||
<md-input-container ng-show="action.method == 'addflag'" >
|
||||
<md-select ng-model="action.argument" >
|
||||
<md-option value="seen"><var:string label:value="Seen"/></md-option>
|
||||
<md-option value="deleted"><var:string label:value="Deleted"/></md-option>
|
||||
<md-option value="answered"><var:string label:value="Answered"/></md-option>
|
||||
<md-option value="flagged"><var:string label:value="Flagged"/></md-option>
|
||||
<md-option value="junk"><var:string label:value="Junk"/></md-option>
|
||||
<md-option value="not_junk"><var:string label:value="Not Junk"/></md-option>
|
||||
<!-- FLAG WITH -->
|
||||
<md-select ng-show="action.method == 'addflag'" ng-model="action.argument" >
|
||||
<md-option ng-value="key" ng-repeat="(key, value) in labels">{{ value[0] }}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
|
||||
<!-- STOP -->
|
||||
<!-- nada -->
|
||||
<!-- STOP -->
|
||||
<!-- nada -->
|
||||
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="removeMailFilterAction($index)">
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="removeMailFilterAction($index)">
|
||||
<md-icon>remove</md-icon>
|
||||
</md-button>
|
||||
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</md-list>
|
||||
|
||||
<div layout="row" layout-align="end center">
|
||||
<md-button class="sg-icon-button" type="button"
|
||||
ng-click="addMailFilterAction($event)">
|
||||
<md-icon>add_circle</md-icon>
|
||||
<md-icon>add</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
<div class="md-actions" layout="row">
|
||||
<md-button type="button" ng-click="cancel()">Cancel</md-button>
|
||||
<md-button type="button" class="md-primary" ng-click="save()">Save</md-button>
|
||||
</div>
|
||||
</md-dialog-content>
|
||||
<div class="md-actions">
|
||||
<md-button type="button" ng-click="save()"><var:string label:value="Save"/></md-button>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</md-dialog-content>
|
||||
</md-dialog>
|
||||
</container>
|
||||
File diff suppressed because it is too large.
Load diff
@@ -4,39 +4,33 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<md-dialog flex="60" flex-sm="100">
|
||||
<md-dialog flex="60">
|
||||
<form name="eventForm" ng-submit="editor.save(eventForm)">
|
||||
<md-toolbar class="sg-padded" ng-class="editor.component.getClassName('bg')">
|
||||
<md-toolbar class="md-padding" ng-class="editor.component.getClassName('bg')">
|
||||
<div class="md-toolbar-tools">
|
||||
<!-- summary -->
|
||||
<md-icon ng-if="editor.component.classification == 'confidential'">visibility_off</md-icon>
|
||||
<md-icon ng-if="editor.component.classification == 'private'">vpn_key</md-icon>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Title"/></label>
|
||||
<md-input-container md-no-float="true">
|
||||
<input type="text"
|
||||
class="md-title"
|
||||
ng-model="editor.component.summary"
|
||||
required="required"/>
|
||||
label:placeholder="Title"
|
||||
ng-model="editor.component.summary"/>
|
||||
</md-input-container>
|
||||
<md-button class="md-icon-button" ng-click="editor.cancel()">
|
||||
<md-icon aria-label="Close dialog">close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<!--<md-chips>
|
||||
<md-chip ng-repeat="category in editor.component.categories">{{category}}</md-chip>
|
||||
</md-chips>-->
|
||||
<md-dialog-content>
|
||||
<!-- location -->
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Location"/></label>
|
||||
<input type="text" ng-model="editor.component.location"/>
|
||||
</md-input-container>
|
||||
<!-- calendar -->
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Calendar"/></label>
|
||||
<md-select ng-model="editor.component.destinationCalendar">
|
||||
<md-option ng-repeat="calendar in ::editor.calendars"
|
||||
ng-value="calendar.id">{{calendar.name}}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
<!-- categories -->
|
||||
<md-chips ng-model="editor.component.categories">
|
||||
<md-autocomplete
|
||||
@@ -47,6 +41,14 @@
|
||||
<span md-highlight-text="editor.categories.searchText">{{category}}</span>
|
||||
</md-autocomplete>
|
||||
</md-chips>
|
||||
<!-- calendar -->
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Calendar"/></label>
|
||||
<md-select ng-model="editor.component.destinationCalendar">
|
||||
<md-option ng-repeat="calendar in ::editor.calendars"
|
||||
ng-value="calendar.id">{{calendar.name}}</md-option>
|
||||
</md-select>
|
||||
</md-input-container>
|
||||
<!-- classification -->
|
||||
<md-radio-group layout="row" layout-align="space-around center"
|
||||
ng-model="editor.component.classification">
|
||||
@@ -61,8 +63,8 @@
|
||||
</md-radio-button>
|
||||
</md-radio-group>
|
||||
<!-- priority -->
|
||||
<div class="pseudo-input-container">
|
||||
<label class="pseudo-input-label"><var:string label:value="Priority"/></label>
|
||||
<div layout="row" layout-align="center center">
|
||||
<div flex="20"><var:string label:value="Priority"/></div>
|
||||
<md-slider class="md-flex"
|
||||
md-discrete="true"
|
||||
ng-model="editor.component.priority"
|
||||
@@ -96,17 +98,15 @@
|
||||
<var:string label:value="Send Appointment Notifications"/>
|
||||
</md-checkbox>
|
||||
<!-- start + end -->
|
||||
<div layout="column">
|
||||
<div layout="row" layout-align="start center">
|
||||
<span><var:string label:value="From"/></span>
|
||||
<md-datepicker ng-model="editor.component.start"> <!-- date picker--></md-datepicker>
|
||||
<sg-timepicker ng-model="editor.component.start"><!-- time picker --></sg-timepicker>
|
||||
</div>
|
||||
<div layout="row" layout-align="start center">
|
||||
<span><var:string label:value="To"/></span>
|
||||
<md-datepicker ng-model="editor.component.end"> <!-- date picker--></md-datepicker>
|
||||
<sg-timepicker ng-model="editor.component.end"><!-- time picker --></sg-timepicker>
|
||||
</div>
|
||||
<div layout="row">
|
||||
<md-input-container>
|
||||
<label><var:string label:value="From"/></label>
|
||||
<input type="text" ng-model="editor.component.startDate"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="To"/></label>
|
||||
<input type="text" ng-model="editor.component.endDate"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<!-- attach urls -->
|
||||
<div class="attr" ng-repeat="attach in editor.component.attachUrls">
|
||||
@@ -188,7 +188,7 @@
|
||||
md-search-text="editor.searchText"
|
||||
md-selected-item-change="editor.addAttendee(card)"
|
||||
md-items="card in editor.cardFilter(editor.searchText)"
|
||||
md-item-text="card.empty"
|
||||
md-item-text="user.empty"
|
||||
md-min-length="3"
|
||||
md-delay="300"
|
||||
md-no-cache="true"
|
||||
@@ -243,8 +243,7 @@
|
||||
<md-button type="button" ng-click="editor.component.$reset()">
|
||||
<var:string label:value="Reset"/>
|
||||
</md-button>
|
||||
<md-button class="md-primary md-hue-3" type="submit"
|
||||
ng-disabled="editor.eventForm.$invalid">
|
||||
<md-button class="md-primary md-hue-3" type="submit">
|
||||
<var:string label:value="Save"/>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
class="md-flex"
|
||||
md-input-name="delegatedTo"
|
||||
md-search-text="editor.component.delegatedTo"
|
||||
md-selected-item="cardToAdd"
|
||||
md-selected-item="editor.cardToAdd"
|
||||
md-items="card in editor.cardFilter(editor.component.delegatedTo)"
|
||||
md-item-text="card.$$email"
|
||||
md-min-length="3"
|
||||
|
||||
@@ -18,30 +18,28 @@
|
||||
<li><var:string label:value="Copy event to my calendar"/></li>
|
||||
<li><var:string label:value="View Raw Source"/></li>
|
||||
</ul>
|
||||
</div>-->
|
||||
<md-content>
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Day"
|
||||
var:date="prevDayQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="currentDayName" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Day"
|
||||
var:date="nextDayQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="calendarContent">
|
||||
<var:component
|
||||
className="UIxCalDayTable"
|
||||
startDate="startDate"
|
||||
const:CSSClass="dayOverview"
|
||||
const:numberOfDays="1"
|
||||
const:currentView="dayview"/>
|
||||
</div>
|
||||
</md-content>
|
||||
</div>-->
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Day"
|
||||
var:date="prevDayQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="currentDayName" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Day"
|
||||
var:date="nextDayQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="calendarContent">
|
||||
<var:component
|
||||
className="UIxCalDayTable"
|
||||
startDate="startDate"
|
||||
const:CSSClass="dayOverview"
|
||||
const:numberOfDays="1"
|
||||
const:currentView="dayview"/>
|
||||
</div>
|
||||
</container>
|
||||
@@ -138,12 +138,15 @@
|
||||
</div>
|
||||
-->
|
||||
|
||||
<main class="view layout-fill" ui-view="calendars" layout="row" ng-controller="navController"><!-- calendars list --></main>
|
||||
<main class="view md-layout-fill" ui-view="calendars" layout="row" ng-controller="navController"><!-- calendars list --></main>
|
||||
|
||||
<script type = "text/ng-template" id="UIxCalMainFrame">
|
||||
<!-- calendars colors -->
|
||||
<div sg-folder-stylesheet="true"
|
||||
ng-repeat="calendar in calendars.service.$findAll()"
|
||||
ng-repeat="calendar in calendars.service.$calendars"
|
||||
ng-model="calendar"><!-- stylesheet --></div>
|
||||
<div sg-folder-stylesheet="true"
|
||||
ng-repeat="calendar in calendars.service.$subscriptions"
|
||||
ng-model="calendar"><!-- stylesheet --></div>
|
||||
<!-- Sidenav -->
|
||||
<md-sidenav id="left-sidenav" class="md-sidenav-left md-whiteframe-z1" md-component-id="left" md-is-locked-open="isGtMedium" layout="column">
|
||||
@@ -305,20 +308,18 @@
|
||||
</md-sidenav>
|
||||
|
||||
<!-- Main section -->
|
||||
<section layout="column" class="sg-app-content layout-fill"
|
||||
<section layout="column" class="sg-app-content md-layout-fill"
|
||||
ng-controller="CalendarListController as list">
|
||||
<md-toolbar layout="column" layout-align="space-between start" class="md-tall toolbar-main">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top" layout="row" layout-align="space-between start">
|
||||
<var:component className="UIxTopnavToolbarTemplate" />
|
||||
<!-- <div class="sg-toolbar-group-2">
|
||||
<div class="md-toolbar-tools md-toolbar-tools-top sg-padded" layout="row" layout-align="space-between start">
|
||||
<!-- <var:component className="UIxTopnavToolbarTemplate" /> -->
|
||||
<div class="sg-toolbar-group-2">
|
||||
<md-button class="sg-icon-button" label:aria-label="Search">
|
||||
<md-icon>search</md-icon>
|
||||
</md-button>
|
||||
</div> -->
|
||||
</div>
|
||||
</div><!-- .md-toolbar-tools -->
|
||||
<div class="md-toolbar-tools" layout="row"
|
||||
layout-align="space-between center"
|
||||
ng-show="list.component.$selectedCount() == 0">
|
||||
<div class="md-toolbar-tools" layout="row" layout-align="space-between center">
|
||||
<!-- sort/filter mode -->
|
||||
<div class="view-list" layout="row" layout-align="space-between center"
|
||||
ng-hide="list.mode.search">
|
||||
@@ -474,18 +475,16 @@
|
||||
</md-menu-item>
|
||||
<md-menu-divider><!-- divider --></md-menu-divider>
|
||||
<md-menu-item ng-if="list.componentType == 'events'">
|
||||
<md-button ng-href="#">
|
||||
<md-button ng-click="list.component.$filter(list.componentType)">
|
||||
<md-checkbox
|
||||
ng-change="list.component.$filter(list.componentType)"
|
||||
ng-model="list.component.$queryEvents.asc"
|
||||
ng-true-value="0"
|
||||
ng-false-value="1"><var:string label:value="Descending Order"/></md-checkbox>
|
||||
</md-button>
|
||||
</md-menu-item>
|
||||
<md-menu-item ng-if="list.componentType == 'tasks'">
|
||||
<md-button ng-href="#">
|
||||
<md-button ng-click="list.component.$filter(list.componentType)">
|
||||
<md-checkbox
|
||||
ng-change="list.component.$filter(list.componentType)"
|
||||
ng-model="list.component.$queryTasks.asc"
|
||||
ng-true-value="0"
|
||||
ng-false-value="1"><var:string label:value="Descending Order"/></md-checkbox>
|
||||
@@ -493,9 +492,6 @@
|
||||
</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
<md-button class="sg-icon-button" ng-click="list.component.$filter(list.componentType)">
|
||||
<md-icon>refresh</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- search mode -->
|
||||
@@ -518,7 +514,7 @@
|
||||
</md-input-container>
|
||||
</div>
|
||||
<!-- day/week/month views -->
|
||||
<div>
|
||||
<div class="sg-padded">
|
||||
<a class="sg-icon-button md-button"
|
||||
label:aria-label="Day"
|
||||
href="#/calendar/day"><md-icon>view_day</md-icon></a>
|
||||
@@ -530,19 +526,6 @@
|
||||
href="#/calendar/month"><md-icon>view_module</md-icon></a>
|
||||
</div>
|
||||
</div>
|
||||
<div layout="row" layout-align="start center" ng-show="list.component.$selectedCount() > 0">
|
||||
<md-button class="sg-icon-button" ng-click="list.unselectComponents()">
|
||||
<md-icon>arrow_back</md-icon>
|
||||
</md-button>
|
||||
<label>{{list.component.$selectedCount()}} selected</label>
|
||||
<md-button class="sg-icon-button" ng-click="list.selectAll()">
|
||||
<md-tooltip md-direction="left"><var:string label:value="Select All"/></md-tooltip>
|
||||
<md-icon>select_all</md-icon>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-click="list.confirmDeleteSelectedComponents()">
|
||||
<md-icon>delete</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
<md-content layout="row" class="md-flex">
|
||||
<md-content class="view-list md-flex" layout="column">
|
||||
@@ -551,28 +534,24 @@
|
||||
<!-- Events list -->
|
||||
<md-tab label:label="Events"
|
||||
md-on-select="list.selectComponentType('events')">
|
||||
<md-list class="sg-section-list">
|
||||
<md-list-item class="md-2-line"
|
||||
<md-list>
|
||||
<md-list-item class="md-clickable md-2-line"
|
||||
ng-repeat="event in list.component.$events"
|
||||
ng-click="list.openEvent($event, event)">
|
||||
<div class="sg-selected-avatar" ng-show="event.selected"
|
||||
ng-click="event.selected = !event.selected">
|
||||
<!-- selected avatar -->
|
||||
</div>
|
||||
<i class="md-tile-left" ng-class="event.getClassName('bg')" ng-show="!event.selected" ng-click="event.selected = !event.selected"><!-- calendar color --></i>
|
||||
<i class="md-avatar" ng-class="event.getClassName('bg')" ><!-- calendar color --></i>
|
||||
<div class="md-list-item-text">
|
||||
<h3>{{event.c_title}}</h3>
|
||||
<p>{{event.c_location}}</p>
|
||||
<p class="md-secondary" layout="row">
|
||||
{{event.formatted_startdate}}
|
||||
<i class="sg-tile-icons">
|
||||
<span class="sg-tile-icons">
|
||||
<md-icon ng-show="event.c_iscycle">repeat</md-icon>
|
||||
<md-icon ng-show="event.c_nextalarm">alarm</md-icon>
|
||||
</i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</md-list-item>
|
||||
<md-list-item disabled="disabled" ng-if="list.component.$events.length == 0">
|
||||
<md-list-item ng-if="list.component.$events.length == 0">
|
||||
<p class="sg-md-caption"><var:string label:value="No events for selected criteria"/></p>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
@@ -580,15 +559,11 @@
|
||||
<!-- Tasks list -->
|
||||
<md-tab label:label="Tasks"
|
||||
md-on-select="list.selectComponentType('tasks')">
|
||||
<md-list class="sg-section-list">
|
||||
<md-list-item class="md-2-line"
|
||||
<md-list>
|
||||
<md-list-item class="md-clickable md-2-line"
|
||||
ng-repeat="task in list.component.$tasks"
|
||||
ng-click="list.openTask($event, task)">
|
||||
<div class="sg-selected-avatar" ng-show="task.selected"
|
||||
ng-click="task.selected = !task.selected">
|
||||
<!-- selected avatar -->
|
||||
</div>
|
||||
<i class="md-tile-left" ng-class="task.getClassName('bg')" ng-show="!task.selected" ng-click="task.selected = !task.selected"><!-- calendar color --></i>
|
||||
<i class="md-avatar" ng-class="task.getClassName('bg')" ><!-- calendar color --></i>
|
||||
<div class="md-list-item-text">
|
||||
<h3>{{task.c_title}}</h3>
|
||||
<p class="md-secondary" layout="row">
|
||||
@@ -600,7 +575,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</md-list-item>
|
||||
<md-list-item disabled="disabled" ng-if="list.component.$tasks.length == 0">
|
||||
<md-list-item ng-if="list.component.$tasks.length == 0">
|
||||
<p class="sg-md-caption"><var:string label:value="No tasks for selected criteria"/></p>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
@@ -612,7 +587,7 @@
|
||||
<md-icon>add</md-icon>
|
||||
</md-button>
|
||||
</md-content>
|
||||
<div id="detailView" hide-sm="hide-sm" class="view-detail" layout="column" ui-view="calendarView"><!-- calendar view --></div>
|
||||
<md-content class="view-detail sg-padded" ui-view="calendarView"><!-- calendar view --></md-content>
|
||||
</md-content>
|
||||
</section>
|
||||
</script>
|
||||
|
||||
@@ -21,22 +21,21 @@
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<md-content>
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Month"
|
||||
var:date="prevMonthQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="monthNameOfThisMonth" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Month"
|
||||
var:date="nextMonthQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Month"
|
||||
var:date="prevMonthQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="monthNameOfThisMonth" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Month"
|
||||
var:date="nextMonthQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="monthView">
|
||||
<div layout="row" layout-align="center center">
|
||||
<var:foreach list="headerDaysToDisplay" item="currentTableDay">
|
||||
@@ -56,16 +55,13 @@
|
||||
var:day-number="currentDayNumber"
|
||||
var:id="currentDayId">
|
||||
<div layout="column" layout-fill="true">
|
||||
<div class="sg-calendar-tile-header"><var:string value="dayHeaderNumber"/></div>
|
||||
<sg-calendar-month-day
|
||||
sg-blocks="calendar.blocks"
|
||||
sg-click="list.openEvent(event, component)"
|
||||
var:sg-day="currentTableDay.shortDateString"><!-- day's events --></sg-calendar-month-day>
|
||||
</div>
|
||||
<div class="sg-calendar-tile-header"><var:string value="dayHeaderNumber"/></div>
|
||||
<sg-calendar-month-day
|
||||
sg-blocks="calendar.blocks"
|
||||
var:sg-day="currentTableDay.shortDateString"><!-- day's events --></sg-calendar-month-day></div>
|
||||
</md-grid-tile>
|
||||
</var:foreach>
|
||||
</var:foreach>
|
||||
</md-grid-list>
|
||||
</div>
|
||||
</md-content>
|
||||
</container>
|
||||
@@ -6,29 +6,27 @@
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
<md-content>
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Week"
|
||||
var:date="prevWeekQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="currentWeekName" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Week"
|
||||
var:date="nextWeekQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="calendarContent">
|
||||
<var:component
|
||||
className="UIxCalDayTable"
|
||||
startDate="startDate"
|
||||
const:CSSClass="weekOverview"
|
||||
const:numberOfDays="7"
|
||||
const:currentView="weekview"/>
|
||||
</div>
|
||||
</md-content>
|
||||
<div layout="row" layout-align="center">
|
||||
<h5>
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Previous Week"
|
||||
var:date="prevWeekQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_left</md-icon></md-button>
|
||||
<var:string value="currentWeekName" />
|
||||
<md-button
|
||||
class="sg-icon-button"
|
||||
label:aria-label="Next Week"
|
||||
var:date="nextWeekQueryParameters.day"
|
||||
ng-click="calendar.changeView($event)"><md-icon>chevron_right</md-icon></md-button>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="calendarContent">
|
||||
<var:component
|
||||
className="UIxCalDayTable"
|
||||
startDate="startDate"
|
||||
const:CSSClass="weekOverview"
|
||||
const:numberOfDays="7"
|
||||
const:currentView="weekview"/>
|
||||
</div>
|
||||
</container>
|
||||
@@ -7,15 +7,14 @@
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
|
||||
<md-dialog flex="60" flex-sm="100">
|
||||
<md-dialog flex="40">
|
||||
<md-toolbar class="sg-padded">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">link</md-icon>
|
||||
<div class="md-toolbar-tools">
|
||||
<div class="pseudo-input-container md-flex">
|
||||
<label class="pseudo-input-label"><var:string label:value="Links to this Calendar"/></label>
|
||||
<div class="pseudo-input-field sg-md-title">{{links.calendar.name}}</div>
|
||||
<div class="pseudo-input-field sg-md-title"><var:string value="calendar.displayName"/></div>
|
||||
</div>
|
||||
<md-button class="md-icon-button" ng-click="links.close()">
|
||||
<md-button class="md-icon-button" ng-click="close()">
|
||||
<md-icon label:aria-label="Close">close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
@@ -25,45 +24,50 @@
|
||||
<div layout="column" layout-padding="layout-padding">
|
||||
|
||||
<div layout="column" layout-padding="layout-padding">
|
||||
<md-input-container ng-show="links.calendar.isWebCalendar">
|
||||
<label><var:string label:value="URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.webCalendarURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
|
||||
<div ng-hide="links.calendar.isWebCalendar">
|
||||
<var:if condition="isWebCalendar">
|
||||
<md-input-container>
|
||||
<label><var:string label:value="URL"/></label>
|
||||
<input var:value="webCalendarURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
</var:if>
|
||||
<var:if condition="isWebCalendar" const:negate="YES">
|
||||
<div class="sg-md-title"><var:string label:value="Authenticated User Access"/></div>
|
||||
|
||||
<md-input-container>
|
||||
<label><var:string label:value="CalDAV URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.calDavURL" ng-readonly="true"/>
|
||||
<input var:value="calDavURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="WebDAV ICS URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.webDavICSURL" ng-readonly="true"/>
|
||||
<input var:value="webDavICSURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="WebDAV XML URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.webDavXMLURL" ng-readonly="true"/>
|
||||
<input var:value="webDavXMLURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
</var:if>
|
||||
</div>
|
||||
|
||||
<var:if condition="isPublicAccessEnabled">
|
||||
<div layout="column" layout-padding="layout-padding" ng-hide="links.calendar.isWebCalendar">
|
||||
<var:if condition="isWebCalendar" const:negate="YES">
|
||||
<div layout="column" layout-padding="layout-padding">
|
||||
<div class="sg-md-title"><var:string label:value="Public Access"/></div>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="CalDAV URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.publicCalDavURL" ng-readonly="true"/>
|
||||
<input var:value="publicCalDavURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="WebDAV ICS URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.publicWebDavICSURL" ng-readonly="true"/>
|
||||
<input var:value="publicWebDavICSURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="WebDAV XML URL"/></label>
|
||||
<input type="text" ng-model="links.calendar.urls.publicWebDavXMLURL" ng-readonly="true"/>
|
||||
<input var:value="publicWebDavXMLURL" ng-readonly="true"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
</var:if>
|
||||
</var:if>
|
||||
</div>
|
||||
|
||||
</md-dialog-content>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<md-dialog flex-sm="100">
|
||||
<md-dialog>
|
||||
|
||||
<md-toolbar ng-style="{ 'background-color': properties.calendar.color }">
|
||||
<div class="md-toolbar-tools sg-padded--right">
|
||||
|
||||
@@ -22,19 +22,15 @@
|
||||
<md-input-container class="md-input-number">
|
||||
<input type="number" label:aria-label="Every" ng-model="editor.component.repeat.interval"/>
|
||||
</md-input-container>
|
||||
<var:string label:value="Week(s)"/>
|
||||
</div>
|
||||
<div class="pseudo-input-container layout-padding" layout="row" layout-align="center center">
|
||||
<label class="pseudo-input-label"><var:string label:value="On"/></label>
|
||||
<md-grid-list md-cols="7" md-row-height="2em" md-gutter="0.5em"
|
||||
flex="50" flex-md="80" flex-sm="100"
|
||||
sg-toggle-grid="editor.component.repeat.days"
|
||||
sg-toggle-grid-attr="day">
|
||||
<var:foreach list="shortWeekDaysList" item="item">
|
||||
<md-grid-tile var:value="valueForWeekDay"><var:string value="labelForWeekDay"/></md-grid-tile>
|
||||
</var:foreach>
|
||||
</md-grid-list>
|
||||
<var:string label:value="Week(s)"/> <var:string label:value="On"/>
|
||||
</div>
|
||||
<md-grid-list md-cols="7" md-row-height="1:1" md-gutter="0.5em"
|
||||
sg-toggle-grid="editor.component.repeat.days"
|
||||
sg-toggle-grid-attr="day">
|
||||
<var:foreach list="shortWeekDaysList" item="item">
|
||||
<md-grid-tile var:value="valueForWeekDay"><var:string value="labelForWeekDay"/></md-grid-tile>
|
||||
</var:foreach>
|
||||
</md-grid-list>
|
||||
</div>
|
||||
|
||||
<!-- monthly -->
|
||||
@@ -50,43 +46,40 @@
|
||||
<md-radio-button value="bymonthday">
|
||||
<var:string label:value="Recur on day(s)"/>
|
||||
</md-radio-button>
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-grid-list md-cols="7" md-row-height="2em" md-gutter="0.5em"
|
||||
flex="50" flex-md="80" flex-sm="100"
|
||||
sg-toggle-grid="editor.component.repeat.monthdays">
|
||||
<md-grid-tile value="1">1</md-grid-tile>
|
||||
<md-grid-tile value="2">2</md-grid-tile>
|
||||
<md-grid-tile value="3">3</md-grid-tile>
|
||||
<md-grid-tile value="4">4</md-grid-tile>
|
||||
<md-grid-tile value="5">5</md-grid-tile>
|
||||
<md-grid-tile value="6">6</md-grid-tile>
|
||||
<md-grid-tile value="7">7</md-grid-tile>
|
||||
<md-grid-tile value="8">8</md-grid-tile>
|
||||
<md-grid-tile value="9">9</md-grid-tile>
|
||||
<md-grid-tile value="10">10</md-grid-tile>
|
||||
<md-grid-tile value="11">11</md-grid-tile>
|
||||
<md-grid-tile value="12">12</md-grid-tile>
|
||||
<md-grid-tile value="13">13</md-grid-tile>
|
||||
<md-grid-tile value="14">14</md-grid-tile>
|
||||
<md-grid-tile value="15">15</md-grid-tile>
|
||||
<md-grid-tile value="16">16</md-grid-tile>
|
||||
<md-grid-tile value="17">17</md-grid-tile>
|
||||
<md-grid-tile value="18">18</md-grid-tile>
|
||||
<md-grid-tile value="19">19</md-grid-tile>
|
||||
<md-grid-tile value="20">20</md-grid-tile>
|
||||
<md-grid-tile value="21">21</md-grid-tile>
|
||||
<md-grid-tile value="22">22</md-grid-tile>
|
||||
<md-grid-tile value="23">23</md-grid-tile>
|
||||
<md-grid-tile value="24">24</md-grid-tile>
|
||||
<md-grid-tile value="25">25</md-grid-tile>
|
||||
<md-grid-tile value="26">26</md-grid-tile>
|
||||
<md-grid-tile value="27">27</md-grid-tile>
|
||||
<md-grid-tile value="28">28</md-grid-tile>
|
||||
<md-grid-tile value="29">29</md-grid-tile>
|
||||
<md-grid-tile value="30">30</md-grid-tile>
|
||||
<md-grid-tile value="31">31</md-grid-tile>
|
||||
</md-grid-list>
|
||||
</div>
|
||||
<md-grid-list md-cols="7" md-row-height="1:1" md-gutter="0.5em"
|
||||
sg-toggle-grid="editor.component.repeat.monthdays">
|
||||
<md-grid-tile value="1">1</md-grid-tile>
|
||||
<md-grid-tile value="2">2</md-grid-tile>
|
||||
<md-grid-tile value="3">3</md-grid-tile>
|
||||
<md-grid-tile value="4">4</md-grid-tile>
|
||||
<md-grid-tile value="5">5</md-grid-tile>
|
||||
<md-grid-tile value="6">6</md-grid-tile>
|
||||
<md-grid-tile value="7">7</md-grid-tile>
|
||||
<md-grid-tile value="8">8</md-grid-tile>
|
||||
<md-grid-tile value="9">9</md-grid-tile>
|
||||
<md-grid-tile value="10">10</md-grid-tile>
|
||||
<md-grid-tile value="11">11</md-grid-tile>
|
||||
<md-grid-tile value="12">12</md-grid-tile>
|
||||
<md-grid-tile value="13">13</md-grid-tile>
|
||||
<md-grid-tile value="14">14</md-grid-tile>
|
||||
<md-grid-tile value="15">15</md-grid-tile>
|
||||
<md-grid-tile value="16">16</md-grid-tile>
|
||||
<md-grid-tile value="17">17</md-grid-tile>
|
||||
<md-grid-tile value="18">18</md-grid-tile>
|
||||
<md-grid-tile value="19">19</md-grid-tile>
|
||||
<md-grid-tile value="20">20</md-grid-tile>
|
||||
<md-grid-tile value="21">21</md-grid-tile>
|
||||
<md-grid-tile value="22">22</md-grid-tile>
|
||||
<md-grid-tile value="23">23</md-grid-tile>
|
||||
<md-grid-tile value="24">24</md-grid-tile>
|
||||
<md-grid-tile value="25">25</md-grid-tile>
|
||||
<md-grid-tile value="26">26</md-grid-tile>
|
||||
<md-grid-tile value="27">27</md-grid-tile>
|
||||
<md-grid-tile value="28">28</md-grid-tile>
|
||||
<md-grid-tile value="29">29</md-grid-tile>
|
||||
<md-grid-tile value="30">30</md-grid-tile>
|
||||
<md-grid-tile value="31">31</md-grid-tile>
|
||||
</md-grid-list>
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-radio-button value="byday">
|
||||
<var:string label:value="The"/>
|
||||
@@ -118,30 +111,27 @@
|
||||
</md-input-container>
|
||||
<var:string label:value="Year(s)"/>
|
||||
</div>
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-grid-list md-cols="6" md-row-height="2em" md-gutter="0.5em"
|
||||
flex="50" flex-md="80" flex-sm="100"
|
||||
sg-toggle-grid="editor.component.repeat.months">
|
||||
<var:foreach list="yearlyMonthList" item="item">
|
||||
<md-grid-tile var:value="valueForYearlyMonth"><var:string value="item"/></md-grid-tile>
|
||||
</var:foreach>
|
||||
</md-grid-list>
|
||||
</div>
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-checkbox ng-model="editor.component.repeat.year.byday">
|
||||
<var:string label:value="The"/>
|
||||
</md-checkbox>
|
||||
<md-select ng-model="editor.component.repeat.month.occurrence">
|
||||
<var:foreach list="monthlyRepeatList" item="item">
|
||||
<md-option var:value="valueForMonthlyRepeat"><var:string value="itemText"/></md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
<md-select ng-model="editor.component.repeat.month.day">
|
||||
<var:foreach list="yearlyDayList" item="item">
|
||||
<md-option var:value="valueForYearlyDay"><var:string value="item"/></md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
</div>
|
||||
<md-grid-list md-cols="6" md-row-height="1:1" md-gutter="0.5em"
|
||||
sg-toggle-grid="editor.component.repeat.months">
|
||||
<var:foreach list="yearlyMonthList" item="item">
|
||||
<md-grid-tile var:value="valueForYearlyMonth"><var:string value="item"/></md-grid-tile>
|
||||
</var:foreach>
|
||||
</md-grid-list>
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-checkbox ng-model="editor.component.repeat.year.byday">
|
||||
<var:string label:value="The"/>
|
||||
</md-checkbox>
|
||||
<md-select ng-model="editor.component.repeat.month.occurrence">
|
||||
<var:foreach list="monthlyRepeatList" item="item">
|
||||
<md-option var:value="valueForMonthlyRepeat"><var:string value="itemText"/></md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
<md-select ng-model="editor.component.repeat.month.day">
|
||||
<var:foreach list="yearlyDayList" item="item">
|
||||
<md-option var:value="valueForYearlyDay"><var:string value="item"/></md-option>
|
||||
</var:foreach>
|
||||
</md-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</container>
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<div layout="row" layout-align="start center" layout-wrap="layout-wrap">
|
||||
<div layout="row" layout-align="start center">
|
||||
<md-input-container class="md-input-number">
|
||||
<input type="number" label:aria-label="quantity" ng-model="editor.component.alarm.quantity"/>
|
||||
</md-input-container>
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<md-dialog flex="60" flex-sm="100">
|
||||
<md-dialog flex="60">
|
||||
<form name="eventForm" ng-submit="editor.save(eventForm)">
|
||||
<md-toolbar ng-class="editor.component.getClassName('bg')">
|
||||
<div class="md-toolbar-tools sg-padded">
|
||||
<md-toolbar class="md-padding" ng-class="editor.component.getClassName('bg')">
|
||||
<div class="md-toolbar-tools">
|
||||
<!-- summary -->
|
||||
<md-icon ng-if="editor.component.classification == 'confidential'">visibility_off</md-icon>
|
||||
<md-icon ng-if="editor.component.classification == 'private'">vpn_key</md-icon>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Title"/></label>
|
||||
<md-input-container md-no-float="true">
|
||||
<input type="text"
|
||||
class="md-title"
|
||||
ng-model="editor.component.summary"
|
||||
required="required"/>
|
||||
label:placeholder="Title"
|
||||
ng-model="editor.component.summary"/>
|
||||
</md-input-container>
|
||||
<md-button class="md-icon-button" ng-click="editor.cancel()">
|
||||
<md-icon aria-label="Close dialog">close</md-icon>
|
||||
@@ -80,35 +79,15 @@
|
||||
<var:string label:value="All day Event"/>
|
||||
</md-checkbox>
|
||||
<!-- start + end -->
|
||||
<div class="section" layout="column">
|
||||
<div layout="row" layout-align="start center" ng-show="editor.component.start">
|
||||
<label><var:string label:value="From"/></label>
|
||||
<md-datepicker ng-model="editor.component.start"> <!-- date picker--></md-datepicker>
|
||||
<sg-timepicker ng-model="editor.component.start"><!-- time picker --></sg-timepicker>
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.component.$deleteStartDate()">
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
<div class="md-layout-margin" layout="row" layout-align="start center" ng-hide="editor.component.start">
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.component.$addStartDate()">
|
||||
<md-icon>add_circle</md-icon>
|
||||
</md-button>
|
||||
<label class="button-label"><var:string label:value="Add From"/></label>
|
||||
</div>
|
||||
</div>
|
||||
<div layout="row" layout-align="start center" ng-show="editor.component.due">
|
||||
<label><var:string label:value="Due"/></label>
|
||||
<md-datepicker ng-model="editor.component.due"> <!-- date picker--></md-datepicker>
|
||||
<sg-timepicker ng-model="editor.component.due"><!-- time picker --></sg-timepicker>
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.component.$deleteDueDate()">
|
||||
<md-icon>remove_circle</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
<div class="md-layout-margin" layout="row" layout-align="start center" ng-hide="editor.component.due">
|
||||
<md-button class="sg-icon-button" type="button" ng-click="editor.component.$addDueDate()">
|
||||
<md-icon>add_circle</md-icon>
|
||||
</md-button>
|
||||
<label class="button-label"><var:string label:value="Add Due"/></label>
|
||||
<div layout="row">
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Start"/></label>
|
||||
<input type="text" ng-model="editor.component.startDate"/>
|
||||
</md-input-container>
|
||||
<md-input-container>
|
||||
<label><var:string label:value="Due"/></label>
|
||||
<input type="text" ng-model="editor.component.dueDate"/>
|
||||
</md-input-container>
|
||||
</div>
|
||||
<!-- status -->
|
||||
<div layout="row">
|
||||
@@ -227,8 +206,7 @@
|
||||
<md-button type="button" ng-click="editor.component.$reset()">
|
||||
<var:string label:value="Reset"/>
|
||||
</md-button>
|
||||
<md-button class="md-primary md-hue-3" type="submit"
|
||||
ng-disabled="editor.eventForm.$invalid">
|
||||
<md-button class="md-primary md-hue-3" type="submit">
|
||||
<var:string label:value="Save"/>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<md-dialog flex="40" flex-md="60" flex-sm="100">
|
||||
<md-toolbar class="md-padding" ng-class="editor.component.getClassName('bg')">
|
||||
<md-dialog flex="40">
|
||||
<md-toolbar class="md-padding" ng-class="viewer.component.getClassName('bg')">
|
||||
<div class="md-toolbar-tools">
|
||||
<md-icon class="material-icons sg-icon-toolbar-bg">assignment_turned_in</md-icon>
|
||||
<div class="sg-md-title md-flex">
|
||||
<h2 class="md-flex">
|
||||
<!-- classification -->
|
||||
<md-icon ng-if="editor.component.classification == 'confidential'">visibility_off</md-icon>
|
||||
<md-icon ng-if="editor.component.classification == 'private'">vpn_key</md-icon>
|
||||
<md-icon ng-if="viewer.component.classification == 'confidential'">visibility_off</md-icon>
|
||||
<md-icon ng-if="viewer.component.classification == 'private'">vpn_key</md-icon>
|
||||
<!-- summary -->
|
||||
{{editor.component.summary}}
|
||||
{{viewer.component.summary}}
|
||||
<!-- priority -->
|
||||
<md-icon ng-repeat="i in editor.component.priority | range">star</md-icon>
|
||||
</div>
|
||||
<md-button class="md-icon-button" ng-click="editor.close()">
|
||||
<md-icon ng-repeat="i in viewer.component.priority | range">star</md-icon>
|
||||
</h2>
|
||||
<md-button class="md-icon-button" ng-click="viewer.close()">
|
||||
<md-icon aria-label="Close dialog">close</md-icon>
|
||||
</md-button>
|
||||
</div>
|
||||
@@ -25,77 +25,77 @@
|
||||
<md-dialog-content>
|
||||
<md-list>
|
||||
<!-- categories -->
|
||||
<md-list-item ng-show="editor.component.categories.length > 0">
|
||||
<md-chips class="sg-readonly" ng-model="editor.component.categories" readonly="true">
|
||||
<md-list-item ng-show="viewer.component.categories.length > 0">
|
||||
<md-chips ng-model="viewer.component.categories" readonly="true">
|
||||
<md-chip-template>
|
||||
<span>{{$chip}}</span>
|
||||
</md-chip-template>
|
||||
</md-chips>
|
||||
</md-list-item>
|
||||
<!-- location -->
|
||||
<md-list-item ng-show="editor.component.location">
|
||||
<md-list-item ng-show="viewer.component.location">
|
||||
<md-icon>place</md-icon>
|
||||
<p>{{editor.component.location}}</p>
|
||||
<p>{{viewer.component.location}}</p>
|
||||
</md-list-item>
|
||||
<!-- calendar -->
|
||||
<md-list-item>
|
||||
<md-icon>event</md-icon>
|
||||
<p>{{editor.component.calendar}}</p>
|
||||
<p>{{viewer.component.calendar}}</p>
|
||||
</md-list-item>
|
||||
<!-- start/due dates -->
|
||||
<md-list-item class="md-2-line">
|
||||
<md-icon>access_time</md-icon>
|
||||
<div layout="row" class="md-flex">
|
||||
<div class="md-list-item-text" ng-show="editor.component.startDate">
|
||||
<div class="md-list-item-text" ng-show="viewer.component.startDate">
|
||||
<p><var:string label:value="Start"/></p>
|
||||
<h3>
|
||||
{{editor.component.localizedStartDate}}
|
||||
<span ng-hide="editor.component.isAllDay"> {{editor.component.localizedStartTime}}</span>
|
||||
{{viewer.component.localizedStartDate}}
|
||||
<span ng-hide="viewer.component.isAllDay"> {{viewer.component.localizedStartTime}}</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="md-list-item-text" ng-show="editor.component.dueDate">
|
||||
<div class="md-list-item-text" ng-show="viewer.component.dueDate">
|
||||
<p><var:string label:value="Due Date"/></p>
|
||||
<h3>
|
||||
{{editor.component.localizedDueDate}}
|
||||
<span ng-hide="editor.component.isAllDay">{{editor.component.localizedDueTime}}</span>
|
||||
{{viewer.component.localizedDueDate}}
|
||||
<span ng-hide="viewer.component.isAllDay">{{viewer.component.localizedDueTime}}</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</md-list-item>
|
||||
<!-- status -->
|
||||
<md-list-item ng-show="editor.component.status == 'completed'">
|
||||
<md-list-item ng-show="viewer.component.status == 'completed'">
|
||||
<md-icon>check</md-icon>
|
||||
<p>{{editor.component.localizedCompletedDate}} {{editor.component.localizedCompletedTime}}</p>
|
||||
<p>{{viewer.component.localizedCompletedDate}} {{viewer.component.localizedCompletedTime}}</p>
|
||||
</md-list-item>
|
||||
<md-list-item ng-show="editor.component.enablePercentComplete()">
|
||||
<md-list-item ng-show="viewer.component.enablePercentComplete()">
|
||||
<md-icon>call_made</md-icon>
|
||||
<p>{{editor.component.percentComplete}} %</p>
|
||||
<p>{{viewer.component.percentComplete}} %</p>
|
||||
</md-list-item>
|
||||
<!-- attach urls -->
|
||||
<md-list-item ng-repeat="url in editor.component.attachUrls">
|
||||
<md-list-item ng-show="viewer.component.attachUrls.length > 0">
|
||||
<md-icon>link</md-icon>
|
||||
<p><a ng-href="url.value">{{url.value}}</a></p>
|
||||
<p ng-repeat="url in viewer.component.attachUrls"><a ng-href="url.value">{{url.value}}</a></p>
|
||||
</md-list-item>
|
||||
<!-- comment -->
|
||||
<md-list-item ng-show="editor.component.comment">
|
||||
<md-list-item ng-show="viewer.component.comment">
|
||||
<md-icon>mode_comment</md-icon>
|
||||
<p>{{editor.component.comment}}</p>
|
||||
<p>{{viewer.component.comment}}</p>
|
||||
</md-list-item>
|
||||
<!-- repeat -->
|
||||
<md-list-item ng-show="editor.component.repeat">
|
||||
<md-list-item ng-show="viewer.component.repeat">
|
||||
<md-icon>repeat</md-icon>
|
||||
<p><!-- editor.component.repeat.toString() --></p>
|
||||
<p><!-- viewer.component.repeat.toString() --></p>
|
||||
</md-list-item>
|
||||
<!-- reminder -->
|
||||
<md-list-item ng-show="editor.component.$hasAlarm">
|
||||
<md-list-item ng-show="viewer.component.$hasAlarm">
|
||||
<md-icon>alarm</md-icon>
|
||||
<p><!-- editor.component.alarm.toString() --></p>
|
||||
<p><!-- viewer.component.alarm.toString() --></p>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</md-dialog-content>
|
||||
<!-- edit -->
|
||||
<div class="md-actions" ng-show="editor.component.isEditable()">
|
||||
<md-button ng-click="editor.edit()">
|
||||
<div class="md-actions">
|
||||
<md-button ng-click="viewer.edit()">
|
||||
<var:string label:value="Edit"/>
|
||||
</md-button>
|
||||
</div>
|
||||
|
||||
+194
-78
@@ -6,31 +6,38 @@
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:rsrc="OGo:url"
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<var:string var:value="doctype" const:escapeHTML="NO" />
|
||||
<var:if condition="hideFrame" const:negate="YES">
|
||||
<html const:xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" const:lang="en">
|
||||
<var:if condition="hideFrame" const:negate="YES"
|
||||
>
|
||||
<html const:xmlns="http://www.w3.org/1999/xhtml"
|
||||
xml:lang="en" const:lang="en">
|
||||
<head>
|
||||
<title>
|
||||
<var:string value="title" />
|
||||
</title>
|
||||
<meta name="hideFrame" var:content="hideFrame" />
|
||||
<meta name="description" content="SOGo Web Interface" />
|
||||
<meta name="author" content="Inverse inc." />
|
||||
<meta name="author" content="SKYRIX Software AG/Inverse inc." />
|
||||
<meta name="robots" content="stop" />
|
||||
<meta name="build" var:content="buildDate" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link href="mailto:support@inverse.ca" rev="made" />
|
||||
<link rel="shortcut icon" var:href="siteFavicon" type="image/x-icon" />
|
||||
<link type="text/css" rel="stylesheet" rsrc:href="css/styles.css" />
|
||||
<var:if condition="hasPageSpecificCSS">
|
||||
<link type="text/css" rel="stylesheet" var:href="pageCSSURL"/>
|
||||
<var:if condition="hasPageSpecificCSS"
|
||||
>
|
||||
<link type="text/css" rel="stylesheet" var:href="pageCSSURL"
|
||||
/>
|
||||
</var:if>
|
||||
<var:foreach list="additionalCSSFiles" item="item">
|
||||
<link type="text/css" rel="stylesheet" var:href="item"/>
|
||||
<var:foreach list="additionalCSSFiles" item="item"
|
||||
>
|
||||
<link type="text/css" rel="stylesheet" var:href="item"
|
||||
/>
|
||||
</var:foreach>
|
||||
<var:if-ie const:lte="9">
|
||||
<var:if-ie const:lte="9"
|
||||
>
|
||||
<link type="text/css" rel="stylesheet" rsrc:href="iefixes.css" />
|
||||
<script type="text/javascript" rsrc:src="XMLHttpRequest.js"><!-- space --></script>
|
||||
</var:if-ie>
|
||||
@@ -42,26 +49,152 @@
|
||||
<div id="popupFrame" style="display: none;">
|
||||
<iframe width="100%" height="100%" src="/SOGo/loading"><!-- space --></iframe>
|
||||
</div>
|
||||
</var:if>
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
<var:if condition="hasUserSettingsKeys">
|
||||
</var:if
|
||||
>
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous"
|
||||
const:negate="YES">
|
||||
<var:if condition="hasUserSettingsKeys"
|
||||
>
|
||||
<script type="text/javascript">
|
||||
var UserSettings =<var:string value="userSettings" const:escapeHTML="NO" />;
|
||||
</script>
|
||||
</script
|
||||
>
|
||||
</var:if>
|
||||
<var:if condition="hasUserDefaultsKeys">
|
||||
<script type="text/javascript">
|
||||
var UserDefaults =<var:string value="userDefaults" const:escapeHTML="NO" />;
|
||||
</script>
|
||||
</var:if>
|
||||
</var:if>
|
||||
<var:if condition="isPopup" const:negate="YES">
|
||||
<var:if condition="isUIxDebugEnabled"><!-- space --></var:if>
|
||||
</script
|
||||
>
|
||||
</var:if
|
||||
>
|
||||
</var:if
|
||||
>
|
||||
<var:if condition="isPopup" const:negate="YES"
|
||||
>
|
||||
<var:if condition="isUIxDebugEnabled"
|
||||
><!-- space --></var:if>
|
||||
</var:if>
|
||||
<!-- MAIN CONTENT ROW -->
|
||||
|
||||
<!-- MAIN CONTENT ROW -->
|
||||
<var:component-content />
|
||||
|
||||
<!-- BOTTOM-SHEET -->
|
||||
<script type="text/ng-template" id="bottomSheetTemplate.html">
|
||||
<md-bottom-sheet class="md-list">
|
||||
<md-list>
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
|
||||
<!-- CALENDAR -->
|
||||
<var:if condition="userHasCalendarAccess">
|
||||
<var:if condition="isCalendar">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" ng-disabled="true">
|
||||
<md-icon>event</md-icon>
|
||||
<var:string label:value="Calendar"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
<var:if condition="isCalendar" const:negate="YES">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:href="relativeCalendarPath">
|
||||
<md-icon>event</md-icon>
|
||||
<var:string label:value="Calendar"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
</var:if>
|
||||
|
||||
<!-- CONTACTS -->
|
||||
<var:if condition="isContacts">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" ng-disabled="true">
|
||||
<md-icon>contacts</md-icon>
|
||||
<var:string label:value="Address Book"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
<var:if condition="isContacts" const:negate="YES">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:href="relativeContactsPath">
|
||||
<md-icon>contacts</md-icon>
|
||||
<var:string label:value="Address Book"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
|
||||
<!-- MAIL -->
|
||||
<var:if condition="userHasMailAccess">
|
||||
<var:if condition="isMail">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" ng-disabled="true">
|
||||
<md-icon>email</md-icon>
|
||||
<var:string label:value="Mail"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
<var:if condition="isMail" const:negate="YES">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:href="relativeMailPath">
|
||||
<md-icon>email</md-icon>
|
||||
<var:string label:value="Mail"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
</var:if>
|
||||
|
||||
<!-- PREFERENCES -->
|
||||
<var:if condition="isPreferences">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" ng-disabled="true">
|
||||
<md-icon>settings</md-icon>
|
||||
<var:string label:value="Preferences"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
<var:if condition="isPreferences" const:negate="YES">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:ng-href="relativePreferencesPath">
|
||||
<md-icon>settings</md-icon>
|
||||
<var:string label:value="Preferences"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
|
||||
<!-- ADMINISTRATION -->
|
||||
<var:if condition="isSuperUser">
|
||||
<var:if condition="isAdministration">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" ng-disabled="true">
|
||||
<md-icon>settings_applications</md-icon>
|
||||
<var:string label:value="Administration"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
<var:if condition="isAdministration" const:negate="YES">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:href="relativeAdministrationPath">
|
||||
<md-icon>settings_applications</md-icon>
|
||||
<var:string label:value="Administration"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
</var:if>
|
||||
|
||||
<!-- DISCONNECT -->
|
||||
<var:if condition="canLogoff">
|
||||
<md-list-item>
|
||||
<md-button class="md-list-item-content" var:ng-href="logoffPath">
|
||||
<md-icon>settings_power</md-icon>
|
||||
<var:string label:value="Disconnect"/>
|
||||
</md-button>
|
||||
</md-list-item>
|
||||
</var:if>
|
||||
</var:if>
|
||||
|
||||
</md-list>
|
||||
</md-bottom-sheet>
|
||||
</script>
|
||||
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
</var:if>
|
||||
|
||||
@@ -69,92 +202,75 @@
|
||||
<script type="text/javascript">
|
||||
var ApplicationBaseURL = '<var:string value="modulePath" />';
|
||||
var ResourcesURL = '<var:string value="applicationPath" />.woa/WebServerResources';
|
||||
var minimumSearchLength = <var:string value="minimumSearchLength" />;
|
||||
<var:if condition="isSuperUser">
|
||||
var IsSuperUser = true;
|
||||
var minimumSearchLength =<var:string value="minimumSearchLength" />;
|
||||
<var:if condition="isSuperUser"
|
||||
>var IsSuperUser = true;
|
||||
</var:if>
|
||||
<var:if condition="isSuperUser" const:negate="YES">
|
||||
var IsSuperUser = false;
|
||||
<var:if condition="isSuperUser" const:negate="YES"
|
||||
>var IsSuperUser = false;
|
||||
</var:if>
|
||||
<var:if condition="usesCASAuthentication">
|
||||
var usesCASAuthentication = true;
|
||||
<var:if condition="usesCASAuthentication"
|
||||
>var usesCASAuthentication = true;
|
||||
</var:if>
|
||||
<var:if condition="usesCASAuthentication" const:negate="YES">
|
||||
var usesCASAuthentication = false;
|
||||
<var:if condition="usesCASAuthentication" const:negate="YES"
|
||||
>var usesCASAuthentication = false;
|
||||
</var:if>
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous" const:negate="YES">
|
||||
var UserFolderURL = '<var:string value="userFolderPath" const:escapeHTML="NO" />';
|
||||
<var:if condition="shortUserNameForDisplay" const:value="anonymous"
|
||||
const:negate="YES"
|
||||
>var UserFolderURL = '<var:string value="userFolderPath" const:escapeHTML="NO" />';
|
||||
var UserLogin = '<var:string value="shortUserNameForDisplay" const:escapeHTML="NO" />';
|
||||
var UserIdentification = '<var:string value="userIdentification" const:escapeHTML="NO" />';
|
||||
var UserEmail = '<var:string value="userEmail" const:escapeHTML="NO" />';
|
||||
var UserLanguage = '<var:string value="userLanguage" const:escapeHTML="NO" />';
|
||||
|
||||
// Application paths
|
||||
var UserCalendarPath = '';
|
||||
<var:if condition="userHasCalendarAccess">
|
||||
UserCalendarPath = '<var:string value="relativeCalendarPath" const:escapeHTML="NO" />';
|
||||
</var:if>
|
||||
|
||||
var UserContactsPath = '<var:string value="relativeContactsPath" const:escapeHTML="NO" />';
|
||||
|
||||
var UserMailPath = '';
|
||||
<var:if condition="userHasMailAccess">
|
||||
UserMailPath = '<var:string value="relativeMailPath" const:escapeHTML="NO" />';
|
||||
</var:if>
|
||||
|
||||
var UserPreferencesPath = '<var:string value="relativePreferencesPath" const:escapeHTML="NO" />';
|
||||
|
||||
<var:if condition="isSuperUser">
|
||||
var UserAdministrationPath = '<var:string value="relativeAdministrationPath" const:escapeHTML="NO" />';
|
||||
</var:if>
|
||||
|
||||
var UserLogoffPath = '';
|
||||
<var:if condition="canLogoff">
|
||||
UserLogoffPath = '<var:string value="logoffPath" const:escapeHTML="NO" />';
|
||||
</var:if>
|
||||
|
||||
</var:if>
|
||||
|
||||
// This is the equivalent of an AJAX call to /SOGo/so/_UserLogin_/date
|
||||
var currentDay = <var:string value="currentDayDescription" const:escapeHTML="NO"/>;
|
||||
// This is the equivalent of an AJAX call to /SOGo/so/_UserLogin_/date
|
||||
var currentDay = <var:string value="currentDayDescription" const:escapeHTML="NO"/>;
|
||||
<var:string value="commonLocalizableStrings" const:escapeHTML="NO" />
|
||||
<var:string value="productLocalizableStrings" const:escapeHTML="NO" />
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" rsrc:src="js/vendor/lodash.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-animate.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-sanitize.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-aria.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-animate.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-sanitize.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-aria.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-material.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-ui-router.min.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/vendor/angular-ui-router.js"><!-- space --></script>
|
||||
<script type="text/javascript" rsrc:src="js/Common/utils.js"><!-- space --></script>
|
||||
|
||||
<var:if condition="hasProductSpecificJavaScript">
|
||||
<script type="text/javascript" var:src="productJavaScriptURL"><!-- space --></script>
|
||||
<script type="text/javascript"
|
||||
var:src="productJavaScriptURL"><!-- space --></script>
|
||||
</var:if>
|
||||
<var:if condition="hasPageSpecificJavaScript">
|
||||
<script type="text/javascript" var:src="pageJavaScriptURL"><!-- space --></script>
|
||||
<script type="text/javascript"
|
||||
var:src="pageJavaScriptURL"><!-- space --></script>
|
||||
</var:if>
|
||||
<var:foreach list="additionalJSFiles" item="item">
|
||||
<var:foreach list="additionalJSFiles" item="item"
|
||||
>
|
||||
<script type="text/javascript" var:src="item"><!-- space --></script>
|
||||
</var:foreach>
|
||||
<var:foreach list="systemAdditionalJSFiles" item="item">
|
||||
<var:foreach list="systemAdditionalJSFiles" item="item"
|
||||
>
|
||||
<script type="text/javascript" var:src="item"><!-- space --></script>
|
||||
</var:foreach>
|
||||
</var:if>
|
||||
<var:if condition="isCompatibleBrowser" const:negate="YES">
|
||||
<var:component className="SOGoBrowsersPanel"/>
|
||||
<var:if condition="isCompatibleBrowser" const:negate="YES"
|
||||
>
|
||||
<var:component className="SOGoBrowsersPanel"
|
||||
/>
|
||||
</var:if>
|
||||
|
||||
<noscript>
|
||||
<div class="javascriptPopupBackground">
|
||||
</div>
|
||||
<div class="javascriptMessagePseudoWindow noJavascriptErrorMessage">
|
||||
<var:string label:value="noJavascriptError"/>
|
||||
<br/>
|
||||
<br/>
|
||||
<a class="button" var:href="page.context.uri">
|
||||
<var:string label:value="noJavascriptRetry"/>
|
||||
<var:string label:value="noJavascriptError"
|
||||
/>
|
||||
<br />
|
||||
<br
|
||||
/>
|
||||
<a class="button" var:href="page.context.uri"
|
||||
>
|
||||
<var:string label:value="noJavascriptRetry"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
@@ -3,14 +3,27 @@
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
<md-toolbar class="md-tall sg-padded">
|
||||
<div layout="column" layout-align="center start">
|
||||
<sg-avatar-image class="md-tile-left"
|
||||
sg-email="activeUser.email"
|
||||
size="48"><!-- avatar --></sg-avatar-image>
|
||||
<p class="sg-md-title">{{activeUser.identification}}</p>
|
||||
<p class="md-caption">{{activeUser.email}}</p>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<md-toolbar class="md-tall">
|
||||
<div class="md-toolbar-tools sg-padded" layout="row" layout-align="start start">
|
||||
<md-button class="sg-icon-button"
|
||||
label:aria-label="Apps"
|
||||
ng-click="openBottomSheet()">
|
||||
<md-icon>apps</md-icon>
|
||||
</md-button>
|
||||
<span class="sg-logo"><!-- logo.svg --></span>
|
||||
</div>
|
||||
|
||||
<div class="md-toolbar-tools sg-padded" layout="row">
|
||||
<div layout="column">
|
||||
<p class="sg-md-title">{{activeUser.identification}}</p>
|
||||
<!--fixme: implement this with the proper model and actions -->
|
||||
<!-- <md-select class="sg-logout" ng-model="accounts.options" var:placeholder="shortUserNameForDisplay">
|
||||
<md-option var:value="relativePreferencesPath"><var:string label:value="Preferences"/></md-option>
|
||||
<var:if condition="canLogoff"><md-option var:value="logoffPath"><var:string label:value="Disconnect" /></md-option></var:if>
|
||||
</md-select> -->
|
||||
</div>
|
||||
</div>
|
||||
</md-toolbar>
|
||||
</container>
|
||||
@@ -3,68 +3,19 @@
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:var="http://www.skyrix.com/od/binding"
|
||||
xmlns:const="http://www.skyrix.com/od/constant"
|
||||
xmlns:label="OGo:label">
|
||||
|
||||
xmlns:label="OGo:label"
|
||||
>
|
||||
<div class="sg-toolbar-group-1" layout="row">
|
||||
<md-button ng-click="toggleLeft()"
|
||||
class="hide-gt-md sg-button-navicon sg-icon-button"
|
||||
label:aria-label="Toggle Menu">
|
||||
<md-icon>menu</md-icon>
|
||||
</md-button>
|
||||
<div class="sg-date-group sg-padded" layout="column" layout-align="space-between end">
|
||||
<div class="sg-date-group" layout="column" layout-align="space-between end">
|
||||
<p class="sg-day" ng-bind="currentDay.weekday"><!-- weekday --></p>
|
||||
<p class="sg-month" ng-bind="currentDay.month"><!-- month --></p>
|
||||
<p class="sg-year" ng-bind="currentDay.year"><!-- year --></p>
|
||||
</div>
|
||||
<p class="sg-md-display-3 sg-date-today" ng-bind="currentDay.day"><!-- day --></p>
|
||||
</div>
|
||||
|
||||
<div class="sg-toolbar-group-last">
|
||||
<md-menu layout-fill="layout-fill">
|
||||
<md-button label:aria-label="Modules"
|
||||
class="sg-icon-button" ng-click="$mdOpenMenu($event)">
|
||||
<md-icon>apps</md-icon>
|
||||
</md-button>
|
||||
<md-menu-content width="8">
|
||||
<div class="md-toolbar-tools sg-padded" layout="row"
|
||||
layout-align="space-around start">
|
||||
<md-button class="sg-icon-button"
|
||||
ng-show="activeUser.path.calendar.length"
|
||||
ng-disabled="baseURL.endsWith('/Calendar')"
|
||||
ng-href="{{activeUser.path.calendar}}">
|
||||
<md-icon>event</md-icon>
|
||||
<md-tooltip><var:string label:value="Calendar"/></md-tooltip>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-disabled="baseURL.endsWith('/Contacts')"
|
||||
ng-href="{{activeUser.path.contacts}}">
|
||||
<md-icon>contacts</md-icon>
|
||||
<md-tooltip><var:string label:value="Address Book"/></md-tooltip>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-show="activeUser.path.mail.length"
|
||||
ng-disabled="baseURL.endsWith('/Mail')"
|
||||
ng-href="{{activeUser.path.mail}}">
|
||||
<md-icon>email</md-icon>
|
||||
<md-tooltip><var:string label:value="Mail"/></md-tooltip>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button"
|
||||
ng-disabled="baseURL.endsWith(activeUser.login)"
|
||||
ng-href="{{activeUser.path.preferences}}">
|
||||
<md-icon>settings</md-icon>
|
||||
<md-tooltip><var:string label:value="Preferences"/></md-tooltip>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-show="activeUser.isSuperUser" ng-href="{{activeUser.path.administration}}">
|
||||
<md-icon>settings_applications</md-icon>
|
||||
<md-tooltip><var:string label:value="Administration"/></md-tooltip>
|
||||
</md-button>
|
||||
<md-button class="sg-icon-button" ng-show="activeUser.path.logoff.length" ng-href="{{activeUser.path.logoff}}">
|
||||
<md-icon>settings_power</md-icon>
|
||||
<md-tooltip><var:string label:value="Disconnect"/></md-tooltip>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</div>
|
||||
|
||||
</container>
|
||||
@@ -4,9 +4,7 @@ include ../common.make
|
||||
|
||||
WEBSERVER_RESOURCE_DIRS = css fonts img js
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
dev:
|
||||
build-static-files:
|
||||
npm install --production
|
||||
@if [ ! -e angular-material/src ]; then \
|
||||
git submodule init; \
|
||||
@@ -19,10 +17,9 @@ dev:
|
||||
fi
|
||||
grunt --stack build
|
||||
|
||||
all:
|
||||
@echo "The 'all' target does nothing. Use 'make dev' to generate static files and 'make install' to install them."
|
||||
all :: build-static-files
|
||||
|
||||
install:
|
||||
install ::
|
||||
@if [ -L "$(SOGO_WEBSERVERRESOURCESDIR)" ]; then \
|
||||
echo "$(SOGO_WEBSERVERRESOURCESDIR) is a symbolic link (for development?). Installation skipped."; \
|
||||
else \
|
||||
@@ -30,13 +27,13 @@ install:
|
||||
cp -r $(WEBSERVER_RESOURCE_DIRS) $(SOGO_WEBSERVERRESOURCESDIR)/; \
|
||||
fi
|
||||
|
||||
check:
|
||||
check ::
|
||||
|
||||
clean:
|
||||
clean ::
|
||||
|
||||
distclean: clean
|
||||
distclean :: clean
|
||||
|
||||
uninstall:
|
||||
uninstall ::
|
||||
@if [ -L "$(SOGO_WEBSERVERRESOURCESDIR)" ]; then \
|
||||
echo "$(SOGO_WEBSERVERRESOURCESDIR) is a symbolic link (for development?). Uninstallation skipped."; \
|
||||
else \
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
module.exports = function(grunt) {
|
||||
var js_files = {
|
||||
'js/Common.js': ['js/Common/Common.app.js', 'js/Common/*.filter.js', 'js/Common/*Controller.js', 'js/Common/*.service.js', 'js/Common/*.directive.js', 'js/Common/utils.js'],
|
||||
'js/Main.js': ['js/Main/Main.app.js'],
|
||||
'js/Common.js': ['js/Common/Common.app.js', 'js/Common/*.filter.js', 'js/Common/*Controller.js', 'js/Common/*.service.js', 'js/Common/*.directive.js'],
|
||||
'js/Scheduler.services.js': ['js/Scheduler/*.service.js'],
|
||||
'js/Scheduler.js': ['js/Scheduler/Scheduler.app.js', 'js/Scheduler/*Controller.js', 'js/Scheduler/*.directive.js'],
|
||||
'js/Scheduler.js': ['js/Scheduler.app.js', 'js/Scheduler/*Controller.js', 'js/Scheduler/*.directive.js'],
|
||||
'js/Contacts.services.js': ['js/Contacts/*.service.js'],
|
||||
'js/Contacts.js': ['js/Contacts/Contacts.app.js', 'js/Contacts/*Controller.js', 'js/Contacts/*.directive.js'],
|
||||
'js/Mailer.services.js': ['js/Mailer/*.service.js', 'js/Mailer/*Controller.js'],
|
||||
'js/Mailer.js': ['js/Mailer/Mailer.app.js', 'js/Mailer/*.directive.js'],
|
||||
'js/Contacts.js': ['js/Contacts.app.js', 'js/Contacts/*Controller.js', 'js/Contacts/*.directive.js'],
|
||||
'js/Mailer.services.js': ['js/Mailer/*.service.js'],
|
||||
'js/Mailer.js': ['js/Mailer.app.js', 'js/Mailer/*Controller.js', 'js/Mailer/*.directive.js'],
|
||||
'js/Preferences.services.js': ['js/Preferences/*.service.js'],
|
||||
'js/Preferences.js': ['js/Preferences/Preferences.app.js', 'js/Preferences/*Controller.js']
|
||||
'js/Preferences.js': ['js/Preferences.app.js', 'js/Preferences/*Controller.js']
|
||||
};
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
Submodule UI/WebServerResources/angular-material updated: f60b5e5a77...c5c148df85.
@@ -2,9 +2,9 @@
|
||||
"name": "sogo-web",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"angular": "1.4.x",
|
||||
"angular-animate": "1.4.x",
|
||||
"angular-sanitize": "1.4.x",
|
||||
"angular": "1.3.x",
|
||||
"angular-animate": "1.3.x",
|
||||
"angular-sanitize": "1.3.x",
|
||||
"angular-ui-router": "latest",
|
||||
"angular-file-upload": "latest",
|
||||
"angular-material": "master",
|
||||
@@ -12,6 +12,6 @@
|
||||
"breakpoint-sass": ">=2.4.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"angular": "1.4.x"
|
||||
"angular": "1.3.x"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["../scss/components/_palette.scss","../scss/core/reset.scss","styles.css","../scss/core/angular.scss","../scss/styles.scss","../angular-material/src/core/style/structure.scss","../angular-material/src/core/style/mixins.scss","../scss/core/variables.scss","../scss/core/structure.scss","../angular-material/src/core/services/layout/layout.scss","../scss/core/layout.scss","../bower_components/breakpoint-sass/stylesheets/_breakpoint.scss","../angular-material/src/core/style/typography.scss","../scss/core/typography.scss","../scss/core/_functions.scss","../angular-material/src/components/autocomplete/autocomplete.scss","../scss/components/autocomplete/autocomplete.scss","../scss/components/backdrop/_extends.scss","../angular-material/src/components/backdrop/backdrop.scss","../scss/components/backdrop/backdrop.scss","../scss/components/button/_extends.scss","../angular-material/src/components/button/button.scss","../scss/components/button/button.scss","../scss/components/card/_extends.scss","../angular-material/src/components/card/card.scss","../scss/components/card/card.scss","../scss/components/checkbox/_extends.scss","../angular-material/src/components/checkbox/checkbox.scss","../scss/components/checkbox/checkbox.scss","../scss/components/chips/_extends.scss","../angular-material/src/components/chips/chips.scss","../scss/components/chips/chips.scss","../scss/components/content/_extends.scss","../angular-material/src/components/content/content.scss","../scss/components/content/content.scss","../scss/components/datepicker/_extends-calendar.scss","../angular-material/src/components/datepicker/calendar.scss","../scss/components/datepicker/_extends-datePicker.scss","../angular-material/src/components/datepicker/datePicker.scss","../scss/components/datepicker/datePicker.scss","../scss/components/dialog/_extends.scss","../angular-material/src/components/dialog/dialog.scss","../scss/components/dialog/dialog.scss","../scss/components/divider/_extends.scss","../angular-material/src/components/divider/divider.scss","../scss/components/fabSpeedDial/_extends.scss","../angular-material/src/components/fabSpeedDial/fabSpeedDial.scss","../angular-material/src/components/gridList/grid-list.scss","../scss/components/gridList/grid-list.scss","../scss/components/icon/_extends.scss","../angular-material/src/components/icon/icon.scss","../scss/components/icon/icon.scss","../scss/components/input/_extends.scss","../angular-material/src/components/input/input.scss","../scss/components/input/input.scss","../scss/components/list/_extends.scss","../angular-material/src/components/list/list.scss","../scss/components/list/list.scss","../scss/components/menu/_extends.scss","../angular-material/src/components/menu/menu.scss","../scss/components/progressCircular/_extends.scss","../angular-material/src/components/progressCircular/progress-circular.scss","../scss/components/progressCircular/progress-circular.scss","../scss/components/radioButton/_extends.scss","../angular-material/src/components/radioButton/radio-button.scss","../scss/components/select/_extends.scss","../angular-material/src/components/select/select.scss","../scss/components/select/select.scss","../scss/components/sidenav/_extends.scss","../angular-material/src/components/sidenav/sidenav.scss","../scss/components/sidenav/sidenav.scss","../scss/components/slider/_extends.scss","../angular-material/src/components/slider/slider.scss","../scss/components/sticky/_extends.scss","../angular-material/src/components/sticky/sticky.scss","../scss/components/subheader/_extends.scss","../angular-material/src/components/subheader/subheader.scss","../scss/components/subheader/subheader.scss","../scss/components/switch/_extends.scss","../angular-material/src/components/switch/switch.scss","../scss/components/tabs/_extends.scss","../angular-material/src/components/tabs/tabs.scss","../scss/components/toast/_extends.scss","../angular-material/src/components/toast/toast.scss","../scss/components/toolbar/_extends.scss","../angular-material/src/components/toolbar/toolbar.scss","../scss/components/toolbar/toolbar.scss","../scss/components/tooltip/_extends.scss","../angular-material/src/components/tooltip/tooltip.scss","../scss/components/virtualRepeat/_extends.scss","../angular-material/src/components/virtualRepeat/virtual-repeater.scss","../scss/components/virtualRepeat/virtual-repeat.scss","../scss/components/whiteframe/_extends.scss","../angular-material/src/components/whiteframe/whiteframe.scss","../scss/components/timepicker/timepicker.scss","../scss/components/pseudo-input/pseudo-input.scss","../scss/views/LoginUI.scss","../scss/views/MailerUI.scss","../scss/views/ContactsUI.scss","../scss/views/MessageEditorUI.scss","../scss/views/SchedulerUI.scss","../scss/views/_view.scss","../scss/core/base_styles/_base_style.scss"],"names":[],"mappings":"AAEA;;;;;GAKG;AAqYiC;EAE9B,eAzSO,EAwSP;;AAEA;EAEA,0BA5SO,EA2SP;;AAJ8B;EAE9B,eAxSO,EAuSP;;AAEA;EAEA,0BA3SO,EA0SP;;AAJ8B;EAE9B,eAvSOLine truncated
|
||||
@@ -1,3 +0,0 @@
|
||||
function l(){var key=arguments[0],value=key;labels[key]?value=labels[key]:clabels[key]&&(value=clabels[key]);for(var i=1,j=0;i<arguments.length;i++,j++)value=value.replace("%{"+j+"}",arguments[i]);return value}!function(){"use strict";function configure($mdThemingProvider){$mdThemingProvider.definePalette("sogo-green",{50:"eaf5e9",100:"cbe5c8",200:"aad6a5",300:"88c781",400:"66b86a",500:"56b04c",600:"4da143",700:"388e3c",800:"367d2e",900:"225e1b",A100:"b9f6ca",A200:"69f0ae",A400:"00e676",A700:"00c853",contrastDefaultColor:"dark",contrastDarkColors:"50 100 200",contrastLightColors:"300 400 500 600 700 800 900"}),$mdThemingProvider.definePalette("sogo-blue",{50:"f0faf9",100:"e1f5f3",200:"ceebe8",300:"bfe0dd",400:"b2d6d3",500:"a1ccc8",600:"8ebfbb",700:"7db3b0",800:"639997",900:"4d8080",A100:"d4f7fa",A200:"c3f5fa",A400:"53e3f0",A700:"00b0c0",contrastDefaultColor:"light",contrastDarkColors:["50","100","200"],contrastLightColors:["300","400","500","600","700","800","900","A100","A200","A400","A700"]}),$mdThemingProvider.definePalette("sogo-paper",{50:"fcf7f8",100:"f7f1dc",200:"ede5ca",300:"e6d8ba",400:"e2d2a3",500:"d6c48d",600:"baa870",700:"857545",800:"524517",900:"433809",1000:"000000",A100:"ffffff",A200:"eeeeee",A400:"bdbdbd",A700:"616161",contrastDefaultColor:"dark",contrastLightColors:"800 900"}),$mdThemingProvider.theme("default").primaryPalette("sogo-blue",{"default":"300","hue-1":"100","hue-2":"400","hue-3":"A700"}).accentPalette("sogo-green",{"default":"500","hue-1":"200","hue-2":"300","hue-3":"A700"}).backgroundPalette("sogo-paper",{"default":"100","hue-1":"200","hue-2":"50","hue-3":"500"})}angular.module("SOGo.Common",["ngMaterial"]).value("sgSettings",{baseURL:function(){return ApplicationBaseURL||null},activeUser:function(param){var settings={login:UserLogin||null,identification:UserIdentification||null,email:UserEmail||null,language:UserLanguage||null,folderURL:UserFolderURL||null,isSuperUser:IsSuperUser||null,path:{calendar:UserCalendarPath||null,contacts:UserContactsPath||null,mail:UserMailPath||null,preferences:UserPreferencesPath||null,administration:IsSuperUser?UserAdministrationPath:null,logoff:UserLogoffPath||null}};return param?settings[param]:settings}}).constant("sgColors",{selection:["#FFFFFF","#330033","#C0C0C0","#999999","#666666","#333333","#000000","#FFCCCC","#FF6666","#FF0000","#CC0000","#990000","#660000","#330000","#FFCC99","#FF9966","#FF9900","#FF6600","#CC6600","#993300","#663300","#FFFF99","#FFFF66","#FFCC66","#FFCC33","#CC9933","#996633","#663333","#FFFFCC","#FFFF33","#FFFF00","#FFCC00","#999900","#666600","#333300","#CCCCCC","#66FF99","#33FF33","#33CC00","#009900","#006600","#003300","#99FFFF","#33FFFF","#66CCCC","#00CCCC","#339999","#336666","#003333","#CCFFFF","#66FFFF","#33CCFF","#3366FF","#3333FF","#000099","#000066","#CCCCFF","#9999FF","#6666CC","#6633FF","#6600CC","#333399","#330099","#FFCCFF","#FF99FF","#CC66CC","#CC33CC","#993399","#663366","#99FF99"]}).constant("sgConstant",{sm:"(max-width: 600px)","gt-sm":"(min-width: 600px)",md:"(min-width: 600px) and (max-width: 1024px)","gt-md":"(min-width: 1025px)",lg:"(min-width: 1024px) and (max-width: 1280px)","gt-lg":"(min-width: 1280px)"}).config(configure),configure.$inject=["$mdThemingProvider"]}(),function(){"use strict";function decodeUri($window){return $window.decodeURIComponent}decodeUri.$inject=["$window"],angular.module("SOGo.Common").filter("decodeUri",decodeUri)}(),function(){"use strict";function encodeUri($window){return $window.encodeURIComponent}encodeUri.$inject=["$window"],angular.module("SOGo.Common").filter("encodeUri",encodeUri)}(),function(){"use strict";function loc(){return l}angular.module("SOGo.Common").filter("loc",loc)}(),function(){"use strict";function range(){return function(n){for(var res=[],i=0;i<parseInt(n);i++)res.push(i);return res}}angular.module("SOGo.Common").filter("range",range)}(),function(){"use strict";function AclController($mdDialog,Dialog,usersWithACL,User,folder){function userFilter($query){return User.$filter($query,folder.$acl.users)}function closeModal(){folder.$acl.$resetUsersRights(),$mdDialog.hide()}function saveModal(){folder.$acl.$saveUsersRights().then(function(){$mdDialog.hide()},function(data,status){Dialog.alert(l("Warning"),l("An error occured please try again."))})}function confirmChange(user){var confirmation=user.$confirmRights();confirmation&&(vm.confirmation.showing=!0,vm.confirmation.message=confirmation)}function removeUser(user){folder.$acl.$removeUser(user.uid)["catch"](function(data,status){Dialog.alert(l("Warning"),l("An error occured please try again."))})}function addUser(data){data&&folder.$acl.$addUser(data).then(function(){vm.userToAdd="",vm.searchText=""},function(error){Dialog.alert(l("Warning"),error)})}function selectUser(user){vm.selectedUser==user?vm.selectedUser=null:(vm.selectedUser=user,vm.selectedUser.$rights())}var vm=this;vm.users=usersWithACL,vm.folder=folder,vm.selectedUser=null,vm.userToAdd="",vm.searchText="",vm.userFilter=userFilter,Line truncated
|
||||
return{template:'<div class="sg-time-pane"><div class="hours-pane"><div ng-repeat="hoursBigLine in hours" layout="row" layout-sm="column" ><div ng-repeat="hoursLine in hoursBigLine" layout="row" class="hours" ><div flex layout="row" layout-align="center center" ng-repeat="hour in hoursLine"><md-button class="hourBtn md-fab md-mini" id="{{hour.id}}" ng-click="hourClickHandler(hour.displayName)">{{hour.displayName}}</md-button></div></div></div></div><div ng-repeat="minutesLine in min5" layout="row" class="min5" ng-show="is5min()"><div flex layout="row" layout-align="center center" ng-repeat="minute in minutesLine"><md-button class="minuteBtn md-fab md-mini" id="{{minute.id}}" ng-click="minuteClickHandler(minute.displayName)">{{minute.displayName}}</md-button></div></div><div ng-repeat="minutesLine in min1" layout="row" class="min1" ng-hide="is5min()"><div flex layout="row" layout-align="center center" ng-repeat="minute in minutesLine"><md-button class="minuteBtn md-fab md-mini" id="{{minute.id}}" ng-click="minuteClickHandler(minute.displayName)">{{minute.displayName}}</md-button></div></div><div flex layout="row" layout-align="center center" class="toggle-pane"><md-button class="toggleBtn md-fab md-mini" ng-bind="getToggleBtnLbl()" ng-click="toggleManual5min()"></md-button></div></div>',scope:{},require:["ngModel","sgTimePane"],controller:TimePaneCtrl,controllerAs:"ctrl",bindToController:!0,link:function(scope,element,attrs,controllers){var ngModelCtrl=controllers[0],sgTimePaneCtrl=controllers[1];console.log(element);var timePaneElement=element;sgTimePaneCtrl.configureNgModel(ngModelCtrl,sgTimePaneCtrl,timePaneElement)}}}function TimePaneCtrl($element,$attrs,$scope,$animate,$q,$mdConstant,$mdTheming,$$mdDateUtil,$mdDateLocale,$mdInkRipple,$mdUtil){var m;this.$scope=$scope,this.$element=$element,this.timePaneElement=$element[0].querySelector(".sg-time-pane"),this.$animate=$animate,this.$q=$q,this.$mdInkRipple=$mdInkRipple,this.$mdUtil=$mdUtil,this.keyCode=$mdConstant.KEY_CODE,this.dateUtil=$$mdDateUtil,this.id=nextTimePaneUniqueId++,this.ngModelCtrl=null,this.selectedTime=null,this.displayTime=null,this.isInitialized=!1,$scope.hours=[],$scope.hours[0]=[],$scope.hours[0][0]=[],$scope.hours[0][1]=[],$scope.hours[1]=[],$scope.hours[1][0]=[],$scope.hours[1][1]=[];for(var i=0;6>i;i++)$scope.hours[0][0][i]={id:"tp-"+this.id+"-hour-"+i,displayName:10>i?"0"+i:""+i,selected:!1},$scope.hours[0][1][i]={id:"tp-"+this.id+"-hour-"+(i+6),displayName:10>i+6?"0"+(i+6):""+(i+6),selected:!1},$scope.hours[1][0][i]={id:"tp-"+this.id+"-hour-"+(i+12),displayName:""+(i+12),selected:!1},$scope.hours[1][1][i]={id:"tp-"+this.id+"-hour-"+(i+18),displayName:""+(i+18),selected:!1};for($scope.min5=[],$scope.min5[0]=[],$scope.min5[1]=[],i=0;6>i;i++)m=5*i,$scope.min5[0][i]={id:"tp-"+this.id+"-minute5-"+m,displayName:10>m?":0"+m:":"+m,selected:!0},$scope.min5[1][i]={id:"tp-"+this.id+"-minute5-"+(m+30),displayName:":"+(m+30),selected:!1};for($scope.min1=[],i=0;12>i;i++){$scope.min1[i]=[];for(var ii=0;5>ii;ii++)m=5*i+ii,$scope.min1[i][ii]={id:"tp-"+this.id+"-minute-"+m,displayName:10>m?":0"+m:":"+m,selected:!0}}$scope.show5min=!0,$scope.getToggleBtnLbl=function(){return $scope.is5min()?">>":"<<"},$scope.toggleManual5min=function(){$scope.manual5min=!$scope.is5min()},$scope.is5min=function(){return $scope.manual5min===!0||$scope.manual5min===!1?$scope.manual5min:$scope.show5min},$attrs.tabindex||$element.attr("tabindex","-1");var self=this;this.hourClickHandler=function(displayVal){var updated=new Date(self.displayTime).setHours(Number(displayVal));self.setNgModelValue(updated,"hours")},$scope.hourClickHandler=this.hourClickHandler,this.minuteClickHandler=function(displayVal){var val=displayVal.substr(1),updated=new Date(self.displayTime).setMinutes(Number(val));self.setNgModelValue(updated,"minutes")},$scope.minuteClickHandler=this.minuteClickHandler,this.attachTimePaneEventListeners()}angular.module("SOGo.Common").directive("sgTimePane",timePaneDirective);var SELECTED_TIME_CLASS2="md-primary",FOCUSED_TIME_CLASS="md-focus",nextTimePaneUniqueId=0;TimePaneCtrl.$inject=["$element","$attrs","$scope","$animate","$q","$mdConstant","$mdTheming","$$mdDateUtil","$mdDateLocale","$mdInkRipple","$mdUtil"],TimePaneCtrl.prototype.configureNgModel=function(ngModelCtrl,sgTimePaneCtrl,timePaneElement){this.ngModelCtrl=ngModelCtrl;var self=this;ngModelCtrl.$render=function(){self.changeSelectedTime(self.ngModelCtrl.$viewValue,sgTimePaneCtrl,timePaneElement)}},TimePaneCtrl.prototype.changeSelectedTime=function(date,sgTimePaneCtrl,timePaneElement){var previousSelectedTime=this.selectedTime;this.selectedTime=new Date(date),this.changeDisplayTime(date).then(function(){if(previousSelectedTime){var prevH=previousSelectedTime.getHours(),prevHCell=document.getElementById("tp-"+sgTimePaneCtrl.id+"-hour-"+prevH);prevHCell&&(prevHCell.classList.remove(SELECTED_TIME_CLASS2),prevHCell.setAttribute("aria-selected","false"));var prevM=previousSelectedTime.getMinutes(),prevMCeLine truncated
|
||||
//# sourceMappingURL=Common.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"Common.js","sources":["Common/utils.js","Common/Common.app.js","Common/decodeUri.filter.js","Common/encodeUri.filter.js","Common/loc.filter.js","Common/range.filter.js","Common/AclController.js","Common/navController.js","Common/Acl.service.js","Common/Alarm.service.js","Common/Authentication.service.js","Common/Dialog.service.js","Common/Gravatar.service.js","Common/Resource.service.js","Common/User.service.js","Common/sgFocus.service.js","Common/sgAvatarImage.directive.js","Common/sgColorPicker.directive.js","Common/sgCompile.directive.js","Common/sgEnter.directive.js","Common/sgEscape.directive.js","Common/sgFocus.directive.js","Common/sgFolderStylesheet.directive.js","Common/sgSearch.directive.js","Common/sgSubscribe.directive.js","Common/sgTarget.directive.js","Common/sgTimepicker.directive.js","Common/sgToggleGrid.directive.js"],"names":["l","key","arguments","value","labels","clabels","i","j","length","replace","configure","$mdThemingProvider","definePalette","50","100","200","300","400","500","600","700","800","900","A100","A200","A400","A700","contrastDefaultColor","contrastDarkColors","contrastLightColors","1000","theme","primaryPalette","default","hue-1","hue-2","hue-3","accentPalette","backgroundPalette","angular","module","baseURL","ApplicationBaseURL","activeUser","param","settings","login","UserLogin","identification","UserIdentification","email","UserEmail","language","UserLanguage","folderURL","UserFolderURL","isSuperUser","IsSuperUser","path","calendar","UserCalendarPath","contacts","UserContactsPath","mail","UserMailPath","preferences","UserPreferencesPath","administration","UserAdministrationPath","logoff","UserLogoffPath","constant","selection","sm","gt-sm","md","gt-md","lg","gt-lg","config","$inject","decodeUri","$window","decodeURIComponent","filter","encodeUri","encodeURIComponent","loc","range","n","res","parseInt","push","AclController","$mdDialog","Dialog","usersWithACL","User","folder","userFilter","$query","$filter","$acl","users","closeModal","$resetUsersRights","hide","saveModal","$saveUsersRights","then","data","status","alert","confirmChange","user","confirmation","$confirmRights","vm","showing","message","removeUser","$removeUser","uid","addUser","$addUser","userToAdd","searchText","error","selectUser","selectedUser","$rights","this","controller","navController","$scope","$timeout","$interval","$http","$mdSidenav","$mdBottomSheet","$mdMedia","$log","sgConstant","sgSettings","Alarm","currentDay","window","get","success","secondsBeforeTomorrow","toggleLeft","toggle","debug","toggleRight","openBottomSheet","show","parent","element","document","getElementById","templateUrl","toggleDetailView","detail","toggleClass","$watch","newVal","isGtMedium","getAlarms","Acl","folderId","factory","$q","Settings","Resource","extend","$$resource","$User","prototype","$users","_this","deferred","defer","resolve","promise","fetch","response","forEach","canSubscribeUser","isSubscribed","wasSubscribed","bind","_","indexOf","pluck","userClass","isGroup","reject","splice","$resetRights","deferredSave","deferredSubscribe","action","$rightsAreDirty","$omit","save","$shadowRights","copy","rights","uids","join","all","currentAlarm","AlarmService","$mdToast","$toast","now","Date","browserTime","Math","floor","getTime","alarms","sort","a","b","x","y","next","pop","utc","url","alarmTime","delay","f","showAlarm","cancel","AlarmController","scope","reminder","ok","position","hideDelay","template","summary","locals","Authentication","readCookie","name","foundCookie","prefix","pairs","currentPair","start","cookie","split","charAt","substr","readLoginCookie","loginValues","base64decode","redirectUrl","username","domain","userName","address","baseAddress","altBaseAddress","parts","hostpart","protocol","newAddress","location","href","startsWith","endsWith","getService","passwordPolicyConfig","service","d","password","rememberLogin","loginSuffix","method","loginCookie","expire","grace","msg","perr","LDAPPasswordPolicyError","PolicyNoError","PolicyAccountLocked","changePassword","newPassword","PolicyPasswordModNotAllowed","PolicyInsufficientPasswordQuality","PolicyPasswordTooShort","PolicyPasswordTooYoung","PolicyPasswordInHistory","formatted","PolicyPasswordUnknown","PolicyPasswordSystemUnknown","$get","PolicyPasswordChangeUnsupported","PolicyPasswordExpired","PolicyChangeAfterReset","PolicyMustSupplyOldPassword","provider","DialogService","$modal","title","content","confirm","options","prompt","label","PromptDialogController","o","body","clickOutsideToClose","escapeToClose","inputType","Gravatar","size","hash","s","substring","md5","_http","_q","_path","_activeUser","$factory","userResource","compact","escape","params","flatten","newguid","create","post","id","newValue","remove","userData","init","$gravatar","search","excludedUsers","when","results","index","compareUids","find","each","isUndefined","$$shortFormat","$shortFormat","$$image","image","c_email","empty","fullname","cn","no_email"Line truncated
|
||||
@@ -48,7 +48,7 @@
|
||||
else {
|
||||
return Acl.$$resource.fetch(this.folderId, 'acls').then(function(response) {
|
||||
_this.users = [];
|
||||
//console.debug(JSON.stringify(users, undefined, 2));
|
||||
// console.debug(JSON.stringify(users, undefined, 2));
|
||||
angular.forEach(response.users, function(data) {
|
||||
user = new Acl.$User(data);
|
||||
user.canSubscribeUser = user.isSubscribed;
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.controller('AclController', AclController);
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.controller('AclController', AclController);
|
||||
})();
|
||||
@@ -58,67 +58,66 @@
|
||||
Alarm.showAlarm = function(url) {
|
||||
var _this = this;
|
||||
|
||||
this.$$resource.fetch(url, '?resetAlarm=yes').then(function(data) {
|
||||
_this.$toast.show({
|
||||
position: 'top right',
|
||||
hideDelay: 0,
|
||||
template: [
|
||||
'<md-toast>',
|
||||
' <md-input-container>',
|
||||
' <label style="color: white;">' + data.summary + '</label>',
|
||||
' <md-select ng-model="reminder">',
|
||||
' <md-option value=5>',
|
||||
l('5 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=10>',
|
||||
l('10 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=15>',
|
||||
l('15 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=30>',
|
||||
l('30 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=45>',
|
||||
l('45 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=60>',
|
||||
l('1 hour'),
|
||||
' </md-option>',
|
||||
' <md-option value=1440>',
|
||||
l('1 day'),
|
||||
' </md-option>',
|
||||
' </md-select>',
|
||||
' </md-input-container>',
|
||||
' <md-button ng-click="cancel()">',
|
||||
l('Cancel'),
|
||||
' </md-button>',
|
||||
' <md-button ng-click="ok()">',
|
||||
l('Ok'),
|
||||
' </md-button>',
|
||||
'</md-toast>'
|
||||
].join(''),
|
||||
locals: {
|
||||
url: url
|
||||
},
|
||||
controller: AlarmController
|
||||
});
|
||||
this.$$resource.fetch(url, '?resetAlarm=yes');
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AlarmController.$inject = ['scope', '$mdToast', 'url'];
|
||||
function AlarmController(scope, $mdToast, url) {
|
||||
scope.reminder = '10';
|
||||
scope.cancel = function() {
|
||||
$mdToast.hide();
|
||||
};
|
||||
scope.ok = function() {
|
||||
_this.$$resource.fetch(url, 'view?snoozeAlarm=' + scope.reminder);
|
||||
$mdToast.hide();
|
||||
};
|
||||
}
|
||||
this.$toast.show({
|
||||
position: 'top right',
|
||||
hideDelay: 0,
|
||||
template: [
|
||||
'<md-toast>',
|
||||
' <md-input-container>',
|
||||
' <md-select ng-model="reminder">',
|
||||
' <md-option value=5>',
|
||||
l('5 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=10>',
|
||||
l('10 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=15>',
|
||||
l('15 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=30>',
|
||||
l('30 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=45>',
|
||||
l('45 minutes'),
|
||||
' </md-option>',
|
||||
' <md-option value=60>',
|
||||
l('1 hour'),
|
||||
' </md-option>',
|
||||
' <md-option value=1440>',
|
||||
l('1 day'),
|
||||
' </md-option>',
|
||||
' </md-select>',
|
||||
' </md-input-container>',
|
||||
' <md-button ng-click="cancel()">',
|
||||
l('Cancel'),
|
||||
' </md-button>',
|
||||
' <md-button ng-click="ok()">',
|
||||
l('Ok'),
|
||||
' </md-button>',
|
||||
'</md-toast>'
|
||||
].join(''),
|
||||
locals: {
|
||||
url: url
|
||||
},
|
||||
controller: AlarmController
|
||||
});
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
AlarmController.$inject = ['scope', '$mdToast', 'url'];
|
||||
function AlarmController(scope, $mdToast, url) {
|
||||
scope.reminder = '10';
|
||||
scope.cancel = function() {
|
||||
$mdToast.hide();
|
||||
};
|
||||
scope.ok = function() {
|
||||
_this.$$resource.fetch(url, 'view?snoozeAlarm=' + scope.reminder);
|
||||
$mdToast.hide();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
// TODO: convert to a Factory recipe?
|
||||
.provider('Authentication', Authentication);
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
function Authentication() {
|
||||
function readCookie(name) {
|
||||
var foundCookie, prefix, pairs, i, currentPair, start;
|
||||
@@ -88,11 +91,9 @@
|
||||
|
||||
this.$get = getService;
|
||||
|
||||
/**
|
||||
* @ngInject
|
||||
*/
|
||||
getService.$inject = ['$q', '$http', 'passwordPolicyConfig'];
|
||||
function getService($q, $http, passwordPolicyConfig) {
|
||||
|
||||
var _this = this, service;
|
||||
|
||||
service = {
|
||||
|
||||
@@ -12,18 +12,9 @@
|
||||
var settings = {
|
||||
login: UserLogin || null,
|
||||
identification: UserIdentification || null,
|
||||
email: UserEmail || null,
|
||||
language: UserLanguage || null,
|
||||
folderURL: UserFolderURL || null,
|
||||
isSuperUser: IsSuperUser || null,
|
||||
path: {
|
||||
calendar: UserCalendarPath || null,
|
||||
contacts: UserContactsPath || null,
|
||||
mail: UserMailPath || null,
|
||||
preferences: UserPreferencesPath || null,
|
||||
administration: (IsSuperUser ? UserAdministrationPath : null),
|
||||
logoff: UserLogoffPath || null
|
||||
}
|
||||
isSuperUser: IsSuperUser || null
|
||||
};
|
||||
if (param)
|
||||
return settings[param];
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
* @param {string} content
|
||||
* @returns a promise that resolves if the user has clicked on the 'OK' button
|
||||
*/
|
||||
Dialog.confirm = function(title, content, options) {
|
||||
Dialog.confirm = function(title, content) {
|
||||
var confirm = this.$modal.confirm()
|
||||
.title(title)
|
||||
.content(content)
|
||||
.ok((options && options.ok)? options.ok : l('OK'))
|
||||
.cancel((options && options.cancel)? options.cancel : l('Cancel'));
|
||||
.ok(l('OK'))
|
||||
.cancel(l('Cancel'));
|
||||
return this.$modal.show(confirm);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,16 +12,10 @@
|
||||
*/
|
||||
function Gravatar() {
|
||||
return function(email, size) {
|
||||
var x, y, hash, s = size;
|
||||
var hash, s = size;
|
||||
if (!email) {
|
||||
return '';
|
||||
}
|
||||
x = email.indexOf('<');
|
||||
if (x >= 0) {
|
||||
y = email.indexOf('>', x);
|
||||
if (y > x)
|
||||
email = email.substring(x+1,y);
|
||||
}
|
||||
if (!size) {
|
||||
s = 48; // default to 48 pixels
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
*/
|
||||
User.$filter = function(search, excludedUsers) {
|
||||
var param = {search: search};
|
||||
var _this = this;
|
||||
|
||||
if (!search) {
|
||||
// No query specified
|
||||
@@ -61,7 +60,7 @@
|
||||
return User.$$resource.fetch(null, 'usersSearch', param).then(function(response) {
|
||||
var results, index, user,
|
||||
compareUids = function(data) {
|
||||
return _this.uid == data.uid;
|
||||
return this.uid == data.uid;
|
||||
};
|
||||
if (excludedUsers) {
|
||||
// Remove excluded users from response
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
function navController($scope, $timeout, $interval, $http, $mdSidenav, $mdBottomSheet, $mdMedia, $log, sgConstant, sgSettings, Alarm) {
|
||||
|
||||
$scope.activeUser = sgSettings.activeUser();
|
||||
$scope.baseURL = sgSettings.baseURL();
|
||||
|
||||
// Show current day in top bar
|
||||
$scope.currentDay = window.currentDay;
|
||||
|
||||
@@ -1,743 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('SOGo.Common')
|
||||
.directive('sgTimePane', timePaneDirective);
|
||||
|
||||
function timePaneDirective() {
|
||||
return {
|
||||
template:
|
||||
'<div class="sg-time-pane">' +
|
||||
'<div class="hours-pane"><div ng-repeat="hoursBigLine in hours" layout="row" layout-sm="column" ><div ng-repeat="hoursLine in hoursBigLine" layout="row" class="hours" >' +
|
||||
'<div flex layout="row" layout-align="center center" ng-repeat="hour in hoursLine">' +
|
||||
'<md-button class="hourBtn md-fab md-mini" id="{{hour.id}}" ng-click="hourClickHandler(hour.displayName)">{{hour.displayName}}</md-button>'+
|
||||
'</div></div></div></div>' +
|
||||
'<div ng-repeat="minutesLine in min5" layout="row" class="min5" ng-show="is5min()">' +
|
||||
'<div flex layout="row" layout-align="center center" ng-repeat="minute in minutesLine">' +
|
||||
'<md-button class="minuteBtn md-fab md-mini" id="{{minute.id}}" ng-click="minuteClickHandler(minute.displayName)">{{minute.displayName}}</md-button>'+
|
||||
'</div></div>' +
|
||||
'<div ng-repeat="minutesLine in min1" layout="row" class="min1" ng-hide="is5min()">' +
|
||||
'<div flex layout="row" layout-align="center center" ng-repeat="minute in minutesLine">' +
|
||||
'<md-button class="minuteBtn md-fab md-mini" id="{{minute.id}}" ng-click="minuteClickHandler(minute.displayName)">{{minute.displayName}}</md-button>' +
|
||||
'</div></div>' +
|
||||
'<div flex layout="row" layout-align="center center" class="toggle-pane"><md-button class="toggleBtn md-fab md-mini" ng-bind="getToggleBtnLbl()" ng-click="toggleManual5min()"></md-button></div></div>',
|
||||
scope: {},
|
||||
require: ['ngModel', 'sgTimePane'],
|
||||
controller: TimePaneCtrl,
|
||||
controllerAs: 'ctrl',
|
||||
bindToController: true,
|
||||
link: function(scope, element, attrs, controllers) {
|
||||
var ngModelCtrl = controllers[0];
|
||||
var sgTimePaneCtrl = controllers[1];
|
||||
console.log(element);
|
||||
var timePaneElement = element;
|
||||
sgTimePaneCtrl.configureNgModel(ngModelCtrl,sgTimePaneCtrl, timePaneElement);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Class applied to the selected hour or minute cell/. */
|
||||
//var SELECTED_TIME_CLASS = 'md-calendar-selected-date';
|
||||
//var SELECTED_TIME_CLASS1 = 'md-raised';
|
||||
var SELECTED_TIME_CLASS2 = 'md-primary';
|
||||
|
||||
/** Class applied to the focused hour or minute cell/. */
|
||||
var FOCUSED_TIME_CLASS = 'md-focus';
|
||||
|
||||
/** Next identifier for calendar instance. */
|
||||
var nextTimePaneUniqueId = 0;
|
||||
|
||||
function TimePaneCtrl($element, $attrs, $scope, $animate, $q, $mdConstant,
|
||||
$mdTheming, $$mdDateUtil, $mdDateLocale, $mdInkRipple, $mdUtil) {
|
||||
var m;
|
||||
this.$scope = $scope;
|
||||
this.$element = $element;
|
||||
this.timePaneElement = $element[0].querySelector('.sg-time-pane');
|
||||
this.$animate = $animate;
|
||||
this.$q = $q;
|
||||
this.$mdInkRipple = $mdInkRipple;
|
||||
this.$mdUtil = $mdUtil;
|
||||
this.keyCode = $mdConstant.KEY_CODE;
|
||||
this.dateUtil = $$mdDateUtil;
|
||||
this.id = nextTimePaneUniqueId++;
|
||||
this.ngModelCtrl = null;
|
||||
this.selectedTime = null;
|
||||
this.displayTime = null;
|
||||
this.isInitialized = false;
|
||||
|
||||
$scope.hours=[];
|
||||
$scope.hours[0]=[];
|
||||
$scope.hours[0][0]=[];
|
||||
$scope.hours[0][1]=[];
|
||||
$scope.hours[1]=[];
|
||||
$scope.hours[1][0]=[];
|
||||
$scope.hours[1][1]=[];
|
||||
for(var i=0; i<6; i++){
|
||||
$scope.hours[0][0][i] = {id:'tp-'+this.id+'-hour-'+i, displayName:i<10?"0"+i:""+i, selected:false};
|
||||
$scope.hours[0][1][i] = {id:'tp-'+this.id+'-hour-'+(i+6),displayName:(i+6)<10?"0"+(i+6):""+(i+6), selected:false};
|
||||
$scope.hours[1][0][i] = {id:'tp-'+this.id+'-hour-'+(i+12), displayName:""+(i+12), selected:false};
|
||||
$scope.hours[1][1][i] = {id:'tp-'+this.id+'-hour-'+(i+18), displayName:""+(i+18), selected:false};
|
||||
}
|
||||
|
||||
$scope.min5=[];
|
||||
$scope.min5[0]=[];
|
||||
$scope.min5[1]=[];
|
||||
for(i=0; i<6; i++){
|
||||
m=i*5;
|
||||
$scope.min5[0][i] = {id:'tp-'+this.id+'-minute5-'+m, displayName:m<10?":0"+m:":"+m, selected:true};
|
||||
$scope.min5[1][i] = {id:'tp-'+this.id+'-minute5-'+(m+30), displayName:":"+(m+30), selected:false};
|
||||
}
|
||||
|
||||
$scope.min1=[];
|
||||
for(i=0; i<12; i++){
|
||||
$scope.min1[i]=[];
|
||||
for(var ii=0; ii<5; ii++){
|
||||
m=i*5 + ii;
|
||||
$scope.min1[i][ii] = {id:'tp-'+this.id+'-minute-'+m, displayName:m<10?":0"+m:":"+m, selected:true};
|
||||
}
|
||||
}
|
||||
|
||||
$scope.show5min=true;
|
||||
$scope.getToggleBtnLbl = function() {
|
||||
return ($scope.is5min()) ? '>>' : '<<';
|
||||
};
|
||||
$scope.toggleManual5min = function() {
|
||||
$scope.manual5min = !$scope.is5min();
|
||||
};
|
||||
$scope.is5min=function(){
|
||||
if($scope.manual5min === true || $scope.manual5min === false) {
|
||||
return $scope.manual5min;
|
||||
}
|
||||
else {
|
||||
return $scope.show5min;
|
||||
}
|
||||
};
|
||||
|
||||
if (!$attrs.tabindex) {
|
||||
$element.attr('tabindex', '-1');
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this.hourClickHandler = function(displayVal) {
|
||||
var updated = new Date(self.displayTime).setHours(Number(displayVal));
|
||||
self.setNgModelValue(updated, 'hours');
|
||||
};
|
||||
$scope.hourClickHandler = this.hourClickHandler;
|
||||
|
||||
this.minuteClickHandler = function(displayVal) {
|
||||
//remove leading ':'
|
||||
var val = displayVal.substr(1);
|
||||
var updated = new Date(self.displayTime).setMinutes(Number(val));
|
||||
self.setNgModelValue(updated, 'minutes');
|
||||
};
|
||||
$scope.minuteClickHandler = this.minuteClickHandler;
|
||||
|
||||
this.attachTimePaneEventListeners();
|
||||
}
|
||||
TimePaneCtrl.$inject = ["$element", "$attrs", "$scope", "$animate", "$q", "$mdConstant", "$mdTheming", "$$mdDateUtil", "$mdDateLocale", "$mdInkRipple", "$mdUtil"];
|
||||
|
||||
TimePaneCtrl.prototype.configureNgModel = function(ngModelCtrl, sgTimePaneCtrl, timePaneElement) {
|
||||
this.ngModelCtrl = ngModelCtrl;
|
||||
var self = this;
|
||||
ngModelCtrl.$render = function() {
|
||||
self.changeSelectedTime(self.ngModelCtrl.$viewValue, sgTimePaneCtrl, timePaneElement);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the selected date in the time (ngModel value has already been changed).
|
||||
*/
|
||||
TimePaneCtrl.prototype.changeSelectedTime = function(date, sgTimePaneCtrl, timePaneElement) {
|
||||
var self = this;
|
||||
var previousSelectedTime = this.selectedTime;
|
||||
this.selectedTime = new Date(date);
|
||||
this.changeDisplayTime(date).then(function() {
|
||||
// Remove the selected class from the previously selected date, if any.
|
||||
if (previousSelectedTime) {
|
||||
var prevH = previousSelectedTime.getHours();
|
||||
var prevHCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-hour-'+prevH);
|
||||
if (prevHCell) {
|
||||
prevHCell.classList.remove(SELECTED_TIME_CLASS2);
|
||||
prevHCell.setAttribute('aria-selected', 'false');
|
||||
}
|
||||
var prevM = previousSelectedTime.getMinutes();
|
||||
var prevMCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-minute-'+prevM);
|
||||
if (prevMCell) {
|
||||
prevMCell.classList.remove(SELECTED_TIME_CLASS2);
|
||||
prevMCell.setAttribute('aria-selected', 'false');
|
||||
}
|
||||
var prevM5Cell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-minute5-'+prevM);
|
||||
if (prevM5Cell) {
|
||||
prevM5Cell.classList.remove(SELECTED_TIME_CLASS2);
|
||||
prevM5Cell.setAttribute('aria-selected', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the select class to the new selected date if it is set.
|
||||
if (date) {
|
||||
var d = new Date(date);
|
||||
var newH = d.getHours();
|
||||
var mCell, hCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-hour-'+newH);
|
||||
if (hCell) {
|
||||
hCell.classList.add(SELECTED_TIME_CLASS2);
|
||||
hCell.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
var newM = d.getMinutes();
|
||||
if (newM % 5 === 0) {
|
||||
sgTimePaneCtrl.$scope.show5min = true;
|
||||
mCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-minute5-'+newM);
|
||||
if (mCell) {
|
||||
mCell.classList.add(SELECTED_TIME_CLASS2);
|
||||
mCell.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
}
|
||||
else {
|
||||
sgTimePaneCtrl.$scope.show5min = false;
|
||||
}
|
||||
mCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-minute-'+newM);
|
||||
if (mCell) {
|
||||
mCell.classList.add(SELECTED_TIME_CLASS2);
|
||||
mCell.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
TimePaneCtrl.prototype.changeDisplayTime = function(date) {
|
||||
var d = new Date(date);
|
||||
if (!this.isInitialized) {
|
||||
this.buildInitialTimePaneDisplay();
|
||||
return this.$q.when();
|
||||
}
|
||||
if (!this.dateUtil.isValidDate(d)) {
|
||||
return this.$q.when();
|
||||
}
|
||||
|
||||
this.displayTime = d;
|
||||
|
||||
return this.$q.when();
|
||||
};
|
||||
TimePaneCtrl.prototype.buildInitialTimePaneDisplay = function() {
|
||||
this.displayTime = this.selectedTime || this.today;
|
||||
this.isInitialized = true;
|
||||
};
|
||||
|
||||
TimePaneCtrl.prototype.attachTimePaneEventListeners = function() {
|
||||
// Keyboard interaction.
|
||||
this.$element.on('keydown', angular.bind(this, this.handleKeyEvent));
|
||||
};
|
||||
|
||||
/*** User input handling ***/
|
||||
|
||||
/**
|
||||
* Handles a key event in the calendar with the appropriate action. The action will either
|
||||
* be to select the focused date or to navigate to focus a new date.
|
||||
* @param {KeyboardEvent} event
|
||||
*/
|
||||
TimePaneCtrl.prototype.handleKeyEvent = function(event) {
|
||||
var self = this;
|
||||
this.$scope.$apply(function() {
|
||||
// Capture escape and emit back up so that a wrapping component
|
||||
// (such as a time-picker) can decide to close.
|
||||
if (event.which == self.keyCode.ESCAPE || event.which == self.keyCode.TAB) {
|
||||
self.$scope.$emit('md-time-pane-close');
|
||||
|
||||
if (event.which == self.keyCode.TAB) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Remaining key events fall into two categories: selection and navigation.
|
||||
// Start by checking if this is a selection event.
|
||||
if (event.which === self.keyCode.ENTER) {
|
||||
self.setNgModelValue(self.displayTime, 'enter');
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// Selection isn't occuring, so the key event is either navigation or nothing.
|
||||
/*var date = self.getFocusDateFromKeyEvent(event);
|
||||
if (date) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// Since this is a keyboard interaction, actually give the newly focused date keyboard
|
||||
// focus after the been brought into view.
|
||||
self.changeDisplayTime(date).then(function () {
|
||||
self.focus(date);
|
||||
});
|
||||
}*/
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the ng-model value for the time pane and emits a change event.
|
||||
* @param {Date} date
|
||||
*/
|
||||
TimePaneCtrl.prototype.setNgModelValue = function(date, mode) {
|
||||
this.$scope.$emit('sg-time-pane-change', {date:date, changed:mode});
|
||||
this.ngModelCtrl.$setViewValue(date);
|
||||
this.ngModelCtrl.$render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Focus the cell corresponding to the given date.
|
||||
* @param {Date=} opt_date
|
||||
*/
|
||||
TimePaneCtrl.prototype.focus = function(opt_date, sgTimePaneCtrl) {
|
||||
var date = opt_date || this.selectedTime || this.today;
|
||||
|
||||
var previousFocus = this.timePaneElement.querySelector('.md-focus');
|
||||
if (previousFocus) {
|
||||
previousFocus.classList.remove(FOCUSED_TIME_CLASS);
|
||||
}
|
||||
|
||||
if (date) {
|
||||
var newH = date.getHours();
|
||||
var hCell = document.getElementById('tp-'+sgTimePaneCtrl.id+'-hour-'+newH);
|
||||
if (hCell) {
|
||||
hCell.classList.add(FOCUSED_TIME_CLASS);
|
||||
hCell.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.Common')
|
||||
.directive('sgTimepicker', timePickerDirective);
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name mdTimepicker
|
||||
* @module material.components.timepicker
|
||||
*
|
||||
* @param {Date} ng-model The component's model. Expects a JavaScript Date object.
|
||||
* @param {expression=} ng-change Expression evaluated when the model value changes.
|
||||
* @param {boolean=} disabled Whether the timepicker is disabled.
|
||||
*
|
||||
* @description
|
||||
* `<sg-timepicker>` is a component used to select a single time.
|
||||
* For information on how to configure internationalization for the time picker,
|
||||
* see `$mdTimeLocaleProvider`.
|
||||
*
|
||||
* @usage
|
||||
* <hljs lang="html">
|
||||
* <sg-timepicker ng-model="birthday"></sg-timepicker>
|
||||
* </hljs>
|
||||
*
|
||||
*/
|
||||
function timePickerDirective() {
|
||||
return {
|
||||
template:
|
||||
// Buttons are not in the tab order because users can open the hours pane via keyboard
|
||||
// interaction on the text input, and multiple tab stops for one component (picker)
|
||||
// may be confusing.
|
||||
'<md-button class="sg-timepicker-button md-icon-button" type="button" ' +
|
||||
'tabindex="-1" aria-hidden="true" ' +
|
||||
'ng-click="ctrl.openTimePane($event)">' +
|
||||
//'<md-icon class="md-timepicker-calendar-icon" md-svg-icon="md-calendar"></md-icon>' +
|
||||
'<i class="material-icons">access_time</i>' +
|
||||
'</md-button>' +
|
||||
'<div class="sg-timepicker-input-container" ' +
|
||||
'ng-class="{\'sg-timepicker-focused\': ctrl.isFocused}">' +
|
||||
'<input class="sg-timepicker-input" aria-haspopup="true" ' +
|
||||
'ng-focus="ctrl.setFocused(true)" ng-blur="ctrl.setFocused(false)">' +
|
||||
'<md-button type="button" md-no-ink ' +
|
||||
'class="sg-timepicker-triangle-button md-icon-button" ' +
|
||||
'ng-click="ctrl.openTimePane($event)" ' +
|
||||
'aria-label="{{::ctrl.dateLocale.msgOpenCalendar}}">' +
|
||||
'<div class="sg-timepicker-expand-triangle"></div>' +
|
||||
'</md-button>' +
|
||||
'</div>' +
|
||||
// This pane will be detached from here and re-attached to the document body.
|
||||
'<div class="sg-timepicker-time-pane md-whiteframe-z1">' +
|
||||
'<div class="sg-timepicker-input-mask">' +
|
||||
'<div class="sg-timepicker-input-mask-opaque"></div>' +
|
||||
'</div>' +
|
||||
'<div class="sg-timepicker-time">' +
|
||||
'<sg-time-pane role="dialog" aria-label="{{::ctrl.dateLocale.msgCalendar}}" ' +
|
||||
'ng-model="ctrl.time" ng-if="ctrl.isTimeOpen"></sg-time-pane>' +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
require: ['ngModel', 'sgTimepicker'],
|
||||
scope: {
|
||||
placeholder: '@mdPlaceholder'
|
||||
},
|
||||
controller: TimePickerCtrl,
|
||||
controllerAs: 'ctrl',
|
||||
bindToController: true,
|
||||
link: function(scope, element, attr, controllers) {
|
||||
var ngModelCtrl = controllers[0];
|
||||
var mdTimePickerCtrl = controllers[1];
|
||||
|
||||
mdTimePickerCtrl.configureNgModel(ngModelCtrl);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Additional offset for the input's `size` attribute, which is updated based on its content. */
|
||||
var EXTRA_INPUT_SIZE = 3;
|
||||
|
||||
/** Class applied to the container if the date is invalid. */
|
||||
var INVALID_CLASS = 'sg-timepicker-invalid';
|
||||
|
||||
/** Default time in ms to debounce input event by. */
|
||||
var DEFAULT_DEBOUNCE_INTERVAL = 500;
|
||||
|
||||
/**
|
||||
* Controller for sg-timepicker.
|
||||
*
|
||||
* ngInject @constructor
|
||||
*/
|
||||
function TimePickerCtrl($scope, $element, $attrs, $compile, $timeout, $mdConstant, $mdTheming,
|
||||
$mdUtil, $mdDateLocale, $$mdDateUtil, $$rAF) {
|
||||
/** @final */
|
||||
this.$compile = $compile;
|
||||
|
||||
/** @final */
|
||||
this.$timeout = $timeout;
|
||||
|
||||
/** @final */
|
||||
this.dateLocale = $mdDateLocale;
|
||||
|
||||
/** @final */
|
||||
this.dateUtil = $$mdDateUtil;
|
||||
|
||||
/** @final */
|
||||
this.$mdConstant = $mdConstant;
|
||||
|
||||
/* @final */
|
||||
this.$mdUtil = $mdUtil;
|
||||
|
||||
/** @final */
|
||||
this.$$rAF = $$rAF;
|
||||
|
||||
/** @type {!angular.NgModelController} */
|
||||
this.ngModelCtrl = null;
|
||||
|
||||
/** @type {HTMLInputElement} */
|
||||
this.inputElement = $element[0].querySelector('input');
|
||||
|
||||
/** @type {HTMLElement} */
|
||||
this.inputContainer = $element[0].querySelector('.sg-timepicker-input-container');
|
||||
|
||||
/** @type {HTMLElement} Floating time pane. */
|
||||
this.timePane = $element[0].querySelector('.sg-timepicker-time-pane');
|
||||
|
||||
/** @type {HTMLElement} Time icon button. */
|
||||
this.timeButton = $element[0].querySelector('.sg-timepicker-button');
|
||||
|
||||
/**
|
||||
* Element covering everything but the input in the top of the floating calendar pane.
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.inputMask = $element[0].querySelector('.sg-timepicker-input-mask-opaque');
|
||||
|
||||
/** @final {!angular.JQLite} */
|
||||
this.$element = $element;
|
||||
|
||||
/** @final {!angular.Attributes} */
|
||||
this.$attrs = $attrs;
|
||||
|
||||
/** @final {!angular.Scope} */
|
||||
this.$scope = $scope;
|
||||
|
||||
/** @type {Date} */
|
||||
this.date = null;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.isFocused = false;
|
||||
|
||||
/** @type {boolean} */
|
||||
this.isDisabled = false;
|
||||
this.setDisabled($element[0].disabled || angular.isString($attrs.disabled));
|
||||
|
||||
/** @type {boolean} Whether the date-picker's calendar pane is open. */
|
||||
this.isTimeOpen = false;
|
||||
|
||||
/**
|
||||
* Element from which the calendar pane was opened. Keep track of this so that we can return
|
||||
* focus to it when the pane is closed.
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.timePaneOpenedFrom = null;
|
||||
|
||||
this.timePane.id = 'sg-time-pane' + $mdUtil.nextUid();
|
||||
|
||||
$mdTheming($element);
|
||||
|
||||
/** Pre-bound click handler is saved so that the event listener can be removed. */
|
||||
this.bodyClickHandler = angular.bind(this, this.handleBodyClick);
|
||||
|
||||
// Unless the user specifies so, the datepicker should not be a tab stop.
|
||||
// This is necessary because ngAria might add a tabindex to anything with an ng-model
|
||||
// (based on whether or not the user has turned that particular feature on/off).
|
||||
if (!$attrs.tabindex) {
|
||||
$element.attr('tabindex', '-1');
|
||||
}
|
||||
|
||||
this.installPropertyInterceptors();
|
||||
this.attachChangeListeners();
|
||||
this.attachInteractionListeners();
|
||||
|
||||
var self = this;
|
||||
$scope.$on('$destroy', function() {
|
||||
self.detachTimePane();
|
||||
});
|
||||
}
|
||||
|
||||
TimePickerCtrl.$inject = ["$scope", "$element", "$attrs", "$compile", "$timeout", "$mdConstant", "$mdTheming",
|
||||
"$mdUtil", "$mdDateLocale", "$$mdDateUtil", "$$rAF"];
|
||||
|
||||
/**
|
||||
* Sets up the controller's reference to ngModelController.
|
||||
* @param {!angular.NgModelController} ngModelCtrl
|
||||
*/
|
||||
TimePickerCtrl.prototype.configureNgModel = function(ngModelCtrl) {
|
||||
this.ngModelCtrl = ngModelCtrl;
|
||||
var self = this;
|
||||
ngModelCtrl.$render = function() {
|
||||
self.time = self.ngModelCtrl.$viewValue;
|
||||
self.inputElement.value = self.formatTime(self.time);
|
||||
self.resizeInputElement();
|
||||
};
|
||||
};
|
||||
|
||||
TimePickerCtrl.prototype.formatTime = function(time) {
|
||||
var t = new Date(time);
|
||||
if(t) {
|
||||
var h= t.getHours();
|
||||
var m= t.getMinutes();
|
||||
return (h<10?('0'+ h) : h) + ':' + (m<10?'0'+ m : m);
|
||||
}
|
||||
else return '';
|
||||
};
|
||||
/**
|
||||
* Attach event listeners for both the text input and the md-time.
|
||||
* Events are used instead of ng-model so that updates don't infinitely update the other
|
||||
* on a change. This should also be more performant than using a $watch.
|
||||
*/
|
||||
TimePickerCtrl.prototype.attachChangeListeners = function() {
|
||||
var self = this;
|
||||
|
||||
self.$scope.$on('sg-time-pane-change', function(event, data) {
|
||||
var time = new Date(data.date);
|
||||
self.ngModelCtrl.$setViewValue(time);
|
||||
self.time = time;
|
||||
self.inputElement.value = self.formatTime(self.time);
|
||||
if(data.changed == 'minutes') {
|
||||
self.closeTimePane();
|
||||
}
|
||||
self.resizeInputElement();
|
||||
self.inputContainer.classList.remove(INVALID_CLASS);
|
||||
});
|
||||
|
||||
var ngElement = angular.element(self.inputElement);
|
||||
ngElement.on('input', angular.bind(self, self.resizeInputElement));
|
||||
ngElement.on('input', self.$mdUtil.debounce(self.handleInputEvent,
|
||||
DEFAULT_DEBOUNCE_INTERVAL, self));
|
||||
};
|
||||
|
||||
/** Attach event listeners for user interaction. */
|
||||
TimePickerCtrl.prototype.attachInteractionListeners = function() {
|
||||
var self = this;
|
||||
var $scope = this.$scope;
|
||||
var keyCodes = this.$mdConstant.KEY_CODE;
|
||||
|
||||
// Add event listener through angular so that we can triggerHandler in unit tests.
|
||||
angular.element(self.inputElement).on('keydown', function(event) {
|
||||
if (event.altKey && event.keyCode == keyCodes.DOWN_ARROW) {
|
||||
self.openTimePane(event);
|
||||
$scope.$digest();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('md-time-close', function() {
|
||||
self.closeTimePane();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Capture properties set to the time-picker and imperitively handle internal changes.
|
||||
* This is done to avoid setting up additional $watches.
|
||||
*/
|
||||
TimePickerCtrl.prototype.installPropertyInterceptors = function() {
|
||||
var self = this;
|
||||
|
||||
if (this.$attrs.ngDisabled) {
|
||||
// The expression is to be evaluated against the directive element's scope and not
|
||||
// the directive's isolate scope.
|
||||
this.$element.scope().$watch(this.$attrs.ngDisabled, function(isDisabled) {
|
||||
self.setDisabled(isDisabled);
|
||||
});
|
||||
}
|
||||
|
||||
Object.defineProperty(this, 'placeholder', {
|
||||
get: function() { return self.inputElement.placeholder; },
|
||||
set: function(value) { self.inputElement.placeholder = value || ''; }
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the date-picker is disabled.
|
||||
* @param {boolean} isDisabled
|
||||
*/
|
||||
TimePickerCtrl.prototype.setDisabled = function(isDisabled) {
|
||||
this.isDisabled = isDisabled;
|
||||
this.inputElement.disabled = isDisabled;
|
||||
this.timeButton.disabled = isDisabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resizes the input element based on the size of its content.
|
||||
*/
|
||||
TimePickerCtrl.prototype.resizeInputElement = function() {
|
||||
this.inputElement.size = this.inputElement.value.length + EXTRA_INPUT_SIZE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the model value if the user input is a valid time.
|
||||
* Adds an invalid class to the input element if not.
|
||||
*/
|
||||
TimePickerCtrl.prototype.handleInputEvent = function(self) {
|
||||
var inputString = this.inputElement.value;
|
||||
var arr = inputString.split(':');
|
||||
if(arr.length < 2) {return;}
|
||||
var h=Number(arr[0]);
|
||||
var m=Number(arr[1]);
|
||||
var newVal = new Date(this.time);
|
||||
if (h && h>=0 && h<=23 && m && m>=0 && m<= 59 && angular.isDate(newVal)) {
|
||||
newVal.setHours(h);
|
||||
newVal.setMinutes(m);
|
||||
this.ngModelCtrl.$setViewValue(newVal);
|
||||
this.time = newVal;
|
||||
this.inputContainer.classList.remove(INVALID_CLASS);
|
||||
}
|
||||
else {
|
||||
// If there's an input string, it's an invalid time.
|
||||
this.inputContainer.classList.toggle(INVALID_CLASS, inputString);
|
||||
}
|
||||
};
|
||||
|
||||
/** Position and attach the floating calendar to the document. */
|
||||
TimePickerCtrl.prototype.attachTimePane = function() {
|
||||
var timePane = this.timePane;
|
||||
this.$element.addClass('sg-timepicker-open');
|
||||
|
||||
var elementRect = this.inputContainer.getBoundingClientRect();
|
||||
var bodyRect = document.body.getBoundingClientRect();
|
||||
|
||||
timePane.style.left = (elementRect.left - bodyRect.left) + 'px';
|
||||
timePane.style.top = (elementRect.top - bodyRect.top) + 'px';
|
||||
document.body.appendChild(this.timePane);
|
||||
|
||||
// The top of the calendar pane is a transparent box that shows the text input underneath.
|
||||
// Since the pane is flowing, though, the page underneath the pane *adjacent* to the input is
|
||||
// also shown unless we cover it up. The inputMask does this by filling up the remaining space
|
||||
// based on the width of the input.
|
||||
this.inputMask.style.left = elementRect.width + 'px';
|
||||
|
||||
// Add CSS class after one frame to trigger open animation.
|
||||
this.$$rAF(function() {
|
||||
timePane.classList.add('md-pane-open');
|
||||
});
|
||||
};
|
||||
|
||||
/** Detach the floating time pane from the document. */
|
||||
TimePickerCtrl.prototype.detachTimePane = function() {
|
||||
this.$element.removeClass('sg-timepicker-open');
|
||||
this.timePane.classList.remove('md-pane-open');
|
||||
|
||||
if (this.timePane.parentNode) {
|
||||
// Use native DOM removal because we do not want any of the angular state of this element
|
||||
// to be disposed.
|
||||
this.timePane.parentNode.removeChild(this.timePane);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Open the floating time pane.
|
||||
* @param {Event} event
|
||||
*/
|
||||
TimePickerCtrl.prototype.openTimePane = function(event) {
|
||||
if (!this.isTimeOpen && !this.isDisabled) {
|
||||
this.isTimeOpen = true;
|
||||
this.timePaneOpenedFrom = event.target;
|
||||
this.attachTimePane();
|
||||
this.focusTime();
|
||||
|
||||
// Because the time pane is attached directly to the body, it is possible that the
|
||||
// rest of the component (input, etc) is in a different scrolling container, such as
|
||||
// an md-content. This means that, if the container is scrolled, the pane would remain
|
||||
// stationary. To remedy this, we disable scrolling while the time pane is open, which
|
||||
// also matches the native behavior for things like `<select>` on Mac and Windows.
|
||||
this.$mdUtil.disableScrollAround(this.timePane);
|
||||
|
||||
// Attach click listener inside of a timeout because, if this open call was triggered by a
|
||||
// click, we don't want it to be immediately propogated up to the body and handled.
|
||||
var self = this;
|
||||
this.$mdUtil.nextTick(function() {
|
||||
document.body.addEventListener('click', self.bodyClickHandler);
|
||||
}, false);
|
||||
}
|
||||
};
|
||||
|
||||
/** Close the floating time pane. */
|
||||
TimePickerCtrl.prototype.closeTimePane = function() {
|
||||
this.isTimeOpen = false;
|
||||
this.detachTimePane();
|
||||
this.timePaneOpenedFrom.focus();
|
||||
this.timePaneOpenedFrom = null;
|
||||
this.$mdUtil.enableScrolling();
|
||||
|
||||
document.body.removeEventListener('click', this.bodyClickHandler);
|
||||
};
|
||||
|
||||
/** Gets the controller instance for the time in the floating pane. */
|
||||
TimePickerCtrl.prototype.getTimePaneCtrl = function() {
|
||||
return angular.element(this.timePane.querySelector('sg-time-pane')).controller('sgTimePane');
|
||||
};
|
||||
|
||||
/** Focus the time in the floating pane. */
|
||||
TimePickerCtrl.prototype.focusTime = function() {
|
||||
// Use a timeout in order to allow the time to be rendered, as it is gated behind an ng-if.
|
||||
var self = this;
|
||||
this.$mdUtil.nextTick(function() {
|
||||
var ctrl = self.getTimePaneCtrl();
|
||||
self.getTimePaneCtrl().focus(null, ctrl);
|
||||
}, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets whether the input is currently focused.
|
||||
* @param {boolean} isFocused
|
||||
*/
|
||||
TimePickerCtrl.prototype.setFocused = function(isFocused) {
|
||||
this.isFocused = isFocused;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles a click on the document body when the floating time pane is open.
|
||||
* Closes the floating time pane if the click is not inside of it.
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
TimePickerCtrl.prototype.handleBodyClick = function(event) {
|
||||
if (this.isTimeOpen) {
|
||||
// TODO(jelbourn): way want to also include the md-datepicker itself in this check.
|
||||
var isInTime = this.$mdUtil.getClosest(event.target, 'sg-time-pane');
|
||||
if (!isInTime) {
|
||||
this.closeTimePane();
|
||||
}
|
||||
|
||||
this.$scope.$digest();
|
||||
}
|
||||
};
|
||||
})();
|
||||
@@ -80,7 +80,7 @@ String.prototype.md5 = function() {
|
||||
|
||||
String.prototype.capitalize = function() {
|
||||
return this.charAt(0).toUpperCase() + this.slice(1);
|
||||
};
|
||||
}
|
||||
|
||||
String.prototype.asDate = function () {
|
||||
var newDate;
|
||||
@@ -129,7 +129,7 @@ String.prototype.formatTime = function(hours, minutes) {
|
||||
};
|
||||
|
||||
Date.prototype.daysUpTo = function(otherDate) {
|
||||
var days = [];
|
||||
var days = new Array();
|
||||
|
||||
var day1 = this.getTime();
|
||||
var day2 = otherDate.getTime();
|
||||
@@ -155,8 +155,10 @@ String.prototype.isValidEmail = function() {
|
||||
};
|
||||
|
||||
String.prototype.asCSSIdentifier = function() {
|
||||
var characters = [ '_' , '\\.', '#' , '@' , '\\*', ':' , ',' , ' ', "'", '&', '\\+' ];
|
||||
var escapeds = [ '_U_', '_D_', '_H_', '_A_', '_S_', '_C_', '_CO_', '_SP_', '_SQ_', '_AM_', '_P_' ];
|
||||
var characters = [ '_' , '\\.', '#' , '@' , '\\*', ':' , ',' , ' '
|
||||
, "'", '&', '\\+' ];
|
||||
var escapeds = [ '_U_', '_D_', '_H_', '_A_', '_S_', '_C_', '_CO_',
|
||||
'_SP_', '_SQ_', '_AM_', '_P_' ];
|
||||
|
||||
var newString = this;
|
||||
for (var i = 0; i < characters.length; i++) {
|
||||
@@ -229,7 +231,7 @@ Date.prototype.beginOfDay = function() {
|
||||
beginOfDay.setMilliseconds(0);
|
||||
|
||||
return beginOfDay;
|
||||
};
|
||||
}
|
||||
|
||||
Date.prototype.beginOfWeek = function() {
|
||||
var offset = firstDayOfWeek - this.getDay();
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular.module('SOGo.ContactsUI', ['ngSanitize', 'ui.router', 'angularFileUpload', 'ck', 'SOGo.Common', 'SOGo.PreferencesUI', 'SOGo.MailerUI'])
|
||||
angular.module('SOGo.ContactsUI', ['ngSanitize', 'ui.router', 'SOGo.Common', 'SOGo.PreferencesUI'])
|
||||
.config(configure)
|
||||
.run(runBlock);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){"use strict";function configure($stateProvider,$urlRouterProvider){$stateProvider.state("app",{url:"/addressbooks","abstract":!0,views:{addressbooks:{templateUrl:"UIxContactFoldersView",controller:"AddressBooksController",controllerAs:"app"}},resolve:{stateAddressbooks:stateAddressbooks}}).state("app.addressbook",{url:"/:addressbookId",views:{addressbook:{templateUrl:"addressbook",controller:"AddressBookController",controllerAs:"addressbook"}},resolve:{stateAddressbook:stateAddressbook}}).state("app.addressbook.new",{url:"/{contactType:(?:card|list)}/new",views:{card:{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}},resolve:{stateCard:stateNewCard}}).state("app.addressbook.card",{url:"/:cardId","abstract":!0,views:{card:{template:"<ui-view/>"}},resolve:{stateCard:stateCard}}).state("app.addressbook.card.view",{url:"/view",views:{"card@app.addressbook":{templateUrl:"UIxContactViewTemplate",controller:"CardController",controllerAs:"editor"}}}).state("app.addressbook.card.editor",{url:"/edit",views:{"card@app.addressbook":{templateUrl:"UIxContactEditorTemplate",controller:"CardController",controllerAs:"editor"}}}),$urlRouterProvider.otherwise("/addressbooks/personal")}function stateAddressbooks(AddressBook){return AddressBook.$findAll(window.contactFolders)}function stateAddressbook($stateParams,AddressBook){return AddressBook.$find($stateParams.addressbookId).$futureAddressBookData}function stateNewCard($stateParams,stateAddressbook,Card){var tag="v"+$stateParams.contactType,card=new Card({pid:$stateParams.addressbookId,c_component:tag});return stateAddressbook.selectedCard=!0,card}function stateCard($stateParams,stateAddressbook){return stateAddressbook.selectedCard=$stateParams.cardId,stateAddressbook.$getCard($stateParams.cardId)}function runBlock($rootScope){$rootScope.$on("$routeChangeError",function(event,current,previous,rejection){console.error(event,current,previous,rejection)})}angular.module("SOGo.ContactsUI",["ngSanitize","ui.router","angularFileUpload","ck","SOGo.Common","SOGo.PreferencesUI","SOGo.MailerUI"]).config(configure).run(runBlock),configure.$inject=["$stateProvider","$urlRouterProvider"],stateAddressbooks.$inject=["AddressBook"],stateAddressbook.$inject=["$stateParams","AddressBook"],stateNewCard.$inject=["$stateParams","stateAddressbook","Card"],stateCard.$inject=["$stateParams","stateAddressbook"],runBlock.$inject=["$rootScope"]}(),function(){"use strict";function AddressBookController($scope,$q,$state,$timeout,$mdDialog,focus,Account,Card,AddressBook,Dialog,Settings,stateAddressbooks,stateAddressbook){function selectCard(card){$state.go("app.addressbook.card.view",{addressbookId:stateAddressbook.id,cardId:card.id})}function newComponent(ev){function ComponentDialogController(scope,$mdDialog,$state,addressbookId){scope.create=function(type){$mdDialog.hide(),$state.go("app.addressbook.new",{addressbookId:addressbookId,contactType:type})}}$mdDialog.show({parent:angular.element(document.body),targetEvent:ev,clickOutsideToClose:!0,escapeToClose:!0,template:['<md-dialog aria-label="'+l("Create component")+'">'," <md-dialog-content>",' <div layout="column">'," <md-button ng-click=\"create('card')\">"," "+l("Contact")," </md-button>"," <md-button ng-click=\"create('list')\">"," "+l("List")," </md-button>"," </div>"," </md-dialog-content>","</md-dialog>"].join(""),locals:{addressbookId:vm.selectedFolder.id},controller:ComponentDialogController}),ComponentDialogController.$inject=["scope","$mdDialog","$state","addressbookId"]}function notSelectedComponent(currentCard,type){return currentCard&¤tCard.c_component==type&&!currentCard.selected}function unselectCards(){_.each(vm.selectedFolder.cards,function(card){card.selected=!1})}function confirmDeleteSelectedCards(){Dialog.confirm(l("Warning"),l("Are you sure you want to delete the selected contacts?")).then(function(){var selectedCards=_.filter(vm.selectedFolder.cards,function(card){return card.selected});vm.selectedFolder.$deleteCards(selectedCards),delete vm.selectedFolder.selectedCard},function(data,status){})}function saveSelectedCards(){var selectedCards=_.filter(vm.selectedFolder.cards,function(card){return card.selected}),selectedUIDs=_.pluck(selectedCards,"id");window.location.href=ApplicationBaseURL+"/"+vm.selectedFolder.id+"/export?uid="+selectedUIDs.join("&uid=")}function copySelectedCards(folder){var selectedCards=_.filter(vm.selectedFolder.cards,function(card){return card.selected});vm.selectedFolder.$copyCards(selectedCards,folder).then(function(){},function(error){Dialog.alert(l("Error"),error)})}function selectAll(){_.each(vm.selectedFolder.cards,function(card){card.selected=!0})}function sort(field){vm.selectedFolder.$filter("",{sort:field})}function sortedBy(field){return AddressBook.$query.sort==field}function cancelSearch(){vm.mode.search=!1,vm.selectedFolder.$filter("")}function newMessage($event,recipients){Account.$findALine truncated
|
||||
//# sourceMappingURL=Contacts.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"Contacts.js","sources":["Contacts/Contacts.app.js","Contacts/AddressBookController.js","Contacts/AddressBooksController.js","Contacts/CardController.js","Contacts/sgAddress.directive.js"],"names":["configure","$stateProvider","$urlRouterProvider","state","url","abstract","views","addressbooks","templateUrl","controller","controllerAs","resolve","stateAddressbooks","addressbook","stateAddressbook","card","stateCard","stateNewCard","template","card@app.addressbook","otherwise","AddressBook","$findAll","window","contactFolders","$stateParams","$find","addressbookId","$futureAddressBookData","Card","tag","contactType","pid","c_component","selectedCard","cardId","$getCard","runBlock","$rootScope","$on","event","current","previous","rejection","console","error","angular","module","config","run","$inject","AddressBookController","$scope","$q","$state","$timeout","$mdDialog","focus","Account","Dialog","Settings","selectCard","go","id","newComponent","ev","ComponentDialogController","scope","create","type","hide","show","parent","element","document","body","targetEvent","clickOutsideToClose","escapeToClose","l","join","locals","vm","selectedFolder","notSelectedComponent","currentCard","selected","unselectCards","_","each","cards","confirmDeleteSelectedCards","confirm","then","selectedCards","filter","$deleteCards","data","status","saveSelectedCards","selectedUIDs","pluck","location","href","ApplicationBaseURL","copySelectedCards","folder","$copyCards","alert","selectAll","sort","field","$filter","sortedBy","$query","cancelSearch","mode","search","newMessage","$event","recipients","accounts","account","o","$getMailboxes","mailboxes","$newMessage","message","stateAccounts","stateMessage","stateRecipients","newMessageWithRecipient","recipient","fn","full","newMessageWithSelectedCards","promises","c_mail","length","push","c_cn","isDefined","refs","ref","email","$futureCardData","all","this","AddressBooksController","$mdToast","FileUploader","User","select","editMode","value","newAddressbook","prompt","name","isEditable","isRemote","owner","UserLogin","$add","edit","originalAddressbook","extend","$omit","revertEditing","save","$rename","confirmDelete","service","isSubscription","$delete","importCards","CardsImportDialogController","uploader","onProgressItem","item","progress","debug","onSuccessItem","response","headers","JSON","stringify","undefined","simple","content","imported","position","hideDelay","$reload","onCancelItem","onErrorItem","close","upload","uploadAll","exportCards","showLinks","LinksDialogController","share","$acl","$users","usersWithACL","users","subscribeToFolder","addressbookData","$subscribe","activeUser","CardController","addOrgUnit","i","$addOrgUnit","addBirthday","birthday","Date","addEmail","$addEmail","addPhone","$addPhone","addUrl","$addUrl","addAddress","$addAddress","addMember","$addMember","userFilter","excludedCards","dry","excludeLists","$cards","form","$valid","$save","indexOf","copy","err","log","reset","$reset","cancel","isNew","$fullname","ok","reject","exportCard","currentFolder","viewRawSource","$$resource","post","CardRawSourceDialogController","allEmailTypes","$EMAIL_TYPES","allTelTypes","$TEL_TYPES","allUrlTypes","$URL_TYPES","allAddressTypes","$ADDRESS_TYPES","categories","userFilterResults","sgAddress","restrict","addressLines","lines","locality_region","street","street2","locality","region","country","postalcode","directive"],"mappings":"CAGA,WACE,YAUA,SAASA,WAAUC,eAAgBC,oBACjCD,eACGE,MAAM,OACLC,IAAK,gBACLC,YAAU,EACVC,OACEC,cACEC,YAAa,wBACbC,WAAY,yBACZC,aAAc,QAGlBC,SACEC,kBAAmBA,qBAGtBT,MAAM,mBACLC,IAAK,kBACLE,OACEO,aACEL,YAAa,cACbC,WAAY,wBACZC,aAAc,gBAGlBC,SACEG,iBAAkBA,oBAGrBX,MAAM,uBACLC,IAAK,mCACLE,OACES,MACEP,YAAa,2BACbC,WAAY,iBACZC,aAAc,WAGlBC,SACEK,UAAWC,gBAGdd,MAAM,wBACLC,IAAK,WACLC,YAAU,EACVC,OACES,MACEG,SAAU,eAGdP,SACEK,UAAWA,aAGdb,MAAM,6BACLC,IAAK,QACLE,OACEa,wBACEX,YAAa,yBACbC,WAAY,iBACZC,aAAc,aAInBP,MAAM,+BACLC,IAAK,QACLE,OACEa,wBACEX,YAAa,2BACbC,WAAY,iBACZC,aAAc,aAMtBR,mBAAmBkB,UAAU,0BAO/B,QAASR,mBAAkBS,aACzB,MAAOA,aAAYC,SAASC,OAAOC,gBAOrC,QAASV,kBAAiBW,aAAcJ,aACtC,MAAOA,aAAYK,MAAMD,aAAaE,eAAeC,uBAOvD,QAASX,cAAaQ,aAAcX,iBAAkBe,MACpD,GAAIC,KAAM,IAAML,aAAaM,YACzBhB,KAAO,GAAIc,OAAOG,IAAKP,aAAaE,cAAeM,YAAaH,KAEpE,OADAhB,kBAAiBoB,cAAe,EACzBnB,KAOT,QAASC,WAAUS,aAAcX,kBAE/B,MADAA,kBAAiBoB,aAAeT,aAAaU,OACtCrB,iBAAiBsB,SAASX,aAAaU,QAOhD,QAASE,UAASC,YAChBA,WAAWC,IAAI,oBAAqB,SAASC,MAAOC,QAASC,SAAUC,WACrEC,QAAQC,MAAML,MAAOC,QAASC,SAAUC,aAjI5CG,QAAQC,OAAO,mBAAoB,aAAc,YAAa,oBAAqB,KAAM,cAAe,qBAAsB,kBAC3HC,OAAOhD,WACPiD,IAAIZ,UAKPrC,UAAUkD,SAAW,iBAAkB,sBAmFvCtC,kBAAkBsC,SAAW,eAQ7BpC,iBAAiBoC,SAAW,eAAgB,eAQ5CjC,aAAaiC,SAAW,eAAgB,mBAAoB,QAW5DlC,UAAUkC,SAAW,eAAgB,oBASrCb,SAASa,SAAW,iBClItB,WACE,YAMA,SAASC,uBAAsBC,OAAQC,GAAIC,OAAQC,SAAUC,UAAWC,MAAOC,QAAS7B,KAAMR,YAAasC,OAAQC,SAAUhD,kBAAmBE,kBAsB9I,QAAS+C,YAAW9C,MAClBuC,OAAOQ,GAAG,6BAA8BnC,cAAeb,iBAAiBiD,GAAI5B,OAAQpB,KAAKgD,KAG3F,QAASC,cAAaC,IA8BpB,QAASC,2BAA0BC,MAAOX,UAAWF,OAAQ3B,eAC3DwC,MAAMC,OAAS,SAASC,MACtBLine truncated
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(){"use strict";function AddressBook(futureAddressBookData){if("function"!=typeof futureAddressBookData.then)if(this.init(futureAddressBookData),this.name&&!this.id){var newAddressBookData=AddressBook.$$resource.create("createFolder",this.name);this.$unwrap(newAddressBookData)}else this.id&&(this.$acl=new AddressBook.$$Acl("Contacts/"+this.id));else this.$unwrap(futureAddressBookData)}AddressBook.$factory=["$q","$timeout","$log","sgSettings","Resource","Card","Acl","Preferences",function($q,$timeout,$log,Settings,Resource,Card,Acl,Preferences){return angular.extend(AddressBook,{$q:$q,$timeout:$timeout,$log:$log,$$resource:new Resource(Settings.activeUser("folderURL")+"Contacts",Settings.activeUser()),$Card:Card,$$Acl:Acl,$Preferences:Preferences,$query:{search:"name_or_address",value:"",sort:"c_cn",asc:1},activeUser:Settings.activeUser(),selectedFolder:null,$refreshTimeout:null}),Preferences.ready().then(function(){Preferences.settings.Contact.SortingState&&(AddressBook.$query.sort=Preferences.settings.Contact.SortingState[0],AddressBook.$query.asc=parseInt(Preferences.settings.Contact.SortingState[1]))}),AddressBook}];try{angular.module("SOGo.ContactsUI")}catch(e){angular.module("SOGo.ContactsUI",["SOGo.Common"])}angular.module("SOGo.ContactsUI").factory("AddressBook",AddressBook.$factory),AddressBook.$filterAll=function(search,options,excludedCards){var params={search:search};if(!search)return AddressBook.$cards=[],AddressBook.$q.when(AddressBook.$cards);if(angular.isUndefined(AddressBook.$cards))AddressBook.$cards=[];else if(AddressBook.$query==search)return AddressBook.$q.when(AddressBook.$cards);return AddressBook.$query=search,angular.extend(params,options),AddressBook.$$resource.fetch(null,"allContactSearch",params).then(function(response){var results,card,index,compareIds=function(data){return this.id==data.id};for(results=excludedCards?_.filter(response.contacts,function(data){return _.isUndefined(_.find(excludedCards,compareIds,data))}):response.contacts,index=AddressBook.$cards.length-1;index>=0;index--)card=AddressBook.$cards[index],_.isUndefined(_.find(results,compareIds,card))&&AddressBook.$cards.splice(index,1);return _.each(results,function(data,index){if(_.isUndefined(_.find(AddressBook.$cards,compareIds,data))){var card=new AddressBook.$Card(data,search);AddressBook.$cards.splice(index,0,card)}}),AddressBook.$cards})},AddressBook.$add=function(addressbook){var list,sibling,i;list=addressbook.isSubscription?this.$subscriptions:this.$addressbooks,sibling=_.find(list,function(o){return"personal"==addressbook.id||"personal"!=o.id&&1===o.name.localeCompare(addressbook.name)}),i=sibling?_.indexOf(_.pluck(list,"id"),sibling.id):1,list.splice(i,0,addressbook)},AddressBook.$findAll=function(data){var _this=this;return data&&(this.$addressbooks=[],this.$subscriptions=[],this.$remotes=[],angular.forEach(data,function(o,i){var addressbook=new AddressBook(o);addressbook.isRemote?_this.$remotes.push(addressbook):addressbook.isSubscription?_this.$subscriptions.push(addressbook):_this.$addressbooks.push(addressbook)})),_.union(this.$addressbooks,this.$subscriptions,this.$remotes)},AddressBook.$find=function(addressbookId){var futureAddressBookData=AddressBook.$Preferences.ready().then(function(){return AddressBook.$$resource.fetch(addressbookId,"view",AddressBook.$query)});return new AddressBook(futureAddressBookData)},AddressBook.$subscribe=function(uid,path){var _this=this;return AddressBook.$$resource.userResource(uid).fetch(path,"subscribe").then(function(addressbookData){var addressbook=new AddressBook(addressbookData);return _.isUndefined(_.find(_this.$subscriptions,function(o){return o.id==addressbookData.id}))&&AddressBook.$add(addressbook),addressbook})},AddressBook.prototype.init=function(data){this.$isLoading=!0,this.$cards=[],this.cards=[],angular.extend(this,data),this.isOwned=AddressBook.activeUser.isSuperUser||this.owner==AddressBook.activeUser.login,this.isSubscription=!this.isRemote&&this.owner!=AddressBook.activeUser.login},AddressBook.prototype.$id=function(){return this.id?AddressBook.$q.when(this.id):this.$futureAddressBookData.then(function(addressbook){return addressbook.id})},AddressBook.prototype.$selectedCount=function(){var count;return count=0,this.cards&&(count=_.filter(this.cards,function(card){return card.selected}).length),count},AddressBook.prototype.$startRefreshTimeout=function(){var _this=this;AddressBook.$refreshTimeout&&AddressBook.$timeout.cancel(AddressBook.$refreshTimeout),AddressBook.$Preferences.ready().then(function(){var refreshViewCheck=AddressBook.$Preferences.defaults.SOGoRefreshViewCheck;if(refreshViewCheck&&"manually"!=refreshViewCheck){var f=angular.bind(_this,AddressBook.prototype.$reload);AddressBook.$refreshTimeout=AddressBook.$timeout(f,1e3*refreshViewCheck.timeInterval())}})},AddressBook.prototype.$reload=function(){return this.$startRefreshTimeout(),this.$filter()},AddressBook.prototype.$filter=function(search,options,excludedCards){var _tLine truncated
|
||||
//# sourceMappingURL=Contacts.services.js.map
|
||||
Loaded 100 of 196 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user