ctdo-trac/TracRendezVous/tracrendezvous/rendezvous/api.py

192 lines
7.8 KiB
Python

# -*- coding: utf-8 -*-
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License version 2 as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; see the file COPYING.LIB. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
# ---
# Copyright (C) 2008, hotshelf <skoegl@online.de>
#
''' the api of the rendezvous system'''
from trac.resource import IResourceManager
from trac.config import ExtensionOption
from trac.core import Interface, Component, implements
from trac.perm import IPermissionRequestor
from trac.util import Ranges
from trac.util.datefmt import get_timezone, utc, format_time, localtz
from trac.wiki import IWikiSyntaxProvider
from genshi.builder import tag
from ctdotools.utils import validate_id, gen_wiki_page
from tracrendezvous.location.model import ItemLocation
from tracrendezvous.event.model import Event
from model import *
from datetime import datetime
__all__ = ['IRendezVousActionController', 'RendezVousSystem']
class IRendezVousActionController(Interface):
"""Extension point interface for components willing to participate
in the rendezvous workflow.
This is mainly about controlling the changes to the rendezvous ''status'',
though not restricted to it.
"""
def get_rendezvous_actions(req, rendezvous):
"""Return an iterable of `(weight, action)` tuples corresponding to
the actions that are contributed by this component.
That list may vary given the current state of the rendezvous and the
actual request parameter.
`action` is a key used to identify that particular action.
(note that 'history' and 'diff' are reserved and should not be used
by plugins)
The actions will be presented on the page in descending order of the
integer weight. The first action in the list is used as the default
action.
When in doubt, use a weight of 0."""
def get_all_status():
"""Returns an iterable of all the possible values for the ''status''
field this action controller knows about.
This will be used to populate the query options and the like.
It is assumed that the initial status of a rendezvous is 'new' and
the terminal status of a rendezvous is 'closed'.
"""
def render_rendezvous_action_control(req, rendezvous, action):
"""Return a tuple in the form of `(label, control, hint)`
`label` is a short text that will be used when listing the action,
`control` is the markup for the action control and `hint` should
explain what will happen if this action is taken.
This method will only be called if the controller claimed to handle
the given `action` in the call to `get_rendezvous_actions`.
Note that the radio button for the action has an `id` of
`"action_%s" % action`. Any `id`s used in `control` need to be made
unique. The method used in the default ITicketActionController is to
use `"action_%s_something" % action`.
"""
def change_rendezvous_workflow(req, rendezvous, action):
"""Change workflow
"""
def current_rendezvous():
"""Return an iterable of current, active rendezvouses."""
def past_rendezvous():
"""Return an iterable of past rendezvouses."""
class RendezVousSystem(Component):
"""base mathods of the rendezvous system"""
implements(IPermissionRequestor,
IResourceManager,
IWikiSyntaxProvider)
workflow_controller = ExtensionOption('rendezvous', 'workflow',
IRendezVousActionController, 'RendezVousWorkflow',
"""Ordered list of workflow controllers to use for rendezvous actions.""")
_actions = ['RENDEZVOUS_ADD', 'RENDEZVOUS_DELETE', 'RENDEZVOUS_MODIFY',
'RENDEZVOUS_VIEW', 'RENDEZVOUS_COMMENT_ADD', 'RENDEZVOUS_COMMENT_VIEW',
'RENDEZVOUS_DATE_ADD', 'RENDEZVOUS_DATE_DELETE', 'RENDEZVOUS_DATE_MODIFY',
'RENDEZVOUS_DATE_VIEW', 'RENDEZVOUS_VOTE_ADD', 'RENDEZVOUS_VOTE_DELETE',
'RENDEZVOUS_VOTE_MODIFY', 'RENDEZVOUS_VOTE_VIEW', 'RENDEZVOUS_VOTE_GRAPH_VIEW',
'RENDEZVOUS_VOTE_VIEW_OTHERS', 'RENDEZVOUS_LOCATION_VIEW', 'RENDEZVOUS_LOCATION_ADD',
'RENDEZVOUS_LOCATION_DELETE', 'RENDEZVOUS_LOCATION_MODIFY',
('RENDEZVOUS_ADMIN',
('RENDEZVOUS_ADD', 'RENDEZVOUS_DELETE', 'RENDEZVOUS_MODIFY', 'RENDEZVOUS_VIEW',
'RENDEZVOUS_VIEW', 'RENDEZVOUS_COMMENT_ADD', 'RENDEZVOUS_DATE_ADD',
'RENDEZVOUS_DATE_DELETE', 'RENDEZVOUS_DATE_MODIFY', 'RENDEZVOUS_DATE_VIEW',
'RENDEZVOUS_VOTE_ADD', 'RENDEZVOUS_VOTE_DELETE', 'RENDEZVOUS_VOTE_MODIFY',
'RENDEZVOUS_VOTE_GRAPH_VIEW', 'RENDEZVOUS_VOTE_VIEW_OTHERS',
'RENDEZVOUS_LOCATION_ADD', 'RENDEZVOUS_LOCATION_DELETE', 'RENDEZVOUS_LOCATION_MODIFY'))]
# workflow stuff
def get_available_actions(self, req, rendezvous):
"""Returns a sorted list of available actions"""
# The list should not have duplicates.
actions = {}
weighted_actions = self.workflow_controller.get_rendezvous_actions(req, rendezvous)
for weight, action in weighted_actions:
if action in actions:
actions[action] = max(actions[action], weight)
else:
actions[action] = weight
all_weighted_actions = [(weight, action) for action, weight in
actions.items()]
return [x[1] for x in sorted(all_weighted_actions, reverse=True)]
def get_all_status(self):
"""Returns a sorted list of all the states all of the action
controllers know about."""
valid_states = set()
valid_states.update(self.workflow_controller.get_all_status())
return sorted(valid_states)
# IWikiSyntaxProvider methods
def get_wiki_syntax(self):
return []
def get_link_resolvers(self):
yield ('rendezvous', self._format_link)
def _format_link(self, formatter, ns, target, label, fullmatch=None):
link, params, fragment = formatter.split_link(target)
r = Ranges(link)
if len(r) == 1:
num = r.a
rendezvous = formatter.resource("rendezvous", num)
validate_id(num)
cursor = formatter.db.cursor()
cursor.execute("SELECT name,status "
"FROM rendezvous WHERE rendezvous_id=%s", (num,))
for name, status in cursor:
title = "rendezvous #%d: %s (%s)" % (num, name, status)
if label == link:
label = title
href = formatter.href.rendezvous(num)
return tag.a(label, title=title, href=href)
return tag.a(label, class_='missing rendezvous')
# IPermissionRequestor methods
def get_permission_actions(self):
'''returns all permissions this component provides'''
return self._actions
# IResourceManager methods
def get_resource_realms(self):
yield 'rendezvous'
def get_resource_description(self, resource, format=None, context=None,
**kwargs):
if format == 'compact':
return 'RendezVous #%s' % resource.id
elif format == 'summary':
from tracrendezvous.model import RendezVous
rendezvous = RendezVous.fetch_one(self.env, resource.id)
return "RendezVous #%d - %s (%s)" % (rendezvous.rendezvous_id, rendezvous.name, rendezvous.status)