[Zope3-checkins] CVS: Zope3/src/zope/app/browser/services/configuration - __init__.py:1.1 changeconfigurations.pt:1.1 configure.zcml:1.1 editconfiguration.pt:1.1 namecomponentconfigurable.pt:1.1 nameconfigurable.pt:1.1 useconfiguration.pt:1.1
Jim Fulton
jim@zope.com
Fri, 21 Mar 2003 16:09:35 -0500
Update of /cvs-repository/Zope3/src/zope/app/browser/services/configuration
In directory cvs.zope.org:/tmp/cvs-serv20505/src/zope/app/browser/services/configuration
Added Files:
__init__.py changeconfigurations.pt configure.zcml
editconfiguration.pt namecomponentconfigurable.pt
nameconfigurable.pt useconfiguration.pt
Log Message:
Refactored the module layout for general configuration views.
Moved the implementation into a separate configuration package.
=== Added File Zope3/src/zope/app/browser/services/configuration/__init__.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Gewneral configuration-related views
$Id: __init__.py,v 1.1 2003/03/21 21:09:33 jim Exp $
"""
from zope.app.browser.container.adding import Adding
from zope.app.browser.form.widget import BrowserWidget
from zope.app.interfaces.browser.form import IBrowserWidget
from zope.app.interfaces.container import IZopeContainer
from zope.app.interfaces.services.configuration import Active, Registered
from zope.app.interfaces.services.configuration import IComponentConfiguration
from zope.app.interfaces.services.configuration import Unregistered
from zope.app.interfaces.services.configuration import IConfigurationManager
from zope.app.interfaces.services.configuration import IUseConfiguration
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.traversing import getPath, traverse
from zope.component import getView, getServiceManager, getAdapter
from zope.proxy.context import getWrapperContainer, ContextWrapper
from zope.proxy.introspection import removeAllProxies
from zope.publisher.browser import BrowserView
class NameConfigurableView(BrowserView):
indexMacros = index = ViewPageTemplateFile('nameconfigurable.pt')
def update(self):
names = list(self.context.listConfigurationNames())
names.sort()
items = []
for name in names:
registry = self.context.queryConfigurations(name)
view = getView(registry, "ChangeConfigurations", self.request)
view.setPrefix(name)
view.update()
cfg = registry.active()
active = cfg is not None
items.append(self._getItem(name, view, cfg))
return items
def _getItem(self, name, view, cfg):
# hook for subclasses. returns a dict to append to an item
return {"name": name,
"active": cfg is not None,
"inactive": cfg is None,
"view": view,
}
class NameComponentConfigurableView(NameConfigurableView):
indexMacros = index = ViewPageTemplateFile('namecomponentconfigurable.pt')
def _getItem(self, name, view, cfg):
item_dict = NameConfigurableView._getItem(self, name, view, cfg)
if cfg is not None:
ob = traverse(cfg, cfg.componentPath)
url = str(getView(ob, 'absolute_url', self.request))
else:
url = None
item_dict['url'] = url
return item_dict
class NameUseConfiguration:
def __init__(self, context, request):
self.context = context
self.request = request
def uses(self):
component = self.context
useconfig = getAdapter(component, IUseConfiguration)
result = []
for path in useconfig.usages():
config = traverse(component, path)
url = getView(config, 'absolute_url', self.request)
result.append({'name': config.name,
'path': path,
'url': url(),
'status': config.status,
})
return result
class ChangeConfigurations(BrowserView):
_prefix = 'configurations'
name = _prefix + ".active"
message = ''
configBase = ''
def setPrefix(self, prefix):
self._prefix = prefix
self.name = prefix + ".active"
def applyUpdates(self):
message = ''
if 'submit_update' in self.request.form:
active = self.request.form.get(self.name)
if active == "disable":
active = self.context.active()
if active is not None:
self.context.deactivate(active)
message = "Disabled"
else:
for info in self.context.info():
if info['id'] == active:
if not info['active']:
self.context.activate(info['configuration'])
message = "Updated"
return message
def update(self):
message = self.applyUpdates()
self.configBase = str(getView(getServiceManager(self.context),
'absolute_url', self.request)
)
configurations = self.context.info()
# This is OK because configurations is just a list of dicts
configurations = removeAllProxies(configurations)
inactive = 1
for info in configurations:
if info['active']:
inactive = None
else:
info['active'] = None
info['summary'] = info['configuration'].implementationSummary()
self.inactive = inactive
self.configurations = configurations
self.message = message
class ConfigurationStatusWidget(BrowserWidget):
def __call__(self):
checked = self._showData() or Unregistered
result = [
('<label>'
'<input type="radio" name="%s" value="%s"%s>'
' '
'%s'
'</label>'
% (self.name, v, (v == checked and ' checked' or ''), v)
)
for v in (Unregistered, Registered, Active)
]
return ' '.join(result)
class ComponentPathWidget(BrowserWidget):
"""Widget for displaying component paths
The widget doesn't actually allow editing. Rather it gets the
value by inspecting its field's context. If the context is an
IComponentConfiguration, then it just gets it's value from the
component using the field's name. Otherwise, it uses the path to
the context.
"""
__implements__ = IBrowserWidget
def __call__(self):
"See zope.app.interfaces.browser.form.IBrowserWidget"
# Render as a link to the component
field = self.context
context = field.context
if IComponentConfiguration.isImplementedBy(context):
# It's a configuration object. Just get the corresponsing attr
path = getattr(context, field.__name__)
component = traverse(context, path)
else:
# It must be a component that is about to be configured.
component = context
path = getPath(context)
url = getView(component, 'absolute_url', self.request)
return ('<a href="%s/@@SelectedManagementView.html">%s</a>'
% (url, path))
def hidden(self):
"See zope.app.interfaces.browser.form.IBrowserWidget"
return ''
def getData(self):
"See zope.app.interfaces.form.IWidget"
field = self.context
context = field.context
if IComponentConfiguration.isImplementedBy(context):
# It's a configuration object. Just get the corresponsing attr
path = getattr(context, self.__name__)
else:
# It must be a component that is about to be configured.
path = getPath(context)
return path
def haveData(self):
"See zope.app.interfaces.form.IWidget"
return True
class AddComponentConfiguration(BrowserView):
"""View for adding component configurations
This class is used to define configuration add forms. It provides
tha ``add`` and ``nextURL`` methods needed when creating add forms
for non IAdding object. We need this here because configuration
add forms are views of the component being configured.
"""
def add(self, configuration):
"""Add a configuration
We are going to add the configuration to the local
configuration manager. We don't want to hard code the name of
this, so we'll simply scan the containing folder and add the
configuration to the first configuration manager we find.
"""
component = self.context
# Get the configuration manager for this folder
folder = getWrapperContainer(component)
for name in folder:
item = folder[name]
if IConfigurationManager.isImplementedBy(item):
# We found one. Get it in context
configure = traverse(folder, name)
break
else:
raise SystemError("Couldn't find an configuration manager")
# Adapt to IZopeContainer, which takes care of generating
# standard events and calling standard hooks
container = getAdapter(configure, IZopeContainer)
# Now add the item, saving the key, which is picked by the config
key = container.setObject("", configuration)
# and return the config in context by fetching it from the container
return container[key]
def nextURL(self):
return "@@useConfiguration.html"
class ConfigurationAdding(Adding):
"""Adding subclass for adding configurations."""
menu_id = "add_configuration"
def nextURL(self):
return str(getView(self.context, "absolute_url", self.request))
class EditConfiguration(BrowserView):
"""A view on a configuration manager, used by configurations.pt."""
def __init__(self, context, request):
self.request = request
self.context = context
def update(self):
"""Perform actions depending on user input."""
if 'keys' in self.request:
k = self.request['keys']
else:
k = []
msg = 'You must select at least one item to use this action'
if 'remove_submit' in self.request:
if not k: return msg
self.remove_objects(k)
elif 'top_submit' in self.request:
if not k: return msg
self.context.moveTop(k)
elif 'bottom_submit' in self.request:
if not k: return msg
self.context.moveBottom(k)
elif 'up_submit' in self.request:
if not k: return msg
self.context.moveUp(k)
elif 'down_submit' in self.request:
if not k: return msg
self.context.moveDown(k)
elif 'refresh_submit' in self.request:
pass # Nothing to do
return ''
def remove_objects(self, key_list):
"""Remove the directives from the container."""
container = getAdapter(self.context, IZopeContainer)
for item in key_list:
del container[item]
def configInfo(self):
"""Render View for each directives."""
result = []
for name, configobj in self.context.items():
configobj = ContextWrapper(configobj, self.context, name=name)
url = str(getView(configobj, 'absolute_url', self.request))
active = configobj.status == Active
summary1 = getattr(configobj, "usageSummary", None)
summary2 = getattr(configobj, "implementationSummary", None)
item = {'name': name, 'url': url, 'active': active}
if summary1:
item['line1'] = summary1()
if summary2:
item['line2'] = summary2()
result.append(item)
return result
=== Added File Zope3/src/zope/app/browser/services/configuration/changeconfigurations.pt ===
<table width="100%">
<tr tal:define="message view/message" tal:condition="message">
<td></td>
<td colspan="2"><em tal:content="message">xxxx</em></td>
</tr>
<tr tal:repeat="configuration view/configurations">
<td><input type="radio" name="Roles" value="0"
tal:attributes="
name view/name;
value configuration/id;
checked configuration/active;
"
/>
</td>
<td><a href="."
tal:attributes="href string:${view/configBase}/${configuration/id}"
tal:content="configuration/id"
>foo/bar</a></td>
<td tal:content="structure configuration/summary">
Configuration summary
</td>
</tr>
<tr>
<td><input type="radio" name="Roles" value="disable"
tal:attributes="
name view/name;
checked view/inactive;
"
/></td>
<td><em>Disable</em></td>
</tr>
</table>
=== Added File Zope3/src/zope/app/browser/services/configuration/configure.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/browser'>
<page
for="zope.app.interfaces.services.configuration.IConfigurationStatus"
name="edit"
class=".ConfigurationStatusWidget"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
permission="zope.ManageServices"
/>
<page
for="zope.app.interfaces.services.configuration.IConfigurationRegistry"
name="ChangeConfigurations"
template="changeconfigurations.pt"
class=".ChangeConfigurations"
allowed_interface="zope.app.interfaces.browser.form.IFormCollaborationView"
permission="zope.ManageServices"
/>
<editform
name="index.html"
schema=
"zope.app.interfaces.services.configuration.INamedComponentConfiguration."
menu="zmi_views"
label="Configuration"
permission="zope.ManageServices"
/>
<page
name="index.html"
for="zope.app.interfaces.services.configuration.INameComponentConfigurable"
class=".NameComponentConfigurableView"
permission="zope.ManageServices"
attribute="index"
/>
<page
permission="zope.Public"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
for="zope.app.interfaces.services.configuration.IComponentPath"
name="edit"
class=".ComponentPathWidget"
/>
<page
permission="zope.Public"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
for="zope.app.interfaces.services.configuration.IComponentPath"
name="display"
class=".ComponentPathWidget"
/>
<!-- ConfigurationManager -->
<page
name="index.html"
for="zope.app.interfaces.services.configuration.IConfigurationManager"
menu="zmi_views" title="Configuration"
permission="zope.ManageServices"
class=".EditConfiguration"
template="editconfiguration.pt"
/>
<view
for="zope.app.interfaces.services.configuration.IConfigurationManager"
name="+"
permission="zope.ManageServices"
class=".ConfigurationAdding">
<page name="index.html" attribute="index" />
<page name="action.html" attribute="action" />
</view>
<menuItem
menu="add_component"
for="zope.app.interfaces.container.IAdding"
action="zope.app.services.ConfigurationManager"
title="Configuration"
/>
</zopeConfigure>
=== Added File Zope3/src/zope/app/browser/services/configuration/editconfiguration.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<title>View Service Configuration</title>
</head>
<body metal:fill-slot="body">
<h2>Configuration Manager</h2>
<form action="." method="POST"
tal:define="message view/update"
tal:attributes="action request/URL">
<p tal:condition="message" tal:content="message" />
<table>
<thead>
<tr>
<th></th>
<th align="left">Summary</th>
</tr>
</thead>
<tbody>
<tr tal:repeat="config view/configInfo">
<td valign="top">
<input type=checkbox name='keys:list' value='1'
tal:attributes="value config/name" />
</td>
<td>
<a href="." tal:attributes="href config/name">
<span tal:content="config/line1|default">
Config item <span tal:content="config/name" />
</span>
</a>
<span tal:condition="not:config/active">(disabled)</span>
<br>
<span tal:content="config/line2|default">
(No implementation summary)
</span>
</td>
</tr>
</tbody>
</table>
<div class="row">
<input type=submit name='refresh_submit' value="Refresh">
<input type=submit name='UPDATE_SUBMIT' value="Submit">
<input type=submit name='remove_submit' value="Remove">
<input type=submit name='top_submit' value="Top">
<input type=submit name='up_submit' value="Up">
<input type=submit name='down_submit' value="Down">
<input type=submit name='bottom_submit' value="Bottom">
</div>
</form>
</body>
</html>
=== Added File Zope3/src/zope/app/browser/services/configuration/namecomponentconfigurable.pt ===
<html metal:use-macro="views/standard_macros/page">
<div metal:fill-slot="body">
<div metal:define-macro="body">
<div tal:define="registries view/update">
<h2 metal:define-slot="heading">Fruits configured in this fruits manager.</h2>
<div tal:condition="not:registries">
<p metal:define-slot="empty_text">No fruits have been configured</p>
</div>
<div tal:condition="registries">
<div metal:define-slot="extra_top" tal:condition="nothing">
<p>For each fruit, the fruit name is given and all of the components
registered to provide the fruit are shown. You may select the
component to provide the fruit or disable the fruit.
</p>
<p>Select a fruit name or a component name to visit the fruit or
component.
</p>
</div>
<form action="." method="post" tal:attributes="action request/URL">
<div tal:repeat="registry registries">
<a href="#"
tal:content="registry/name"
tal:attributes="href registry/url"
tal:condition="registry/active"
>Orange</a>
<span tal:replace="registry/name"
tal:condition="registry/inactive" />
<br>
<span tal:content="structure registry/view" />
</div>
<input type=submit name="submit_update" value="Update"><br>
</form>
<div metal:define-slot="extra_bottom" tal:condition="nothing">
</div>
</div>
</div>
</div>
</div>
</html>
=== Added File Zope3/src/zope/app/browser/services/configuration/nameconfigurable.pt ===
<html metal:use-macro="views/standard_macros/page">
<body metal:fill-slot="body">
<div metal:define-macro="body">
<div tal:define="registries view/update">
<h2 metal:define-slot="heading">Fruits configured in this fruits manager.</h2>
<div tal:condition="not:registries">
<p metal:define-slot="empty_text">No fruits have been configured</p>
</div>
<div tal:condition="registries">
<div metal:define-slot="extra_top">
<p>For each fruit, the fruit name is given and all of the
registrations are shown. You may select the
registration to provide the fruit or disable the fruit.
</p>
</div>
<form action="." method="post" tal:attributes="action request/URL">
<table width="100%">
<tr tal:repeat="registry registries">
<td valign="top" align="right">
<span
tal:content="registry/name"
tal:condition="registry/active"
>Orange</span>
<span tal:replace="registry/name"
tal:condition="registry/inactive" />
</td>
<td tal:content="structure registry/view">
</td>
</tr>
</table>
<input type=submit name="submit_update" value="Update"><br>
</form>
<div metal:define-slot="extra_bottom" />
</div>
<p metal:define-slot="help_text">To configure a fruit, add a fruit component
to a <em>package</em> in <a href="Packages">Packages</a> or to the <a
href="Packages/default">default package</a>. After the fruit is added, add
a fruit configuration that configures the component to provide a fruit.
These instructions may not apply, depending what kind of fruit you have.
</p>
</div>
</div>
</body>
</html>
=== Added File Zope3/src/zope/app/browser/services/configuration/useconfiguration.pt ===
<html metal:use-macro="context/@@standard_macros/page">
<body>
<div metal:fill-slot="body">
<p>Configurations for this object:</p>
<ul>
<li tal:repeat="use view/uses">
<a href="http://."
tal:attributes="href use/url"
tal:content="use/name">
Example Service
</a> (<span tal:replace="use/status">Active</span>)
</li>
</ul>
<p><a href="addConfiguration.html">Add a configuration for this object</a>
</div>
</body>
</html>