192 lines
7.8 KiB
Python
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)
|