r7500 - in dumbhippo/trunk: server/src/com/dumbhippo/server server/src/com/dumbhippo/server/impl server/src/com/dumbhippo/web/pages server/web/css-gnome server/web/images-gnome server/web/javascript/dh server/web/jsp-gnome server/web/tags/3 server/web/tags/gnome super/jboss/files/scripts



Author: marinaz
Date: 2008-08-27 23:10:13 -0500 (Wed, 27 Aug 2008)
New Revision: 7500

Added:
   dumbhippo/trunk/server/web/images-gnome/feedspinner.gif
   dumbhippo/trunk/server/web/images-gnome/save_button.gif
   dumbhippo/trunk/server/web/images-gnome/x_button.gif
   dumbhippo/trunk/server/web/javascript/dh/love.js
   dumbhippo/trunk/server/web/tags/gnome/loveEntry.tag
Modified:
   dumbhippo/trunk/server/src/com/dumbhippo/server/ExternalAccountSystem.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ExternalAccountSystemBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/web/pages/AccountPage.java
   dumbhippo/trunk/server/web/css-gnome/account.css
   dumbhippo/trunk/server/web/javascript/dh/account.js
   dumbhippo/trunk/server/web/javascript/dh/accountpage.js
   dumbhippo/trunk/server/web/jsp-gnome/account.jsp
   dumbhippo/trunk/server/web/tags/3/accountEditTableExternals.tag
   dumbhippo/trunk/server/web/tags/3/addImAccount.tag
   dumbhippo/trunk/super/jboss/files/scripts/jboss-start.sh
Log:
Add Twitter account entry on the online.gnome.org account page. 


Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/ExternalAccountSystem.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/ExternalAccountSystem.java	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/ExternalAccountSystem.java	2008-08-28 04:10:13 UTC (rev 7500)
@@ -83,6 +83,8 @@
 	
 	public OnlineAccountType getOnlineAccountType(ExternalAccountType accountType);
 	
+	public List<OnlineAccountType> getAllOnlineAccountTypes();
+	
 	public OnlineAccountType lookupOnlineAccountTypeForName(String name) throws NotFoundException;
 	
 	public OnlineAccountType lookupOnlineAccountTypeForFullName(String fullName) throws NotFoundException;

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ExternalAccountSystemBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ExternalAccountSystemBean.java	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ExternalAccountSystemBean.java	2008-08-28 04:10:13 UTC (rev 7500)
@@ -120,6 +120,11 @@
 		}
 	}
 	
+	public List<OnlineAccountType> getAllOnlineAccountTypes() {
+		 Query q = em.createQuery("SELECT oat FROM OnlineAccountType oat");						
+         return TypeUtils.castList(OnlineAccountType.class, q.getResultList());
+	}
+	
 	public OnlineAccountType lookupOnlineAccountTypeForName(String name) throws NotFoundException {
 		Query q = em.createQuery("SELECT oat FROM OnlineAccountType oat WHERE " +
 				                 "LOWER(oat.name) = :name");

Modified: dumbhippo/trunk/server/src/com/dumbhippo/web/pages/AccountPage.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/web/pages/AccountPage.java	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/src/com/dumbhippo/web/pages/AccountPage.java	2008-08-28 04:10:13 UTC (rev 7500)
@@ -10,6 +10,7 @@
 import com.dumbhippo.persistence.ExternalAccount;
 import com.dumbhippo.persistence.ExternalAccountType;
 import com.dumbhippo.persistence.FacebookAccount;
+import com.dumbhippo.persistence.OnlineAccountType;
 import com.dumbhippo.persistence.Sentiment;
 import com.dumbhippo.persistence.XmppResource;
 import com.dumbhippo.server.AmazonUpdater;
@@ -360,6 +361,24 @@
 		}
 		return new ListBean<ExternalAccountView>(supportedAccounts);
 	}
+
+	public ListBean<ExternalAccountView> getGnomeSupportedAccounts() {
+		List<ExternalAccountView> supportedAccounts = new ArrayList<ExternalAccountView>(); 
+		for (OnlineAccountType type : externalAccounts.getAllOnlineAccountTypes()) {
+			// this takes advantage of the fact that all online account types currently have corresponding
+			// external accounts, but we'll need to change this soon
+			if (type.isSupported() && type.getAccountType() != null) {
+				try {
+				    ExternalAccount externalAccount = 
+				    	externalAccounts.lookupExternalAccount(signin.getViewpoint(), signin.getUser(), type.getAccountType());
+				    supportedAccounts.add(new ExternalAccountView(externalAccount));
+				} catch (NotFoundException e) {
+					supportedAccounts.add(new ExternalAccountView(type.getAccountType()));
+				}
+			}
+		}
+		return new ListBean<ExternalAccountView>(supportedAccounts);
+	}
 	
 	/**
 	 * Returns names and links for user's Amazon reviews page and public wish lists.

Modified: dumbhippo/trunk/server/web/css-gnome/account.css
===================================================================
--- dumbhippo/trunk/server/web/css-gnome/account.css	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/css-gnome/account.css	2008-08-28 04:10:13 UTC (rev 7500)
@@ -60,9 +60,6 @@
     height:         0px;
 }
 
-
-
-
 #dhAddImLink {
 	position:       relative;
 }	

Added: dumbhippo/trunk/server/web/images-gnome/feedspinner.gif
===================================================================
(Binary files differ)


Property changes on: dumbhippo/trunk/server/web/images-gnome/feedspinner.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: dumbhippo/trunk/server/web/images-gnome/save_button.gif
===================================================================
(Binary files differ)


Property changes on: dumbhippo/trunk/server/web/images-gnome/save_button.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: dumbhippo/trunk/server/web/images-gnome/x_button.gif
===================================================================
(Binary files differ)


Property changes on: dumbhippo/trunk/server/web/images-gnome/x_button.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: dumbhippo/trunk/server/web/javascript/dh/account.js
===================================================================
--- dumbhippo/trunk/server/web/javascript/dh/account.js	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/javascript/dh/account.js	2008-08-28 04:10:13 UTC (rev 7500)
@@ -4,6 +4,7 @@
 dojo.require("dh.fileinput");
 dojo.require("dh.photochooser");
 dojo.require("dh.lovehate");
+dojo.require("dh.love");
 dojo.require("dh.password");
 dojo.require("dh.util");
 dojo.require("dh.dom");
@@ -764,6 +765,12 @@
 	dh.account.twitterEntry.onCanceled = dh.account.createExternalAccountOnCanceledFunc(dh.account.twitterEntry, 'TWITTER');
 }
 
+dh.account.createGnomeTwitterEntry = function() {	
+	dh.account.twitterEntry = new dh.love.Entry('dhTwitter', 'Twitter username or profile URL', dh.account.initialTwitterName);
+	dh.account.twitterEntry.onLoveSaved = dh.account.onTwitterLoveSaved;
+	dh.account.twitterEntry.onCanceled = dh.account.createExternalAccountOnCanceledFunc(dh.account.twitterEntry, 'TWITTER');
+}
+
 dh.account.createDiggEntry = function() {	
 	dh.account.diggEntry = new dh.lovehate.Entry('dhDigg', 'Digg username or profile URL', dh.account.initialDiggName,
 					'I don\'t dig it', dh.account.initialDiggHateQuip, 'Your friends get updates when you add diggs.');
@@ -892,7 +899,10 @@
 		dh.account.createGoogleReaderEntry();
 		dh.account.createPicasaEntry();	
 		dh.account.createAmazonEntry();
-	}
+	} else {
+	    // TODO: not sure yet how we'll figure out which entries to create, so hardcoding Twitter for now
+		dh.account.createGnomeTwitterEntry();
+	}	
 }
 
 dh.event.addPageLoadListener(dhAccountInit);

Modified: dumbhippo/trunk/server/web/javascript/dh/accountpage.js
===================================================================
--- dumbhippo/trunk/server/web/javascript/dh/accountpage.js	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/javascript/dh/accountpage.js	2008-08-28 04:10:13 UTC (rev 7500)
@@ -12,4 +12,5 @@
 dojo.require("dh.popup")
 dojo.require("dh.feeds");
 dojo.require("dh.password");
-dojo.require("dh.lovehate");
\ No newline at end of file
+dojo.require("dh.lovehate");
+dojo.require("dh.love");
\ No newline at end of file

Added: dumbhippo/trunk/server/web/javascript/dh/love.js
===================================================================
--- dumbhippo/trunk/server/web/javascript/dh/love.js	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/javascript/dh/love.js	2008-08-28 04:10:13 UTC (rev 7500)
@@ -0,0 +1,198 @@
+dojo.provide("dh.love");
+dojo.require("dh.util");
+dojo.require("dh.formtable");
+dojo.require("dh.textinput");
+dojo.require("dh.dom");
+dojo.require("dh.event");
+
+dh.love.allEntries = {}
+
+dh.love.Entry = function(baseId, defaultLoveText, currentLoveValue)
+{
+	dh.love.allEntries[baseId] = this;
+
+	// creates a variable that can be captured in closures below, while "this" can't be
+	var me = this;
+
+	me._baseId = baseId;
+	this._rootNode = document.getElementById(baseId + 'AllId');	
+	this._loveNode = document.getElementById(baseId + 'LoveId');
+	this._loveEditNode = document.getElementById(baseId + 'LoveEditId');
+	this._indifferentNode = document.getElementById(baseId + 'IndifferentId');
+	this._busyNode = document.getElementById(baseId + 'BusyId');
+	
+	this._loveEntryNode = document.getElementById(baseId + 'LoveEntryId');
+	
+	this._defaultLoveText = defaultLoveText;
+
+	this._loveEntry = new dh.textinput.Entry(this._loveEntryNode, defaultLoveText, currentLoveValue);
+
+	this._loveValue = document.getElementById(baseId + 'LoveValueId');
+	this._specialLoveValue = null;
+
+	this._allNodes = [me._loveNode, me._loveEditNode, me._indifferentNode, me._busyNode];
+	
+	this._errorText = "";
+	
+	dh.formtable.initExpanded(me._baseId, true);
+
+    // Traverse root node of this widget, calling function on each node
+	this._foreachDhIdNode = function(id, func) {
+	  dh.util.foreachChildElements(me._rootNode, 	                                    
+								   function(node) {
+	                                 if (node.getAttribute("dhId") == id) func(node);
+	                               });
+	}
+	
+	this._loveEntryNode.onkeydown = function(ev) {
+		var key = dh.event.getKeyCode(ev);
+		if (key == ENTER) {
+			me._saveClicked("love");
+		}
+	}
+
+	this._showNode = function(node) {
+		if (!node)
+			throw new Error("null/undefined node passed to _showNode");
+		
+		// Sync the "not in edit mode" values with the entries, if we're about to show them
+		if (node == me._loveNode && me._specialLoveValue == null) {
+			dh.dom.textContent(me._loveValue, me._loveEntry.getValue());			
+		}
+
+		var i;
+		for (i = 0; i < me._allNodes.length; ++i) {
+			var each = me._allNodes[i];
+			if (!each)
+				throw new Error("null/undefined node in allNodes " + i);
+			if (each == node)
+				each.style.display = 'block';
+			else
+				each.style.display = 'none';
+		}
+		if (node.style.display == 'none')
+			throw new Error("node " + node.id + " was not found...");
+			
+		dh.formtable.setExpandedEditing(me._baseId, node == me._loveEditNode);
+					
+	}
+	
+	this.getMode = function() {
+		var i;
+		for (i = 0; i < me._allNodes.length; ++i) {
+			var each = me._allNodes[i];
+			if (!each)
+				throw new Error("null/undefined node in allNodes " + i);
+			if (each.style.display == 'block') {
+				if (each == me._loveNode)
+					return "love";
+				else if (each == me._loveEditNode)
+					return "loveEdit";
+				else if (each == me._indifferentNode)
+					return "indifferent";
+				else if (each == me._busyNode)
+					return "busy";
+			}
+		}
+		return null;
+	}
+	
+	this.getLoveEntry = function() {
+	    return me._loveEntry;
+	}
+	
+	this.setMode = function(mode) {
+		var nodeVar = "_" + mode + "Node";
+		var node = me[nodeVar];
+		if (!node)
+			throw new Error("invalid mode '" + mode + "' leading to var '" + nodeVar + "'");
+		me._showNode(node);	
+	}
+	
+	this.setBusy = function() {
+		me.setMode('busy');
+	}
+	
+	this.setError = function(msg) {
+		if (msg) {
+			me._foreachDhIdNode("DescriptionError",
+			                    function(node) {
+			                      node.style.display = "block";
+			                    });
+			me._foreachDhIdNode("DescriptionErrorText",
+			                    function(node) {			                    
+			                      node.innerHTML = "";
+                                  node.appendChild(document.createTextNode(msg));
+                                });
+			me._foreachDhIdNode("DescriptionNormal",
+			                    function(node) {
+			                      node.style.display = "none";
+			                    });
+			
+		} else {
+			me._foreachDhIdNode("DescriptionNormal",
+			                    function(node) {
+			                      node.style.display = "block";
+			                    });
+			me._foreachDhIdNode("DescriptionError",
+			                    function(node) {
+			                      node.style.display = "none";
+			                    });			                    			
+		}
+		dh.formtable.setExpandedError(me._baseId, msg);
+	}
+	
+	this.setSpecialLoveValue = function(value) {
+	    // this is used when we don't want a long value for the entry to be visible 
+	    // when the entry is not being edited
+	    dh.dom.textContent(me._loveValue, value);	
+	    me._specialLoveValue = value;
+	}
+	
+	this.setLoveValueAlreadySaved = function(value) {
+		me._loveEntry.setValue(value, true); // true = don't emit changed
+	}
+	
+	// to be set by api user
+	this.onLoveSaved = function(value) {
+	
+	}
+	
+	// to be set by api user
+	this.onCanceled = function() {
+	
+	}
+	
+	this._saveClicked = function(mode) {
+		if (mode == 'love') {
+			me.onLoveSaved(me._loveEntry.getValue());
+		} else {
+			throw new Error("unknown mode " + mode);
+		}
+	}
+	
+	this._cancelClicked = function() {
+		me.onCanceled();
+	}
+	
+	// this updates the current values and what's showing
+	this.setError(null);
+	this.setMode(this.getMode());
+	
+	return this;
+}
+
+dh.love.setMode = function(baseId, mode) {
+	var entry = dh.love.allEntries[baseId];
+	entry.setMode(mode)
+}
+
+dh.love.saveClicked = function(baseId, mode) {
+	var entry = dh.love.allEntries[baseId];
+	entry._saveClicked(mode);
+}
+
+dh.love.cancelClicked = function(baseId) {
+	var entry = dh.love.allEntries[baseId];
+	entry._cancelClicked();
+}

Modified: dumbhippo/trunk/server/web/jsp-gnome/account.jsp
===================================================================
--- dumbhippo/trunk/server/web/jsp-gnome/account.jsp	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/jsp-gnome/account.jsp	2008-08-28 04:10:13 UTC (rev 7500)
@@ -2,13 +2,13 @@
 <%@ page pageEncoding="UTF-8" %>
 <%@ taglib uri="http://java.sun.com/jsp/jstl/core"; prefix="c" %>
 <%@ taglib uri="/jsp/dumbhippo.tld" prefix="dh" %>
-<%@ taglib tagdir="/WEB-INF/tags/2" prefix="dht2" %>
+<%@ taglib tagdir="/WEB-INF/tags/2" prefix="dht" %>
 <%@ taglib tagdir="/WEB-INF/tags/3" prefix="dht3" %>
 <%@ taglib tagdir="/WEB-INF/tags/gnome" prefix="gnome" %>
 
 <c:if test="${!signin.valid}">
 	<%-- this is a bad error message but should never happen since we require signin to get here --%>
-	<dht2:errorPage>Not signed in</dht2:errorPage>
+	<dht:errorPage>Not signed in</dht:errorPage>
 </c:if>
 
 <dht3:requirePersonBean beanClass="com.dumbhippo.web.pages.PersonPage"/>
@@ -37,6 +37,6 @@
 			</div>
 		</div>
 	</gnome:page>
-	<dht2:photoChooser/>
+	<dht:photoChooser/>
 </body>
 </html>

Modified: dumbhippo/trunk/server/web/tags/3/accountEditTableExternals.tag
===================================================================
--- dumbhippo/trunk/server/web/tags/3/accountEditTableExternals.tag	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/tags/3/accountEditTableExternals.tag	2008-08-28 04:10:13 UTC (rev 7500)
@@ -2,6 +2,7 @@
 <%@ taglib uri="/jsp/dumbhippo.tld" prefix="dh"%>
 <%@ taglib tagdir="/WEB-INF/tags/2" prefix="dht2"%>
 <%@ taglib tagdir="/WEB-INF/tags/3" prefix="dht3"%>
+<%@ taglib tagdir="/WEB-INF/tags/gnome" prefix="gnome"%>
 
 <%@ attribute name="account" required="true" type="com.dumbhippo.web.pages.AccountPage" %>
 
@@ -127,6 +128,19 @@
 		</table>
 		<dht3:addImAccount/>
 	    </dht2:formTableRow>
+	    <c:forEach items="${account.gnomeSupportedAccounts.list}" var="supportedAccount">
+	        <dht2:formTableRow controlId="dh${supportedAccount.domNodeIdName}"
+				label="${supportedAccount.siteName}"				
+				icon="/images3/${buildStamp}/${supportedAccount.iconName}">
+	            <gnome:loveEntry name="${supportedAccount.siteName}"
+				  			        userInfoType="${supportedAccount.siteUserInfoType}"
+							        isInfoTypeProvidedBySite="${supportedAccount.infoTypeProvidedBySite}"
+							        link="${supportedAccount.externalAccountType.siteLink}"
+							        baseId="dh${supportedAccount.domNodeIdName}"
+							        mode="${supportedAccount.sentiment}">				        
+			    </gnome:loveEntry>
+			</dht2:formTableRow>			
+	    </c:forEach>
 	</c:if>    
 	<c:if test="${dh:enumIs(site, 'MUGSHOT')}">
 		<dht2:formTableRow label="Website"

Modified: dumbhippo/trunk/server/web/tags/3/addImAccount.tag
===================================================================
--- dumbhippo/trunk/server/web/tags/3/addImAccount.tag	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/tags/3/addImAccount.tag	2008-08-28 04:10:13 UTC (rev 7500)
@@ -6,7 +6,7 @@
 <div id="dhAddImLink">
 	<a href="javascript:dh.account.showImAccountPopup()">
 		<dh:png klass="dh-add-icon" src="/images3/${buildStamp}/add_icon.png" style="width: 10; height: 10; overflow: hidden;" />
-		Add an IM account
+		Add an account
 	</a>
 	<div id="dhAddImPopup" style="display: none">
 		<div id="dhAddImClose">

Added: dumbhippo/trunk/server/web/tags/gnome/loveEntry.tag
===================================================================
--- dumbhippo/trunk/server/web/tags/gnome/loveEntry.tag	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/server/web/tags/gnome/loveEntry.tag	2008-08-28 04:10:13 UTC (rev 7500)
@@ -0,0 +1,54 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core"; prefix="c" %>
+<%@ taglib uri="/jsp/dumbhippo.tld" prefix="dh" %>
+<%@ taglib tagdir="/WEB-INF/tags/2" prefix="dht" %>
+
+<%@ attribute name="name" required="true" type="java.lang.String" %>
+<%@ attribute name="userInfoType" required="true" type="java.lang.String" %>
+<%@ attribute name="isInfoTypeProvidedBySite" required="true" type="java.lang.Boolean" %>
+<%@ attribute name="link" required="true" type="java.lang.String" %>
+<%@ attribute name="baseId" required="true" type="java.lang.String" %>
+<%@ attribute name="mode" required="true" type="java.lang.String" %>
+
+<%--  the Javascript manages this visibility also, but we want to get it right on page load --%>
+<c:choose>
+	<c:when test="${mode == 'love'}">
+		<c:set var="loveDisplay" value="block" scope="page"/>
+		<c:set var="indifferentDisplay" value="none" scope="page"/>
+	</c:when>
+	<c:when test="${mode == 'hate' || mode == 'indifferent'}">
+		<c:set var="loveDisplay" value="none" scope="page"/>
+		<c:set var="indifferentDisplay" value="block" scope="page"/>
+	</c:when>	
+	<c:otherwise>
+		<dht:errorPage>Internal error (mode = ${mode}), sorry!</dht:errorPage>
+	</c:otherwise>
+</c:choose>
+
+<div id="${baseId}AllId" class="dh-love-hate">
+	<div id="${baseId}LoveId" style="display: ${loveDisplay};">
+		<a href="javascript:dh.love.setMode('${baseId}', 'loveEdit')" title="Click to change">
+			<span id="${baseId}LoveValueId"></span>
+		</a>
+	</div>
+	<div id="${baseId}IndifferentId" style="display: ${indifferentDisplay};">
+		<a href="javascript:dh.love.setMode('${baseId}', 'loveEdit')" title="Add an account"><dh:png klass="dh-add-icon" src="/images3/${buildStamp}/add_icon.png" style="width: 10; height: 10; overflow: hidden;" />
+		Add an account</a>
+	</div>
+	<div id="${baseId}LoveEditId" style="display: none;">
+		<dht:textInput id="${baseId}LoveEntryId" maxlength="255"/>
+		<img src="/images-gnome/${buildStamp}/save_button.gif" onclick="dh.love.saveClicked('${baseId}', 'love')"/>
+		<a href="javascript:dh.love.cancelClicked('${baseId}')" title="Remove the account"><img src="/images-gnome/${buildStamp}/x_button.gif"/></a>
+        <div dhId="DescriptionNormal">
+            Enter your  
+	        <jsp:element name="a">
+		        <jsp:attribute name="href"><c:out value="${link}"/></jsp:attribute>
+			    <jsp:attribute name="target">_blank</jsp:attribute>
+		 	    <jsp:body><c:out value="${name}"/></jsp:body>
+		    </jsp:element>
+		    <c:out value="${userInfoType}"/>
+		</div>    		    
+	</div>	
+	<div id="${baseId}BusyId" style="display: none;">
+		<img src="/images-gnome/${buildStamp}/feedspinner.gif"/> Please wait...
+	</div>	
+</div>
\ No newline at end of file

Modified: dumbhippo/trunk/super/jboss/files/scripts/jboss-start.sh
===================================================================
--- dumbhippo/trunk/super/jboss/files/scripts/jboss-start.sh	2008-08-13 00:47:09 UTC (rev 7499)
+++ dumbhippo/trunk/super/jboss/files/scripts/jboss-start.sh	2008-08-28 04:10:13 UTC (rev 7500)
@@ -83,7 +83,7 @@
 $bindopt \
 "
 
-$JAVA $JAVA_OPTS > /dev/null 2>&1 &
+$JAVA $JAVA_OPTS > /tmp/jboss.start 2>&1 &
 pid=$!
 started=false
 for i in `seq 1 30` ; do



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]