Return-Path: X-Original-To: apmail-incubator-bloodhound-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-bloodhound-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 90B289FA0 for ; Mon, 16 Apr 2012 13:16:06 +0000 (UTC) Received: (qmail 94066 invoked by uid 500); 16 Apr 2012 13:16:06 -0000 Delivered-To: apmail-incubator-bloodhound-dev-archive@incubator.apache.org Received: (qmail 94042 invoked by uid 500); 16 Apr 2012 13:16:06 -0000 Mailing-List: contact bloodhound-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: bloodhound-dev@incubator.apache.org Delivered-To: mailing list bloodhound-dev@incubator.apache.org Received: (qmail 94025 invoked by uid 99); 16 Apr 2012 13:16:05 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 16 Apr 2012 13:16:05 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of gary.martin@wandisco.com designates 209.85.214.47 as permitted sender) Received: from [209.85.214.47] (HELO mail-bk0-f47.google.com) (209.85.214.47) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 16 Apr 2012 13:16:00 +0000 Received: by bkcjg15 with SMTP id jg15so4089627bkc.6 for ; Mon, 16 Apr 2012 06:15:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type:content-transfer-encoding :x-gm-message-state; bh=NIkvqcv9uHKReSZkd8z8y7wQy9DMCl6AieGOftfiCSg=; b=imZkFQUYRLSte2kd+qvqDJ+0yIFMhQ/DKifjzt4A7z9H5cU3n/GtHk2P8PFqAwNsif mmhUmvQxqg9w8GOdlCk3U7kCoDV/2iiaf8MAjOcrHGcazezEbpYK9ib6BP4B2WGVsGsc cHp8iUvU7uXyzszcTP+dqCmM4nvEsdGHMvX2Z+fkknTD7G0iF5gzamUd1XXKDp0n3L1n tnKZvpc68xSNGSSp7bA+eT/spjns8xohFqA31FaEz5Q3yUrwwnRriAYH/GUZXhmsTr3P tSw5kRlWbrSYckc5OjK4Ut7NmkAvk6Syx/3zmhyUgt9KgU5xUB5d4nIqoSrQ8KBy3Qx0 qLuA== Received: by 10.204.130.151 with SMTP id t23mr3440608bks.27.1334582138713; Mon, 16 Apr 2012 06:15:38 -0700 (PDT) Received: from [10.2.5.127] ([77.86.30.139]) by mx.google.com with ESMTPS id u5sm31531505bka.5.2012.04.16.06.15.37 (version=SSLv3 cipher=OTHER); Mon, 16 Apr 2012 06:15:37 -0700 (PDT) Message-ID: <4F8C1B77.3090804@wandisco.com> Date: Mon, 16 Apr 2012 14:15:35 +0100 From: Gary User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120329 Thunderbird/11.0.1 MIME-Version: 1.0 To: bloodhound-dev@incubator.apache.org 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/ References: <20120416130037.44F4E2388C1C@eris.apache.org> In-Reply-To: <20120416130037.44F4E2388C1C@eris.apache.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Gm-Message-State: ALoCoQkGhOm159FRIyHcl9KhbsM6mhFm9NkrBy4qsTATbHPSZ1audKO9+WOWeaosUjti2XV5ZtEW X-Virus-Checked: Checked by ClamAV on apache.org 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=""> > > + > + >
>

${w.title}

> > @@ -27,4 +30,70 @@ >
> ${w.content} >
> + > + > + > +
> +Error > + Dashboard data is missing . > + Isbhdashboard.web_ui.DashboardModule component disabled? > +
> + > + > + > + > + > + ${bhdb.embed_layout(context, layout=select('@type'), schema=select('bh:schema'), widgets=select('bh:widgets'))} > + > + > + ${bhnotfound()} > + > + > + > + > + > + > + + 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)))} > + > + > + ${bhnotfound()} > + > + > + > > > 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 @@ > + + PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" > + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> > + + xmlns:py="http://genshi.edgewall.org/" > + xmlns:bh="http://issues.apache.org/bloodhound/wiki/Ui/Dashboard" > + xmlns:xi="http://www.w3.org/2001/XInclude"> > + > + > + > +Milestone ${milestone.name} > + + title="Edit this milestone" href="${href.milestone(milestone.name, action='edit')}" /> > + > + > + > +
> +
> +
> +TODO Include milestone data. > +
> +
> +
> + > +
> +
> + > + > > 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 @@ > + > +
+ xmlns="http://www.w3.org/1999/xhtml" > + xmlns:py="http://genshi.edgewall.org/" > + xmlns:xi="http://www.w3.org/2001/XInclude"> > + $legend > +
${'%d%%' % stats.done_percent}
> +
> > 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 > >