Author: agilliland
Date: Thu May  3 17:08:57 2007
New Revision: 535036

URL: http://svn.apache.org/viewvc?view=rev&rev=535036
Log:
struts2 versions of the pings, member permissions, and members invite actions.


Added:
    roller/trunk/src/org/apache/roller/ui/authoring/struts2/Members.java
    roller/trunk/src/org/apache/roller/ui/authoring/struts2/MembersInvite.java
    roller/trunk/src/org/apache/roller/ui/authoring/struts2/Pings.java
    roller/trunk/web/WEB-INF/jsps/authoring/struts2/Members.jsp
    roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp
    roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp
    roller/trunk/web/WEB-INF/jsps/authoring/struts2/Pings.jsp
Modified:
    roller/trunk/src/org/apache/roller/ui/authoring/struts2/editor-menu.xml
    roller/trunk/src/org/apache/roller/util/MailUtil.java
    roller/trunk/web/WEB-INF/classes/struts.xml
    roller/trunk/web/WEB-INF/tiles.xml
    roller/trunk/web/roller-ui/styles/roller.css

Added: roller/trunk/src/org/apache/roller/ui/authoring/struts2/Members.java
URL: 
http://svn.apache.org/viewvc/roller/trunk/src/org/apache/roller/ui/authoring/struts2/Members.java?view=auto&rev=535036
==============================================================================
--- roller/trunk/src/org/apache/roller/ui/authoring/struts2/Members.java (added)
+++ roller/trunk/src/org/apache/roller/ui/authoring/struts2/Members.java Thu 
May  3 17:08:57 2007
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.ui.authoring.struts2;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.business.RollerFactory;
+import org.apache.roller.business.UserManager;
+import org.apache.roller.pojos.PermissionsData;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.ui.core.util.struts2.UIAction;
+import org.apache.struts2.interceptor.ParameterAware;
+
+
+/**
+ * Allows weblog admin to list/modify member permissions.
+ *
+ * TODO: fix bug in UserManager which doesn't remove permissions from the
+ * website.permissions collection when a permission is deleted.
+ */
+public class Members extends UIAction implements ParameterAware {
+    
+    private static Log log = LogFactory.getLog(Members.class);
+    
+    // raw parameters from request
+    private Map parameters = Collections.EMPTY_MAP;
+    
+    
+    public Members() {
+        log.debug("Instantiating members action");
+        
+        this.actionName = "members";
+        this.desiredMenu = "editor";
+        this.pageTitle = "memberPermissions.title";
+    }
+    
+    
+    // admin perms required
+    public short requiredWeblogPermissions() {
+        return PermissionsData.ADMIN;
+    }
+    
+    
+    public String execute() {
+        
+        log.debug("Showing weblog members page");
+        
+        return LIST;
+    }
+    
+    
+    public String save() {
+        
+        log.debug("Attempting to processing weblog permissions updates");
+        
+        UserManager userMgr = RollerFactory.getRoller().getUserManager();
+        
+        List<PermissionsData> permissions = getActionWeblog().getPermissions();
+        
+        int removed = 0;
+        int changed = 0;
+        try {
+            for( PermissionsData perms : permissions ) {
+                
+                String sval = getParameter("perm-" + perms.getId());
+                if (sval != null) {
+                    short val = Short.parseShort(sval);
+                    UserData user = getAuthenticatedUser();
+                    if (perms.getUser().getId().equals(user.getId()) && 
+                            val < perms.getPermissionMask()) {
+                        addError("memberPermissions.noSelfDemotions");
+                    } else if (val != perms.getPermissionMask()) {
+                        if (val == -1) {
+                            userMgr.removePermissions(perms);
+                            removed++;
+                        } else {
+                            perms.setPermissionMask(val);
+                            userMgr.savePermissions(perms);
+                            changed++;
+                        }
+                    }
+                }
+            }
+            
+            if (removed > 0 || changed > 0) {
+                log.debug("Weblog permissions updated, flushing changes");
+                
+                RollerFactory.getRoller().flush();
+            }
+        } catch (Exception ex) {
+            log.error("Error saving permissions on weblog - 
"+getActionWeblog().getHandle(), ex);
+            // TODO: i18n
+            addError("Error saving permissions");
+        }
+        
+        if (removed > 0) {
+            addMessage("memberPermissions.membersRemoved", ""+removed);
+        }
+        if (changed > 0) {
+            addMessage("memberPermissions.membersChanged", ""+changed);
+        }
+        
+        return LIST;
+    }
+    
+    
+    // convenience for accessing a single parameter with a single value
+    public String getParameter(String key) {
+        if(key != null) {
+            String[] value = (String[]) getParameters().get(key);
+            if(value != null && value.length > 0) {
+                return value[0];
+            }
+        }
+        return null;
+    }
+    
+    
+    public Map getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map parameters) {
+        this.parameters = parameters;
+    }
+}

Added: 
roller/trunk/src/org/apache/roller/ui/authoring/struts2/MembersInvite.java
URL: 
http://svn.apache.org/viewvc/roller/trunk/src/org/apache/roller/ui/authoring/struts2/MembersInvite.java?view=auto&rev=535036
==============================================================================
--- roller/trunk/src/org/apache/roller/ui/authoring/struts2/MembersInvite.java 
(added)
+++ roller/trunk/src/org/apache/roller/ui/authoring/struts2/MembersInvite.java 
Thu May  3 17:08:57 2007
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.ui.authoring.struts2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.business.RollerFactory;
+import org.apache.roller.business.UserManager;
+import org.apache.roller.pojos.PermissionsData;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.ui.core.util.struts2.UIAction;
+import org.apache.roller.util.MailUtil;
+
+
+/**
+ * Allows website admin to invite new members to website.
+ *
+ * TODO: handle 'disabled' result
+ */
+public class MembersInvite extends UIAction {
+    
+    private static Log log = LogFactory.getLog(MembersInvite.class);
+    
+    // user being invited
+    private String userName = null;
+    
+    // permissions being given to user
+    private String permissionsMask = null;
+    
+    
+    public MembersInvite() {
+        this.actionName = "invite";
+        this.desiredMenu = "editor";
+        this.pageTitle = "inviteMember.title";
+    }
+    
+    
+    // admin perms required
+    public short requiredWeblogPermissions() {
+        return PermissionsData.ADMIN;
+    }
+    
+    
+    public String execute() {
+        
+        // if group blogging is disabled then you can't change permissions
+        if (!RollerConfig.getBooleanProperty("groupblogging.enabled")) {
+            return "disabled";
+        }
+        
+        log.debug("Showing weblog inivitation form");
+        
+        return INPUT;
+    }
+    
+    
+    /**
+     * Save the new invitation and notify the user.
+     */
+    public String save() {
+        
+        // if group blogging is disabled then you can't change permissions
+        if (!RollerConfig.getBooleanProperty("groupblogging.enabled")) {
+            return "disabled";
+        }
+        
+        log.debug("Attempting to process weblog invitation");
+        
+        UserManager umgr = RollerFactory.getRoller().getUserManager();
+        
+        // user being invited
+        UserData user = null;
+        try {
+            user = umgr.getUserByUserName(getUserName());
+            if (user == null) {
+                addError("inviteMember.error.userNotFound");
+            }
+        } catch(RollerException ex) {
+            log.error("Error looking up user by id - "+getUserName(), ex);
+            // TODO: i18n
+            addError("Error looking up invitee");
+        }
+        
+        // if we already have an error then bail now
+        if(hasActionErrors()) {
+            return INPUT;
+        }
+        
+        // check for existing permissions or invitation
+        try {
+            PermissionsData perms = umgr.getPermissions(getActionWeblog(), 
user);
+            
+            if (perms != null && perms.isPending()) {
+                addError("inviteMember.error.userAlreadyInvited");
+            } else if (perms != null) {
+                addError("inviteMember.error.userAlreadyMember");
+            }
+            
+        } catch (RollerException ex) {
+            log.error("Error looking up permissions for weblog - 
"+getActionWeblog().getHandle(), ex);
+            // TODO: i18n
+            addError("Error checking existing permissions");
+        }
+        
+        // if no errors then send the invitation
+        if(!hasActionErrors()) try {
+            
+            umgr.inviteUser(getActionWeblog(), user, 
Short.parseShort(getPermissionsMask()));
+            RollerFactory.getRoller().flush();
+            
+            addMessage("inviteMember.userInvited");
+            
+            try {
+                MailUtil.sendWeblogInvitation(getActionWeblog(), user);
+            } catch (RollerException e) {
+                addError("error.untranslated", e.getMessage());
+            }
+            
+            log.debug("Invitation successfully recorded");
+            
+            return SUCCESS;
+            
+        } catch (Exception ex) {
+            log.error("Error creating user invitation", ex);
+            // TODO: i18n
+            addError("Error creating user invitation");
+        }
+        
+        log.debug("Invitation had errors, giving user another chance");
+        
+        return INPUT;
+    }
+    
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userId) {
+        this.userName = userId;
+    }
+
+    public String getPermissionsMask() {
+        return permissionsMask;
+    }
+
+    public void setPermissionsMask(String permission) {
+        this.permissionsMask = permission;
+    }
+    
+}

Added: roller/trunk/src/org/apache/roller/ui/authoring/struts2/Pings.java
URL: 
http://svn.apache.org/viewvc/roller/trunk/src/org/apache/roller/ui/authoring/struts2/Pings.java?view=auto&rev=535036
==============================================================================
--- roller/trunk/src/org/apache/roller/ui/authoring/struts2/Pings.java (added)
+++ roller/trunk/src/org/apache/roller/ui/authoring/struts2/Pings.java Thu May  
3 17:08:57 2007
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.ui.authoring.struts2;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.PingConfig;
+import org.apache.roller.business.pings.AutoPingManager;
+import org.apache.roller.business.pings.PingTargetManager;
+import org.apache.roller.business.RollerFactory;
+import org.apache.roller.pojos.AutoPingData;
+import org.apache.roller.pojos.PingTargetData;
+import org.apache.roller.business.pings.WeblogUpdatePinger;
+import org.apache.xmlrpc.XmlRpcException;
+import java.io.IOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.roller.pojos.PermissionsData;
+import org.apache.roller.ui.core.util.struts2.UIAction;
+
+
+/**
+ * Actions for setting up automatic ping configuration for a weblog.
+ */
+public class Pings extends UIAction {
+    
+    private static Log log = LogFactory.getLog(Pings.class);
+    
+    // ping target id to work on
+    private String pingTargetId = null;
+    
+    // ping target object we are working on, if available
+    private PingTargetData pingTarget = null;
+    
+    // commong ping targets list
+    private List commonPingTargets = Collections.EMPTY_LIST;
+    
+    // custom ping targets list for weblog
+    private List customPingTargets = Collections.EMPTY_LIST;
+    
+    // track the enabled/disabled status for pings
+    private Map pingStatus = Collections.EMPTY_MAP;
+    
+    
+    public Pings() {
+        this.actionName = "pings";
+        this.desiredMenu = "editor";
+        this.pageTitle = "pings.title";
+    }
+    
+    
+    // admin perms required
+    public short requireWeblogPermissions() {
+        return PermissionsData.ADMIN;
+    }
+    
+    
+    public void myPrepare() {
+        
+        PingTargetManager pingTargetMgr = 
RollerFactory.getRoller().getPingTargetManager();
+        
+        // load selected ping target, if possible
+        if(getPingTargetId() != null) try {
+            setPingTarget(pingTargetMgr.getPingTarget(getPingTargetId()));
+        } catch (RollerException ex) {
+            log.error("Error looking up ping target - "+getPingTargetId(), ex);
+        }
+        
+        try {
+            // load common ping targets list
+            setCommonPingTargets(pingTargetMgr.getCommonPingTargets());
+            
+            // load custom ping targets list for weblog, if applicable
+            if(!PingConfig.getDisallowCustomTargets()) {
+                
setCustomPingTargets(pingTargetMgr.getCustomPingTargets(getActionWeblog()));
+            }
+            
+        } catch (RollerException ex) {
+            log.error("Error loading ping target lists for weblog - 
"+getActionWeblog().getHandle(), ex);
+            // TODO: i18n
+            addError("Error loading ping targets");
+        }
+    }
+    
+    
+    /*
+     * Display the common ping targets with page
+     */
+    public String execute() {
+        
+        // load map of enabled auto pings
+        buildIsEnabledMap();
+        
+        return LIST;
+    }
+    
+    
+    /**
+     * Enable a ping target.
+     */
+    public String enable() {
+        
+        if(getPingTarget() != null) try {
+            AutoPingManager autoPingMgr = 
RollerFactory.getRoller().getAutopingManager();
+            AutoPingData autoPing = new AutoPingData(null, getPingTarget(), 
getActionWeblog());
+            autoPingMgr.saveAutoPing(autoPing);
+            RollerFactory.getRoller().flush();
+        } catch(Exception ex) {
+            log.error("Error saving auto ping for target - 
"+getPingTargetId(), ex);
+            // TODO: i18n
+            addError("Error enabling auto ping");
+        }
+        
+        return execute();
+    }
+    
+    
+    /**
+     * Disable a ping target.
+     */
+    public String disable() {
+        
+        if(getPingTarget() != null) try {
+            AutoPingManager autoPingMgr = 
RollerFactory.getRoller().getAutopingManager();
+            autoPingMgr.removeAutoPing(getPingTarget(), getActionWeblog());
+            RollerFactory.getRoller().flush();
+        } catch (Exception ex) {
+            log.error("Error removing auto ping for target - 
"+getPingTargetId(), ex);
+            // TODO: i18n
+            addError("Error disabling auto ping");
+        }
+        
+        return execute();
+    }
+    
+    
+    /**
+     * Ping the selected target now.
+     */
+    public String pingNow() {
+        
+        if(getPingTarget() != null) try {
+            if (PingConfig.getSuspendPingProcessing()) {
+                log.debug("Ping processing is disabled.");
+                addError("ping.pingProcessingIsSuspended");
+            } else {
+                WeblogUpdatePinger.PingResult pingResult = 
WeblogUpdatePinger.sendPing(getPingTarget(), getActionWeblog());
+                if (pingResult.isError()) {
+                    log.debug("Ping Result: " + pingResult);
+                    if (pingResult.getMessage() != null && 
pingResult.getMessage().trim().length() > 0) {
+                        addError("ping.transmittedButError");
+                        addError(pingResult.getMessage());
+                    } else {
+                        addError("ping.transmissionFailed");
+                    }
+                } else {
+                    addMessage("ping.successful");
+                }
+            }
+        } catch (IOException ex) {
+            log.debug(ex);
+            addError("ping.transmissionFailed");
+            addSpecificMessages(ex);
+        } catch (XmlRpcException ex) {
+            log.debug(ex);
+            addError("ping.transmissionFailed");
+            addSpecificMessages(ex);
+        }
+        
+        return execute();
+    }
+    
+    
+    // some extra error messaging
+    private void addSpecificMessages(Exception ex) {
+        if (ex instanceof UnknownHostException) {
+            addError("ping.unknownHost");
+        } else if (ex instanceof SocketException) {
+            addError("ping.networkConnectionFailed");
+        }
+    }
+
+    
+    /**
+     * Private helper to build a map indexed by ping target id with values 
Boolean.TRUE and Boolean.FALSE
+     * based on whether the ping target is enabled (has a corresponding auto 
ping configuration).
+     */
+    private void buildIsEnabledMap() {
+        
+        AutoPingManager autoPingMgr = 
RollerFactory.getRoller().getAutopingManager();
+        
+        // Build isEnabled map (keyed by ping target id and values 
Boolean.TRUE/Boolean.FALSE)
+        Map isEnabled = new HashMap();
+        
+        List autopings = Collections.EMPTY_LIST;
+        try {
+            autopings = autoPingMgr.getAutoPingsByWebsite(getActionWeblog());
+        } catch (RollerException ex) {
+            log.error("Error looking up auto pings for weblog - 
"+getActionWeblog().getHandle(), ex);
+        }
+        
+        // Add the enabled auto ping configs with TRUE
+        for (Iterator i = autopings.iterator(); i.hasNext();) {
+            AutoPingData autoPing = (AutoPingData) i.next();
+            isEnabled.put(autoPing.getPingTarget().getId(), Boolean.TRUE);
+        }
+        
+        // Somewhat awkward, but the two loops save building a separate 
combined list.
+        // Add disabled common ones with FALSE
+        for (Iterator i = getCommonPingTargets().iterator(); i.hasNext();) {
+            PingTargetData pingTarget = (PingTargetData) i.next();
+            if (isEnabled.get(pingTarget.getId()) == null) {
+                isEnabled.put(pingTarget.getId(), Boolean.FALSE);
+            }
+        }
+        
+        // Add disabled custom ones with FALSE
+        for (Iterator i = getCustomPingTargets().iterator(); i.hasNext();) {
+            PingTargetData pingTarget = (PingTargetData) i.next();
+            if (isEnabled.get(pingTarget.getId()) == null) {
+                isEnabled.put(pingTarget.getId(), Boolean.FALSE);
+            }
+        }
+        
+        if(isEnabled.size() > 0) {
+            setPingStatus(isEnabled);
+        }
+    }
+    
+    
+    public String getPingTargetId() {
+        return pingTargetId;
+    }
+
+    public void setPingTargetId(String pingTargetId) {
+        this.pingTargetId = pingTargetId;
+    }
+
+    public PingTargetData getPingTarget() {
+        return pingTarget;
+    }
+
+    public void setPingTarget(PingTargetData pingTarget) {
+        this.pingTarget = pingTarget;
+    }
+
+    public List getCommonPingTargets() {
+        return commonPingTargets;
+    }
+
+    public void setCommonPingTargets(List commonPingTargets) {
+        this.commonPingTargets = commonPingTargets;
+    }
+
+    public List getCustomPingTargets() {
+        return customPingTargets;
+    }
+
+    public void setCustomPingTargets(List customPingTargets) {
+        this.customPingTargets = customPingTargets;
+    }
+
+    public Map getPingStatus() {
+        return pingStatus;
+    }
+
+    public void setPingStatus(Map pingStatus) {
+        this.pingStatus = pingStatus;
+    }
+}

Modified: 
roller/trunk/src/org/apache/roller/ui/authoring/struts2/editor-menu.xml
URL: 
http://svn.apache.org/viewvc/roller/trunk/src/org/apache/roller/ui/authoring/struts2/editor-menu.xml?view=diff&rev=535036&r1=535035&r2=535036
==============================================================================
--- roller/trunk/src/org/apache/roller/ui/authoring/struts2/editor-menu.xml 
(original)
+++ roller/trunk/src/org/apache/roller/ui/authoring/struts2/editor-menu.xml Thu 
May  3 17:08:57 2007
@@ -87,10 +87,10 @@
                    name="tabbedmenu.website.members" 
                    roles="editor"
                    perms="admin" 
-                   subactions="inviteMember,invitations" 
+                   subactions="invite" 
                    enabledProperty="groupblogging.enabled"/>
         
-        <menu-item action="pingSetup"         
+        <menu-item action="pings"         
                    name="tabbedmenu.weblog.pingSetup" 
                    roles="editor"
                    perms="admin" 

Modified: roller/trunk/src/org/apache/roller/util/MailUtil.java
URL: 
http://svn.apache.org/viewvc/roller/trunk/src/org/apache/roller/util/MailUtil.java?view=diff&rev=535036&r1=535035&r2=535036
==============================================================================
--- roller/trunk/src/org/apache/roller/util/MailUtil.java (original)
+++ roller/trunk/src/org/apache/roller/util/MailUtil.java Thu May  3 17:08:57 
2007
@@ -18,6 +18,8 @@
 
 package org.apache.roller.util;
 
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import javax.mail.Message;
@@ -28,7 +30,16 @@
 import javax.mail.Address;
 import javax.mail.internet.InternetAddress;
 import javax.mail.internet.MimeMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
 import org.apache.commons.lang.StringUtils;
+import org.apache.roller.RollerException;
+import org.apache.roller.business.RollerFactory;
+import org.apache.roller.business.UserManager;
+import org.apache.roller.config.RollerRuntimeConfig;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WebsiteData;
 
 
 /**
@@ -37,6 +48,82 @@
 public class MailUtil {
     
     private static Log log = LogFactory.getLog(MailUtil.class);
+    
+    
+    /**
+     * Lookup the configured mail Session if possible.
+     *
+     * @returns Mail Session if possible, otherwise null.
+     */
+    public static Session getMailSession() throws RollerException {
+        try {
+            Context ctx = (Context) new 
InitialContext().lookup("java:comp/env");
+            Session mailSession = (Session) ctx.lookup("mail/Session");
+            return mailSession;
+        } catch (NamingException ex) {
+            throw new RollerException("ERROR: Notification email(s) not sent, "
+                    + "Roller's mail session not properly configured", ex);
+        }
+    }
+    
+    
+    /**
+     * Send a weblog invitation email.
+     */
+    public static void sendWeblogInvitation(WebsiteData website, 
+                                            UserData user)
+            throws RollerException {
+        
+        Session mailSession = getMailSession();
+        if(mailSession == null) {
+            throw new RollerException("ERROR: Notification email(s) not sent, "
+                    + "Roller's mail session not properly configured");
+        }
+        
+        try {
+            UserManager umgr = RollerFactory.getRoller().getUserManager();
+            
+            String userName = user.getUserName();
+            String from = website.getEmailAddress();
+            String cc[] = new String[] {from};
+            String bcc[] = new String[0];
+            String to[] = new String[] {user.getEmailAddress()};
+            String subject;
+            String content;
+            
+            // Figure URL to entry edit page
+            String rootURL = RollerRuntimeConfig.getAbsoluteContextURL();
+            String url = rootURL + "/roller-ui/yourWebsites.do";
+            
+            ResourceBundle resources = ResourceBundle.getBundle(
+                    "ApplicationResources",
+                    website.getLocaleInstance());
+            StringBuffer sb = new StringBuffer();
+            sb.append(MessageFormat.format(
+                    resources.getString("inviteMember.notificationSubject"),
+                    new Object[] {
+                website.getName(),
+                website.getHandle()})
+                );
+            subject = sb.toString();
+            sb = new StringBuffer();
+            sb.append(MessageFormat.format(
+                    resources.getString("inviteMember.notificationContent"),
+                    new Object[] {
+                website.getName(),
+                website.getHandle(),
+                user.getUserName(),
+                url
+            }));
+            content = sb.toString();
+            MailUtil.sendTextMessage(
+                    mailSession, from, to, cc, bcc, subject, content);
+        } catch (MessagingException e) {
+            throw new RollerException("ERROR: Notification email(s) not sent, "
+                    + "due to Roller configuration or mail server problem.", 
e);
+        }
+    }
+    
     
     // agangolli: Incorporated suggested changes from Ken Blackler.
     

Modified: roller/trunk/web/WEB-INF/classes/struts.xml
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/classes/struts.xml?view=diff&rev=535036&r1=535035&r2=535036
==============================================================================
--- roller/trunk/web/WEB-INF/classes/struts.xml (original)
+++ roller/trunk/web/WEB-INF/classes/struts.xml Thu May  3 17:08:57 2007
@@ -228,12 +228,21 @@
             <result name="cancel" type="redirect-action">templates</result>
         </action>
         
-        <action name="members">
-            <result>/roller-ui/authoring/memberPermissions.do</result>
+        <action name="members!*" method="{1}"
+                class="org.apache.roller.ui.authoring.struts2.Members">
+            <result name="list" type="tiles">.Members</result>
         </action>
         
-        <action name="pingSetup">
-            <result>/roller-ui/authoring/pingSetup.do</result>
+        <action name="invite!*" method="{1}"
+                class="org.apache.roller.ui.authoring.struts2.MembersInvite">
+            <result name="input" type="tiles">.MembersInvite</result>
+            <result name="disabled" type="tiles">.disabled</result>
+            <result name="success" type="chain">members</result>
+        </action>
+        
+        <action name="pings!*" method="{1}"
+                class="org.apache.roller.ui.authoring.struts2.Pings">
+            <result name="list" type="tiles">.Pings</result>
         </action>
         
         <action name="customPingTargets!*" method="{1}"
@@ -261,11 +270,7 @@
         
         
         <!--
-        <action name="pingSetup!*" method="{1}"
-                class="org.apache.roller.ui.authoring.struts2.PingSetupAction">
-            <result name="pingSetup.page">.Pings</result>
-            <result name="pingResult.page">.PingResult</result>
-        </action>
+        
         
         <action name="importBookmarks!*" method="{1}"
                 
class="org.apache.roller.ui.authoring.struts2.ImportBookmarksFormAction">
@@ -298,10 +303,7 @@
         <action name="categorySave!*" method="{1}"
                 
class="org.apache.roller.ui.authoring.struts2.CategorySaveAction">
         </action>
-        <action name="inviteMember!*" method="{1}"
-                
class="org.apache.roller.ui.authoring.struts2.InviteMemberAction">
-            <result name="inviteMember.page">.InviteMember</result>
-        </action>
+        
         <action name="weblog!*" method="{1}"
                 
class="org.apache.roller.ui.authoring.struts2.WeblogEntryFormAction">
             <result name="weblogEdit.page">.WeblogEdit</result>
@@ -313,11 +315,6 @@
             <result 
name="weblogEntryManagement.page">.WeblogEntryManagement</result>
         </action>
         
-        <action name="memberPermissions!*" method="{1}"
-                
class="org.apache.roller.ui.authoring.struts2.MemberPermissionsAction">
-            <result name="memberPermissions.page">.MemberPermissions</result>
-        </action>
-        
         <action name="referers!*" method="{1}"
                 class="org.apache.roller.ui.authoring.struts2.ReferersAction">
             <result name="referers.page">.referers</result>
@@ -331,10 +328,6 @@
         <action name="folderSave!*" method="{1}"
                 
class="org.apache.roller.ui.authoring.struts2.FolderSaveAction">
             <result name="Bookmarks" 
type="dispatcher">/roller-ui/authoring/bookmarks.action!selectFolder</result>
-        </action>
-        <action name="invitations!*" method="{1}"
-                
class="org.apache.roller.ui.authoring.struts2.InvitationsAction">
-            <result name="invitations.page">.Invitations</result>
         </action>
         <action name="toggleLinkback!*" method="{1}"
                 
class="org.apache.roller.ui.authoring.struts2.ToggleLinkbackDisplayAction">

Added: roller/trunk/web/WEB-INF/jsps/authoring/struts2/Members.jsp
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/jsps/authoring/struts2/Members.jsp?view=auto&rev=535036
==============================================================================
--- roller/trunk/web/WEB-INF/jsps/authoring/struts2/Members.jsp (added)
+++ roller/trunk/web/WEB-INF/jsps/authoring/struts2/Members.jsp Thu May  3 
17:08:57 2007
@@ -0,0 +1,113 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  The ASF licenses this file to You
+  under the Apache License, Version 2.0 (the "License"); you may not
+  use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.  For additional information regarding
+  copyright in this work, please see the NOTICE file in the top level
+  directory of this distribution.
+--%>
+<%@ include file="/WEB-INF/jsps/taglibs-struts2.jsp" %>
+        
+<script>
+// <!--  
+function save() {
+    radios = document.getElementsByTagName("input");
+    var removing = false;
+    for (var i=0; i<radios.length; i++) {
+        if (radios[i].value == -1 && radios[i].checked) {
+            removing = true;
+        }
+    }
+    if (removing && !confirm("<s:text name='memberPermissions.confirmRemove' 
/>")) return;
+    document.memberPermissionsForm.submit();
+}
+// -->
+</script>
+
+<p class="subtitle">
+    <s:text name="memberPermissions.subtitle" >
+        <s:param value="actionWeblog.handle" />
+    </s:text>
+</p>
+
+<p><s:text name="memberPermissions.description" /></p>
+
+<s:form action="members!save">
+    <s:hidden name="weblog" value="%{actionWeblog.handle}" />
+    
+    <div style="text-align: right; padding-bottom: 6px;">
+        <span class="pendingCommentBox">&nbsp;&nbsp;&nbsp;&nbsp;</span>
+            <s:text name="commentManagement.pending" />&nbsp;
+    </div>
+    
+    <table class="rollertable">
+        <tr class="rHeaderTr">
+           <th class="rollertable" width="20%">
+               <s:text name="memberPermissions.userName" />
+           </th>
+           <th class="rollertable" width="20%">
+               <s:text name="memberPermissions.administrator" />
+           </th>
+           <th class="rollertable" width="20%">
+               <s:text name="memberPermissions.author" />
+           </th>
+           <th class="rollertable" width="20%">
+               <s:text name="memberPermissions.limited" />
+           </th>
+           <th class="rollertable" width="20%">
+               <s:text name="memberPermissions.remove" />
+           </th>
+        </tr>
+        <s:iterator id="perm" value="actionWeblog.permissions" 
status="rowstatus">
+            <s:if test="#perm.pending">
+                <tr class="rollertable_pending">
+            </s:if>
+            <s:elseif test="#rowstatus.odd == true">
+                <tr class="rollertable_odd">
+            </s:elseif>
+            <s:else>
+                <tr class="rollertable_even">
+            </s:else>
+            
+                <td class="rollertable">
+                    <img src='<s:url value="/images/user.png"/>' border="0" 
alt="icon" />
+                       <s:property value="#perm.user.userName" />
+                </td>               
+                <td class="rollertable">
+                    <input type="radio" onchange="dirty()" 
+                        <s:if test="#perm.permissionMask == 3">checked</s:if>
+                        name='perm-<s:property value="#perm.id" />' value="3" 
/>
+                </td>
+                <td class="rollertable">
+                       <input type="radio"  onchange="dirty()"
+                        <s:if test="#perm.permissionMask == 1">checked</s:if>
+                        name='perm-<s:property value="#perm.id" />' value="1" 
/>
+                </td>                
+                <td class="rollertable">
+                    <input type="radio" onchange="dirty()"
+                        <s:if test="#perm.permissionMask == 0">checked</s:if>
+                        name='perm-<s:property value="#perm.id" />' value="0" 
/>
+                </td>                
+                <td class="rollertable">
+                    <input type="radio" onchange="dirty()"
+                        name='perm-<s:property value="#perm.id" />' value="-1" 
/>
+                </td>
+           </tr>
+       </s:iterator>
+    </table>
+    <br />
+     
+    <div class="control">
+       <s:submit key="memberPermissions.button.save" />
+    </div>
+    
+</s:form>

Added: roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp?view=auto&rev=535036
==============================================================================
--- roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp (added)
+++ roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp Thu May  
3 17:08:57 2007
@@ -0,0 +1,63 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  The ASF licenses this file to You
+  under the Apache License, Version 2.0 (the "License"); you may not
+  use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.  For additional information regarding
+  copyright in this work, please see the NOTICE file in the top level
+  directory of this distribution.
+--%>
+<%@ include file="/WEB-INF/jsps/taglibs-struts2.jsp" %>
+
+<script type="text/javascript">
+// <!--
+<%@ include file="/roller-ui/scripts/ajax-user.js" %>
+// -->
+</script> 
+
+<p class="subtitle"><s:text name="inviteMember.subtitle" /></p>
+<p><s:text name="inviteMember.prompt" /></p>
+
+<s:form action="invite!save">
+    <s:hidden name="weblog" value="%{actionWeblog.handle}" />
+    
+    <div class="formrow">
+       <label for="userName" class="formrow" />
+           <s:text name="inviteMember.userName" /></label>
+       <div>
+           <input name="userName" id="userName" size="30" maxlength="30" 
+               onfocus="onUserNameFocus(true)" 
onkeyup="onUserNameChange(true)" /><br />
+       </div>
+    </div>    
+    
+    <div class="formrow">
+       <label class="formrow" />&nbsp;</label>
+       <div>
+           <select id="userList" size="10" onchange="onUserSelected()" 
style="width:300px"></select>
+       </div>
+    </div>    
+    
+    <div style="clear:left">
+       <label for="userName" class="formrow" />
+           <s:text name="inviteMember.permissions" /></label>
+       <input type="radio" name="permissionsMask" value="3"  />
+       <s:text name="inviteMember.administrator" />
+       <input type="radio" name="permissionsMask" value="1" checked />
+       <s:text name="inviteMember.author" />
+       <input type="radio" name="permissionsMask" value="0" />
+       <s:text name="inviteMember.limited" />
+    </div>  
+         
+    <br />      
+    <s:submit key="inviteMember.button.save" />
+    <s:submit key="application.cancel" action="members" />
+
+</s:form>

Added: roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp?view=auto&rev=535036
==============================================================================
--- roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp (added)
+++ roller/trunk/web/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp Thu May  
3 17:08:57 2007
@@ -0,0 +1,66 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  The ASF licenses this file to You
+  under the Apache License, Version 2.0 (the "License"); you may not
+  use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.  For additional information regarding
+  copyright in this work, please see the NOTICE file in the top level
+  directory of this distribution.
+--%>
+<%@ include file="/WEB-INF/jsps/taglibs-struts2.jsp" %>
+
+<div class="sidebarFade">
+    <div class="menu-tr">
+        <div class="menu-tl">
+            
+        <div class="sidebarInner">
+
+            <h3><s:text name="mainPage.actions" /></h3>            
+            <hr size="1" noshade="noshade" />
+            
+            <img src='<s:url value="/images/email_edit.png"/>' alt="mail-icon" 
align="bottom" />
+            <s:url action="invite" id="inviteUrl">
+               <s:param name="weblog" value="%{actionWeblog.handle}" />
+            </s:url>
+            <a href='<s:property value="#inviteUrl" />'>
+                <s:text name="memberPermissions.inviteMember" />
+            </a>
+            <br />
+            <s:text name="memberPermissions.whyInvite" />       
+            <br />
+            <br />
+        </div>                                                 
+        </div>
+    </div>
+</div> 
+
+<br />
+<br />
+
+<div class="sidebarFade">
+    <div class="menu-tr">
+        <div class="menu-tl">
+            <div class="sidebarBody">
+            <div class="sidebarInner">
+            
+            <h3>
+                <s:text name="memberPermissions.permissionsHelpTitle" />
+            </h3>
+            <hr size="1" noshade="noshade" />
+            
+            <s:text name="memberPermissions.permissionHelp" /> 
+                   <br />
+                   <br />
+        </div>             
+            </div>
+        </div>
+    </div>
+</div> 

Added: roller/trunk/web/WEB-INF/jsps/authoring/struts2/Pings.jsp
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/jsps/authoring/struts2/Pings.jsp?view=auto&rev=535036
==============================================================================
--- roller/trunk/web/WEB-INF/jsps/authoring/struts2/Pings.jsp (added)
+++ roller/trunk/web/WEB-INF/jsps/authoring/struts2/Pings.jsp Thu May  3 
17:08:57 2007
@@ -0,0 +1,184 @@
+<%--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  The ASF licenses this file to You
+  under the Apache License, Version 2.0 (the "License"); you may not
+  use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.  For additional information regarding
+  copyright in this work, please see the NOTICE file in the top level
+  directory of this distribution.
+--%>
+<%@ include file="/WEB-INF/jsps/taglibs-struts2.jsp" %>
+
+<p class="subtitle">
+   <s:text name="pings.subtitle" >
+       <s:param value="actionWeblog.handle" />
+   </s:text>
+</p>  
+<p class="pagetip">
+    <s:text name="pings.explanation"/>
+<p/>
+
+<p/>
+<h2><s:text name="pings.commonPingTargets"/></h2>
+<p/>
+
+<p/>
+<s:text name="pings.commonPingTargetsExplanation"/>
+<p/>
+
+<table class="rollertable">
+<%-- Headings --%>
+<tr class="rollertable">
+    <th class="rollertable" width="20%"><s:text name="pingTarget.name" /></th>
+    <th class="rollertable" width="40%"><s:text name="pingTarget.pingUrl" 
/></th>
+    <th class="rollertable" width="20%" colspan=2><s:text 
name="pingTarget.auto" /></th>
+    <th class="rollertable" width="20%"><s:text name="pingTarget.manual" 
/></th>
+</tr>
+
+<%-- Table of current common targets with actions --%>
+<s:iterator id="pingTarget" value="commonPingTargets" status="rowstatus">
+    <s:if test="#rowstatus.odd == true">
+        <tr class="rollertable_odd">
+    </s:if>
+    <s:else>
+        <tr class="rollertable_even">
+    </s:else>
+    
+    <td class="rollertable">
+        <str:truncateNicely lower="15" upper="20" ><s:property 
value="#pingTarget.name" /></str:truncateNicely>
+    </td>
+    
+    <td class="rollertable">
+        <str:truncateNicely lower="70" upper="75" ><s:property 
value="#pingTarget.pingUrl" /></str:truncateNicely>
+    </td>
+    
+    <!-- TODO: Use icons here -->
+    <td class="rollertable" align="center" >
+        <s:if test="pingStatus[#pingTarget.id]">
+            <span style="{color: #00aa00; font-weight: bold;}"><s:text 
name="pingTarget.enabled"/></span>&nbsp;
+        </s:if>
+        <s:else>
+            <span style="{color: #aaaaaa; font-weight: bold;}"><s:text 
name="pingTarget.disabled"/></span>&nbsp;
+        </s:else>
+    </td>
+    
+    <!-- TODO: Use icons here -->
+    <td class="rollertable" align="center" >
+        <s:if test="pingStatus[#pingTarget.id]">
+            <s:url id="disableUrl" action="pings!disable" >
+                <s:param name="weblog" value="%{actionWeblog.handle}" />
+                <s:param name="pingTargetId" value="#pingTarget.id" />
+            </s:url>
+            <s:a href="%{disableUrl}"><s:text name="pingTarget.disable"/></s:a>
+        </s:if>
+        <s:else>
+            <s:url id="enableUrl" action="pings!enable" >
+                <s:param name="weblog" value="%{actionWeblog.handle}" />
+                <s:param name="pingTargetId" value="#pingTarget.id" />
+            </s:url>
+            <s:a href="%{enableUrl}"><s:text name="pingTarget.enable"/></s:a>
+        </s:else>
+    </td>
+    
+    <td class="rollertable">
+        <s:url id="pingNowUrl" action="pings!pingNow" >
+            <s:param name="weblog" value="%{actionWeblog.handle}" />
+            <s:param name="pingTargetId" value="#pingTarget.id" />
+        </s:url>
+        <s:a href="%{pingNowUrl}"><s:text name="pingTarget.sendPingNow"/></s:a>
+    </td>
+    
+    </tr>
+</s:iterator>
+</table>
+
+<br />
+
+<s:if test="!getBooleanProp('pings.disallowCustomTargets')">
+<h2><s:text name="pings.customPingTargets"/></h2>
+
+<p/>
+<s:if test="!customPingTargets.isEmpty">
+    <s:text name="pings.customPingTargetsExplanationNonEmpty"/>
+</s:if>
+<s:else>
+    <s:text name="pings.customPingTargetsExplanationEmpty"/>
+</s:else>
+<p/>
+
+<s:if test="!customPingTargets.isEmpty">
+<table class="rollertable">
+<%-- Headings --%>
+<tr class="rollertable">
+    <th class="rollertable" width="20%"><s:text name="pingTarget.name" /></th>
+    <th class="rollertable" width="40%"><s:text name="pingTarget.pingUrl" 
/></th>
+    <th class="rollertable" width="20%" colspan=2><s:text 
name="pingTarget.auto" /></th>
+    <th class="rollertable" width="20%"><s:text name="pingTarget.manual" 
/></th>
+</tr>
+
+<%-- Table of current custom targets with actions --%>
+<s:iterator id="pingTarget" value="customPingTargets" status="rowstatus">
+    <s:if test="#rowstatus.odd == true">
+        <tr class="rollertable_odd">
+    </s:if>
+    <s:else>
+        <tr class="rollertable_even">
+    </s:else>
+    
+    <td class="rollertable">
+        <str:truncateNicely lower="15" upper="20" ><s:property 
value="#pingTarget.name" /></str:truncateNicely>
+    </td>
+    
+    <td class="rollertable">
+        <str:truncateNicely lower="70" upper="75" ><s:property 
value="#pingTarget.pingUrl" /></str:truncateNicely>
+    </td>
+    
+    <!-- TODO: Use icons here -->
+    <td class="rollertable" align="center" >
+        <s:if test="pingStatus[#pingTarget.id]">
+            <span style="{color: #00aa00; font-weight: bold;}"><s:text 
name="pingTarget.enabled"/></span>&nbsp;
+        </s:if>
+        <s:else >
+            <span style="{color: #aaaaaa; font-weight: bold;}"><s:text 
name="pingTarget.disabled"/></span>&nbsp;
+        </s:else>
+    </td>
+    
+    <!-- TODO: Use icons here -->
+    <td class="rollertable" align="center" >
+        <s:if test="pingStatus[#pingTarget.id]">
+            <s:url id="disableUrl" action="pings!disable" >
+                <s:param name="weblog" value="%{actionWeblog.handle}" />
+                <s:param name="pingTargetId" value="#pingTarget.id" />
+            </s:url>
+            <s:a href="%{disableUrl}"><s:text name="pingTarget.disable"/></s:a>
+        </s:if>
+        <s:else>
+            <s:url id="enableUrl" action="pings!enable" >
+                <s:param name="weblog" value="%{actionWeblog.handle}" />
+                <s:param name="pingTargetId" value="#pingTarget.id" />
+            </s:url>
+            <s:a href="%{enableUrl}"><s:text name="pingTarget.enable"/></s:a>
+        </s:else>
+    </td>
+    
+    <td class="rollertable">
+        <s:url id="pingNowUrl" action="pings!pingNow" >
+            <s:param name="weblog" value="%{actionWeblog.handle}" />
+            <s:param name="pingTargetId" value="#pingTarget.id" />
+        </s:url>
+        <s:a href="%{pingNowUrl}"><s:text name="pingTarget.sendPingNow"/></s:a>
+    </td>
+    
+    </tr>
+</s:iterator>
+</table>
+</s:if><!-- end if non-empty custom targets list -->
+</s:if><!-- end if custom ping targets are allowed -->

Modified: roller/trunk/web/WEB-INF/tiles.xml
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/WEB-INF/tiles.xml?view=diff&rev=535036&r1=535035&r2=535036
==============================================================================
--- roller/trunk/web/WEB-INF/tiles.xml (original)
+++ roller/trunk/web/WEB-INF/tiles.xml Thu May  3 17:08:57 2007
@@ -99,6 +99,7 @@
     </definition>
     
     <definition name=".GlobalCommentManagement" extends=".tiles-tabbedpage" >
+        <put name="head" value="/WEB-INF/jsps/tiles/struts2/head-ajax.jsp" />
         <put name="content" 
value="/WEB-INF/jsps/admin/struts2/GlobalCommentManagement.jsp" />
         <put name="sidebar" 
value="/WEB-INF/jsps/admin/struts2/GlobalCommentManagementSidebar.jsp" />
         <put name="styles" value="/WEB-INF/jsps/tiles/struts2/css-sidebar.jsp" 
/>
@@ -162,7 +163,6 @@
     </definition>
     
     <definition name=".CommentManagementGlobal" extends=".tiles-tabbedpage" >
-        <put name="head" value="/WEB-INF/jsps/tiles/struts2/head-ajax.jsp" />
         <put name="content" 
value="/WEB-INF/jsps/authoring/CommentManagement.jsp" />
         <put name="sidebar" 
value="/WEB-INF/jsps/authoring/CommentManagementSidebar.jsp" />
         <put name="styles" value="/WEB-INF/jsps/tiles/struts2/css-sidebar.jsp" 
/>
@@ -238,25 +238,19 @@
         <put name="styles" 
value="/WEB-INF/jsps/tiles/struts2/css-nosidebar.jsp" />
     </definition>
     
-    <definition name=".MemberPermissions" extends=".tiles-tabbedpage" >
-        <put name="content" 
value="/WEB-INF/jsps/authoring/MemberPermissions.jsp" />
-        <put name="sidebar" 
value="/WEB-INF/jsps/authoring/MemberPermissionsSidebar.jsp" />
+    <definition name=".Members" extends=".tiles-tabbedpage" >
+        <put name="content" 
value="/WEB-INF/jsps/authoring/struts2/Members.jsp" />
+        <put name="sidebar" 
value="/WEB-INF/jsps/authoring/struts2/MembersSidebar.jsp" />
         <put name="styles" value="/WEB-INF/jsps/tiles/struts2/css-sidebar.jsp" 
/>
     </definition>
     
-    <definition name=".Invitations" extends=".tiles-tabbedpage"  >
-        <put name="content" value="/WEB-INF/jsps/authoring/Invitations.jsp" />
-        <put name="styles" 
value="/WEB-INF/jsps/tiles/struts2/css-nosidebar.jsp" />
-    </definition>
-    
-    <definition name=".InviteMember" extends=".tiles-tabbedpage" >
-        <put name="content" value="/WEB-INF/jsps/authoring/InviteMember.jsp" />
+    <definition name=".MembersInvite" extends=".tiles-tabbedpage" >
+        <put name="content" 
value="/WEB-INF/jsps/authoring/struts2/MembersInvite.jsp" />
         <put name="styles" 
value="/WEB-INF/jsps/tiles/struts2/css-nosidebar.jsp" />
     </definition>
     
-    <definition name=".InviteMemberDone" extends=".tiles-tabbedpage" >
-        <put name="content" 
value="/WEB-INF/jsps/authoring/InviteMemberDone.jsp" />
-        <put name="styles" 
value="/WEB-INF/jsps/tiles/struts2/css-nosidebar.jsp" />
+    <definition name=".Pings" extends=".tiles-tabbedpage" >
+        <put name="content" value="/WEB-INF/jsps/authoring/struts2/Pings.jsp" 
/>
     </definition>
     
     <definition name=".CustomPingTargets" extends=".tiles-tabbedpage" >

Modified: roller/trunk/web/roller-ui/styles/roller.css
URL: 
http://svn.apache.org/viewvc/roller/trunk/web/roller-ui/styles/roller.css?view=diff&rev=535036&r1=535035&r2=535036
==============================================================================
--- roller/trunk/web/roller-ui/styles/roller.css (original)
+++ roller/trunk/web/roller-ui/styles/roller.css Thu May  3 17:08:57 2007
@@ -306,6 +306,12 @@
     vertical-align: top;
     color: black;
 }
+.rollertable_pending td {
+    border: 1px solid #ccc;
+    background: #ffffcc;
+    color: black;
+    vertical-align: top;
+}
 td.rollertable_entry, div.rollertable_entry {
     border: 1px solid #ccc;
     background: inherit;


Reply via email to