diff roundup/cgi_client.py @ 681:1b2d0e702ca8 search_indexing-0-4-2-branch

Added feature [SF#526730] - search for messages capability
author Roche Compaan <rochecompaan@users.sourceforge.net>
date Wed, 03 Apr 2002 11:55:57 +0000
parents 9667625a5695
children 0521ddc7bb31
line wrap: on
line diff
--- a/roundup/cgi_client.py	Wed Apr 03 11:55:57 2002 +0000
+++ b/roundup/cgi_client.py	Wed Apr 03 11:55:57 2002 +0000
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.114 2002-03-17 23:06:05 richard Exp $
+# $Id: cgi_client.py,v 1.114.2.1 2002-04-03 11:55:57 rochecompaan Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -26,6 +26,7 @@
 
 import roundupdb, htmltemplate, date, hyperdb, password
 from roundup.i18n import _
+from roundup_indexer import RoundupIndexer
 
 class Unauthorised(ValueError):
     pass
@@ -45,6 +46,7 @@
     there is no cookie). This allows them to modify the database, and all
     modifications are attributed to the 'anonymous' user.
     '''
+    classes_to_search = ['issue']
 
     def __init__(self, instance, request, env, form=None):
         self.instance = instance
@@ -70,6 +72,7 @@
         except ValueError:
             # someone gave us a non-int debug level, turn it off
             self.debug = 0
+        self.indexer = RoundupIndexer('%s/db'%instance.INSTANCE_HOME)
 
     def getuid(self):
         return self.db.user.lookup(self.user)
@@ -208,6 +211,9 @@
             links.append(_('<a href="user">User List</a>'))
             links.append(_('<a href="newuser">Add User</a>'))
 
+        # add the search link
+        links.append(_('<a href="search">Search</a>'))
+        
         # now we have all the links, join 'em
         links = '\n | '.join(links)
 
@@ -557,6 +563,129 @@
     showissue = shownode
     showmsg = shownode
 
+    def search(self):
+        ''' display search form
+        '''
+        self.pagehead(_('Search'))
+        self.write(_('''
+<form action="searchresults" method="post">
+<table border=0 cellspacing=0 cellpadding=2>
+<tr>
+<th>Search terms</th>
+<td><input name="search_terms" size="50"></td>
+</tr>
+<tr>
+<td>&nbsp;</td>
+<td><input type="submit" value="  Search  "></td>
+</tr>
+</table>
+</form>
+'''))
+        self.pagefoot()
+
+    def searchresults(self):
+        ''' display search results
+        '''
+        search_terms = self.form['search_terms'].value
+        hits = self.indexer.find(search_terms.split(' '))
+        links = []
+        nodeids = {}
+        designator_propname = {'msg': 'messages',
+                               'file': 'files'}
+        if hits:
+            hitcount = len(hits)
+            instance_url = '%s/%s'%(self.env['SCRIPT_NAME'], 
+                self.instance_path_name)
+            # build a dictionary of nodes and their associated messages
+            # and files
+            for hit in hits.keys():
+                filename = hits[hit].split('/')[-1]
+                for designator, propname in designator_propname.items():
+                    if filename.find(designator) == -1: continue
+                    nodeid = filename[len(designator):]
+                    for classname in self.classes_to_search:
+                        if not classname in self.db.getclasses(): continue
+                        cl = self.db.getclass(classname)
+                        result = apply(cl.find, (), {propname:nodeid})
+                        if not result: continue
+
+                        if not nodeids.has_key(classname):
+                            nodeids[classname] = {}
+
+                        id = int(result[0])
+                        class_dict = nodeids[classname]
+                        if not class_dict.has_key(id):
+                            class_dict[id] = {}
+
+                        node_dict = class_dict[id]
+                        if not node_dict.has_key(propname):
+                            node_dict[propname] = [nodeid]
+                        elif class_dict.has_key(propname):
+                            node_dict[propname].append(nodeid)
+
+            for classname in self.classes_to_search:
+                if not nodeids.has_key(classname): continue
+                ids = nodeids[classname].keys()
+                # TODO: sort hits on relevance, not on ids
+                ids.sort()
+                # generate hyperlinks for nodes
+                for id in ids:
+                    nodepath = '%s/%s%s'%(instance_url, classname, id)
+                    title = self.db.issue.get(`id`, 'title')
+                    node_link = _(''' 
+<a href="%(nodepath)s">%(classname)s%(id)s: %(title)s</a>
+''')%locals()
+
+                    node_dict = nodeids[classname][id]
+                    # hyperlinks for messages
+                    message_links = []
+                    if node_dict.has_key('messages'):
+                        for msgid in node_dict['messages']:
+                            k = self.db.msg.labelprop()
+                            lab = self.db.msg.get(msgid, k)
+                            msgpath = '%s/msg%s'%(instance_url, msgid)
+                            message_links.append(_(''' 
+<a href="%(msgpath)s">%(lab)s</a>''')%locals())
+                        message_links = _('<li>Messages: %s</li>')%(
+                            ', '.join(message_links))
+                    else:
+                        message_links = ''
+
+                    # hyperlinks for files
+                    file_links = []
+                    if node_dict.has_key('files'):
+                        for fileid in node_dict['files']:
+                            filename = self.db.file.get(fileid, 'name')
+                            filepath = '%s/file%s/%s'%(instance_url, 
+                                fileid, filename)
+                            file_links.append(_(''' 
+<a href="%(filepath)s">%(filename)s</a>''')%locals())
+                        file_links = _('<li>Files: %s</li>')%(
+                            ', '.join(file_links))
+                    else:
+                        file_links = ''
+
+                    links.append(_('''%(node_link)s
+<ul>
+%(message_links)s
+%(file_links)s
+</ul>''')%locals())
+        else:
+            hitcount = 0
+
+        self.pagehead(_('Search Results'))
+        if links:
+            links = '<li>'.join(links)
+            self.write(_('''<p>Searching for "%(search_terms)s" returned
+%(hitcount)s results:</p>
+<ol>
+<li>%(links)s
+</ol>''')%locals())
+        else:
+            self.write(_('''<p>Searching for "%(search_terms)s" returned
+no results.</p>''')%locals())
+        self.pagefoot()
+
     def _add_assignedto_to_nosy(self, props):
         ''' add the assignedto value from the props to the nosy list
         '''
@@ -1220,6 +1349,12 @@
         if action == 'logout':
             self.logout()
             return
+        if action == 'search':
+            self.search()
+            return
+        if action == 'searchresults':
+            self.searchresults()
+            return
 
         # see if we're to display an existing node
         m = dre.match(action)
@@ -1269,6 +1404,7 @@
     showtimelog = Client.shownode
     newsupport = Client.newnode
     newtimelog = Client.newnode
+    classes_to_search = ['issue', 'support']
 
     default_index_sort = ['-activity']
     default_index_group = ['priority']
@@ -1357,6 +1493,9 @@
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.114  2002/03/17 23:06:05  richard
+# oops
+#
 # Revision 1.113  2002/03/14 23:59:24  richard
 #  . #517734 ] web header customisation is obscure
 #

Roundup Issue Tracker: http://roundup-tracker.org/