[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">
+          &nbsp;
+        </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