Author: jure
Date: Wed Mar 13 12:31:28 2013
New Revision: 1455906

URL: http://svn.apache.org/r1455906
Log:
Sync merge from trunk


Added:
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch_breadcrumbs.html
      - copied unchanged from r1455900, 
incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch_breadcrumbs.html
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_timeline.html
      - copied unchanged from r1455900, 
incubator/bloodhound/trunk/bloodhound_theme/bhtheme/templates/bh_timeline.html
Modified:
    incubator/bloodhound/branches/bep_0003_multiproduct/   (props changed)
    incubator/bloodhound/branches/bep_0003_multiproduct/LICENSE
    incubator/bloodhound/branches/bep_0003_multiproduct/NOTICE
    incubator/bloodhound/branches/bep_0003_multiproduct/RELEASE_NOTES
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/api.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/query_parser.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/search_resources/ticket_search.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch.html
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/__init__.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/api.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/query_parser.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/web_ui.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/web_ui.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/whoosh_backend.py
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket.html
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket_box.html
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
    
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/theme.py

Propchange: incubator/bloodhound/branches/bep_0003_multiproduct/
------------------------------------------------------------------------------
  Merged /incubator/bloodhound/trunk:r1455438-1455900

Modified: incubator/bloodhound/branches/bep_0003_multiproduct/LICENSE
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/LICENSE?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- incubator/bloodhound/branches/bep_0003_multiproduct/LICENSE (original)
+++ incubator/bloodhound/branches/bep_0003_multiproduct/LICENSE Wed Mar 13 
12:31:28 2013
@@ -209,7 +209,7 @@ separate copyright notices and license t
 for the these subcomponents is subject to the terms and conditions of the
 following licenses.
 
-For Trac, found in the trac/ directory:
+For Trac, in the trac/ directory:
 
     Copyright (C) 2003-2013 Edgewall Software
     All rights reserved.
@@ -243,7 +243,7 @@ For Trac, found in the trac/ directory:
 For Bootstrap, as provided by the files
 bloodhound_dashboard/bhdashboard/htdocs/css/bootstrap.css
 bloodhound_dashboard/bhdashboard/htdocs/css/bootstrap-responsive.css
-and the bloodhound_dashboard/bhdashboard/htdocs/js/ directory:
+and bloodhound_dashboard/bhdashboard/htdocs/js/bootstrap.js:
 
     Copyright 2012 Twitter, Inc.
     
@@ -262,9 +262,14 @@ and the bloodhound_dashboard/bhdashboard
 For jQuery, in the file
 trac/trac/htdocs/js/jquery.js
 
-    Copyright 2011 jQuery Foundation and other contributors
-    http://jquery.com/
-    
+    Copyright 2013 jQuery Foundation and other contributors,
+    http://jqueryui.com/
+
+    This software consists of voluntary contributions made by many
+    individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
+    contribution history, see the revision history and logs, available
+    at http://jquery-ui.googlecode.com/svn/
+
     Permission is hereby granted, free of charge, to any person obtaining
     a copy of this software and associated documentation files (the
     "Software"), to deal in the Software without restriction, including
@@ -272,10 +277,10 @@ trac/trac/htdocs/js/jquery.js
     distribute, sublicense, and/or sell copies of the Software, and to
     permit persons to whom the Software is furnished to do so, subject to
     the following conditions:
-    
+
     The above copyright notice and this permission notice shall be
     included in all copies or substantial portions of the Software.
-    
+
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -284,6 +289,59 @@ trac/trac/htdocs/js/jquery.js
     OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
+For jQuery UI, in the file
+trac/trac/htdocs/js/jquery-ui.js
+
+    Copyright 2013 jQuery Foundation and other contributors,
+    http://jqueryui.com/
+
+    This software consists of voluntary contributions made by many
+    individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
+    contribution history, see the revision history and logs, available
+    at http://jquery-ui.googlecode.com/svn/
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For jQuery Timepicker Addon, in the file
+trac/trac/htdocs/js/jquery-ui-addons.js
+
+    Copyright (c) 2009 Trent Richardson, http://trentrichardson.com/Impromptu/
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+    LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 For LRU and LFU cache decorators, developed by Raymond Hettinger, in the file
 bloodhound_multiproduct/multiproduct/cache.py:

Modified: incubator/bloodhound/branches/bep_0003_multiproduct/NOTICE
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/NOTICE?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- incubator/bloodhound/branches/bep_0003_multiproduct/NOTICE (original)
+++ incubator/bloodhound/branches/bep_0003_multiproduct/NOTICE Wed Mar 13 
12:31:28 2013
@@ -16,7 +16,15 @@ jQuery - licensed under the MIT License
 This product includes software (jQuery) developed by
 jQuery (http://jquery.org/)
 
+jQuery UI - licensed under MIT License
+This product includes software (jQuery UI) developed by
+jQuery UI (http://jqueryui.com/)
+
+jQuery Timepicker Addon - licensed under MIT License
+This product includes software (jQuery Timepicker Addon)
+developed by Trent Richardson
+(http://trentrichardson.com/examples/timepicker/)
+
 LRU and LFU cache decorators - licensed under the PSF License
 This product includes code (LRU and LFU cache decorators) developed by
 Raymond Hettinger 
(http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/)
-

Modified: incubator/bloodhound/branches/bep_0003_multiproduct/RELEASE_NOTES
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/RELEASE_NOTES?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- incubator/bloodhound/branches/bep_0003_multiproduct/RELEASE_NOTES (original)
+++ incubator/bloodhound/branches/bep_0003_multiproduct/RELEASE_NOTES Wed Mar 
13 12:31:28 2013
@@ -3,6 +3,7 @@
  * Implemented Bootstrap templates for the repository browser, log viewer and 
attachment pages.
  * Upgraded Bootstrap to version 2.3.1.
  * Upgraded Trac to version 1.0.1.
+ * Added beta version of bhsearch plugin. Find more information on 
https://issues.apache.org/bloodhound/wiki/BloodhoundSearch
  * Various bug fixes and enhancements.
 
  * Not fixed for this release:

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/api.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/api.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/api.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/api.py
 Wed Mar 13 12:31:28 2013
@@ -186,7 +186,7 @@ class IQueryParser(Interface):
     """Extension point for Bloodhound Search query parser.
     """
 
-    def parse(query_string):
+    def parse(query_string, context):
         """Parse query from string"""
 
     def parse_filters(filters):
@@ -219,7 +219,7 @@ class IQueryPreprocessor(Interface):
 class IMetaKeywordParser(Interface):
     """Extension point for custom meta keywords."""
 
-    def match(text):
+    def match(text, context):
         """If text matches the keyword, return its transformed value."""
 
 
@@ -255,7 +255,8 @@ class BloodhoundSearchApi(Component):
             pagenum = 1,
             pagelen = 20,
             highlight = False,
-            highlight_fields = None):
+            highlight_fields = None,
+            context = None):
         """Return query result from an underlying search backend.
 
         Arguments:
@@ -271,12 +272,13 @@ class BloodhoundSearchApi(Component):
         :param pagelen: paging support
         :param highlight: highlight matched terms in fields
         :param highlight_fields: list of fields to highlight
+        :param context: request context
 
         :return: result QueryResult
         """
         self.env.log.debug("Receive query request: %s", locals())
 
-        parsed_query = self.parser.parse(query)
+        parsed_query = self.parser.parse(query, context)
 
         parsed_filters = self.parser.parse_filters(filter)
         # TODO: add query parsers and meta keywords post-parsing

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/query_parser.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/query_parser.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/query_parser.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/query_parser.py
 Wed Mar 13 12:31:28 2013
@@ -39,9 +39,10 @@ class MetaKeywordPlugin(qparser.TaggingP
     expr = r"[$](?P<text>[^ \t\r\n]+)(?= |$|\))"
     nodetype = qparser.syntax.WordNode
 
-    def __init__(self, meta_keyword_parsers=()):
+    def __init__(self, meta_keyword_parsers=(), context=None):
         super(MetaKeywordPlugin, self).__init__()
         self.meta_keyword_parsers = meta_keyword_parsers
+        self.context = context
 
     def match(self, parser, text, pos):
         match = qparser.TaggingPlugin.match(self, parser, text, pos)
@@ -50,7 +51,8 @@ class MetaKeywordPlugin(qparser.TaggingP
 
         candidate = match.text
         for meta_keyword_parser in self.meta_keyword_parsers:
-            expanded_meta_keyword = meta_keyword_parser.match(candidate)
+            expanded_meta_keyword = meta_keyword_parser.match(candidate,
+                                                              self.context)
             if expanded_meta_keyword is not None:
                 node = MetaKeywordNode(parser.tag(expanded_meta_keyword))
                 return node.set_range(match.startchar, match.endchar)
@@ -91,28 +93,13 @@ class DefaultQueryParser(Component):
 
     meta_keyword_parsers = ExtensionPoint(IMetaKeywordParser)
 
-    def __init__(self):
-        super(DefaultQueryParser, self).__init__()
-        self.parser = MultifieldParser(
-            self.field_boosts.keys(),
-            WhooshBackend.SCHEMA,
-            fieldboosts=self.field_boosts
-        )
-        self.parser.add_plugin(
-            MetaKeywordPlugin(meta_keyword_parsers=self.meta_keyword_parsers)
-        )
-
-    def parse(self, query_string):
+    def parse(self, query_string, context=None):
+        parser = self._create_parser(context)
         query_string = query_string.strip()
-
         if query_string == "" or query_string == "*" or query_string == "*:*":
             return query.Every()
-
         query_string = unicode(query_string)
-        parsed_query = self.parser.parse(query_string)
-
-        #todo: impalement pluggable mechanism for query post processing
-        #e.g. meta keyword replacement etc.
+        parsed_query = parser.parse(query_string)
         return parsed_query
 
     def parse_filters(self, filters):
@@ -125,13 +112,25 @@ class DefaultQueryParser(Component):
     def _parse_filter(self, filter):
         return self.parse(unicode(filter))
 
+    def _create_parser(self, context):
+        parser = MultifieldParser(
+            self.field_boosts.keys(),
+            WhooshBackend.SCHEMA,
+            fieldboosts=self.field_boosts
+        )
+        parser.add_plugin(
+            MetaKeywordPlugin(meta_keyword_parsers=self.meta_keyword_parsers,
+                              context=context)
+        )
+        return parser
+
 
 class DocTypeMetaKeywordParser(Component):
     implements(IMetaKeywordParser)
 
     search_participants = ExtensionPoint(ISearchParticipant)
 
-    def match(self, text):
+    def match(self, text, context):
         documents = [p.get_participant_type()
                      for p in self.search_participants]
         if text in documents:
@@ -141,7 +140,7 @@ class DocTypeMetaKeywordParser(Component
 class ResolvedMetaKeywordParser(Component):
     implements(IMetaKeywordParser)
 
-    def match(self, text):
+    def match(self, text, context):
         if text == u'resolved':
             return u'status:(resolved OR closed)'
 
@@ -149,7 +148,23 @@ class ResolvedMetaKeywordParser(Componen
 class UnResolvedMetaKeywordParser(Component):
     implements(IMetaKeywordParser)
 
-    def match(self, text):
+    def match(self, text, context):
         if text == u'unresolved':
             return u'NOT $resolved'
 
+
+class MeMetaKeywordParser(Component):
+    implements(IMetaKeywordParser)
+
+    def match(self, text, context):
+        if text == u'me':
+            username = unicode(context.req.authname)
+            return username
+
+
+class MyMetaKeywordParser(Component):
+    implements(IMetaKeywordParser)
+
+    def match(self, text, context):
+        if text == u'my':
+            return u'owner:$me'

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/search_resources/ticket_search.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/search_resources/ticket_search.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/search_resources/ticket_search.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/search_resources/ticket_search.py
 Wed Mar 13 12:31:28 2013
@@ -39,6 +39,7 @@ class TicketFields(IndexFields):
     KEYWORDS = "keywords"
     RESOLUTION = "resolution"
     CHANGES = 'changes'
+    OWNER = 'owner'
 
 class TicketIndexer(BaseIndexer):
     implements(ITicketChangeListener, IIndexParticipant)
@@ -52,6 +53,7 @@ class TicketIndexer(BaseIndexer):
         'status': TicketFields.STATUS,
         'resolution': TicketFields.RESOLUTION,
         'reporter': TicketFields.AUTHOR,
+        'owner': TicketFields.OWNER,
     }
 
     def __init__(self):
@@ -205,5 +207,6 @@ class TicketSearchParticipant(BaseSearch
 
         id = res['hilited_id'] or res['id']
         id = tag.span('#', id, class_=css_class)
-        return tag(id, ': ', res['hilited_summary'], ' (%s)' % stat)
+        summary = res['hilited_summary'] or res['summary']
+        return tag(id, ': ', summary, ' (%s)' % stat)
 

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch.html
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch.html?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch.html
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/templates/bhsearch.html
 Wed Mar 13 12:31:28 2013
@@ -56,33 +56,6 @@
   <body>
     <div id="content" class="row">
       <div class="span12">
-        <h1>Advanced search</h1>
-          <form id="fullsearch" action="${href.bhsearch()}" method="get">
-            <!--So far, we will not support noquickjump mode for form 
submission-->
-            <!--<input type="hidden" name="noquickjump" value="1" />-->
-            <input py:if="active_type" type="hidden" name="type" 
value="${active_type}" />
-            <input py:if="active_view" type="hidden" name="view" 
value="${active_view}" />
-            <input py:if="active_sort" type="hidden" name="sort" 
value="${active_sort.expression}" />
-            <py:for each="active_filter in active_filter_queries">
-              <input type="hidden" name="fq" value="${active_filter.query}" />
-            </py:for>
-
-            <div class="input-append">
-              <input type="text" id="q" name="q" class="span4" 
value="${query}" />
-              <button type="submit" class="btn btn-warning">
-                <span class="hidden-phone">${_('Search')}</span>
-                <i class="icon-search icon-white"></i>
-              </button>
-            </div>
-
-            <div id="active_sort" py:if="active_sort">
-                Sort by: <strong>${active_sort.expression}</strong> (<a 
href="${active_sort.href}">remove</a>)
-            </div>
-
-          </form>
-      </div>
-
-      <div class="span12">
         <py:if test="quickjump">
           <dt id="quickjump">
             <a href="${quickjump.href}" i18n:msg="name">Quickjump to 
${quickjump.name}</a>
@@ -102,13 +75,6 @@
           </ul>
         </div>
 
-        <!--Render filters breadcrumbs-->
-        <div id="active_filter_queries" py:if="active_filter_queries">
-          <py:for each="active_filter in active_filter_queries">
-            &gt; <a href="${active_filter.href}">${active_filter.label}</a>
-          </py:for>
-        </div>
-
         <div py:if="results" class="row">
           <div class="span3 facets">
             <py:if test="facet_counts">
@@ -128,7 +94,8 @@
             </py:if>
           </div>
 
-          <div class="${'span12' if not facet_counts else 'span9 
search_results'}">
+            <div class="${'span12' if not facet_counts else 'span9'}${
+                        ' search_results'}">
             <h2>
               Results <small>(${results.displayed_items()})</small>
             </h2>
@@ -200,7 +167,7 @@
                 <dl id="results">
                   <py:for each="result in results">
                     <dt><a href="${result.href}" 
class="searchable">${result.title}</a></dt>
-                    <dd class="searchable">${result.content}</dd>
+                    <dd class="searchable">${result.hilited_content or 
result.content}</dd>
                     <dd>
                       <py:if test="result.author"><span class="author" 
i18n:msg="author">By ${format_author(result.author)}</span> &mdash;</py:if>
                       <span class="date">${result.date}</span>
@@ -215,7 +182,6 @@
         </div>
       </div>
 
-
       <div class="span12"
           py:if="query and not (results or quickjump)">
         <p id="notfound" class="alert">
@@ -223,6 +189,12 @@
         </p>
       </div>
 
+      <div py:if="debug.enabled" class="span12">
+        <p>DEBUG INFO:
+        <pre>${pprint(debug)}</pre>
+        </p>
+      </div>
+
       <div id="help" class="help-block pull-right" i18n:msg="">
         <strong>Note:</strong> See <a 
href="${href.wiki('BloodhoundSearch')}">BloodhoundSearch</a>
         for help on searching.

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/__init__.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/__init__.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/__init__.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/__init__.py
 Wed Mar 13 12:31:28 2013
@@ -29,6 +29,7 @@ def suite():
     test_suite.addTest(whoosh_backend.suite())
     test_suite.addTest(web_ui.suite())
     test_suite.addTest(api.suite())
+    test_suite.addTest(query_parser.suite())
     test_suite.addTest(ticket_search.suite())
     test_suite.addTest(wiki_search.suite())
     test_suite.addTest(milestone_search.suite())

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/api.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/api.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/api.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/api.py
 Wed Mar 13 12:31:28 2013
@@ -18,26 +18,18 @@
 #  specific language governing permissions and limitations
 #  under the License.
 import unittest
-import tempfile
 import shutil
 from bhsearch.api import BloodhoundSearchApi, ASC, SortInstruction
 from bhsearch.query_parser import DefaultQueryParser
 from bhsearch.tests.base import BaseBloodhoundSearchTest
 from bhsearch.search_resources.ticket_search import TicketSearchParticipant
-
 from bhsearch.whoosh_backend import WhooshBackend
-from trac.test import EnvironmentStub
-from trac.ticket.api import TicketSystem
 
 
 class ApiQueryWithWhooshTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(enable=['bhsearch.*'])
-        self.env.path = tempfile.mkdtemp('bhsearch-tempenv')
-        self.env.config.set('bhsearch', 'silence_on_error', "False")
-        self.ticket_system = TicketSystem(self.env)
-        self.whoosh_backend = WhooshBackend(self.env)
-        self.whoosh_backend.recreate_index()
+        super(ApiQueryWithWhooshTestCase, self).setUp()
+        WhooshBackend(self.env).recreate_index()
         self.search_api = BloodhoundSearchApi(self.env)
         self.ticket_participant = TicketSearchParticipant(self.env)
         self.query_parser = DefaultQueryParser(self.env)

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/query_parser.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/query_parser.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/query_parser.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/query_parser.py
 Wed Mar 13 12:31:28 2013
@@ -69,6 +69,26 @@ class MetaKeywordsParsingTestCase(BaseBl
                              )
                          ]))
 
+    def test_can_parse_keyword_me(self):
+        context = self._mock_context_with_username('username')
+
+        parsed_query = self.parser.parse("author:$me", context)
+
+        self.assertEqual(parsed_query, terms.Term('author', 'username'))
+
+    def test_can_parse_keyword_my(self):
+        context = self._mock_context_with_username('username')
+
+        parsed_query = self.parser.parse("$my", context)
+
+        self.assertEqual(parsed_query, terms.Term('owner', 'username'))
+
+    def _mock_context_with_username(self, username):
+        class context:
+            class req:
+                authname = username
+        return context
+
 
 def suite():
     test_suite = unittest.TestSuite()

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/web_ui.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/web_ui.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/web_ui.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/tests/web_ui.py
 Wed Mar 13 12:31:28 2013
@@ -140,8 +140,8 @@ class WebUiTestCaseWithWhoosh(BaseBloodh
         #act
         data = self.process_request()
         #assert
-        active_type = data["active_type"]
-        self.assertEquals("ticket", active_type)
+        extra_search_options = dict(data["extra_search_fields"])
+        self.assertEquals("ticket", extra_search_options['type'])
 
         resource_types = data["types"]
 
@@ -513,7 +513,8 @@ class WebUiTestCaseWithWhoosh(BaseBloodh
         self.req.args[RequestParameters.VIEW] = "grid"
         data = self.process_request()
         #assert
-        self.assertEqual("grid", data["active_view"])
+        extra_search_options = dict(data["extra_search_fields"])
+        self.assertEqual("grid", extra_search_options["view"])
 
     def test_can_apply_sorting(self):
         #arrange
@@ -585,9 +586,9 @@ class WebUiTestCaseWithWhoosh(BaseBloodh
 
         data = self.process_request()
         #assert
-        active_sort = data["active_sort"]
-        self.assertEquals("id, time desc", active_sort["expression"])
-        self.assertNotIn("sort=", active_sort["href"])
+        extra_search_options = dict(data["extra_search_fields"])
+        self.assertEquals("id, time desc", extra_search_options["sort"])
+        #self.assertNotIn("sort=", active_sort["href"])
 
     def test_that_document_summary_contains_highlighted_search_terms(self):
         term = "searchterm"

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/web_ui.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/web_ui.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/web_ui.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/web_ui.py
 Wed Mar 13 12:31:28 2013
@@ -60,6 +60,7 @@ class RequestParameters(object):
     FILTER_QUERY = "fq"
     VIEW = "view"
     SORT = "sort"
+    DEBUG = "debug"
 
     def __init__(self, req):
         self.req = req
@@ -85,6 +86,7 @@ class RequestParameters(object):
             DEFAULT_RESULTS_PER_PAGE))
         self.page = int(req.args.getfirst(self.PAGE, '1'))
         self.type = req.args.getfirst(self.TYPE)
+        self.debug = int(req.args.getfirst(self.DEBUG, '0'))
 
         self.params = {
             RequestParameters.FILTER_QUERY: []
@@ -106,6 +108,8 @@ class RequestParameters(object):
             self.params[RequestParameters.FILTER_QUERY] = self.filter_queries
         if self.sort_string:
             self.params[RequestParameters.SORT] = self.sort_string
+        if self.debug:
+            self.params[RequestParameters.DEBUG] = self.debug
 
     def _parse_sort(self, sort_string):
         if not sort_string:
@@ -272,6 +276,9 @@ class BloodhoundSearchModule(Component):
             self.default_facets
         )
 
+        # compatibility with legacy search
+        req.search_query = request_context.parameters.query
+
         query_result = BloodhoundSearchApi(self.env).query(
             request_context.parameters.query,
             pagenum=request_context.page,
@@ -281,6 +288,7 @@ class BloodhoundSearchModule(Component):
             facets=request_context.facets,
             filter=request_context.query_filter,
             highlight=True,
+            context=request_context,
         )
 
         request_context.process_results(query_result)
@@ -301,20 +309,19 @@ class BloodhoundSearchModule(Component):
 
 class RequestContext(object):
     DATA_ACTIVE_FILTER_QUERIES = 'active_filter_queries'
-    DATA_ACTIVE_TYPE = "active_type"
-    DATA_ACTIVE_SORT = "active_sort"
+    DATA_BREADCRUMBS_TEMPLATE = 'resourcepath_template'
     DATA_TYPES = "types"
     DATA_HEADERS = "headers"
     DATA_ALL_VIEWS = "all_views"
-    DATA_ACTIVE_VIEW = "active_view"
     DATA_VIEW = "view"
     DATA_VIEW_GRID = "grid"
     DATA_FACET_COUNTS = 'facet_counts'
     DATA_DEBUG = 'debug'
     DATA_PAGE_HREF = 'page_href'
     DATA_RESULTS = 'results'
+    DATA_QUERY = 'query'
     DATA_QUICK_JUMP = "quickjump"
-
+    DATA_SEARCH_EXTRAS = 'extra_search_fields'
 
     #bhsearch may support more pluggable views later
     VIEWS_SUPPORTED = {
@@ -338,7 +345,10 @@ class RequestContext(object):
         self.env = env
         self.req = req
         self.parameters = RequestParameters(req)
-        self.data = {'query': self.parameters.query}
+        self.data = {
+            self.DATA_QUERY: self.parameters.query,
+            self.DATA_SEARCH_EXTRAS: [],
+        }
         self.search_participants = search_participants
         self.default_view = default_view
         self.all_grid_fields = all_grid_fields
@@ -349,9 +359,8 @@ class RequestContext(object):
 
         if self.parameters.sort:
             self.sort = self.parameters.sort
-            self.data[self.DATA_ACTIVE_SORT] = dict(
-                expression=self.parameters.sort_string,
-                href=self.parameters.create_href(skip_sort=True)
+            self.data[self.DATA_SEARCH_EXTRAS].append(
+                (RequestParameters.SORT, self.parameters.sort_string)
             )
         else:
             self.sort = self.DEFAULT_SORT
@@ -417,7 +426,9 @@ class RequestContext(object):
                 ),
             ))
         self.data[self.DATA_TYPES] = allowed_types
-        self.data[self.DATA_ACTIVE_TYPE] = active_type
+        self.data[self.DATA_SEARCH_EXTRAS].append(
+            (RequestParameters.TYPE, active_type)
+        )
 
     def _prepare_active_filter_queries(self):
         current_filters = self.parameters.filter_queries
@@ -435,6 +446,10 @@ class RequestContext(object):
             ) for filter_query in self.parameters.filter_queries
         ]
         self.data[self.DATA_ACTIVE_FILTER_QUERIES] = active_filter_queries
+        for filter_query in active_filter_queries:
+            self.data[self.DATA_SEARCH_EXTRAS].append(
+                (RequestParameters.FILTER_QUERY, filter_query['query'])
+            )
 
     def _prepare_quick_jump(self):
         if not self.parameters.query:
@@ -497,7 +512,9 @@ class RequestContext(object):
     def _add_views_selector(self):
         active_view = self.parameters.view
         if active_view:
-            self.data[self.DATA_ACTIVE_VIEW] = active_view
+            self.data[self.DATA_SEARCH_EXTRAS].append(
+                (RequestParameters.VIEW, active_view)
+            )
 
         all_views = []
         for view, label in self.VIEWS_SUPPORTED.iteritems():
@@ -635,7 +652,11 @@ class RequestContext(object):
                                   query_result.highlighting)
         self._prepare_results(docs, query_result.hits)
         self._prepare_result_facet_counts(query_result.facets)
+        self._prepare_breadcrumbs_template()
         self.data[self.DATA_DEBUG] = query_result.debug
+        if self.parameters.debug:
+            self.data[self.DATA_DEBUG]['enabled'] = True
+            self.data[self.DATA_SEARCH_EXTRAS].append(('debug', '1'))
         self.data[self.DATA_PAGE_HREF] = self.parameters.create_href()
 
     def _prepare_result_facet_counts(self, result_facets):
@@ -697,3 +718,6 @@ class RequestContext(object):
 
     def _create_genshi_fragment(self, html_fragment):
         return tag(HTML(html_fragment))
+
+    def _prepare_breadcrumbs_template(self):
+        self.data[self.DATA_BREADCRUMBS_TEMPLATE] = 'bhsearch_breadcrumbs.html'

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/whoosh_backend.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/whoosh_backend.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/whoosh_backend.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_search/bhsearch/whoosh_backend.py
 Wed Mar 13 12:31:28 2013
@@ -69,7 +69,9 @@ class WhooshBackend(Component):
         content=TEXT(stored=True,
                      analyzer=analysis.StandardAnalyzer(stoplist=None)),
         changes=TEXT(analyzer=analysis.StandardAnalyzer(stoplist=None)),
-        )
+        owner=TEXT(stored=True,
+                   analyzer=analysis.SimpleAnalyzer()),
+    )
 
     max_fragment_size = IntOption('bhsearch', 'max_fragment_size', 240,
                                'The maximum number of characters allowed in a '
@@ -224,6 +226,11 @@ class WhooshBackend(Component):
                                             fields,
                                             highlight_fields,
                                             query_parameters)
+            try:
+                results.debug['actual_query'] = 
unicode(query.simplify(searcher))
+            except TypeError:
+                # Simplify has a bug that causes it to fail sometimes.
+                pass
         return results
 
     def _workaround_join_query_and_filter(

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket.html
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket.html?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket.html
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket.html
 Wed Mar 13 12:31:28 2013
@@ -64,6 +64,8 @@
 
         <py:if test="has_property_editor">
         // Install in place editing
+        install_workflow();
+        $('#edit-cancel').click(revert_ticket);
 
         var modify_elem = $('#modify');
         <py:if test="ticket.exists">
@@ -109,45 +111,7 @@
                   addWikiFormattingToolbar(editor.get(0));
               }
               if (fieldnm === 'summary') {
-                // Install inline edit form 
-                var submit_ticket = $('#tmpl-inplace-submit').html();
-                submit_ticket = $(submit_ticket).prepend(editor)
-                    .appendTo(fc);
-                submit_ticket.find('#edit-cancel').click(revert_ticket);
                 editor.wrap('<div class="btn-group"></div>')
-
-                // Workflow actions
-                var actions_box = submit_ticket.find('#workflow-actions')
-                    .click(function(e) { e.stopPropagation(); });
-                $('#action').children('div').each(function() {
-                    var action_ui = $(this).clone(false).prependTo(actions_box)
-                        .wrap('<li style="padding: 5px 10px"></li>');
-                    var action_trigger = action_ui.find('input[name=action]');
-
-                    function action_click() {
-                      var newlabel = action_ui.find('label[for^=action_]')
-                          .text();
-                      $('#submit-action-label').text(newlabel);
-
-                      // Enable | disable action controls
-                      actions_box.find('input[name=action]').each(function() {
-                          $(this).siblings().find("*[id]")
-                              .enable($(this).checked());
-                          $(this).siblings().filter("*[id]")
-                              .enable($(this).checked());
-                        });
-                    }
-                    action_trigger.click(action_click);
-                    if (action_trigger.attr('checked'))
-                      action_click();
-
-                    var action_help = action_ui.find('.help-block').detach()
-                        .text().replace(/\s+/g, ' ').replace(/^ Tip /g, 'Tip: 
')
-                        .replace(/^\s$/, '');
-                    if (action_help)
-                        $('<i class="icon-info-sign"></i>').appendTo(action_ui)
-                            .attr('title', action_help);
-                  })
               }
             });
 
@@ -157,18 +121,72 @@
           $('#inplace-propertyform').submit(function() {
               $('#hidden-comment').val($('#comment').val());
             })
-          $('#inplace-edit-button').hide();
+          $('#inplace-edit').hide();
+          $('#edit-state-buttons').show();
+          $('#vc-status a').hide();
+          $('#edit-workflow-buttons').show();
         }
 
-        function revert_ticket() {
+        function revert_ticket(e) {
           $('[data-edit="inplace"]').each(function() {
               var fc = $(this).removeClass('edit-active');
               fc.html(fc.attr('data-edit-orig')).attr('data-edit-orig', '');
             });
-          $('#inplace-edit-button').show();
+          $('#inplace-edit').show();
           $('h2#vc-summary span').attr('contenteditable', 'false');
+          $('#edit-state-buttons').hide();
+          $('#vc-status a').show();
+          $('#edit-workflow-buttons').hide();
+          e.preventDefault();
         }
 
+        function install_workflow(){
+          var actions_box = $('#workflow-actions')
+              .click(function(e) { e.stopPropagation(); });
+          $('#action').children('div').each(function() {
+              var action_ui = $(this).clone(false).prependTo(actions_box)
+                  .wrap('<li style="padding: 5px 10px"></li>');
+              var action_trigger = action_ui.find('input[name=action]');
+              var action_select_trigger = action_ui.find('select');
+              var action_input_trigger = 
action_ui.find('input:not([name=action])');
+
+              function action_click() {
+                var action = action_ui.find('input[name=action]').val();
+                var newowner = 
action_ui.find('input[id$=_reassign_owner]').val();
+                var newresolution = 
action_ui.find('select[id$=_resolution]').val();
+                var newlabel = action_ui.find('label[for^=action_]')
+                    .text();
+                if (action === 'leave')
+                  newlabel = newlabel + ' as ' + $('#vc-status a').text();
+                else if (newowner)
+                  newlabel = newlabel + ' to ' + newowner;
+                else if (newresolution)
+                  newlabel = newlabel + ' as ' + newresolution;
+                $('#submit-action-label').text(newlabel);
+
+                // Enable | disable action controls
+                actions_box.find('input[name=action]').each(function() {
+                    $(this).siblings().find("*[id]")
+                        .enable($(this).checked());
+                    $(this).siblings().filter("*[id]")
+                        .enable($(this).checked());
+                  });
+              }
+              action_trigger.click(action_click);
+              action_select_trigger.change(action_click);
+              action_input_trigger.blur(action_click);
+              if (action_trigger.attr('checked'))
+                action_click();
+
+              var action_help = action_ui.find('.help-block').detach()
+                  .text().replace(/\s+/g, ' ').replace(/^ Tip /g, 'Tip: ')
+                  .replace(/^\s$/, '');
+              if (action_help)
+                  $('<i class="icon-info-sign"></i>').appendTo(action_ui)
+                      .attr('title', action_help);
+            });
+          }
+
         $('h2#vc-summary span').blur(function () {
           if ($('#vc-summary.edit-active').length == 1) {
             $('#vc-summary.ticket-summary 
input#field-summary').val($('#vc-summary span').text());
@@ -270,6 +288,15 @@
             <i class="icon-edit"></i>
             <span class="hidden-phone hidden-tablet">${_('Modify 
Ticket')}</span>
           </button>
+          <div id="edit-state-buttons" class="btn-toolbar" style="display: 
None">
+            <button id="edit-submit" class="btn" type="submit"
+                value="Submit changes" name="submit">
+              Submit changes
+            </button>
+            <button id="edit-cancel" class="btn-link" title="Discard changes">
+              Cancel
+            </button>
+          </div>
         </div>
       </py:if>
     </py:def>
@@ -373,7 +400,7 @@
         </div>
 
         <!--! do not show attachments for old versions of this ticket or for 
new tickets -->
-        <div py:if="not version and version != 0 and ticket.exists" 
class="span8">
+        <div class="$colspan" py:if="not version and version != 0 and 
ticket.exists">
           <xi:include href="bh_list_of_attachments.html"
                       py:with="alist = attachments; foldable = True"/>
         </div>
@@ -665,24 +692,6 @@
     <script type="text/x-tmpl" id="tmpl-inplace-submit" 
py:if="has_property_editor">
       <div class="btn-toolbar">
         <div class="btn-group">
-          <button id="edit-submit" class="btn btn-primary" type="submit" 
-              value="Submit changes" name="submit">
-            Update (<span id="submit-action-label"></span>)
-          </button>
-          <button class="btn btn-primary dropdown-toggle" 
data-toggle="dropdown">
-            <span class="caret"></span>
-          </button>
-          <ul class="dropdown-menu">
-            <fieldset id="workflow-actions">
-            </fieldset>
-          </ul>
-        </div>
-        <div class="btn-group">
-          <button id="edit-cancel" class="btn-link" title="Discard changes">
-            Cancel
-          </button>
-        </div>
-        <div class="btn-group">
           <span class="trac-loading">&nbsp;</span>
         </div>
       </div>

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket_box.html
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket_box.html?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket_box.html
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bh_ticket_box.html
 Wed Mar 13 12:31:28 2013
@@ -60,6 +60,18 @@ Arguments:
                   <py:otherwise>${ticket[field.name]}</py:otherwise>
                 </py:choose>
               </py:if>
+              <py:if test="field.name == 'status'">
+                <div id="edit-workflow-buttons" class="btn-group" 
style="display: none">
+                  <button class="btn dropdown-toggle" data-toggle="dropdown" 
style="white-space: normal">
+                    <span id="submit-action-label"></span>
+                    <span class="caret"></span>
+                  </button>
+                  <ul class="dropdown-menu">
+                    <fieldset id="workflow-actions">
+                    </fieldset>
+                  </ul>
+                </div>
+              </py:if>
             </div>
           </div>
         </div>

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bloodhound_theme.html?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/templates/bloodhound_theme.html
 Wed Mar 13 12:31:28 2013
@@ -90,11 +90,20 @@
           <div class="span6">
             <div id="searchbox" class="btn-toolbar">
               <div class="btn-group">
-                <form id="mainsearch" class="form-inline" 
action="${href.search()}" method="get">
+                <form id="mainsearch" class="form-inline"
+                      action="${href.search()   if req.path_info == u'/search' 
else
+                                href.bhsearch() if (req.path_info == 
u'/bhsearch' or
+                                                    is_bhsearch_default) else
+                                href.search()}"
+                      method="get">
                   <div class="input-append">
                     <input type="text" class="span3" id="q" name="q"
                         placeholder="Search anything. Try #EF-492."
                         value="${req.search_query}" />
+                    <input py:for="name, value in extra_search_fields"
+                           type="hidden"
+                           name="$name"
+                           value="$value" />
                     <button type="submit" class="btn btn-warning">
                       <span class="hidden-phone hidden-tablet">Search</span>
                       <i class="icon-search icon-white"></i>

Modified: 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/theme.py
URL: 
http://svn.apache.org/viewvc/incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/theme.py?rev=1455906&r1=1455905&r2=1455906&view=diff
==============================================================================
--- 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/theme.py
 (original)
+++ 
incubator/bloodhound/branches/bep_0003_multiproduct/bloodhound_theme/bhtheme/theme.py
 Wed Mar 13 12:31:28 2013
@@ -23,7 +23,7 @@ from genshi.core import TEXT
 from genshi.filters.transform import Transformer
 from genshi.output import DocType
 
-from trac.config import Option
+from trac.config import Option, BoolOption
 from trac.core import *
 from trac.config import ListOption
 from trac.mimeview.api import get_mimetype
@@ -135,6 +135,7 @@ class BloodhoundTheme(ThemeBase):
         # General purpose
         'about.html' : ('bh_about.html', None),
         'history_view.html' : ('bh_history_view.html', None),
+        'timeline.html' : ('bh_timeline.html', None),
 
         # Account manager plugin
         'login.html' : ('bh_login.html', None),
@@ -157,6 +158,8 @@ class BloodhoundTheme(ThemeBase):
     
     labels_footer_right = Option('labels', 'footer_right', '')
 
+    is_bhsearch_default = BoolOption('bhsearch', 'is_default', False)
+
     _wiki_pages = None
     Chrome.default_html_doctype = DocType.HTML5
 
@@ -283,6 +286,7 @@ class BloodhoundTheme(ThemeBase):
         if is_active_theme and data is not None:
             data['responsive_layout'] = self.env.config.getbool(
                     'bloodhound', 'responsive_layout', 'true')
+            data['is_bhsearch_default'] = self.is_bhsearch_default
 
         return template, data, content_type
 


Reply via email to