Opened 9 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


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 import format_to_html
from trac.util import TracError
from trac.util.text import to_unicode
from trac.web.api import IRequestFilter, RequestDone
from import add_script
from import parse_args, IWikiMacroProvider
from import WikiMacroBase
from import WikiPage
from import WikiModule

from macropost.api import IMacroPoster

class AddMinuteMacro(WikiMacroBase):
    """A macro to add meeting minutes to a page more interactively. Usage:
    The macro accepts one optional argument that allows appending
    to the wiki page even though user may not have modify permission:
    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 =
        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
            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())),
            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?",
        # 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.')
                    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),
                                the_message += tag.div(tag.strong("invalid: "),

                # 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:        
          , 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.
                            "AddMinute saved - redirecting to: %s" % page_url)
                        req._outheaders = []
                    except RequestDone:
                        req.AddMinute_raise = True
                the_message = tag.div(tag.strong("ERROR: "), "[[AddMinute]] "
                          "macro call must be the only content on its line. "
                          "Could not add minute.",

        the_form = tag.form(
                        tag.legend("Add Minute"),
                            (wikipreview and "Page preview..." or None),
                            tag.textarea((not cancel and minute or ""),
                                        cols=80, rows=5,
                                    disabled=(not canminute and "disabled" or None)),
                        (req.authname == 'anonymous' and tag.div(
                            tag.label("Your email or username:",
                            tag.input(id="authorAddMinute", type="text",
                                    size=30, value=authname)
                        ) or None),
                        tag.input(type="hidden", name="__FORM_TOKEN",
                            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",
                                    disabled=(not canminute and "disabled" or None)),
                            tag.input(value="Cancel", type="submit",
                                    disabled=(not canminute and "disabled" or None)),

        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")
            raise RequestDone
        return template, data, content_type

Attachments (0)

Change History (0)

Modify Ticket

Change Properties
Set your email in Preferences
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.