[Zope3-checkins] CVS: Zope3/src/zope/app/browser/services/registration - __init__.py:1.1.2.1 changeregistrations.pt:1.1.2.1 configure.zcml:1.1.2.1 editregistration.pt:1.1.2.1 namecomponentregistry.pt:1.1.2.1 nameregistry.pt:1.1.2.1 registered.pt:1.1.2.1
Grégoire Weber
zope@i-con.ch
Sun, 22 Jun 2003 10:22:46 -0400
Update of /cvs-repository/Zope3/src/zope/app/browser/services/registration
In directory cvs.zope.org:/tmp/cvs-serv24874/src/zope/app/browser/services/registration
Added Files:
Tag: cw-mail-branch
__init__.py changeregistrations.pt configure.zcml
editregistration.pt namecomponentregistry.pt nameregistry.pt
registered.pt
Log Message:
Synced up with HEAD
=== Added File Zope3/src/zope/app/browser/services/registration/__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 registry-related views
$Id: __init__.py,v 1.1.2.1 2003/06/22 14:22:45 gregweb 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.registration import RegisteredStatus
from zope.app.interfaces.services.registration import ActiveStatus
from zope.app.interfaces.services.registration import IComponentRegistration
from zope.app.interfaces.services.registration import UnregisteredStatus
from zope.app.interfaces.services.registration import IRegistered
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.traversing import getPath, getName, traverse
from zope.component import getView, getServiceManager, getAdapter
from zope.context import getWrapperContainer
from zope.app.context import ContextWrapper
from zope.proxy import removeAllProxies
from zope.publisher.browser import BrowserView
from zope.interface import implements
class NameRegistryView(BrowserView):
indexMacros = index = ViewPageTemplateFile('nameregistry.pt')
def update(self):
names = list(self.context.listRegistrationNames())
names.sort()
items = []
for name in names:
registry = self.context.queryRegistrations(name)
view = getView(registry, "ChangeRegistrations", 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 NameComponentRegistryView(NameRegistryView):
indexMacros = index = ViewPageTemplateFile('namecomponentregistry.pt')
def _getItem(self, name, view, cfg):
item_dict = NameRegistryView._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 NameRegistered:
def __init__(self, context, request):
self.context = context
self.request = request
def uses(self):
component = self.context
useconfig = getAdapter(component, IRegistered)
result = []
for path in useconfig.usages():
config = traverse(component, path)
description = None
summaryMethod = getattr(config, "usageSummary", None)
if summaryMethod:
description = summaryMethod()
url = getView(config, 'absolute_url', self.request)
# XXX This assumes the registration implements
# INamedComponentRegistration rather than just
# IComponentRegistration. ATM there are no
# counterexamples, so this is a sleeper bug;
# but what to do? Could move the registration
# management up to INamedComponentRegistration,
# or could use path as default for name here.
result.append({'name': config.name,
'path': path,
'url': url(),
'status': config.status,
'description': description or config.name,
})
return result
class ChangeRegistrations(BrowserView):
_prefix = 'registrations'
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['registration'])
message = "Updated"
return message
def update(self):
message = self.applyUpdates()
self.configBase = str(getView(getServiceManager(self.context),
'absolute_url', self.request)
)
registrations = self.context.info()
# This is OK because registrations is just a list of dicts
registrations = removeAllProxies(registrations)
inactive = 1
for info in registrations:
if info['active']:
inactive = None
else:
info['active'] = None
info['summary'] = info['registration'].implementationSummary()
self.inactive = inactive
self.registrations = registrations
self.message = message
class RegistrationStatusWidget(BrowserWidget):
def __call__(self):
checked = self._showData() or UnregisteredStatus
result = [
('<label>'
'<input type="radio" name="%s" value="%s"%s>'
' '
'%s'
'</label>'
% (self.name, v, (v == checked and ' checked' or ''), v)
)
for v in (UnregisteredStatus, RegisteredStatus, ActiveStatus)
]
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
IComponentRegistration, then it just gets its 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 IComponentRegistration.isImplementedBy(context):
# It's a registration object. Just get the corresponding attr
path = getattr(context, field.__name__)
# The path may be relative; then interpret relative to ../..
if not path.startswith("/"):
context = traverse(context, "../..")
component = traverse(context, path)
else:
# It must be a component that is about to be configured.
component = context
# Always use a relative path (just the component name)
path = getName(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 IComponentRegistration.isImplementedBy(context):
# It's a registration object. Just get the corresponding attr
# XXX this code has no unittests !!!
path = getattr(context, field.__name__)
else:
# It must be a component that is about to be configured.
# Always return a relative path (just the component name)
path = getName(context)
return path
def haveData(self):
"See zope.app.interfaces.form.IWidget"
return True
class AddComponentRegistration(BrowserView):
"""View for adding component registrations
This class is used to define registration add forms. It provides
tha ``add`` and ``nextURL`` methods needed when creating add forms
for non IAdding object. We need this here because registration
add forms are views of the component being configured.
"""
def add(self, registration):
"""Add a registration
We are going to add the registration to the local
registration manager. We don't want to hard code the name of
this, so we'll simply scan the containing folder and add the
registration to the first registration manager we find.
"""
component = self.context
# Get the registration manager for this folder
folder = getWrapperContainer(component)
configure = folder.getRegistrationManager()
# 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("", registration)
# and return the config in context by fetching it from the container
return container[key]
def nextURL(self):
return "@@SelectedManagementView.html"
class RegistrationAdding(Adding):
"""Adding subclass for adding registrations."""
menu_id = "add_registration"
def nextURL(self):
return str(getView(self.context, "absolute_url", self.request))
class EditRegistration(BrowserView):
"""A view on a registration manager, used by registrations.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 == ActiveStatus
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/registration/changeregistrations.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="registration view/registrations">
<td><input type="radio" name="Roles" value="0"
tal:attributes="
name view/name;
value registration/id;
checked registration/active;
"
/>
</td>
<td><a href="."
tal:attributes="href string:${view/configBase}/${registration/id}"
tal:content="registration/id"
>foo/bar</a></td>
<td tal:content="structure registration/summary">
Registration 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/registration/configure.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/browser'>
<page
for="zope.app.interfaces.services.registration.IRegistrationStatus"
name="edit"
class=".RegistrationStatusWidget"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
permission="zope.ManageServices"
/>
<page
for="zope.app.interfaces.services.registration.IRegistrationStack"
name="ChangeRegistrations"
template="changeregistrations.pt"
class=".ChangeRegistrations"
allowed_interface="zope.app.interfaces.browser.form.IFormCollaborationView"
permission="zope.ManageServices"
/>
<editform
name="index.html"
schema=
"zope.app.interfaces.services.registration.INamedComponentRegistration."
menu="zmi_views"
label="Edit Registration"
permission="zope.ManageServices"
fields="name componentPath permission status"
/>
<page
name="index.html"
for="zope.app.interfaces.services.registration.INameComponentRegistry"
class=".NameComponentRegistryView"
permission="zope.ManageServices"
attribute="index"
/>
<page
permission="zope.Public"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
for="zope.app.interfaces.services.registration.IComponentPath"
name="edit"
class=".ComponentPathWidget"
/>
<page
permission="zope.Public"
allowed_interface="zope.app.interfaces.browser.form.IBrowserWidget"
for="zope.app.interfaces.services.registration.IComponentPath"
name="display"
class=".ComponentPathWidget"
/>
<!-- RegistrationManager -->
<page
name="index.html"
for="zope.app.interfaces.services.registration.IRegistrationManager"
menu="zmi_views" title="Registration"
permission="zope.ManageServices"
class=".EditRegistration"
template="editregistration.pt"
/>
<!-- For now, we'll allow CMs to be added, but we won't include them
in the add_component menu. -->
<view
for="zope.app.interfaces.services.registration.IRegistrationManager"
name="+"
menu="zmi_actions" title="Add"
permission="zope.ManageServices"
class=".RegistrationAdding">
<page name="index.html" attribute="index" />
<page name="action.html" attribute="action" />
</view>
<!-- Error views -->
<page
for="
zope.app.interfaces.services.registration.INoRegistrationManagerError"
name="index.html"
permission="zope.Public"
template="../../exception/user.pt"
class="zope.app.browser.exception.user.UserErrorView"
/>
<page
for="zope.app.interfaces.services.registration.INoLocalServiceError"
name="index.html"
permission="zope.Public"
template="../../exception/user.pt"
class="zope.app.browser.exception.user.UserErrorView"
/>
</zopeConfigure>
=== Added File Zope3/src/zope/app/browser/services/registration/editregistration.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
<title>View Registration Manager</title>
</head>
<body metal:fill-slot="body">
<h2>Registration 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/registration/namecomponentregistry.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">Registered fruits in this fruits manager.</h2>
<div tal:condition="not:registries">
<p metal:define-slot="empty_text">No fruits have been registered</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/registration/nameregistry.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">Registered fruits in this fruits manager.</h2>
<div tal:condition="not:registries">
<p metal:define-slot="empty_text">No fruits have been registered</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 register 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 registration that registers 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/registration/registered.pt ===
<html metal:use-macro="context/@@standard_macros/page">
<body>
<div metal:fill-slot="body">
<p>Registrations for this object:</p>
<ul>
<li tal:repeat="use view/uses">
<a href="http://."
tal:attributes="href use/url"
tal:content="use/description">Description</a>
(<span tal:replace="use/status">Active</span>)
</li>
</ul>
<p><a href="addRegistration.html">Add a registration for this object</a>
</div>
</body>
</html>