source: tagsplugin/tags/0.3.1/tractags/web_ui.py

Last change on this file was 1812, checked in by Alec Thomas, 17 years ago
  • Fix for bug in non-expression_space mode.
File size: 7.8 KB
Line 
1from trac.core import *
2from trac.web.main import IRequestHandler
3from trac.web.chrome import ITemplateProvider, INavigationContributor
4from trac.util import Markup
5from StringIO import StringIO
6from trac.wiki.web_ui import WikiModule
7from trac.wiki.formatter import wiki_to_oneliner
8import re
9try:
10    set = set
11except:
12    from sets import Set as set
13
14_tag_split = re.compile('[,\s]+')
15
16class TagsWikiModule(WikiModule):
17    """ Replacement for the default Wiki module. Tag editing is much more
18        intuitive now, as it no longer requires the TagIt macro and JavaScript
19        magic. """
20
21    def _do_save(self, req, db, page):
22        # This method is overridden so the user doesn't get "Page not modified"
23        # exceptions when updating tags but not wiki content.
24        from tractags.api import TagEngine
25        if 'tags' in req.args:
26            newtags = set([t.strip() for t in
27                          _tag_split.split(req.args.get('tags')) if t.strip()])
28            wikitags = TagEngine(self.env).tagspace.wiki
29            oldtags = wikitags.get_tags([page.name])
30
31            if oldtags != newtags:
32                wikitags.replace_tags(req, page.name, newtags)
33                # No changes, just redirect
34                if req.args.get('text') == page.text:
35                    req.redirect(self.env.href.wiki(page.name))
36                    return
37        return WikiModule._do_save(self, req, db, page)
38
39    def process_request(self, req):
40        from tractags.api import TagEngine
41        from trac.web.chrome import add_stylesheet
42
43        add_stylesheet(req, 'tags/css/tractags.css')
44
45        pagename = req.args.get('page', 'WikiStart')
46        action = req.args.get('action', 'view')
47
48        engine = TagEngine(self.env)
49        wikitags = engine.tagspace.wiki
50        tags = list(wikitags.get_tags([pagename]))
51        tags.sort()
52
53        if action == 'edit':
54            req.hdf['tags'] = req.args.get('tags', ', '.join(tags))
55        elif action == 'view':
56            hdf_tags = []
57            for tag in tags:
58                href, title = engine.get_tag_link(tag)
59                hdf_tags.append({'name': tag,
60                                 'href': href,
61                                 'title': title})
62            req.hdf['tags'] = hdf_tags
63        result = WikiModule.process_request(self, req)
64        if result is None:
65            return None
66        if result[0] == 'wiki.cs':
67            return 'tagswiki.cs', None
68        return result
69
70class TagsModule(Component):
71    """ Serve a /tags namespace. Top-level displays tag cloud, sub-levels
72        display output of ListTagged(tag).
73
74        The following configuration options are supported:
75
76        [tags]
77        # Use a tag list or cloud for the main index
78        index = cloud|list
79        # The keyword arguments to pass to the TagCloud or ListTags macros that
80        # is being used for the index.
81        index.args = ...
82        # Keyword arguments to pass to the listing for each tag under the
83        # /tags/ URL space.
84        listing.args = ...
85    """
86    implements(IRequestHandler, INavigationContributor, ITemplateProvider)
87
88    def _prepare_wiki(self, req):
89        from tractags.api import TagEngine
90        page = req.path_info[6:] or 'WikiStart'
91        engine = TagEngine(self.env)
92        wikitags = engine.tagspace.wiki
93        tags = list(wikitags.get_tags(page))
94        tags.sort()
95
96        action = req.args.get('action', 'view')
97        if action == 'edit':
98            req.hdf['tags'] = req.args.get('tags', ', '.join(tags))
99        elif action == 'view':
100            hdf_tags = []
101            for tag in tags:
102                href, title = engine.get_tag_link(tag)
103                hdf_tags.append({'name': tag,
104                                 'href': href,
105                                 'title': title})
106            req.hdf['tags'] = hdf_tags
107
108    # ITemplateProvider methods
109    def get_templates_dirs(self):
110        """
111        Return the absolute path of the directory containing the provided
112        ClearSilver templates.
113        """
114        from pkg_resources import resource_filename
115        return [resource_filename(__name__, 'templates')]
116
117    def get_htdocs_dirs(self):
118        """Return the absolute path of a directory containing additional
119        static resources (such as images, style sheets, etc).
120        """
121        from pkg_resources import resource_filename
122        return [('tags', resource_filename(__name__, 'htdocs'))]
123   
124    # INavigationContributor methods
125    def get_active_navigation_item(self, req):
126        return 'tags'
127
128    def get_navigation_items(self, req):
129        from trac.web.chrome import Chrome
130        yield ('metanav', 'tags',
131               Markup('<a href="%s" accesskey="T">Tag Index</a>',
132                      self.env.href.tags()))
133
134    # IRequestHandler methods
135    def match_request(self, req):
136        return req.path_info.startswith('/tags')
137
138    def process_request(self, req):
139        from tractags.macros import TagMacros
140        from tractags.parseargs import parseargs
141        from trac.web.chrome import add_stylesheet
142
143        add_stylesheet(req, 'tags/css/tractags.css')
144        req.hdf['trac.href.tags'] = self.env.href.tags()
145
146        def update_from_req(args):
147            for k in req.args.keys():
148                args[str(k)] = str(req.args.get(k))
149
150        if re.match('^/tags/?$', req.path_info):
151            index = self.env.config.get('tags', 'index', 'cloud')
152            index_kwargs = {'smallest': 10, 'biggest': 30}
153            _, config_kwargs = parseargs(self.env.config.get('tags', 'index.args', ''))
154            index_kwargs.update(config_kwargs)
155            update_from_req(index_kwargs)
156
157            if index == 'cloud':
158                req.hdf['tag.body'] = Markup(
159                    TagMacros(self.env).render_tagcloud(req, **index_kwargs))
160            elif index == 'list':
161                req.hdf['tag.body'] = Markup(
162                    TagMacros(self.env).render_listtagged(req, **index_kwargs))
163            else:
164                raise TracError("Invalid index style '%s'" % index)
165        else:
166            expression_space = self.env.config.getbool('tags', 'expression_space', 'false')
167            _, args = parseargs(self.env.config.get('tags', 'listing.args', ''))
168            if expression_space:
169                req.hdf['tag.title'] = Markup('Objects matching the expression <i>%s</i>' % req.path_info[6:])
170                args['expression'] = req.path_info[6:]
171                tags = []
172            else:
173                req.hdf['tag.title'] = Markup('Objects tagged <i>%s</i>' % req.path_info[6:])
174                tags = re.split('[,+]', req.path_info[6:])
175            update_from_req(args)
176            req.hdf['tag.body'] = Markup(
177                TagMacros(self.env).render_listtagged(req, *tags, **args))
178        return 'tags.cs', None
179
180# XXX I think this is planned for some AJAX goodness, commenting out for now. (Alec) XXX
181#class TagsLi(Component):
182#    implements(IRequestHandler)
183#   
184#    # IRequestHandler methods
185#    def match_request(self, req):
186#        return req.path_info == '/tagli'
187#               
188#    def process_request(self, req):
189#        db = self.env.get_db_cnx()
190#        cursor = db.cursor()
191#        cs = db.cursor()
192#        tag = req.args.get('tag')
193#        req.send_response(200)
194#        req.send_header('Content-Type', 'text/plain')
195#        req.end_headers()
196#        buf = StringIO()
197#        if tag:
198#            buf.write('WHERE tag LIKE \'%s%s\'' % (tag,'%'))
199#           
200#        cursor.execute('SELECT DISTINCT tag FROM tags %s ORDER BY tag' % (buf.getvalue()))
201#
202#        msg = StringIO()
203#
204#        msg.write('<ul>')
205#        while 1:
206#            row = cursor.fetchone()
207#            if row == None:
208#                 break
209#
210#            t = row[0]
211#            msg.write('<li>')
212#            msg.write(t)
213#            msg.write('</li>')
214#
215#        msg.write('</ul>')
216#        req.write(msg.getvalue())
Note: See TracBrowser for help on using the repository browser.