added the mechanisms to manage community services, and the community-level

pages for doing so
This commit is contained in:
Eric J. Bowersox 2003-06-19 22:55:45 +00:00
parent c8b6a513b9
commit c6a86a167f
15 changed files with 540 additions and 1 deletions

View File

@ -601,6 +601,8 @@ INSERT INTO globalprop (nsid, prop_name, prop_value) VALUES
(6, 'bnc.previous', '!Previous' ),
(6, 'bn.reminder', '!reminder.jpg' ),
(6, 'bnc.reminder', '!Reminder' ),
(6, 'bn.remove', '!remove.jpg' ),
(6, 'bnc.remove', '!Remove' ),
(6, 'bn.search', '!search.jpg' ),
(6, 'bnc.search', '!Search' ),
(6, 'bn.send.again', '!send_again.jpg' ),
@ -936,6 +938,7 @@ INSERT INTO ace (aceid, pri, flags) VALUES (9, 2, 0);
INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 1, 9);
INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES
(9, 14, 'grant.revoke.access'),
(9, 14, 'manage.services' ),
(9, 15, 'set.category' ),
(9, 15, 'set.visibility' ),
(9, 15, 'set.name' ),
@ -947,6 +950,7 @@ INSERT INTO ace (aceid, pri, flags) VALUES (10, 5, 1);
INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 2, 10);
INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES
(10, 14, 'grant.revoke.access'),
(10, 14, 'manage.services' ),
(10, 15, 'set.category' ),
(10, 15, 'set.visibility' ),
(10, 15, 'set.name' ),
@ -1423,7 +1427,8 @@ INSERT INTO menuvars (menuid, var_name, default_val) VALUES
(7, 'name', NULL),
(7, 'cid', NULL);
INSERT INTO menuitems (menuid, sequence, itemtype, text, linktype, link, perm_nsid, perm_name) VALUES
(7, 0, 'TEXT', 'Edit Community Profile', 'SERVLET', 'comm/admin/profile.js.vs?cc=${cid}', 15, 'set.property');
(7, 0, 'TEXT', 'Edit Community Profile', 'SERVLET', 'comm/admin/profile.js.vs?cc=${cid}', 15, 'set.property' ),
(7, 1, 'TEXT', 'Set Community Services', 'SERVLET', 'comm/admin/services.js.vs?cc=${cid}', 14, 'manage.services');
# Create the sysadmin globals menu. (ID #8)
INSERT INTO menus (menuid, menu_nsid, menu_name, title, subtitle)

View File

@ -31,6 +31,7 @@ import com.silverwrist.dynamo.util.*;
import com.silverwrist.venice.CommunityVisibility;
import com.silverwrist.venice.VeniceNamespaces;
import com.silverwrist.venice.event.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.iface.*;
/**
@ -1120,4 +1121,79 @@ class CommunityImpl implements VeniceCommunity
} // end getServices
public boolean isUsingService(String namespace, String name) throws DatabaseException
{
return m_ops.isUsingService(m_id,m_nscache.namespaceNameToId(namespace),name);
} // end isUsingService
public synchronized void addService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException
{
testPermission(caller,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"manage.services","auth.addService");
int nsid = m_nscache.namespaceNameToId(namespace);
if (m_ops.isUsingService(m_id,nsid,name))
{ // we're already using this service - throw an exception
CommunityServiceException cse = new CommunityServiceException(CommunityImpl.class,"CommunityMessages",
"svc.already.using");
cse.setParameter(0,namespace);
cse.setParameter(1,name);
throw cse;
} // end if
CommunityServiceDescriptor descr = m_base.getServiceForName(namespace,name);
if (descr==null)
{ // this service is not defined - throw an exception
CommunityServiceException cse = new CommunityServiceException(CommunityImpl.class,"CommunityMessages",
"svc.notFound");
cse.setParameter(0,namespace);
cse.setParameter(1,name);
throw cse;
} // end if
descr.getController().addServiceToCommunity(req,this);
m_ops.addService(m_id,nsid,name);
m_service_list = null;
} // end addService
public void removeService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException
{
testPermission(caller,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"manage.services","auth.removeService");
int nsid = m_nscache.namespaceNameToId(namespace);
synchronized (this)
{ // see if we're using this service
if (!(m_ops.isUsingService(m_id,nsid,name)))
{ // we're not using this service - throw an exception
CommunityServiceException cse = new CommunityServiceException(CommunityImpl.class,"CommunityMessages",
"svc.not.using");
cse.setParameter(0,namespace);
cse.setParameter(1,name);
throw cse;
} // end if
CommunityServiceDescriptor descr = m_base.getServiceForName(namespace,name);
if (descr==null)
{ // this service is not defined - throw an exception
CommunityServiceException cse = new CommunityServiceException(CommunityImpl.class,"CommunityMessages",
"svc.notFound");
cse.setParameter(0,namespace);
cse.setParameter(1,name);
throw cse;
} // end if
descr.getController().removeServiceFromCommunity(req,this);
m_ops.removeService(m_id,nsid,name);
m_service_list = null;
} // end synchronized block
} // end removeService
} // end class CommunityImpl

View File

@ -660,6 +660,12 @@ public class CommunityManager
} // end getServiceForID
public CommunityServiceDescriptor getServiceForName(String namespace, String name)
{
return (CommunityServiceDescriptor)(m_qname_to_service.get(new QualifiedNameKey(namespace,name)));
} // end getServiceForName
/*--------------------------------------------------------------------------------
* Implementations from interface CommunityProxyService
*--------------------------------------------------------------------------------

View File

@ -34,3 +34,8 @@ join.authFail=Unable to authenticate to community "{0}"; cannot join.
svc.modname.mismatch=The name of the service module "{0}" did not match the name stored in the database.
svc.object.badType=The service controller object {0}::{1} was of the wrong type.
auth.unjoin=You are not permitted to unjoin community "{0}."
svc.already.using=This community is already using the service {0}::{1}.
svc.not.using=This community is not using the service {0}::{1}.
svc.notFound=No service is defined with the name {0}::{1}.
auth.addService=You are not authorized to add services to community "{0}."
auth.removeService=You are not authorized to remove services from community "{0}."

View File

@ -82,4 +82,10 @@ abstract class CommunityOps extends OpsBase
abstract int[] getServiceIDs(int cid) throws DatabaseException;
abstract boolean isUsingService(int cid, int nsid, String name) throws DatabaseException;
abstract void addService(int cid, int nsid, String name) throws DatabaseException;
abstract void removeService(int cid, int nsid, String name) throws DatabaseException;
} // end class CommunityOps

View File

@ -1085,4 +1085,142 @@ class CommunityOps_mysql extends CommunityOps
} // end getServiceIDs
boolean isUsingService(int cid, int nsid, String name) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT c.svcid FROM commsvc c, commsvc_master m WHERE c.cid = ? "
+ "AND c.svcid = m.svcid AND m.svc_nsid = ? AND m.svc_name = ?;");
stmt.setInt(1,cid);
stmt.setInt(2,nsid);
stmt.setString(3,name);
rs = stmt.executeQuery();
return rs.next();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end isUsingService
void addService(int cid, int nsid, String name) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the tables
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES commsvc WRITE, commsvc_master READ;");
// get the index for the service
stmt = conn.prepareStatement("SELECT svcid FROM commsvc_master WHERE svc_nsid = ? AND svc_name = ?;");
stmt.setInt(1,nsid);
stmt.setString(2,name);
rs = stmt.executeQuery();
int ndx = -1;
if (rs.next())
ndx = rs.getInt(1);
else
return;
rs.close();
rs = null;
stmt.close();
// Insert the record into the table.
stmt = conn.prepareStatement("INSERT INTO commsvc (cid, svcid) VALUES (?, ?);");
stmt.setInt(1,cid);
stmt.setInt(2,ndx);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end addService
void removeService(int cid, int nsid, String name) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the tables
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES commsvc WRITE, commsvc_master READ;");
// get the index for the service
stmt = conn.prepareStatement("SELECT svcid FROM commsvc_master WHERE svc_nsid = ? AND svc_name = ?;");
stmt.setInt(1,nsid);
stmt.setString(2,name);
rs = stmt.executeQuery();
int ndx = -1;
if (rs.next())
ndx = rs.getInt(1);
else
return;
rs.close();
rs = null;
stmt.close();
// delete the record from the table
stmt = conn.prepareStatement("DELETE FROM commsvc WHERE cid = ? AND svcid = ?;");
stmt.setInt(1,cid);
stmt.setInt(2,ndx);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
MySQLUtils.unlockTables(conn);
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end removeService
} // end class CommunityOps_mysql

View File

@ -23,6 +23,7 @@ import java.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.venice.CommunityVisibility;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.iface.*;
/**
@ -621,6 +622,26 @@ abstract class CommunityProxy implements VeniceCommunity, DynamicWrapper
} // end getServices
public boolean isUsingService(String namespace, String name) throws DatabaseException
{
return getRealCommunity().isUsingService(namespace,name);
} // end isUsingService
public void addService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException
{
getRealCommunity().addService(caller,req,namespace,name);
} // end addService
public void removeService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException
{
getRealCommunity().removeService(caller,req,namespace,name);
} // end removeService
/*--------------------------------------------------------------------------------
* Implementations from interface DynamicWrapper
*--------------------------------------------------------------------------------

View File

@ -54,4 +54,6 @@ public interface CommunityService
public CommunityServiceDescriptor getServiceForID(int id);
public CommunityServiceDescriptor getServiceForName(String namespace, String name);
} // end interface CommunityService

View File

@ -17,11 +17,20 @@
*/
package com.silverwrist.venice.iface;
import com.silverwrist.dynamo.except.DatabaseException;
import com.silverwrist.dynamo.iface.ComponentShutdown;
import com.silverwrist.dynamo.iface.DynamicObject;
import com.silverwrist.dynamo.iface.Request;
import com.silverwrist.venice.except.CommunityServiceException;
public interface CommunityServiceController extends DynamicObject, ComponentShutdown
{
public String getDescription();
public void addServiceToCommunity(Request req, VeniceCommunity comm)
throws DatabaseException, CommunityServiceException;
public void removeServiceFromCommunity(Request req, VeniceCommunity comm)
throws DatabaseException, CommunityServiceException;
} // end interface CommunityServiceController

View File

@ -28,8 +28,10 @@ import com.silverwrist.dynamo.iface.DynamoAcl;
import com.silverwrist.dynamo.iface.DynamoGroup;
import com.silverwrist.dynamo.iface.DynamoUser;
import com.silverwrist.dynamo.iface.NamedObject;
import com.silverwrist.dynamo.iface.Request;
import com.silverwrist.dynamo.iface.SecureObjectStore;
import com.silverwrist.venice.CommunityVisibility;
import com.silverwrist.venice.except.CommunityServiceException;
/**
* The interface representing a top-level <EM>community object</EM>. A <EM>community</EM> is the primary unit of
@ -318,4 +320,12 @@ public interface VeniceCommunity extends NamedObject, SecureObjectStore
public List getServices() throws DatabaseException;
public boolean isUsingService(String namespace, String name) throws DatabaseException;
public void addService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException;
public void removeService(DynamoUser caller, Request req, String namespace, String name)
throws DatabaseException, DynamoSecurityException, CommunityServiceException;
} // end interface VeniceCommunity

View File

@ -23,6 +23,7 @@ import com.silverwrist.dynamo.iface.*;
import com.silverwrist.venice.app.AdvancedUserService;
import com.silverwrist.venice.community.CategoryService;
import com.silverwrist.venice.community.CommunityService;
import com.silverwrist.venice.community.CommunityServiceDescriptor;
import com.silverwrist.venice.iface.*;
import com.silverwrist.venice.sidebox.SideboxDescriptor;
import com.silverwrist.venice.sidebox.SideboxService;
@ -139,6 +140,14 @@ public class LibraryVeniceCast
} // end queryUserDefaultPropertyNamespace
public final CommunityServiceDescriptor toCommunityServiceDescriptor(Object obj)
{
if (obj instanceof CommunityServiceDescriptor)
return (CommunityServiceDescriptor)obj;
throw new ClassCastException("LibraryVeniceCast.toCommunityServiceDescriptor: invalid cast");
} // end toCommunityServiceDescriptor
public final SideboxDescriptor toSideboxDescriptor(Object obj)
{
if (obj instanceof SideboxDescriptor)

View File

@ -0,0 +1,64 @@
// The contents of this file are subject to the Mozilla Public License Version 1.1
// (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.mozilla.org/MPL/>.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
// WARRANTY OF ANY KIND, either express or implied. See the License for the specific
// language governing rights and limitations under the License.
//
// The Original Code is the Venice Web Communities System.
//
// The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
// for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
// Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
//
// Contributor(s):
importPackage(java.lang);
importClass(Packages.com.silverwrist.dynamo.Namespaces);
importPackage(Packages.com.silverwrist.dynamo.except);
importPackage(Packages.com.silverwrist.dynamo.iface);
importPackage(Packages.com.silverwrist.dynamo.security);
importPackage(Packages.com.silverwrist.dynamo.util);
importClass(Packages.com.silverwrist.venice.VeniceNamespaces);
importPackage(Packages.com.silverwrist.venice.community);
importPackage(Packages.com.silverwrist.venice.content);
importPackage(Packages.com.silverwrist.venice.frame);
importPackage(Packages.com.silverwrist.venice.iface);
req = bsf.lookupBean("request");
req_help = bsf.lookupBean("request_help");
user = vlib.getUser(req);
comm = vlib.getCommunity(req);
// Make sure we are permitted to be here.
acl = comm.getAcl();
if (!(acl.testPermission(user,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"manage.services")))
dynamo.scriptReturn(vlib.stdErrorBox(req,"Security Error",
"You are not permitted to modify this community's services."));
// Get the community service object.
commsvc = vcast.queryCommunityService(rhelp.getRequestObject(Namespaces.DYNAMO_OBJECT_NAMESPACE,"communities"));
// Get the currently-defined list of community services.
svclist = commsvc.getAvailableServices();
// Use that to create a list of which services we have and which services we don't.
mainlist = new ArrayList();
it = svclist.iterator();
while (it.hasNext())
{ // create list entries and add them
csd = vcast.toCommunityServiceDescriptor(it.next());
tmp = new HashMap();
tmp.put("id",cast.toIntegerObject(csd.index));
tmp.put("descr",csd.description);
tmp.put("using",cast.toBooleanObject(comm.isUsingService(csd.name.namespace,csd.name.name)));
mainlist.add(tmp);
} // end while
// Create and return the view.
rc = new VelocityView(comm.name + ": Community Services","comm/admin/services.vm");
rc.setParameter("community",comm);
rc.setParameter("services",mainlist);
dynamo.scriptOutput(rc);

View File

@ -0,0 +1,55 @@
// The contents of this file are subject to the Mozilla Public License Version 1.1
// (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.mozilla.org/MPL/>.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
// WARRANTY OF ANY KIND, either express or implied. See the License for the specific
// language governing rights and limitations under the License.
//
// The Original Code is the Venice Web Communities System.
//
// The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
// for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
// Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
//
// Contributor(s):
importPackage(java.lang);
importClass(Packages.com.silverwrist.dynamo.Namespaces);
importPackage(Packages.com.silverwrist.dynamo.except);
importPackage(Packages.com.silverwrist.dynamo.iface);
importPackage(Packages.com.silverwrist.dynamo.security);
importPackage(Packages.com.silverwrist.dynamo.util);
importClass(Packages.com.silverwrist.venice.VeniceNamespaces);
importPackage(Packages.com.silverwrist.venice.community);
importPackage(Packages.com.silverwrist.venice.content);
importPackage(Packages.com.silverwrist.venice.frame);
importPackage(Packages.com.silverwrist.venice.iface);
req = bsf.lookupBean("request");
req_help = bsf.lookupBean("request_help");
user = vlib.getUser(req);
comm = vlib.getCommunity(req);
// Make sure we are permitted to be here.
acl = comm.getAcl();
if (!(acl.testPermission(user,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"manage.services")))
dynamo.scriptReturn(vlib.stdErrorBox(req,"Security Error",
"You are not permitted to modify this community's services."));
// Get the community service object.
commsvc = vcast.queryCommunityService(rhelp.getRequestObject(Namespaces.DYNAMO_OBJECT_NAMESPACE,"communities"));
// Get the service index.
ndx = req_help.getParameterInt("id",-1);
// Work from there to the service descriptor.
csd = commsvc.getServiceForID(ndx);
if (csd==null)
dynamo.scriptReturn(vlib.stdErrorBox(req,"Internal Error","Service descriptor not found."));
// Now add the service!
comm.addService(user,req,csd.name.namespace,csd.name.name);
// Bounce back to the services list.
dynamo.scriptOutput(new Redirect("SERVLET","comm/admin/services.js.vs"));

View File

@ -0,0 +1,70 @@
// The contents of this file are subject to the Mozilla Public License Version 1.1
// (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.mozilla.org/MPL/>.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
// WARRANTY OF ANY KIND, either express or implied. See the License for the specific
// language governing rights and limitations under the License.
//
// The Original Code is the Venice Web Communities System.
//
// The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
// for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
// Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
//
// Contributor(s):
importPackage(java.lang);
importClass(Packages.com.silverwrist.dynamo.Namespaces);
importPackage(Packages.com.silverwrist.dynamo.except);
importPackage(Packages.com.silverwrist.dynamo.iface);
importPackage(Packages.com.silverwrist.dynamo.security);
importPackage(Packages.com.silverwrist.dynamo.util);
importClass(Packages.com.silverwrist.venice.VeniceNamespaces);
importPackage(Packages.com.silverwrist.venice.community);
importPackage(Packages.com.silverwrist.venice.content);
importPackage(Packages.com.silverwrist.venice.frame);
importPackage(Packages.com.silverwrist.venice.iface);
req = bsf.lookupBean("request");
req_help = bsf.lookupBean("request_help");
user = vlib.getUser(req);
comm = vlib.getCommunity(req);
// Make sure we are permitted to be here.
acl = comm.getAcl();
if (!(acl.testPermission(user,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"manage.services")))
dynamo.scriptReturn(vlib.stdErrorBox(req,"Security Error",
"You are not permitted to modify this community's services."));
// Get the community service object.
commsvc = vcast.queryCommunityService(rhelp.getRequestObject(Namespaces.DYNAMO_OBJECT_NAMESPACE,"communities"));
// Get the service index.
ndx = req_help.getParameterInt("id",-1);
// Work from there to the service descriptor.
csd = commsvc.getServiceForID(ndx);
if (csd==null)
dynamo.scriptReturn(vlib.stdErrorBox(req,"Internal Error","Service descriptor not found."));
rc = null;
if (vlib.confirmed(req,"/comm/admin/svc_remove.js.vs","confirmation","confnum"))
{ // remove the service!
comm.removeService(user,req,csd.name.namespace,csd.name.name);
rc = new Redirect("SERVLET","comm/admin/services.js.vs");
} // end if
else
{ // create the confirmation dialog
msg = "You are about to remove the service " + csd.name.namespace + "::" + csd.name.name + " from the community '"
+ comm.name + "'! This may cause any and all data associated with this service in the community (such as "
+ "database table contents) to be <b>DESTROYED AND IRREVOCABLY LOST!</b> Are you <em>really</em> sure you "
+ "want to do this?";
rc = new ConfirmBox(req,"/comm/admin/svc_remove.js.vs","confirmation","confnum","Service Remove Confirmation",msg,
"SERVLET","comm/admin/svc_remove.js.vs?cc=" + comm.getCID() + "&id=" + ndx,"SERVLET",
"comm/admin/services.js.vs");
} // end else
dynamo.scriptOutput(rc);

View File

@ -0,0 +1,63 @@
#*
The contents of this file are subject to the Mozilla Public License Version 1.1
(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.mozilla.org/MPL/>.
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
WARRANTY OF ANY KIND, either express or implied. See the License for the specific
language governing rights and limitations under the License.
The Original Code is the Venice Web Communities System.
The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
Contributor(s):
*#
#*
Parameters:
community = Community we're displaying the services of.
services = List of all available services, with an indication as to whether we're using them.
*#
#header2( "Community Services", $community.Name )
<p><a href="#formatURL( "SERVLET" "comm/admin/main.js.vs" )">Return to Previous Menu</a></p>
#if( $services.isEmpty() )
<p><em>There are no community-level services currently defined.</em></p>
#else
<p>Your community may make use of any or all of the following services. Click the appropriate buttons to
add or remove services for your community.</p>
<div align="center"><table border="1" cellpadding="2" cellspacing="0">
<tr>
<th><b>In Use?</b></th>
<th><b>Service Description</b></th>
<th>&nbsp;</th>
</tr>
#set( $cid = $community.getCID() )
#foreach( $s in $services )
<tr>
<td>
#if( $s.using )
<b>Yes</b>
#else
&nbsp;
#end
</td>
<td>
#if( $s.using )
<b>#encodeHTML( $s.descr )</b>
#else
#encodeHTML( $s.descr )
#end
</td>
<td>
#if( $s.using )
<a href="#formatURL( "SERVLET" "comm/admin/svc_remove.js.vs?cc=$cid&id=$s.id" )">#button( "IMAGE" "remove" )</a>
#else
<a href="#formatURL( "SERVLET" "comm/admin/svc_add.js.vs?cc=$cid&id=$s.id" )">#button( "IMAGE" "add" )</a>
#end
</td>
</tr>
#end
</table></div>
#end