2007-09-17 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ * UI/MailPartViewers/UIxMailPartICalViewer.m
+ ([UIxMailPartICalViewer -calendarFolder]): returns the "personal"
+ entry of the Calendars parent folder.
+
+ * UI/MailerUI/UIxMailListView.m ([UIxMailListView
+ -messageSubject]): new accessor method to work-around a problem
+ within SOPE where a subject could be returned as an NSData.
+
* SoObjects/SOGo/SOGoParentFolder.m ([SOGoParentFolder
-appendPersonalSources]): make sure the value of the "c_path4" of
the returned rows are not NSNull, otherwise, discard them.
- fixed search in message content;
- added tooltips for toolbar buttons (English and French);
- added checkmarks in live search options popup menus;
+- added browser detection with recommanded alternatives;
- initial support for resizable columns in tables;
+- improved IE7 and Safari support: attendees selector;
- countless bugfixes;
0.9.0-20070824
--- /dev/null
+#!/bin/bash
+# chkconfig: - 85 15
+# description: SOGo is a groupware server
+# processname: sogod-0.9
+# config: /etc/sysconfig/sogo
+# config: /etc/httpd/conf.d/SOGo.conf
+# pidfile: /var/run/sogo/sogod.pid
+
+# SOGo init script for RedHat
+#
+# Copyright (C) 2007 Inverse groupe conseil
+#
+# 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
+# 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.
+
+# sogod Scalable OpenGroupware.org (Inverse edition)
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+. /etc/rc.d/init.d/functions
+
+if [ -z "$GNUSTEP_SYSTEM_ROOT" ]
+then
+ . /usr/GNUstep/System/Library/Makefiles/GNUstep.sh
+fi
+
+REAL_DAEMON=$GNUSTEP_SYSTEM_ROOT/Tools/sogod-0.9
+DAEMON=/usr/sbin/sogod
+NAME=sogo
+DESC="Scalable OpenGroupware.Org (Inverse edition)"
+
+PIDFILE=/var/run/sogo/sogod.pid
+
+SOGO_ARGS=""
+
+if [ -f /etc/sysconfig/sogo ]; then
+ . /etc/sysconfig/sogo
+fi
+
+test -x $DAEMON || exit 0
+
+#set -e
+
+case "$1" in
+ start)
+ echo -n $"Starting $DESC: "
+ daemon su - sogo -c $DAEMON
+ echo "$NAME."
+ ;;
+ stop)
+ echo -n $"Stopping $DESC: "
+ killproc `basename $REAL_DAEMON` && rm -f $PIDFILE
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n $"Restarting $DESC: "
+ killproc `basename $REAL_DAEMON` && rm -f $PIDFILE
+ sleep 1
+ daemon su - sogo -c $DAEMON
+ echo "$NAME."
+ ;;
+ status)
+ status $REAL_DAEMON
+ ;;
+ *)
+ N=/etc/init.d/$NAME
+ echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
"Sorry, the user rights can not be configured for that object." = "Sorry, the user rights can not be configured for that object.";
+"browserNotCompatible" = "We've detected that your browser version is currently not supported on this site. Our recommendation is to use Firefox. Link to download the most current version of this browser is provided bellow:";
+"alternativeBrowsers" = "Alternatively, you can also use the following compatible browsers";
+"alternativeBrowserSafari" = "Alternatively, you can also use Safari.";
+"Download" = "Download";
+
/* generic.js */
"Unable to subscribe to that folder!"
= "Unable to subscribe to that folder!";
"Sorry, the user rights can not be configured for that object." = "Sorry, the user rights can not be configured for that object.";
+"browserNotCompatible" = "La version de votre navigateur Web n'est présentement pas supportée par ce site. Nous recommandons d'utiliser Firefox. Vous trouverez un lien vers la plus récente version de ce navigateur ci-dessous:";
+"alternativeBrowsers" = "Comme alternative, vous pouvez aussi utiliser les navigateurs suivants:";
+"alternativeBrowserSafari" = "Comme alternative, vous pouvez aussi utiliser Safari.";
+"Download" = "Télécharger";
+
/* generic.js */
"Unable to subscribe to that folder!" = "Impossible de s'abonner à ce dossier.";
"You cannot subscribe to a folder that you own!" = "Impossible de vous abonner à un dossier qui vous appartient.";
#define UIXPAGEFRAME_H
#import <SOGoUI/UIxComponent.h>
+#import <NGObjWeb/WEClientCapabilities.h>
@interface WOComponent (PopupExtension)
- (void) setToolbar: (NSString *) newToolbar;
- (NSString *) toolbar;
+- (BOOL) isCompatibleBrowser;
+- (BOOL) isIE7Compatible;
+- (BOOL) isMac;
+
@end
#endif /* UIXPAGEFRAME_H */
return toolbar;
}
+/* browser/os identification */
+
+- (BOOL) isCompatibleBrowser
+{
+ WEClientCapabilities *cc;
+
+ cc = [[context request] clientCapabilities];
+
+ //NSLog(@"Browser = %@", [cc description]);
+ NSLog(@"User agent = %@", [cc userAgent]);
+ //NSLog(@"Browser major version = %i", [cc majorVersion]);
+
+ return (
+ ([[cc userAgentType] isEqualToString: @"IE"] && [cc majorVersion] >= 7) ||
+ ([[cc userAgentType] isEqualToString: @"Mozilla"] && [cc majorVersion] >= 5) ||
+ ([[cc userAgentType] isEqualToString: @"Safari"] && [cc majorVersion] >= 4)
+ );
+}
+
+- (BOOL) isIE7Compatible
+{
+ WEClientCapabilities *cc;
+
+ cc = [[context request] clientCapabilities];
+
+ return ([cc isWindowsBrowser] &&
+ ([[cc userAgent] rangeOfString: @"NT 5.1"].location != NSNotFound ||
+ [[cc userAgent] rangeOfString: @"NT 6"].location != NSNotFound));
+}
+
+- (BOOL) isMac
+{
+ WEClientCapabilities *cc;
+
+ cc = [[context request] clientCapabilities];
+
+ return [cc isMacBrowser];
+}
+
+
@end /* UIxPageFrame */
{
url = [[elements objectAtIndex: 0] value: 0];
data = [NSString stringWithFormat:
- @"<a href=\"%@\">%@</a>",
+ @"<a href=\"%@\" target=\"_blank\">%@</a>",
url, url];
}
else
/* calendar folder support */
-- (id)calendarFolder {
+- (id) calendarFolder
+{
/* return scheduling calendar of currently logged-in user */
SOGoUser *user;
id folder;
inContext: context
acquire: NO];
- return folder;
+ return [folder lookupName: @"personal" inContext: context acquire: NO];
}
- (id)storedEventObject {
return [dateFormatter formattedDateAndTime: messageDate];
}
+- (NSString *) messageSubject
+{
+ NSString *subject;
+ id envSubject;
+
+ envSubject = [[message valueForKey: @"envelope"] subject];
+ if ([envSubject isKindOfClass: [NSData class]])
+ {
+ subject = [[NSString alloc] initWithData: envSubject
+ encoding: NSUTF8StringEncoding];
+ [subject autorelease];
+ }
+ else
+ subject = envSubject;
+
+ return subject;
+}
+
- (BOOL) showToAddress
{
NSString *ftype;
date = [NSCalendarDate calendarDate];
[cookie setExpires: [date yesterday]];
[response addCookie: cookie];
+
+ [response setHeader: date forKey: @"Last-Modified"];
+ [response setHeader: @"no-store, no-cache, must-revalidate, max-age=0" forKey: @"Cache-Control"];
+ [response setHeader: @"post-check=0, pre-check=0" forKey: @"Cache-Control"];
+ [response setHeader: @"no-cache" forKey: @"Pragma"];
return response;
}
{
NSArray *calendars;
- calendars = [[self calendarList] valueForKey: @"folder"];
+ calendars = [[self calendarList] valueForKey: @"nameInContainer"];
return [calendars componentsJoinedByString: @","];
}
/><var:string value="primaryEmail" escapeHTML="NO"
/><var:string value="secondaryEmail" escapeHTML="NO"
/><var:string value="screenName" escapeHTML="NO"
- /><var:string value="preferredTel" escapeHTML="NO"
/><var:string value="preferredAddress" escapeHTML="NO"
/></div
><td
var:class="messageSubjectCellStyleClass"
var:id="msgDivID"
- ><var:string value="message.envelope.subject"
+ ><var:string value="messageSubject"
/></td
><td class="messageAddressColumn"
xmlns:const="http://www.skyrix.com/od/constant"
xmlns:rsrc="OGo:url"
xmlns:label="OGo:label"
- ><var:string var:value="doctype" const:escapeHTML="NO" />
+ ><var:string var:value="doctype" const:escapeHTML="NO"/>
<form id="connectForm" var:href="connectURL">
<div id="loginScreen">
- <img rsrc:src="lori-login.jpg"/><br/><br/>
+ <img id="splash" rsrc:src="lori-login.jpg"/><br/><br/>
<label><var:string label:value="Login:"/><br/>
<input class="textField" id="userName" name="userName"
type="text" var:value="userName" /></label><br/>
<input class="button" id="submit" name="submit" type="submit" label:value="Connect" />
</div>
</div>
- </form>
- <img id="preparedAnimation" rsrc:src="busy.gif"/>
+ </form
+ ><img id="preparedAnimation" rsrc:src="busy.gif"/>
</var:component>
/></var:if-ie>
</head>
- <body var:class="bodyClasses">
- <script type="text/javascript">
+ <body var:class="bodyClasses"
+ ><var:if condition="isCompatibleBrowser"
+ ><script type="text/javascript">
var ApplicationBaseURL = '<var:string value="applicationPath" />';
var ResourcesURL = '/SOGo.woa/WebServerResources';
<var:if condition="shortUserNameForDisplay" const:value="anonymous"
<div class="pageContent"
><var:component-content
/></div>
+ </var:if>
+ <var:if condition="isCompatibleBrowser" const:negate="YES">
+ <div id="loginScreen">
+ <img id="splash" rsrc:src="lori-login.jpg"/><br/><br/>
+ <p><var:string label:value="browserNotCompatible"/></p>
+ <p class="browser"><a href="http://www.getfirefox.com/"><img rsrc:src="browser_firefox.gif"/><var:string label:value="Download"/> Firefox</a></p>
+ <var:if condition="isIE7Compatible">
+ <p><var:string label:value="alternativeBrowsers"/></p>
+ <p class="browser"><a href="http://www.microsoft.com/ie/download/"><img rsrc:src="browser_ie.gif"/><var:string label:value="Download"/> Internet Explorer 7</a></p>
+ <p class="browser"><a href="http://www.apple.com/safari/download/"><img rsrc:src="browser_safari.gif"/><var:string label:value="Download"/> Safari 3</a></p>
+ </var:if>
+ <var:if condition="isMac">
+ <p><var:string label:value="alternativeBrowserSafari"/></p>
+ <p class="browser"><a href="http://www.apple.com/safari/download/"><img rsrc:src="browser_safari.gif"/><var:string label:value="Download"/> Safari 3</a></p>
+ </var:if>
+ </div>
+ </var:if>
<noscript>
<div class="javascriptPopupBackground">
</div>
left: 0px;
right: 0px;
height: 16em;
- overflow: hidden;
- overflow-y: auto; }
+ overflow: scroll;
+ overflow-x: hidden; }
.aptview_text
{
}
DIV#contactFoldersList
-{
- position: absolute;
+{ position: absolute;
top: 6em;
left: 0px;
width: 15em;
list-style-image: none;
clear: both;
cursor: default;
- color: #000;
+ color: #000;
background: #fff;
+ position: absolute; /* required for Safari & IE */
+ top: 53px; /* leave space for the mini addressbook */
+ bottom: 0px;
width: 100%;
height: 100%;
margin: 0px;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
-moz-border-top-colors: #9c9a94 #000;
- -moz-border-left-colors: #9c9a94 #000;
- overflow: auto; }
+ -moz-border-left-colors: #9c9a94 #000; }
DIV#contactFoldersList LI
{
DIV#contactView H3.contactCardTitle
{ display: block;
- margin: .2em 0px;
+ margin: 0px;
+ padding: .2em 0px;
font-size: large;
font-weight: bold;
width: 100%;
handle.addInterface(SOGoDragHandlesInterface);
handle.leftBlock=$("contactFoldersList");
handle.rightBlock=$("rightPanel");
+ handle.leftMargin = 100;
}
handle = $("rightDragHandle");
}
DIV#rightPanel
-{
- position: absolute;
+{ position: absolute;
top: 5.5em;
left: 15em;
right: 0px;
margin: 0px;
margin-left: 5px;
padding: 0px;
- overflow: hidden;
-}
+ overflow: hidden; }
/* top list */
DIV#mailboxContent
left: 0px;
right: 0px;
height: 15.5em;
- overflow: hidden;
- overflow-y: auto; }
+ overflow: scroll;
+ overflow-x: hidden; }
DIV#messageContent
{ position: absolute;
padding: 5px;
border: 2px solid transparent;
width: 200px;
- height: 315px;
-moz-border-top-colors: #efebe7 #fff;
-moz-border-left-colors: #efebe7 #fff;
-moz-border-right-colors: #000 #9c9a94 transparent;
-moz-border-bottom-colors: #000 #9c9a94 transparent;
}
-DIV#loginScreen IMG
+IMG#splash
{ border: 0px;
margin: 0px;
padding: 0px;
border: 0px none;
margin-top: 5px;
margin-left: 5px; }
+
+P.browser
+{ background-color: #fff;
+ border-top: 1px solid #888;
+ border-left: 1px solid #888;
+ border-right: 1px solid #eee;
+ border-bottom: 1px solid #eee;
+ line-height: 32px; }
+
+P.browser img
+{ padding: 2px;
+ vertical-align: middle; }
\ No newline at end of file
-moz-border-top-colors: #9c9a94 #000;
-moz-border-left-colors: #9c9a94 #000; }
+TABLE#freeBusy
+{ border-collapse: collapse;
+ table-layout: auto; }
+
+TABLE#freeBusy THEAD TH
+{ white-space: nowrap; }
+
TABLE#freeBusy TD,
TABLE#freeBusy TH
{ padding: 0px;
TABLE#freeBusy TR.freeBusyHeader3 TH
{ text-align: left;
color: #777;
- background: #fff;
- border-collapse: collapse; }
+ background: #fff; }
TABLE#freeBusy TR.freeBusyHeader2 TH
-{ width: 6em; }
+{ padding-right: 2em; }
TABLE#freeBusy TR.freeBusyHeader3 TH
-{ border-bottom: 1px solid #cecbff; }
+{ border-left: 1px solid #fff;
+ border-bottom: 1px solid #cecbff; }
TABLE#freeBusy TR.attendeeModel
{ display: none; }
SPAN.freeBusyZoneElement
{ display: block;
float: left;
+ clear: right;
width: 25%;
margin: 0px;
padding: 0px;
var td = tds[i];
var spans = $(td).childNodesWithTag("span");
if (status == '2')
- spans[spannbr].addClassName("maybe-busy");
+ $(spans[spannbr]).addClassName("maybe-busy");
else
- spans[spannbr].addClassName("busy");
+ $(spans[spannbr]).addClassName("busy");
}
}
var tds = node.parentNode.parentNode.cells;
for (var i = 0; i < slots.length; i++) {
if (slots[i] != '0')
- setSlot(tds, i, slots[i]);
+ setSlot(tds, i, slots[i]);
}
}
document.contactFreeBusyAjaxRequest = null;
for (var i = 0; i < attendeesNames.length; i++) {
var tr = body.insertRow(i);
var td = document.createElement("td");
- td.addClassName("attendees");
+ $(td).addClassName("attendees");
var input = document.createElement("input");
var value = "";
if (attendeesNames[i].length > 0)
value += attendeesNames[i] + " ";
value += "<" + attendeesEmails[i] + ">";
input.value = value;
- input.addClassName("textField");
+ $(input).addClassName("textField");
input.setAttribute("modified", "0");
tr.appendChild(td);
td.appendChild(input);
var form = document.forms["editform"];
var urlElems = form.getAttribute("action").split("/");
var choice = calendars[this.value];
- var ownerLogin;
- if (choice.indexOf(":") > -1)
- ownerLogin = choice.split(":")[0];
- else
- ownerLogin = UserLogin;
- urlElems[urlElems.length-4] = ownerLogin;
-
+ urlElems[urlElems.length-3] = choice;
form.setAttribute("action", urlElems.join("/"));
}