incubator-bloodhound-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gary <gary.mar...@wandisco.com>
Subject Re: svn commit: r1326583 - in /incubator/bloodhound/trunk/bloodhound_dashboard: ./ bhdashboard/ bhdashboard/layouts/templates/ bhdashboard/web_ui/ bhdashboard/web_ui/templates/ bhdashboard/web_ui/ticket/ bhdashboard/widgets/ bhdashboard/widgets/templates/
Date Mon, 16 Apr 2012 13:15:35 GMT
Hi,

This commit is a little on the large side as it includes a refactor of 
the dashboard web_ui, but it provides a timeline for the milestone view 
and the beginnings of a progress bar.

Cheers,
     Gary


On 04/16/2012 02:00 PM, gjm@apache.org wrote:
> Author: gjm
> Date: Mon Apr 16 13:00:35 2012
> New Revision: 1326583
>
> URL: http://svn.apache.org/viewvc?rev=1326583&view=rev
> Log:
> dashboard: Activity feed in milestone view using Bloodhound widget markup; initial version
of progress bar widget
>
> Added:
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py   (with props)
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py 
 (with props)
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
  (with props)
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py
  (with props)
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py
  (with props)
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
  (with props)
> Removed:
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui.py
> Modified:
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/layouts/templates/widget_macros.html
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/util.py
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/query.py
>      incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py
>      incubator/bloodhound/trunk/bloodhound_dashboard/setup.py
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py (added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py Mon Apr 16 13:00:35
2012
> @@ -0,0 +1,30 @@
> +#!/usr/bin/env python
> +# -*- coding: UTF-8 -*-
> +
> +#  Licensed to the Apache Software Foundation (ASF) under one
> +#  or more contributor license agreements.  See the NOTICE file
> +#  distributed with this work for additional information
> +#  regarding copyright ownership.  The ASF licenses this file
> +#  to you under the Apache License, Version 2.0 (the
> +#  "License"); you may not use this file except in compliance
> +#  with the License.  You may obtain a copy of the License at
> +#
> +#   http://www.apache.org/licenses/LICENSE-2.0
> +#
> +#  Unless required by applicable law or agreed to in writing,
> +#  software distributed under the License is distributed on an
> +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +#  KIND, either express or implied.  See the License for the
> +#  specific language governing permissions and limitations
> +#  under the License.
> +
> +
> +r"""Project dashboard for Apache(TM) Bloodhound
> +
> +Provide a single namespace to access JSON functions.
> +"""
> +
> +try :
> +    from json import *
> +except ImportError:
> +    from simplejson import *
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/_json.py
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/layouts/templates/widget_macros.html
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/layouts/templates/widget_macros.html?rev=1326583&r1=1326582&r2=1326583&view=diff
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/layouts/templates/widget_macros.html
(original)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/layouts/templates/widget_macros.html
Mon Apr 16 13:00:35 2012
> @@ -2,8 +2,11 @@
>       xmlns="http://www.w3.org/1999/xhtml"
>       xmlns:py="http://genshi.edgewall.org/"
>       xmlns:xi="http://www.w3.org/2001/XInclude"
> +    xmlns:bh="http://issues.apache.org/bloodhound/wiki/Ui/Dashboard"
>       py:strip="">
>
> +<!-- Helper functions (py:def) -->
> +
>     <div py:def="widget_container(w)" role="application">
>       <h1 style="display: inline;">${w.title}</h1>
>       <py:if test="w.ctxtnav">
> @@ -27,4 +30,70 @@
>       <br/>
>       ${w.content}
>     </div>
> +
> +<!-- Widget markup (py:match) -->
> +
> +<div py:def="bhnotfound()" class="alert alert-error">
> +<span class="label label-important">Error</span>
> +    Dashboard data is missing .
> +    Is<code>bhdashboard.web_ui.DashboardModule</code>  component disabled?
> +</div>
> +
> +<!--
> +  Sample layout tag
> +
> +<bh:layout type="LayoutName">
> +<bh:schema>
> +      JSON object describing positioning and ...
> +</bh:schema>
> +<bh:widgets>
> +<bh:w id="simple_widget" type="WidgetName" altlinks="false">
> +<bh:args>
> +<bh:arg name="arg1">value1</bh:arg>
> +<bh:arg name="arg2">value2</bh:arg>
> +</bh:args>
> +</bh:w>
> +<bh:l id="nested_layout" type="LayoutName">
> +<bh:schema>
> +          JSON object describing positioning and ...
> +</bh:schema>
> +<bh:widgets>
> +          ... Same as before ...
> +</bh:widgets>
> +</bh:l>
> +</bh:widgets>
> +</bh:layout>
> +  -->
> +<py:match path="bh:layout">
> +<py:choose test="">
> +<py:when test="bhdb">
> +        ${bhdb.embed_layout(context, layout=select('@type'), schema=select('bh:schema'),
widgets=select('bh:widgets'))}
> +</py:when>
> +<py:otherwise>
> +        ${bhnotfound()}
> +</py:otherwise>
> +</py:choose>
> +</py:match>
> +<!--
> +  Sample widget tag
> +
> +<bh:widget id="simple_widget" type="WidgetName" altlinks="false">
> +<bh:args>
> +<bh:arg name="arg1">value1</bh:arg>
> +<bh:arg name="arg2">value2</bh:arg>
> +</bh:args>
> +</bh:widget>
> +
> +  -->
> +<py:match path="bh:widget">
> +<py:choose test="">
> +<py:when test="bhdb"
> +          py:with="wnm = unicode(select('@type')); args = unicode(select('bh:args/text()'))
or {}; altlinks = unicode(select('@altlinks')) != 'false'; ctxtnav = unicode(select('@ctxtnav'))
!= 'false';">
> +        ${widget_container(bhdb.expand_widget(context, dict(args=[wnm, None, {'args':
args}], altlinks=altlinks, ctxtnav=ctxtnav)))}
> +</py:when>
> +<py:otherwise>
> +        ${bhnotfound()}
> +</py:otherwise>
> +</py:choose>
> +</py:match>
>   </html>
>
> Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/util.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/util.py?rev=1326583&r1=1326582&r2=1326583&view=diff
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/util.py (original)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/util.py Mon Apr 16 13:00:35
2012
> @@ -144,6 +144,24 @@ def pretty_wrapper(wrapped, *decorators)
>       return update_wrapper(wrapper, wrapped)
>
>   #------------------------------------------------------
> +#    Trac core
> +#------------------------------------------------------
> +
> +def resolve_ep_class(interface, component, clsnm, **kwargs):
> +    r"""Retrieve the class implementing an interface (by name)
> +    """
> +    ep = ExtensionPoint(interface)
> +    for c in ep.extensions(component):
> +        if c.__class__.__name__ == clsnm :
> +            return c
> +    else:
> +        if 'default' in kwargs:
> +            return kwargs['default']
> +        else:
> +            raise LookupError('No match found for class %s implementing %s' %
> +                    (clsnm, interface) )
> +
> +#------------------------------------------------------
>   #    Context information
>   #------------------------------------------------------
>
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py (added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py Mon
Apr 16 13:00:35 2012
> @@ -0,0 +1,290 @@
> +#!/usr/bin/env python
> +# -*- coding: UTF-8 -*-
> +
> +#  Licensed to the Apache Software Foundation (ASF) under one
> +#  or more contributor license agreements.  See the NOTICE file
> +#  distributed with this work for additional information
> +#  regarding copyright ownership.  The ASF licenses this file
> +#  to you under the Apache License, Version 2.0 (the
> +#  "License"); you may not use this file except in compliance
> +#  with the License.  You may obtain a copy of the License at
> +#
> +#   http://www.apache.org/licenses/LICENSE-2.0
> +#
> +#  Unless required by applicable law or agreed to in writing,
> +#  software distributed under the License is distributed on an
> +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +#  KIND, either express or implied.  See the License for the
> +#  specific language governing permissions and limitations
> +#  under the License.
> +
> +
> +r"""Project dashboard for Apache(TM) Bloodhound
> +
> +Implementing dashboard user interface.
> +"""
> +
> +__metaclass__ = type
> +
> +from itertools import izip
> +import pkg_resources
> +import re
> +
> +from genshi.builder import tag
> +from trac.core import Component, implements
> +from trac.config import Option, IntOption
> +from trac.mimeview.api import Context
> +from trac.util.translation import _
> +from trac.ticket.query import QueryModule
> +from trac.ticket.report import ReportModule
> +from trac.util.compat import groupby
> +from trac.web.api import IRequestHandler, IRequestFilter
> +from trac.web.chrome import add_ctxtnav, add_stylesheet, Chrome, \
> +                            INavigationContributor, ITemplateProvider
> +
> +from bhdashboard.api import DashboardSystem
> +from bhdashboard import json
> +
> +class DashboardModule(Component):
> +    """Web frontend for dashboard infrastructure.
> +    """
> +    implements(IRequestHandler, IRequestFilter, INavigationContributor, \
> +                ITemplateProvider)
> +
> +    mainnav_label = Option('dashboard', 'mainnav', 'Dashboard', \
> +                            """Dashboard label in mainnav""")
> +    default_widget_height = IntOption('widgets', 'default_height', 320, \
> +                            """Default widget height in pixels""")
> +
> +    # IRequestFilter methods
> +
> +    def pre_process_request(self, req, handler):
> +        """Always returns the request handler unchanged.
> +        """
> +        return handler
> +
> +    def post_process_request(self, req, template, data, content_type):
> +        """Inject dashboard helpers in data.
> +        """
> +        if data is not None :
> +            data['bhdb'] = DashboardChrome(self.env)
> +        return template, data, content_type
> +
> +    # IRequestHandler methods
> +    def match_request(self, req):
> +        """Match dashboard prefix"""
> +        return bool(re.match(r'^/dashboard(/.)?', req.path_info))
> +
> +    def process_request(self, req):
> +        """Initially this will render static widgets. With time it will be
> +        more and more dynamic and flexible.
> +        """
> +        if self.env[QueryModule] is not None:
> +            add_ctxtnav(req, _('Custom Query'), req.href.query())
> +        if self.env[ReportModule] is not None:
> +            add_ctxtnav(req, _('Reports'), req.href.report())
> +        template, layout_data = self.expand_layout_data(req,
> +            'bootstrap_grid', self.DASHBOARD_SCHEMA)
> +        widgets = self.expand_widget_data(req, layout_data)
> +        return template, {
> +                    'context' : Context.from_request(req),
> +                    'layout' : layout_data,
> +                    'widgets' : widgets,
> +                    'title' : _(self.mainnav_label),
> +                    'default' : {
> +                            'height' : self.default_widget_height or None
> +                        }
> +                }, None
> +
> +    # INavigationContributor methods
> +    def get_active_navigation_item(self, req):
> +        """Highlight dashboard mainnav item.
> +        """
> +        return 'dashboard'
> +
> +    def get_navigation_items(self, req):
> +        """Add an item in mainnav to access global dashboard
> +        """
> +        if 'DASHBOARD_VIEW' in req.perm:
> +            yield ('mainnav', 'dashboard',
> +                    tag.a(_(self.mainnav_label), href=req.href.dashboard()))
> +
> +    # ITemplateProvider methods
> +    def get_htdocs_dirs(self):
> +        """List `htdocs` dirs for dashboard and widgets.
> +        """
> +        resource_filename = pkg_resources.resource_filename
> +        return [
> +                 ('dashboard', resource_filename('bhdashboard', 'htdocs')),
> +                 #('widgets', resource_filename('bhdashboard.widgets', 'htdocs'))
> +                 ('layouts', resource_filename('bhdashboard.layouts', 'htdocs'))
> +                 ]
> +
> +    def get_templates_dirs(self):
> +        """List `templates` folders for dashboard and widgets.
> +        """
> +        resource_filename = pkg_resources.resource_filename
> +        return [resource_filename('bhdashboard.layouts', 'templates'),
> +                resource_filename('bhdashboard.web_ui', 'templates'),
> +                resource_filename('bhdashboard.widgets', 'templates')]
> +
> +    # Temp vars
> +    DASHBOARD_SCHEMA = {
> +            'div' : [
> +                    {
> +                        '_class' : 'row',
> +                        'div' : [
> +                                {
> +                                    '_class' : 'span8',
> +                                    'widgets' : [0]
> +                                },
> +                                {
> +                                    '_class' : 'span4',
> +                                    'widgets' : [1]
> +                                }
> +                            ]
> +                    }
> +                ],
> +            'widgets' : [
> +                    {
> +                        'args' : ['Container', None,
> +                                {'args' : {'layout' : 'bootstrap_btnbar',
> +                                        'schema' : '''
> +                                        {
> +                                          "toolbar" : [
> +                                              ["Products", null],
> +                                              ["My Tickets", 2],
> +                                              ["All tickets", 1],
> +                                              ["|", null],
> +                                              ["Projects", null],
> +                                              ["Components", 0]
> +                                            ],
> +                                          "active" : 1,
> +                                          "widgets" : [
> +                                            {
> +                                              "args" : [
> +                                                  "TicketFieldCloud",
> +                                                  null,
> +                                                  {"args" : {
> +                                                      "field" : "component",
> +                                                      "verbose" : true}}]
> +                                            },
> +                                            {
> +                                              "args" : [
> +                                                  "TicketQuery", null,
> +                                                  {"args" : {
> +                                                      "max" : 10,
> +                                                      "query" : "''' +
> +                'status!=closed&group=time&col=id&col=summary&col=owner'
\
> +                '&col=status&col=priority&order=priority&groupdesc=1&desc=1'
+
> +                                                      '''",
> +                                                      "title" : "All Tickets"}
> +                                                  }],
> +                                              "altlinks" : false
> +                                            },
> +                                            {
> +                                              "args" : [
> +                                                  "TicketQuery", null,
> +                                                  {"args" : {
> +                                                      "max" : 10,
> +                                                      "query" : "''' +
> +                'status!=closed&group=time&col=id&col=summary&col=owner'
\
> +                '&col=status&col=priority&order=priority&groupdesc=1&desc=1'
\
> +                '&owner=$USER' +
> +                                                      '''",
> +                                                      "title" : "My Tickets"}
> +                                                  }],
> +                                              "altlinks" : false
> +                                            }
> +                                          ]
> +                                        }
> +                                        ''',
> +                                        'title' : _("Dashboard")
> +                                        }
> +                                }]
> +                    },
> +                    {
> +                        'args' : ['Timeline', None, {'args' : {}}]
> +                    },
> +                ]
> +        }
> +
> +    # Public API
> +    def expand_layout_data(self, req, layout_name, schema):
> +        """Determine the template needed to render a specific layout
> +        and the data needed to place the widgets at expected
> +        location.
> +        """
> +        layout = DashboardSystem(self.env).resolve_layout(layout_name)
> +
> +        ctx = Context.from_request(req)
> +        template = layout.expand_layout(layout_name, ctx, {
> +                'schema' : schema
> +            })['template']
> +        return template, schema
> +
> +    def expand_widget_data(self, req, schema):
> +        """Expand raw widget data and format it for use in template
> +        """
> +        # TODO: Implement dynamic dashboard specification
> +        widgets_spec = schema.pop('widgets', [])
> +        widgets_index = dict([k, list(v)] for k,v in \
> +                groupby(widgets_spec, lambda w : w['args'][0]))
> +        ctx = Context.from_request(req)
> +        try :
> +            for wp in DashboardSystem(self.env).widget_providers:
> +                for wnm in wp.get_widgets():
> +                    substitutions = widgets_index.pop(wnm, [])
> +                    i = -1
> +                    for i, w in enumerate(substitutions):
> +                        w['c'] = wp
> +                        w['args'][1] = ctx
> +                    self.log.debug('Widget %s (%s substitutions)', wnm, i + 1)
> +                    if not widgets_index:
> +                        raise StopIteration("No more widgets")
> +        except StopIteration:
> +            pass
> +        if len(widgets_index)>  0:
> +            raise LookupError('Unknown provider for widgets %s',
> +                    ' , '.join(widgets_index.keys()))
> +        chrome = Chrome(self.env)
> +        render = chrome.render_template
> +        data_strm = (w['c'].render_widget(*w['args']) for w in widgets_spec)
> +        return [{'title' : data['title'],
> +                'content' : render(wctx.req, template, data['data'], fragment=True),
> +                'ctxtnav' : w.get('ctxtnav', True) and data.get('ctxtnav') or None,
> +                'altlinks' : w.get('altlinks', True) and data.get('altlinks') or None}
\
> +                for w, (template, data, wctx) in izip(widgets_spec, data_strm)]
> +
> +class DashboardChrome:
> +    """Helper functions providing access to dashboard infrastructure
> +    in Genshi templates. Useful to reuse layouts and widgets across
> +    website.
> +    """
> +    def __init__(self, env):
> +        self.env = env
> +
> +    def embed_layout(self, context, **kwargs):
> +        """Render layout and widgets
> +
> +        :param context: Rendering context
> +        :param layout: Identifier of target layout
> +        :param schema: Data describing widget positioning
> +        :param widgets: Widgets definition
> +        """
> +        dbmod = DashboardModule(self.env)
> +        raise NotImplementedError("DashboardChrome.embed_layout")
> +
> +    def expand_widget(self, context, widget):
> +        """Render single widget
> +
> +        :param context: Rendering context
> +        :param widget: Widget definition
> +        """
> +        dbmod = DashboardModule(self.env)
> +        if isinstance(widget['args'], basestring):
> +            widgets['args'] = json.loads(widget['args'])
> +        return dbmod.expand_widget_data(
> +                    context.req,
> +                    {'widgets' : [widget]}
> +                )[0]
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/__init__.py
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
(added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
Mon Apr 16 13:00:35 2012
> @@ -0,0 +1,28 @@
> +<!DOCTYPE html
> +    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
> +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
> +<html xmlns="http://www.w3.org/1999/xhtml"
> +      xmlns:py="http://genshi.edgewall.org/"
> +      xmlns:bh="http://issues.apache.org/bloodhound/wiki/Ui/Dashboard"
> +      xmlns:xi="http://www.w3.org/2001/XInclude">
> +<xi:include href="layout.html" />
> +<xi:include href="widget_macros.html" />
> +<head>
> +<title>Milestone ${milestone.name}</title>
> +<link py:if="'MILESTONE_MODIFY' in perm(milestone.resource)" rel="alternate" type="application/x-wiki"
> +          title="Edit this milestone" href="${href.milestone(milestone.name, action='edit')}"
/>
> +</head>
> +
> +<body>
> +<div class="row">
> +<div class="span8">
> +<div class="alert">
> +<span class="label label-warning">TODO</span>  Include milestone data.
> +</div>
> +</div>
> +<div class="span4">
> +<bh:widget type="Timeline" />
> +</div>
> +</div>
> +</body>
> +</html>
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/templates/bhmilestone.html
> ------------------------------------------------------------------------------
>      svn:mime-type = text/html
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py
(added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py
Mon Apr 16 13:00:35 2012
> @@ -0,0 +1,25 @@
> +#!/usr/bin/env python
> +# -*- coding: UTF-8 -*-
> +
> +#  Licensed to the Apache Software Foundation (ASF) under one
> +#  or more contributor license agreements.  See the NOTICE file
> +#  distributed with this work for additional information
> +#  regarding copyright ownership.  The ASF licenses this file
> +#  to you under the Apache License, Version 2.0 (the
> +#  "License"); you may not use this file except in compliance
> +#  with the License.  You may obtain a copy of the License at
> +#
> +#   http://www.apache.org/licenses/LICENSE-2.0
> +#
> +#  Unless required by applicable law or agreed to in writing,
> +#  software distributed under the License is distributed on an
> +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +#  KIND, either express or implied.  See the License for the
> +#  specific language governing permissions and limitations
> +#  under the License.
> +
> +
> +r"""Project dashboard for Apache(TM) Bloodhound
> +
> +Overriden version of Trac ticket interface
> +"""
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/__init__.py
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py
(added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py
Mon Apr 16 13:00:35 2012
> @@ -0,0 +1,61 @@
> +#!/usr/bin/env python
> +# -*- coding: UTF-8 -*-
> +
> +#  Licensed to the Apache Software Foundation (ASF) under one
> +#  or more contributor license agreements.  See the NOTICE file
> +#  distributed with this work for additional information
> +#  regarding copyright ownership.  The ASF licenses this file
> +#  to you under the Apache License, Version 2.0 (the
> +#  "License"); you may not use this file except in compliance
> +#  with the License.  You may obtain a copy of the License at
> +#
> +#   http://www.apache.org/licenses/LICENSE-2.0
> +#
> +#  Unless required by applicable law or agreed to in writing,
> +#  software distributed under the License is distributed on an
> +#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> +#  KIND, either express or implied.  See the License for the
> +#  specific language governing permissions and limitations
> +#  under the License.
> +
> +r"""Roadmap view for Apache(TM) Bloodhound
> +
> +Customizing roadmap user interface.
> +"""
> +
> +__metaclass__ = type
> +
> +from itertools import izip
> +import pkg_resources
> +import re
> +
> +from genshi.builder import tag
> +from trac.core import Component, implements
> +from trac.mimeview.api import Context
> +from trac.ticket.roadmap import MilestoneModule, RoadmapModule
> +from trac.util.translation import _
> +from trac.web.api import IRequestFilter
> +from trac.web.chrome import add_ctxtnav, add_stylesheet
> +
> +from bhdashboard.api import DashboardSystem
> +
> +class BloodhoundMilestoneModule(Component):
> +    """Override default milestone views.
> +    """
> +    implements(IRequestFilter)
> +
> +    # IRequestFilter methods
> +
> +    def pre_process_request(self, req, handler):
> +        """Always returns the request handler unchanged.
> +        """
> +        return handler
> +
> +    def post_process_request(self, req, template, data, content_type):
> +        """Customize milestone view.
> +        """
> +        mdl = self.env[MilestoneModule]
> +        if mdl is not None and mdl.match_request(req):
> +            return 'bhmilestone.html', data, content_type
> +        else:
> +            return template, data, content_type
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/web_ui/ticket/roadmap.py
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/query.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/query.py?rev=1326583&r1=1326582&r2=1326583&view=diff
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/query.py (original)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/query.py Mon
Apr 16 13:00:35 2012
> @@ -32,7 +32,7 @@ from genshi.builder import tag
>   from trac.core import implements, TracError
>   from trac.mimeview.api import Context
>   from trac.resource import Resource, ResourceNotFound
> -from trac.ticket.query import QueryModule
> +from trac.ticket.query import Query, QueryModule
>   from trac.util.translation import _
>   from trac.web.api import RequestDone
>
> @@ -136,3 +136,11 @@ class TicketQueryWidget(WidgetBase):
>
>       render_widget = pretty_wrapper(render_widget, check_widget_name)
>
> +#--------------------------------------
> +# Query functions and methods
> +#--------------------------------------
> +
> +def exec_query(env, req, qstr='status!=closed'):
> +    """ Perform a ticket query, returning a list of ticket ID's.
> +    """
> +    return Query.from_string(env, qstr).execute(req)
>
> Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html?rev=1326583&view=auto
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
(added)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
Mon Apr 16 13:00:35 2012
> @@ -0,0 +1,8 @@
> +
> +<div class="well"
> +    xmlns="http://www.w3.org/1999/xhtml"
> +    xmlns:py="http://genshi.edgewall.org/"
> +    xmlns:xi="http://www.w3.org/2001/XInclude">
> +  $legend
> +<div class="pull-right">${'%d%%' % stats.done_percent}</div>
> +</div>
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
> ------------------------------------------------------------------------------
>      svn:eol-style = native
>
> Propchange: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/templates/widget_progress.html
> ------------------------------------------------------------------------------
>      svn:mime-type = text/html
>
> Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py?rev=1326583&r1=1326582&r2=1326583&view=diff
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py (original)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/ticket.py Mon
Apr 16 13:00:35 2012
> @@ -29,13 +29,18 @@ from itertools import imap, islice
>   from genshi.builder import tag
>   from trac.core import implements, TracError
>   from trac.ticket.api import TicketSystem
> +from trac.ticket.roadmap import apply_ticket_permissions, get_ticket_stats, \
> +                            ITicketGroupStatsProvider, RoadmapModule
>   from trac.util.translation import _
> +from trac.web.chrome import add_stylesheet
>
>   from bhdashboard.api import DateField, EnumField, InvalidWidgetArgument, \
>                               ListField
> +from bhdashboard.widgets.query import exec_query
>   from bhdashboard.util import WidgetBase, check_widget_name, \
> -                              dummy_request, merge_links, minmax, \
> -                              pretty_wrapper, trac_version, trac_tags
> +                            dummy_request, merge_links, minmax, \
> +                            pretty_wrapper, resolve_ep_class, \
> +                            trac_version, trac_tags
>
>   class TicketFieldCloudWidget(WidgetBase):
>       """Display a tag cloud representing frequency of values assigned to
> @@ -116,3 +121,70 @@ class TicketFieldCloudWidget(WidgetBase)
>
>       render_widget = pretty_wrapper(render_widget, check_widget_name)
>
> +class TicketGroupStatsWidget(WidgetBase):
> +    """Display progress bar illustrating statistics gathered on a group
> +    of tickets.
> +    """
> +    def get_widget_params(self, name):
> +        """Return a dictionary containing arguments specification for
> +        the widget with specified name.
> +        """
> +        return {
> +                'query' : {
> +                        'default' : 'status!=closed',
> +                        'desc' : """Query string""",
> +                    },
> +                'stats_provider' : {
> +                        'desc' : """Name of the component implementing
> +        `ITicketGroupStatsProvider`, which is used to collect statistics
> +        on groups of tickets.""",
> +                        'default' : 'DefaultTicketGroupStatsProvider'
> +                    },
> +                'skin' : {
> +                        'desc' : """Look and feel of the progress bar""",
> +                        'type' : EnumField('info', 'success', 'warning',
> +                                'danger',
> +                                'info-stripped', 'success-stripped',
> +                                'warning-stripped', 'danger-stripped')
> +                    },
> +                'title' : {
> +                        'desc' : """Widget title""",
> +                    },
> +                'legend' : {
> +                        'desc' : """Text on top of the progress bar""",
> +                    },
> +                'desc' : {
> +                        'desc' : """Descriptive (wiki) text""",
> +                    },
> +            }
> +    get_widget_params = pretty_wrapper(get_widget_params, check_widget_name)
> +
> +    def render_widget(self, name, context, options):
> +        """Prepare ticket stats
> +        """
> +        req = context.req
> +        params = ('query', 'stats_provider', 'skin', 'title', 'legend', 'desc')
> +        qstr, pnm, skin, title, legend, desc = \
> +                self.bind_params(name, options, *params)
> +        statsp = resolve_ep_class(ITicketGroupStatsProvider, self, pnm,
> +                                    default=RoadmapModule(self.env).stats_provider)
> +        skin = (skin or '').split('-', 2)
> +        progress_css = 'progress ' + ' '.join('progress-'+c for c in skin if c)
> +
> +        tickets = exec_query(self.env, req, qstr)
> +        tickets = apply_ticket_permissions(self.env, req, tickets)
> +        stat = get_ticket_stats(self.stats_provider, tickets)
> +
> +        add_stylesheet('dashboard/bootstrap.css')
> +        return 'widget_progress.html', \
> +                {
> +                    'title' : title,
> +                    'data' : dict(
> +                            desc=desc,
> +                            legend=legend,
> +                            stats=stat,
> +                        ),
> +                }, \
> +                context
> +
> +    render_widget = pretty_wrapper(render_widget, check_widget_name)
>
> Modified: incubator/bloodhound/trunk/bloodhound_dashboard/setup.py
> URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/setup.py?rev=1326583&r1=1326582&r2=1326583&view=diff
> ==============================================================================
> --- incubator/bloodhound/trunk/bloodhound_dashboard/setup.py (original)
> +++ incubator/bloodhound/trunk/bloodhound_dashboard/setup.py Mon Apr 16 13:00:35 2012
> @@ -102,6 +102,14 @@ PKG_INFO = {'bhdashboard' : ('bhdashboar
>                               # Package data
>                               ['templates/*', 'htdocs/*'],
>                             ),
> +            'bhdashboard.web_ui' : ('bhdashboard/web_ui',     # Package dir
> +                            # Package data
> +                            ['templates/*', 'htdocs/*'],
> +                          ),
> +            'bhdashboard.web_ui.ticket' : ('bhdashboard/web_ui/ticket',     # Package
dir
> +                            # Package data
> +                            [],
> +                          ),
>               'bhdashboard.tests' : ('bhdashboard/tests',     # Package dir
>                               # Package data
>                               ['data/**'],
> @@ -113,6 +121,7 @@ ENTRY_POINTS = r"""
>                  bhdashboard.api = bhdashboard.api
>                  bhdashboard.layouts.bootstrap = bhdashboard.layouts.bootstrap
>                  bhdashboard.web_ui = bhdashboard.web_ui
> +               bhdashboard.web_ui.ticket.roadmap = bhdashboard.web_ui.ticket.roadmap
>                  bhdashboard.widgets.containers = bhdashboard.widgets.containers
>                  bhdashboard.widgets.query = bhdashboard.widgets.query
>                  bhdashboard.widgets.report = bhdashboard.widgets.report
>
>


Mime
View raw message