[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Onlinehelp fix.
Eckart Hertzler
eckart at hertzler.de
Mon May 24 09:59:11 EDT 2004
Log message for revision 24924:
Onlinehelp fix.
Context help for interfaces and view work.
While traversing to the ++help++ namespace the onlinehelp instance
gets the context of the ++help++ namespace.
This is used in the view to extract the correct help topic.
Changed the way the help topics box is generated. It now
uses a recursivly called page template for rendering the
links.
added a simple macro to the rotterdam skin, that is
used by the online help.
Added a functional test for the contex help
-=-
Modified: Zope3/trunk/src/zope/app/onlinehelp/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/__init__.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/__init__.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -21,6 +21,7 @@
import os
import zope.app
+from zope.app import zapi
from zope.app.container.sample import SampleContainer
from zope.app.traversing.interfaces import IContainmentRoot
from zope.app.traversing import traverse
@@ -33,22 +34,14 @@
implements(IOnlineHelpTopic)
+ title = u""
+
def __init__(self, title, path, doc_type='txt'):
"""Initialize object."""
self.title = title
self.setContentPath(path, doc_type)
super(OnlineHelpTopic, self).__init__()
- def setTitle(self, title):
- "See Zope.App.OnlineHelp.interfaces.IOnlineHelpTopic"
- self._title = title
-
- def getTitle(self):
- "See Zope.App.OnlineHelp.interfaces.IOnlineHelpTopic"
- return self._title
-
- title = property(getTitle, setTitle, None)
-
def setContentPath(self, path, doc_type='txt'):
"See Zope.App.OnlineHelp.interfaces.IOnlineHelpTopic"
self._content_path = path
@@ -91,11 +84,11 @@
parent[id] = OnlineHelpTopic(title, doc_path, doc_type)
topic = parent[id]
# Add topic to registry
- if not self._registry.has_key((interface, view)):
- self._registry[(interface, view)] = []
- self._registry[(interface, view)].append(topic)
+ if interface is not None:
+ if not self._registry.has_key((interface, view)):
+ self._registry[(interface, view)] = []
+ self._registry[(interface, view)].append(topic)
-
# Global Online Help
path = os.path.join(os.path.dirname(zope.app.__file__),
'onlinehelp', 'welcome.txt')
Modified: Zope3/trunk/src/zope/app/onlinehelp/browser/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/__init__.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/__init__.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -15,63 +15,101 @@
$Id$
"""
+from zope.proxy import removeAllProxies
from zope.interface import providedBy
+from zope.app.publisher.interfaces.browser import IBrowserView
+from zope.app import zapi
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+from zope.app.onlinehelp.interfaces import IOnlineHelpTopic
-from zope.component import getService, getView
-from zope.app.publisher.browser import BrowserView
-from zope.app.traversing import getRoot
-from zope.app.traversing import getParents, getName
-
-class OnlineHelpTopicView(BrowserView):
+class OnlineHelpTopicView(object):
"""View for one particular help topic."""
- def _makeSubTree(self, topic):
- html = '<ul>\n'
- for entry in topic.items():
- html += ' <li><a href="%s">%s</a></li>\n' %(
- getView(entry, 'absolute_url', self.request)(),
- entry.getTitle())
- html += self._makeSubTree(entry)
- html += '</ul>\n'
- return html
+ def __init__(self, context, request, base_url=''):
+ self.context = context
+ self.request = request
+ self.base_url = base_url
+ self.onlinehelp = removeAllProxies(zapi.getRoot(self.context))
+ if base_url == '':
+ self.base_url = zapi.getPath(self.onlinehelp.context)+"/++help++"
def getTopicTree(self):
- onlinehelp = getRoot(self.context)
- return self._makeSubTree(onlinehelp)
+ """ return the tree of help topics."""
+ self.context = zapi.getRoot(self.context)
+ return self.subtopics()
-# XXX The view below is highly qeustionable on many levels.
-# - It uses the global view service (now refactored to presentation service
-# - It's very expensive.
-# Perhaps we'll resurrect this later when we have time to do it bit better.
+ def getContextHelpTopic(self):
+ """ Retrieve a help topic based on the context of the
+ help namespace.
-## class FindRelevantHelpTopics(BrowserView):
-## """This object is used as a view on a view, so that we can get all the
-## required information."""
+ If the context is a view, try to find
+ a matching help topic for the view and its context.
+ If not help topic is found, try got get a help topic for
+ and interface only.
-## def __call__(self):
+ If the context is not a view, try to retrieve a help topic
+ for an interface only.
-## class FindResult:
-## def __init__(self, url, topic):
-## self.url = url
-## self.topic = topic
+ If nothing is found, return the onlinehelp root topic
-## view_class = self.context.__class__
-## obj = self.context.context
-## help = getService(obj, 'OnlineHelp')
-## ifaces = providedBy(obj).flattened()
-## topics = []
-## for iface in ifaces:
-## specs = viewService.getRegisteredMatching((iface,),
-## IBrowserRequest)
-## for spec in specs:
-## if spec[2][0] is not view_class:
-## continue
-## for topic in help.getTopicsForInterfaceAndView(iface, spec[4]):
-## parents = getParents(topic)
-## path = map(getName, [topic]+parents[:-1])
-## path.reverse()
-## url = getView(obj, 'absolute_url', self.request)()
-## url += '/++help++/++skin++Onlinehelp/'+'/'.join(path)
-## topics.append(FindResult(url, topic))
-
-## return topics
+ """
+ help_context = self.onlinehelp.context
+ topic = self.context
+ if IBrowserView.providedBy(help_context):
+ # called from a view
+ for iface in providedBy(zapi.getParent(help_context)):
+ # try for interface and view match
+ topics = self.onlinehelp.getTopicsForInterfaceAndView(
+ iface,
+ zapi.getName(help_context)
+ )
+ if len(topics)>0:
+ topic = topics[0]
+ break
+ if topic == self.context:
+ # nothing found for view try iface only
+ for iface in providedBy(zapi.getParent(help_context)):
+ topics = self.onlinehelp.getTopicsForInterfaceAndView(
+ iface,
+ None
+ )
+ if len(topics)>0:
+ topic = topics[0]
+ break
+ else:
+ # called without view
+ for iface in providedBy(help_context):
+ topics = self.onlinehelp.getTopicsForInterfaceAndView(
+ iface,
+ None
+ )
+ if len(topics)>0:
+ topic = topics[0]
+ break
+
+ # XXX returns only the first of the matching topics.
+ # The page template only processes one topic
+ return topic
+
+ def listHelpItems(self):
+ """ recurse through the help topic tree"""
+ #
+ children=[]
+ for name, helpitem in self.context.items():
+ info={}
+ info['title'] = helpitem.title
+ info['path'] = self.base_url+'/'+name
+ topic = OnlineHelpTopicView(
+ helpitem,
+ self.request,
+ self.base_url+'/'+name)
+
+ info['topics']=topic.subtopics()
+ children.append(info)
+
+ return children
+
+ subtopics = ViewPageTemplateFile('topiclink.pt')
+
+
+
Modified: Zope3/trunk/src/zope/app/onlinehelp/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/configure.zcml 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/configure.zcml 2004-05-24 13:59:08 UTC (rev 24924)
@@ -9,16 +9,6 @@
title="Menu for displaying help actions to be performed with popup"
/>
-<!--
- <page
- name="find_help_topics"
- for="*"
- class=".FindRelevantHelpTopics"
- permission="zope.Public"
- allowed_attributes="__call__" />
-
--->
-
<pages
for="zope.app.onlinehelp.interfaces.IOnlineHelpTopic"
permission="zope.Public"
@@ -26,6 +16,7 @@
>
<page name="index.html" template="helptopic.pt" />
+ <page name="contexthelp.html" template="contexthelp.pt" />
<page name="getTopicTree" attribute="getTopicTree" />
</pages>
@@ -35,7 +26,7 @@
filter="python:request.getURL().find('++help++')==-1"
menu="help_actions"
title="Help"
- action="++help++/@@index.html"
+ action="++help++/@@contexthelp.html"
/>
</zope:configure>
Added: Zope3/trunk/src/zope/app/onlinehelp/browser/contexthelp.pt
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/contexthelp.pt 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/contexthelp.pt 2004-05-24 13:59:08 UTC (rev 24924)
@@ -0,0 +1,36 @@
+<html metal:use-macro="views/popup_macros/page">
+<head>
+ <title metal:fill-slot="title"
+ tal:content="view/getContextHelpTopic/title"
+ i18n:translate="">Title</title>
+</head>
+<body>
+
+<div metal:fill-slot="left_slot">
+ <div class="box" id="help">
+ <h4 i18n:translate="">Online Help - TOC</h4>
+ <div class="body">
+ <div tal:content="structure view/getTopicTree|nothing"
+ tal:omit-tag="">content of topicTree</div>
+ <br />
+ </div>
+ </div>
+</div>
+
+<div metal:fill-slot="body">
+
+ <div tal:define="topic view/getContextHelpTopic">
+
+ <h1 tal:content="topic/title"
+ i18n:translate="">Title of Help Topic</h1>
+
+ <p tal:content="structure topic/getContent"
+ i18n:translate="">Content of Online Help.</p>
+
+ </div>
+
+</div>
+
+</body>
+</html>
+
Property changes on: Zope3/trunk/src/zope/app/onlinehelp/browser/contexthelp.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Zope3/trunk/src/zope/app/onlinehelp/browser/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/ftests.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/ftests.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -0,0 +1,93 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""Functional Tests for Onlinehelp
+
+$Id$
+"""
+import os
+import unittest
+import re
+
+from zope.app.folder.interfaces import IRootFolder
+from zope.app.file import File
+from zope.app.tests.functional import BrowserTestCase
+from zope.app.onlinehelp.tests.test_onlinehelptopic import testdir
+from zope.app.onlinehelp import help
+
+class Test(BrowserTestCase):
+
+ def test_contexthelp(self):
+ path = os.path.join(testdir(), 'help.txt')
+ help.registerHelpTopic('ui','help','Help',path, 'txt',
+ IRootFolder,
+ None)
+ path = os.path.join(testdir(), 'help2.txt')
+ help.registerHelpTopic('ui','help2','Help2',path, 'txt',
+ IRootFolder,
+ 'contents.html')
+ root = self.getRootFolder()
+ root['file']=File()
+
+ response = self.publish(
+ '/contents.html',
+ basic='mgr:mgrpw')
+
+ self.assertEqual(response.getStatus(), 200)
+ body = ' '.join(response.getBody().split())
+ self.assert_(body.find(
+ "javascript:popup('contents.html/++help++/@@contexthelp.html") >= 0)
+
+ response = self.publish(
+ '/contents.html/++help++/@@contexthelp.html',
+ basic='mgr:mgrpw')
+
+ self.assertEqual(response.getStatus(), 200)
+ body = ' '.join(response.getBody().split())
+ self.assert_(body.find("This is another help!") >= 0)
+
+ response = self.publish(
+ '/index.html/++help++/@@contexthelp.html',
+ basic='mgr:mgrpw')
+
+ self.assertEqual(response.getStatus(), 200)
+ body = ' '.join(response.getBody().split())
+ self.assert_(body.find("This is a help!") >= 0)
+
+ response = self.publish(
+ '/file/edit.html/++help++/@@contexthelp.html',
+ basic='mgr:mgrpw')
+
+ self.assertEqual(response.getStatus(), 200)
+ body = ' '.join(response.getBody().split())
+ self.assert_(body.find(
+ "Welcome to the Zope 3 Online Help System.") >= 0)
+
+ path = '/contents.html/++help++'
+ response = self.publish(
+ path,
+ basic='mgr:mgrpw')
+
+ self.assertEqual(response.getStatus(), 200)
+ body = ' '.join(response.getBody().split())
+ self.assert_(body.find(
+ "Online Help - TOC") >= 0)
+
+ self.checkForBrokenLinks(body, path, basic='mgr:mgrpw')
+
+
+def test_suite():
+ return unittest.makeSuite(Test)
+
+if __name__ == '__main__':
+ unittest.main()
Property changes on: Zope3/trunk/src/zope/app/onlinehelp/browser/ftests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/onlinehelp/browser/helptopic.pt
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/helptopic.pt 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/helptopic.pt 2004-05-24 13:59:08 UTC (rev 24924)
@@ -1,12 +1,26 @@
-<html metal:use-macro="views/standard_macros/page">
+<html metal:use-macro="views/popup_macros/page">
<head>
- <title metal:fill-slot="title" tal:content="context/getTitle"
+ <title metal:fill-slot="title"
+ tal:content="context/title"
i18n:translate="">Title</title>
</head>
<body>
+
+<div metal:fill-slot="left_slot">
+ <div class="box" id="help">
+ <h4 i18n:translate="">Online Help - TOC</h4>
+ <div class="body">
+ <div tal:content="structure view/getTopicTree|nothing"
+ tal:omit-tag="">content of topicTree</div>
+ <br />
+ </div>
+ </div>
+</div>
+
<div metal:fill-slot="body">
- <h1 tal:content="context/getTitle"
+
+ <h1 tal:content="context/title"
i18n:translate="">Title of Help Topic</h1>
<p tal:content="structure context/getContent"
@@ -17,3 +31,4 @@
</body>
</html>
+
Added: Zope3/trunk/src/zope/app/onlinehelp/browser/topiclink.pt
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/topiclink.pt 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/topiclink.pt 2004-05-24 13:59:08 UTC (rev 24924)
@@ -0,0 +1,9 @@
+<ul>
+ <li tal:repeat="item view/listHelpItems">
+ <a href=""
+ tal:attributes="href item/path"
+ tal:content="item/title"
+ i18n:translate="">Title</a>
+ <div tal:replace="structure item/topics" />
+ </li>
+</ul>
Property changes on: Zope3/trunk/src/zope/app/onlinehelp/browser/topiclink.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/onlinehelp/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/interfaces.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/interfaces.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -17,6 +17,7 @@
$Id$
"""
+from zope.schema import TextLine
from zope.app.container.interfaces import IContainer
@@ -35,11 +36,11 @@
interface.
"""
- def setTitle(title):
- """Set the title of the Topic."""
-
- def getTitle():
- """Get the title of the Topic."""
+ title = TextLine(
+ title = u"Help Topic Title",
+ description = u"The Title of a Help Topic",
+ default = u"Help Topic",
+ required = True)
def setContentPath(filename, doc_type="stx"):
"""Tell the Topic where it can find"""
Modified: Zope3/trunk/src/zope/app/onlinehelp/tests/test_onlinehelptopic.py
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/tests/test_onlinehelptopic.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/onlinehelp/tests/test_onlinehelptopic.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -31,13 +31,10 @@
self.topic = OnlineHelpTopic('Help', path, 'txt')
def test_title(self):
- self.assertEqual(self.topic.getTitle(), 'Help')
self.assertEqual(self.topic.title, 'Help')
- self.topic.setTitle('Help1')
- self.assertEqual(self.topic.getTitle(), 'Help1')
+ self.topic.title = 'Help1'
self.assertEqual(self.topic.title, 'Help1')
self.topic.title = 'Help2'
- self.assertEqual(self.topic.getTitle(), 'Help2')
self.assertEqual(self.topic.title, 'Help2')
def test_content(self):
Modified: Zope3/trunk/src/zope/app/rotterdam/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/configure.zcml 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/rotterdam/configure.zcml 2004-05-24 13:59:08 UTC (rev 24924)
@@ -90,6 +90,14 @@
template="navigation_macros.pt"
/>
+ <browser:page
+ for="*"
+ name="popup_macros"
+ permission="zope.View"
+ layer="rotterdam"
+ template="popup_macros.pt"
+ />
+
<view
type="zope.publisher.interfaces.browser.IBrowserRequest"
for="zope.schema.interfaces.ISourceText"
Added: Zope3/trunk/src/zope/app/rotterdam/popup_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/popup_macros.pt 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/rotterdam/popup_macros.pt 2004-05-24 13:59:08 UTC (rev 24924)
@@ -0,0 +1,83 @@
+<metal:block define-macro="page"><metal:block define-slot="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></metal:block>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xml:lang="en"
+ lang="en"
+ i18n:domain="zope"
+ tal:define="sitemgmt python:'/++etc++site/' in str(request.URL)">
+
+ <head>
+ <title metal:define-slot="title"
+ tal:content="string:Z3: ${context/zope:title_or_name}">Z3 UI</title>
+
+ <style type="text/css" media="all"
+ tal:content="string:@import url(${context/++resource++zope3.css});">
+ @import url(zope3.css);
+ </style>
+
+ <style type="text/css" media="all" tal:condition="sitemgmt"
+ tal:content="string:@import url(${context/++resource++site_management.css});">
+ @import url(site_management.css);
+ </style>
+
+ <meta http-equiv="Content-Type"
+ content="text/html;charset=utf-8" />
+
+ <metal:block define-slot="headers" />
+ <metal:block define-slot="style_slot" />
+ <metal:block define-slot="ecmascript_slot" />
+
+ <link rel="icon" type="image/png"
+ tal:attributes="href context/++resource++favicon.png" />
+ </head>
+
+ <body>
+
+ <div id="navigators">
+
+ <!-- Tree of the help topics that appears on the help namespace -->
+ <metal:block define-slot="left_slot " />
+
+ </div>
+
+
+ <div id="workspace">
+
+ <div id="viewspace">
+
+ <div id="content">
+ <metal:block define-slot="body">
+ <table class="listing">
+ <thead>
+ <th>Test</th>
+ <th>Another</th>
+ </thead>
+ <tbody>
+ <tr>
+ <td>content</td>
+ <td>thingy</td>
+ </tr>
+ <tr class="even">
+ <td>more</td>
+ <td>data</td>
+ </tr>
+ </tbody>
+ </table>
+ </metal:block>
+ </div>
+
+ <div class="spacer">
+
+ </div>
+
+ </div>
+ </div>
+
+ <div id="footer" metal:define-macro="footer" />
+
+ </body>
+
+</html>
+
+</metal:block>
+
Property changes on: Zope3/trunk/src/zope/app/rotterdam/popup_macros.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/rotterdam/template.pt
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/template.pt 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/rotterdam/template.pt 2004-05-24 13:59:08 UTC (rev 24924)
@@ -141,16 +141,16 @@
tal:repeat="help_info help_actions"
tal:omit-tag="">
<a href="#"
- tal:define="url string:'${help_info/action}';
+ tal:define="url string:'${view/__name__}/${help_info/action}';
name string:'OnlineHelp';
settings string:'height=400
,width=700
,resizable=1
,scrollbars=yes
- ,location=yes
- ,status=yes
- ,toolbar=yes
- ,menubar=yes'"
+ ,location=no
+ ,status=no
+ ,toolbar=no
+ ,menubar=no'"
tal:attributes="href python:'javascript:popup('
+ url + ','
+ name + ','
Modified: Zope3/trunk/src/zope/app/traversing/namespace.py
===================================================================
--- Zope3/trunk/src/zope/app/traversing/namespace.py 2004-05-24 12:18:46 UTC (rev 24923)
+++ Zope3/trunk/src/zope/app/traversing/namespace.py 2004-05-24 13:59:08 UTC (rev 24924)
@@ -180,9 +180,9 @@
zope.interface.implements(ITraversable)
def __init__(self, context, request=None):
- """Simple hadlers can be usd as adapters or views
+ """Simple handlers can be used as adapters or views
- The ignore their second constructor arg and store the first
+ They ignore their second constructor arg and store the first
one in their context attr:
>>> SimpleHandler(42).context
@@ -328,7 +328,9 @@
def traverse(self, name, ignored):
"""Used to traverse to an online help topic."""
- return component.getService(self.context, 'OnlineHelp')
+ onlinehelp = component.getService(self.context, 'OnlineHelp')
+ onlinehelp.context = self.context
+ return onlinehelp
class view(object):
More information about the Zope3-Checkins
mailing list