Modify

Opened 16 years ago

#4308 new enhancement

modified to add minutes...

Reported by: Mogga Owned by: Alec Thomas
Priority: normal Component: AddCommentMacro
Severity: normal Keywords:
Cc: Trac Release: 0.10

Description

I like this macro for recording minutes in a meeting... I modified to remove the commenting and changed it to AddMinuteMacro...

# vim: expandtab
import re, time
from StringIO import StringIO

from genshi.builder import tag

from trac.core import *
from trac.wiki.formatter import format_to_html
from trac.util import TracError
from trac.util.text import to_unicode
from trac.web.api import IRequestFilter, RequestDone
from trac.web.chrome import add_script
from trac.wiki.api import parse_args, IWikiMacroProvider
from trac.wiki.macros import WikiMacroBase
from trac.wiki.model import WikiPage
from trac.wiki.web_ui import WikiModule

from macropost.api import IMacroPoster

class AddMinuteMacro(WikiMacroBase):
    """A macro to add meeting minutes to a page more interactively. Usage:
    {{{
    [[AddMinute]]
    }}}
    The macro accepts one optional argument that allows appending
    to the wiki page even though user may not have modify permission:
    {{{
    [[AddMinute(appendonly)]]
    }}}
    """
    implements(IWikiMacroProvider, IRequestFilter, IMacroPoster)

    def expand_macro(self, formatter, name, content):
        
        args, kw = parse_args(content)
        req = formatter.req
        context = formatter.context
        
        # Prevent multiple inclusions - store a temp in req
        if hasattr(req, 'AddMinutemacro'):
            raise TracError('\'AddMinute\' macro cannot be included twice.')
        req.AddMinutemacro = True
        
        # Prevent it being used outside of wiki page context
        resource = context.resource
        if not resource.realm == 'wiki':
            raise TracError('\'AddMinute\' macro can only be used in Wiki pages.')
        
        # Setup info and defaults
        authname = req.authname
        page = WikiPage(self.env, resource)
        page_url = req.href.wiki(resource.id)
        wikipreview = req.args.get("preview", "")
        
        # Can this user add a minute to this page?
        appendonly = ('appendonly' in args)
        canminute = False
        if page.readonly:
            if 'WIKI_ADMIN' in req.perm(resource):
                canminute = True
        elif 'WIKI_MODIFY' in req.perm(resource):
            canminute = True
        elif appendonly and 'WIKI_VIEW' in req.perm(resource):
            canminute = True
        else:
            raise TracError('Error: Insufficient privileges to AddMinute')
        
        # Get the data from the POST
        minute = req.args.get("AddMinute", "")
        preview = req.args.get("previewAddMinute", "")
        cancel = req.args.get("cancelAddMinute", "")
        submit = req.args.get("submitAddMinute", "")
        if not cancel and req.authname == 'anonymous':
            authname = req.args.get("authorAddMinute", authname)
        
        # Ensure [[AddMinute]] is not present in minute, so that infinite
        # recursion does not occur.
        minute = to_unicode(re.sub('(^|[^!])(\[\[AddMinute)', '\\1!\\2', minute))
        
        the_preview = the_message = the_form = tag()

        # If we are submitting or previewing, inject minute as it should look
        if canminute and minute and (preview or submit):
            heading = tag.h4("minute by ", authname, " on ",
                        to_unicode(time.strftime('%c', time.localtime())),
                        id="minutepreview")
            if preview:
                the_preview = tag.div(heading,
                                format_to_html(self.env, context, minute),
                                class_="wikipage", id="preview")
        
        # Check the form_token
        form_ok = True
        if submit and req.args.get('__FORM_TOKEN','') != req.form_token:
            form_ok = False
            the_message = tag.div(tag.strong("ERROR: "),
                "AddMinute received incorrect form token. "
                "Do you have cookies enabled?",
                class_="system-message")
        
        # When submitting, inject minute before macro
        if minute and submit and canminute and form_ok:
            submitted = False
            newtext = ""
            for line in page.text.splitlines():
                if line.find('[[AddMinute') == 0:
                    newtext += "%s\n" % (minute)
                    submitted = True
                newtext += line+"\n"
            if submitted:
                page.text = newtext
                
                # Let the wiki page manipulators have a look at the
                # submission.
                valid = True
                req.args.setdefault('minute', 'Minute added.')
                try:
                    for manipulator in WikiModule(self.env).page_manipulators:
                        for field, message in manipulator.validate_wiki_page(req, page):
                            valid = False
                            if field:
                                the_message += tag.div(tag.strong("invalid field '%s': " % field),
                                                       message,
                                                       class_="system-message")
                            else:
                                the_message += tag.div(tag.strong("invalid: "),
                                                       message,
                                                       class_="system-message")

                # The TracSpamfilterPlugin does not generate messages,
                # but throws RejectContent.
                except TracError, s:
                    valid = False
                    the_message += tag.div(tag.strong("ERROR: "), s, class_="system-message")

                if valid:        
                    page.save(authname, req.args['minute'], req.environ['REMOTE_ADDR'])
                    # We can't redirect from macro as it will raise RequestDone
                    # which like other macro errors gets swallowed in the Formatter.
                    # We need to re-raise it in a post_process_request instead.
                    try:
                        self.env.log.debug(
                            "AddMinute saved - redirecting to: %s" % page_url)
                        req._outheaders = []
                        req.redirect(page_url)
                    except RequestDone:
                        req.AddMinute_raise = True
            else:
                the_message = tag.div(tag.strong("ERROR: "), "[[AddMinute]] "
                          "macro call must be the only content on its line. "
                          "Could not add minute.",
                          class_="system-message")

        the_form = tag.form(
                    tag.fieldset(
                        tag.legend("Add Minute"),
                        tag.div(
                            (wikipreview and "Page preview..." or None),
                            tag.textarea((not cancel and minute or ""),
                                        class_="wikitext",
                                        id="AddMinute",
                                        name="AddMinute",
                                        cols=80, rows=5,
                                    disabled=(not canminute and "disabled" or None)),
                            class_="field"
                        ),
                        (req.authname == 'anonymous' and tag.div(
                            tag.label("Your email or username:",
                                    for_="authorAddMinute"),
                            tag.input(id="authorAddMinute", type="text",
                                    size=30, value=authname)
                        ) or None),
                        tag.input(type="hidden", name="__FORM_TOKEN",
                                        value=req.form_token),
                        tag.div(
                            tag.input(value="Add Minute", type="submit",
                                    name="submitAddMinute", size=30,
                                    disabled=(not canminute and "disabled" or None)),
                            tag.input(value="Preview Minute", type="submit",
                                    name="previewAddMinute",
                                    disabled=(not canminute and "disabled" or None)),
                            tag.input(value="Cancel", type="submit",
                                    name="cancelAddMinute",
                                    disabled=(not canminute and "disabled" or None)),
                            class_="buttons"
                        ),
                    ),
                    method="post",
                    action=page_url+"#minuteing",
                )

        if not wikipreview:
            # Wiki edit preview already adds this javascript file
            add_script(req, 'common/js/wikitoolbar.js')
        
        return tag.div(the_preview, the_message, the_form, id="minuteing")
    
    # IMacroPoster method
    
    def process_macro_post(self, req):
        self.log.debug('AddMinuteMacro: Got a POST')

    # IRequestFilter methods

    def pre_process_request(self, req, handler):
        return handler

    def post_process_request(self, req, template, data, content_type):
        if hasattr(req, 'AddMinute_raise'):
            self.env.log.debug("AddMinuteMacro: Re-raising RequestDone from redirect")
            del(req.AddMinute_raise)
            raise RequestDone
        return template, data, content_type


Attachments (0)

Change History (0)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The owner will remain Alec Thomas.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.