r7255 - in dumbhippo/trunk/server: src/com/dumbhippo/server src/com/dumbhippo/server/blocks src/com/dumbhippo/server/impl web/css3 web/tags/3



Author: marinaz
Date: 2008-01-24 17:03:46 -0600 (Thu, 24 Jan 2008)
New Revision: 7255

Modified:
   dumbhippo/trunk/server/src/com/dumbhippo/server/FacebookTracker.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/HttpMethods.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/blocks/AccountQuestionBlockHandlerBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/HttpMethodsBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/StackerBean.java
   dumbhippo/trunk/server/web/css3/site-positions.css
   dumbhippo/trunk/server/web/css3/site.css
   dumbhippo/trunk/server/web/tags/3/accountQuestionBlock.tag
   dumbhippo/trunk/server/web/tags/3/blockLeft.tag
Log:
Format displaying the Account Question block on the web. Omit it at its regular 
stacking spot if it is unaswered.

Make sure we don't reset applicationEnabled flag from true to false,
if someone clicks on "No, Thanks" after enabling the application.
(They shouldn't normally be inclined to do it, since we open the Facebook
application add page in the same browser tab, but I suppose that can use
the Back button instead of reload to get back to Mugshot.)

Only exclude people who've added the Mugshot application to their Facebook
profile, when creating an invitation page for the Mugshot application.
Facebook web services friends.getAppUsers also includes people who authorized
the Mugshot application to access their information, but some of them might 
not have the new application installed on their profiles.


Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/FacebookTracker.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/FacebookTracker.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/FacebookTracker.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -21,6 +21,8 @@
 
 	public FacebookAccount getFacebookAccount(String facebookUserId);
 	
+	public List<FacebookAccount> getFacebookAccounts(List<String> facebookUserIds);
+	
 	public List<String> getFriendAppUsers(User user);
 	
 	public void updateFbmlForUser(User user);

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/HttpMethods.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/HttpMethods.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/HttpMethods.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -446,8 +446,12 @@
 	@HttpContentTypes(HttpResponseData.NONE)
 	@HttpParams( { "email", "enabled" })
 	public void doSetGoogleServicedEmail(UserViewpoint viewpoint, String email, boolean enabled) throws IOException, RetryException, ValidationException;
-	
+
 	@HttpContentTypes(HttpResponseData.NONE)
+	@HttpParams( { "blockId", "response" })
+	public void doAnswerAccountQuestion(UserViewpoint viewpoint, String blockId, String response) throws IOException, HumanVisibleException;
+
+	@HttpContentTypes(HttpResponseData.NONE)
 	@HttpParams( { "enabled" })
 	public void doSetApplicationUsageEnabled(UserViewpoint viewpoint, boolean enabled) throws IOException, HumanVisibleException;
 

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/blocks/AccountQuestionBlockHandlerBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/blocks/AccountQuestionBlockHandlerBean.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/blocks/AccountQuestionBlockHandlerBean.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -188,7 +188,10 @@
 		// we handle a positive response in FacebookTrackerBean when the person adds the application
 		if (response.equals("no"))
 			try {
-				facebookSystem.lookupFacebookAccount(viewpoint, ((UserViewpoint)viewpoint).getViewer()).setApplicationEnabled(false);
+				FacebookAccount facebookAccount = facebookSystem.lookupFacebookAccount(viewpoint, ((UserViewpoint)viewpoint).getViewer());
+				// only set applicationEnabled to false based on this if it was not previously true
+                if (facebookAccount.isApplicationEnabled() == null)
+                	facebookAccount.setApplicationEnabled(false);
 			} catch (NotFoundException e) {
 				logger.warn("Did not find a FacebookAccount for user {} when trying to set their applicationEnabled status to false");
 			}

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -27,6 +27,8 @@
 import com.dumbhippo.GlobalSetup;
 import com.dumbhippo.Pair;
 import com.dumbhippo.Site;
+import com.dumbhippo.StringUtils;
+import com.dumbhippo.TypeUtils;
 import com.dumbhippo.persistence.Account;
 import com.dumbhippo.persistence.AccountClaim;
 import com.dumbhippo.persistence.Block;
@@ -279,12 +281,44 @@
 			return null;
 		}		
 	}
+
+	public List<FacebookAccount> getFacebookAccounts(List<String> facebookUserIds) {		
+		if (facebookUserIds.isEmpty())
+			return new ArrayList<FacebookAccount>();
+        Query q = em.createQuery("from FacebookAccount f where f.facebookUserId IN (" + StringUtils.join(facebookUserIds, ",") + ")");	
+        return TypeUtils.castList(FacebookAccount.class, q.getResultList());	
+	}
 	
-	public List<String> getFriendAppUsers(User user) {
+	// This method returns a list of people who we know have installed our application on their Facebook profile
+	// page. Those people can be excluded on the application invitation page on Facebook.
+	public List<String> getFriendAppUsers(User user) {	
 		try {
 		    FacebookAccount facebookAccount = facebookSystem.lookupFacebookAccount(SystemViewpoint.getInstance(), user);
 	        FacebookWebServices ws = new FacebookWebServices(REQUEST_TIMEOUT, config);
-	        return ws.getFriendAppUsers(facebookAccount);
+	        List<String> allFriendAppUsers = ws.getFriendAppUsers(facebookAccount);
+	        // We now need to filter out people from this list who don't actually have the application installed.
+	        // (Those people have only registered their Facebook acount with Mugshot.)
+	        List<String> friendInstalledAppUsers = new ArrayList<String>();
+	        List<FacebookAccount> friendFacebookAccounts = getFacebookAccounts(allFriendAppUsers);
+	        
+	        // this really shouldn't happen == paranoia
+	        if (allFriendAppUsers.size() != friendFacebookAccounts.size()) {
+	        	StringBuilder sb = new StringBuilder("Found FacebookAccounts for: ");
+	        	for (FacebookAccount friendFacebookAccount : friendFacebookAccounts ) {
+	        		sb.append(friendFacebookAccount.getFacebookUserId());
+	        		sb.append(",");
+	        	}
+	    		sb.setLength(sb.length() - 1); // chop comma or the last space if we didn't find any accounts	    		
+	        	logger.error("Facebook thinks that Facebook users " + StringUtils.join(allFriendAppUsers, ",") + " use Mugshot application, but we don't have FacebookAccounts for all of them. \n" + 
+	        			     sb.toString());
+	        }
+	        
+	        for (FacebookAccount friendFacebookAccount : friendFacebookAccounts) {
+	        	if (friendFacebookAccount.isApplicationEnabled() != null && friendFacebookAccount.isApplicationEnabled()) {
+	        	    friendInstalledAppUsers.add(friendFacebookAccount.getFacebookUserId());
+	        	}        		
+	        }
+	        return friendInstalledAppUsers;		      
 	    } catch (NotFoundException e) {
 			return new ArrayList<String>();
 		}

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/HttpMethodsBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/HttpMethodsBean.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/HttpMethodsBean.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -120,9 +120,11 @@
 import com.dumbhippo.server.applications.AppinfoUploadView;
 import com.dumbhippo.server.applications.ApplicationSystem;
 import com.dumbhippo.server.applications.ApplicationView;
+import com.dumbhippo.server.blocks.AccountQuestionBlockHandler;
 import com.dumbhippo.server.blocks.BlockView;
 import com.dumbhippo.server.blocks.TitleBlockView;
 import com.dumbhippo.server.blocks.TitleDescriptionBlockView;
+import com.dumbhippo.server.blocks.AccountQuestionBlockHandler.BadResponseCodeException;
 import com.dumbhippo.server.dm.DataService;
 import com.dumbhippo.server.dm.ExternalAccountDMO;
 import com.dumbhippo.server.dm.ExternalAccountKey;
@@ -238,6 +240,9 @@
 	@EJB
 	private OnlineDesktopSystem onlineDesktopSystem;
 	
+	@EJB
+	private AccountQuestionBlockHandler accountQuestionBlockHandler;
+	
 	@PersistenceContext(unitName = "dumbhippo")
 	private EntityManager em;
 	
@@ -2528,6 +2533,23 @@
 		out.write(rss.getBytes());
 	}
 
+	public void doAnswerAccountQuestion(UserViewpoint viewpoint, String blockId, String response) throws IOException, HumanVisibleException {
+        Guid blockGuid;
+	    try {
+	        blockGuid = new Guid(blockId);
+	    } catch (ParseException e) {
+	        throw new RuntimeException("invalid blockId " + blockId);
+	    }
+	    
+	    try {
+		    accountQuestionBlockHandler.handleResponse(viewpoint, blockGuid, response);
+	    } catch (NotFoundException e) {
+		    throw new RuntimeException("blockId " + blockId + " doesn't point to a question for this user", e);
+		} catch (BadResponseCodeException e) {
+			throw new RuntimeException("response '" + response +"' had an unexpected value", e);
+		}
+	}
+
 	public void doSetApplicationUsageEnabled(UserViewpoint viewpoint, boolean enabled) throws IOException, HumanVisibleException {
 		identitySpider.setApplicationUsageEnabled(viewpoint, enabled);
 	}

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/StackerBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/StackerBean.java	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/StackerBean.java	2008-01-24 23:03:46 UTC (rev 7255)
@@ -66,6 +66,7 @@
 import com.dumbhippo.server.Stacker;
 import com.dumbhippo.server.XmppMessageSender;
 import com.dumbhippo.server.blocks.AccountQuestionBlockHandler;
+import com.dumbhippo.server.blocks.AccountQuestionBlockView;
 import com.dumbhippo.server.blocks.AmazonActivityBlockHandler;
 import com.dumbhippo.server.blocks.BlockHandler;
 import com.dumbhippo.server.blocks.BlockNotVisibleException;
@@ -1195,7 +1196,20 @@
 				return results;
 			}
 			public BlockView prepareView(Viewpoint viewpoint, Block block, UserBlockData ubd) throws BlockNotVisibleException {
-				return prepareBlockView(viewpoint, block, ubd, participantOnly);
+				BlockView blockView = prepareBlockView(viewpoint, block, ubd, participantOnly);
+		        if (block.getBlockType() == BlockType.ACCOUNT_QUESTION) { 
+		        	// ACCOUNT_QUESTION blocks should be populated anyway, since they are not public, and we
+		        	// populate all blocks that are not public when preparing the blockView, but let's do
+		        	// it here just in case
+		        	// We could have also used clickedTimestamp to check if the question has been answered, because
+		        	// we assign this meaning to it for this block type (see AccountQuestionBlockHandlerBean::questionAnswered()),
+		        	// but since we should have the block populated anyway, we might as well check the answer directly.
+		        	getHandler(block).populateBlockView(blockView);
+		        	if (((AccountQuestionBlockView)blockView).getAnswer() == null) {
+		        		throw new BlockNotVisibleException("We don't include unanswered account questions in the regular stack.");
+		        	}
+		        }
+		        return blockView;
 			}
 		}, pageable, expectedHitFactor);
 		
@@ -1631,6 +1645,7 @@
 	}
 	
 	private List<UserBlockData> getUnansweredQuestionsBlockData(UserViewpoint viewpoint, long stackedBefore) {
+		// clickedTimestamp is NULL for unanswered blocks
 		Query q = em.createQuery("   SELECT ubd FROM UserBlockData ubd " +
                 "    WHERE ubd.user = :user " +
                 "      AND ubd.block.blockType = " + BlockType.ACCOUNT_QUESTION.ordinal() + " " +

Modified: dumbhippo/trunk/server/web/css3/site-positions.css
===================================================================
--- dumbhippo/trunk/server/web/css3/site-positions.css	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/web/css3/site-positions.css	2008-01-24 23:03:46 UTC (rev 7255)
@@ -760,6 +760,14 @@
 .dh-account-status-secondary input {
 	margin-left:		0px;
 }
+
+.dh-account-question-buttons {
+    margin-top:         5px;
+}
+
+.dh-account-question-buttons input {
+    margin-right:       5px;
+}
 
 #dhDownloadMessageClose {
 	position:			absolute;

Modified: dumbhippo/trunk/server/web/css3/site.css
===================================================================
--- dumbhippo/trunk/server/web/css3/site.css	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/web/css3/site.css	2008-01-24 23:03:46 UTC (rev 7255)
@@ -610,7 +610,12 @@
 	background-color:	#fbfadc;
 	border:				1px solid #cccc99;
 	font-size:			12px;
-}
+}
+
+.dh-box-account-question {
+	background-color:	#fbfadc;
+	border:				1px solid #cccc99;
+}
 
 .dh-account-status-primary {
 	font-size:			16px;

Modified: dumbhippo/trunk/server/web/tags/3/accountQuestionBlock.tag
===================================================================
--- dumbhippo/trunk/server/web/tags/3/accountQuestionBlock.tag	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/web/tags/3/accountQuestionBlock.tag	2008-01-24 23:03:46 UTC (rev 7255)
@@ -25,10 +25,12 @@
 
 <c:set var="hasDescription" value="${dh:myInstanceOf(block, 'com.dumbhippo.server.blocks.TitleDescriptionBlockView') && block.description != ''}"/>
 
-<dht3:blockContainer cssClass="${offset ? 'dh-box-grey2' : 'dh-box-grey1'}" blockId="${blockId}" title="${block.title}" expandable="false">
-	<dht3:blockLeft block="${block}">
+<dht3:blockContainer cssClass="${block.answer == null ? 'dh-box-account-question' : (offset ? 'dh-box-grey2' : 'dh-box-grey1')}" blockId="${blockId}" title="${block.title}" expandable="false">
+	<dht3:blockLeft block="${block}" showFrom="false">
 		<dht3:simpleBlockTitle block="${block}" oneLine="${oneLine}" homeStack="false" spanClass="dh-stacker-block-title-generic"/>
-		<dht3:blockDescription blockId="${blockId}">${block.descriptionAsHtml}</dht3:blockDescription>
+		<div class="dh-stacker-block-header-description">
+			${block.descriptionAsHtml}
+		</div>    
         <c:if test="${block.moreLink != null}"> 
 		    <div class="dh-thumbnail-block-more">
 	            <jsp:element name="a">
@@ -44,10 +46,12 @@
 				<dht3:chatPreview block="${block}" blockId="${blockId}"/>
 			</dht3:blockContent>		    
 		</c:if>
-		<form>
-		    <c:forEach items="${block.question.buttons}" var="button">
-		        <input type="button" value="${button.text}" onclick="dhAnswerAccountQuestion(${blockId},${button.response})"></input>
-		    </c:forEach>    
-		</form>
+        <c:if test="${block.answer == null}"> 
+		    <form class="dh-account-question-buttons">
+		        <c:forEach items="${block.question.buttons}" var="button">
+		            <input type="button" value="${button.text}" onclick="javascript:dhAnswerAccountQuestion('${block.identifyingGuid}', '${button.response}')"></input>
+		        </c:forEach>    
+		    </form>
+		</c:if>
 	</dht3:blockLeft>
 </dht3:blockContainer>
\ No newline at end of file

Modified: dumbhippo/trunk/server/web/tags/3/blockLeft.tag
===================================================================
--- dumbhippo/trunk/server/web/tags/3/blockLeft.tag	2008-01-24 17:08:29 UTC (rev 7254)
+++ dumbhippo/trunk/server/web/tags/3/blockLeft.tag	2008-01-24 23:03:46 UTC (rev 7255)
@@ -6,8 +6,11 @@
 <%@ attribute name="block" required="true" type="com.dumbhippo.server.blocks.BlockView" %>
 <%@ attribute name="chatHeader" required="false" type="java.lang.Boolean" %>
 <%@ attribute name="oneLine" required="false" type="java.lang.Boolean" %>
+<%@ attribute name="showFrom" required="false" type="java.lang.Boolean" %>
+
+<dh:default var="showFrom" value="true"/>
 
-<td align="left" valign="top" width="${chatHeader ? 70 : (oneLine ? 80 : 75)}%">
+<td align="left" valign="top" width="${showFrom ? (chatHeader ? 70 : (oneLine ? 80 : 75)) : 100}%">
 <table cellspacing="0" cellpadding="0" width="100%">
 <tr>
 <td valign="top" class="dh-stacker-block-icon-column"><dh:png klass="dh-stacker-block-icon" src="${block.icon}" style="width: 16; height: 16; border: none;"/></td>



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