bloodhound-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Thimal Kempitiya <tkempit...@gmail.com>
Subject Re: svn commit: r1616294 - /bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py
Date Wed, 06 Aug 2014 18:08:00 GMT
Improved the duplicate ticket search. Now it search for partial and
complete phrases enter into the summary in new ticket.
change the keywords suggest : add the query page javascript to separate
file, change the db use so it can find keywords in query page also.


On Wed, Aug 6, 2014 at 11:32 PM, <thimal@apache.org> wrote:

> Author: thimal
> Date: Wed Aug  6 18:02:52 2014
> New Revision: 1616294
>
> URL: http://svn.apache.org/r1616294
> Log:
> Improved the duplicate ticket search. Now it search for partial and
> complete phrases enter into the summary in new ticket.
> change the keywords suggest : add the query page javascript to separate
> file, change the db use so it can find keywords in query page also.
>
> Modified:
>
> bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py
>
> Modified:
> bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py
> URL:
> http://svn.apache.org/viewvc/bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py?rev=1616294&r1=1616293&r2=1616294&view=diff
>
> ==============================================================================
> ---
> bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py
> (original)
> +++
> bloodhound/branches/bep_0013_dynamic_clientside_features/bloodhound_theme/bhtheme/theme.py
> Wed Aug  6 18:02:52 2014
> @@ -19,8 +19,9 @@
>
>  import sys
>
> +import re
> +
>  from trac.util.datefmt import format_datetime, user_time
> -from collections import Counter
>
>  import fnmatch
>
> @@ -28,8 +29,6 @@ from genshi.builder import tag
>  from genshi.core import TEXT, Markup
>  from genshi.filters.transform import Transformer
>  from genshi.output import DocType
> -from bhsearch.api import BloodhoundSearchApi
> -from bhsearch.web_ui import RequestContext
>
>  from trac.config import ListOption, Option
>  from trac.core import Component, TracError, implements
> @@ -861,8 +860,7 @@ class KeywordSuggestModule(Component):
>              self.log.debug("""
>                  No keywords found. KeywordSuggestPlugin is disabled.""")
>              keywords = []
> -        # data = {'keywords': keywords}
> -        # add_script_data(req, data)
> +
>          if filename == 'bh_ticket.html':
>              # add_script(req, 'theme/js/keywordsuggest_ticket.js')
>              if req.path_info.startswith('/ticket/'):
> @@ -890,61 +888,10 @@ class KeywordSuggestModule(Component):
>                          });"""
>
>          if filename == 'bh_query.html':
> -            js = """jQuery(document).ready(function ($) {
> -                          function addAutocompleteBehavior() {
> -                            var filters = $('#filters');
> -                            var contains = $.contains // jQuery 1.4+
> -                              || function (container, contained) {
> -                              while (contained !== null) {
> -                                if (container === contained)
> -                                  return true;
> -                                contained = contained.parentNode;
> -                              }
> -                              return false;
> -                            };
> -                            var listener = function (event) {
> -                              var target = event.target ||
> event.srcElement;
> -                              filters.each(function () {
> -                                if (contains(this, target)) {
> -                                  var input =
> $(this).find('input:text').filter(function () {
> -                                    return target === this;
> -                                  });
> -                                  var name = input.attr('name');
> -                                  if (input.attr('autocomplete') !==
> 'off' &&
> -
>  /^(?:[0-9]+_)?(?:keywords)$/.test(name)) {
> -                                    input.tagsinput({
> -                                        typeahead: {
> -                                            source: %(keywords)s
> -                                            }
> -                                        });
> -                                    input.focus(); // XXX Workaround for
> Trac 0.12.2 and jQuery 1.4.2
> -                                  }
> -                                }
> -                              });
> -                            };
> -                            if ($.fn.on) {
> -                              // delegate method is available in jQuery
> 1.7+
> -                              filters.on('focusin', 'input:text',
> listener);
> -                            }
> -                            else if ($.fn.delegate) {
> -                              // delegate method is available in jQuery
> 1.4.2+
> -                              filters.delegate('input:text', 'focus',
> listener);
> -                            }
> -                            else if (window.addEventListener) {
> -                              // use capture=true cause focus event
> doesn't bubble in the default
> -                              filters.each(function () {
> -                                this.addEventListener('focus', listener,
> true);
> -                              });
> -                            }
> -                            else {
> -                              // focusin event bubbles, the event is
> avialable for IE only
> -                              filters.each(function () {
> -                                this.attachEvent('onfocusin', listener);
> -                              });
> -                            }
> -                          }
> -                          addAutocompleteBehavior();
> -                });"""
> +            data = {'keywords': keywords}
> +            add_script_data(req, data)
> +            add_script(req, 'theme/js/keywordsuggest_query.js')
> +
>          # inject transient part of javascript directly into ticket.html
> template
>          if req.path_info.startswith('/ticket/') or \
>                  req.path_info.startswith('/newticket'):
> @@ -952,9 +899,6 @@ class KeywordSuggestModule(Component):
>                                'keywords': keywords
>                                }
>              stream = stream |
> Transformer('.//head').append(tag.script(Markup(js_ticket),
> type='text/javascript'))
> -        if req.path_info.startswith('/query'):
> -            js_ticket = js % {'keywords': keywords}
> -            stream = stream |
> Transformer('.//head').append(tag.script(Markup(js_ticket),
> type='text/javascript'))
>
>          return stream
>
> @@ -964,29 +908,30 @@ class KeywordSuggestModule(Component):
>          """
>          #currently all the keywords are taken through the db query and
> then sort them according to there frequency
>          # get keywords from db
> -        db = self.env.get_db_cnx()
> -        cursor = db.cursor()
>          keywords = []
> -        if self.env.product is not None:
> -            product = self.env.product._data['prefix']
> -            product_sql = " AND t.product = '%s'" % product
> -        else:
> -            product_sql = ""
> -        sql = """SELECT t.keywords FROM ticket AS t WHERE t.keywords IS
> NOT null%s""" % product_sql
> +        with self.env.db_direct_query as db:
> +            cursor = db.cursor()
> +
> +            if self.env.product is not None:
> +                product = self.env.product._data['prefix']
> +                product_sql = " AND t.product = '%s'" % product
> +            else:
> +                product_sql = ""
> +            sql = """SELECT t.keywords FROM ticket AS t WHERE t.keywords
> IS NOT null%s""" % product_sql
>
> -        cursor.execute(sql)
> +            cursor.execute(sql)
>
> -        for row in cursor:
> -            if not row[0] == '':
> -                row_val = str(row[0]).split(',')
> -                for val in row_val:
> -                    keywords.append(val.strip())
> -        # sort keywords according to frequency of occurrence
> -        if keywords:
> -            keyword_dic = Counter(keywords)
> -            keywords = sorted(keyword_dic, key=lambda key:
> -keyword_dic[key])
> -        else:
> -            keywords = ''
> +            for row in cursor:
> +                if not row[0] == '':
> +                    row_val = str(row[0]).split(',')
> +                    for val in row_val:
> +                        keywords.append(val.strip())
> +            # sort keywords according to frequency of occurrence
> +            if keywords:
> +                keyword_dic = {keyword: keywords.count(keyword) for
> keyword in keywords}
> +                keywords = sorted(keyword_dic, key=lambda key:
> -keyword_dic[key])
> +            else:
> +                keywords = ''
>
>          return keywords
>
> @@ -1001,6 +946,7 @@ class DuplicateTicketSearch(Component):
>      # ITemplateStreamFilter methods
>
>      def filter_stream(self, req, method, filename, stream, data):
> +
>          add_script(req, 'theme/js/popoverDupSearch.js')
>
>          if filename == 'bh_ticket.html':
> @@ -1015,15 +961,17 @@ class DuplicateTicketSearch(Component):
>      def match_request(self, req):
>          """Handle requests sent to /user_list and /ticket/user_list
>          """
> -        return req.path_info.rstrip('/') == '/duplicate_ticket_search'
> +        return re.match('.*/duplicate_ticket_search$', req.path_info)
>
>      def process_request(self, req):
> -        terms = req.args.get('q').split(' ')
> +
> +        terms = self._terms_to_search(req)
> +        term_split = req.args.get('q').split(' ')
>
>          with self.env.db_direct_query as db:
> -            sql, args = self._search_to_sql(db, ['summary', 'keywords',
> 'description'], terms)
> -            sql2, args2 = self._search_to_sql(db, ['newvalue'], terms)
> -            sql3, args3 = self._search_to_sql(db, ['value'], terms)
> +            sql, args = self._sql_to_search(db, ['summary', 'keywords',
> 'description'], terms)
> +            sql2, args2 = self._sql_to_search(db, ['newvalue'], terms)
> +            sql3, args3 = self._sql_to_search(db, ['value'], terms)
>              if self.env.product is not None:
>                  product_sql = "product='%s' AND" %
> self.env.product._data['prefix']
>              else:
> @@ -1048,9 +996,9 @@ class DuplicateTicketSearch(Component):
>                  summary_term_count = 0
>                  summary_list = summary.split(' ')
>                  for s in summary_list:
> -                    for t in terms:
> +                    for t in term_split:
>                          if s.lower() == t.lower():
> -                            summary = summary.replace(s,'<em>'+t+'</em>')
> +                            summary = summary.replace(s, '<em>'+t+'</em>')
>                              summary_term_count += 1
>                              break
>
> @@ -1064,7 +1012,7 @@ class DuplicateTicketSearch(Component):
>
>      # Private methods
>
> -    def _search_to_sql(self, db, columns, terms):
> +    def _sql_to_search(self, db, columns, terms):
>          """Convert a search query into an SQL WHERE clause and
> corresponding
>          parameters.
>
> @@ -1080,17 +1028,22 @@ class DuplicateTicketSearch(Component):
>              args.extend(['%' + db.like_escape(t) + '%'] * len(columns))
>          return sql, tuple(args)
>
> +    def _terms_to_search(self, req):
> +        """Convert a search query into different terms to search.
>
> +        The result is returned as a list of terms.
> +        """
> +        search_string = req.args.get('q')
> +        terms = [search_string]
> +        temp_string = search_string
> +        search_string_split = search_string.split(' ')
> +
> +        for i in range(len(search_string_split)-3):
> +            search_string = re.sub('^'+search_string_split[i]+' ', '',
> search_string)
> +            terms.append(search_string)
> +        search_string = temp_string
> +        for i in reversed(xrange(3, len(search_string_split))):
> +            search_string = re.sub(' '+search_string_split[i]+'$', '',
> search_string)
> +            terms.append(search_string)
>
> -
> -
> -
> -
> -
> -
> -
> -
> -
> -
> -
> -
> +        return terms
> \ No newline at end of file
>
>
>


-- 




*Thimal Kempitiya <http://www.facebook.com/thimalk> UndergraduateDepartment
of Computer Science and Engineering University of Moratuwa.*

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message