bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1415755 - /incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets
Date Fri, 30 Nov 2012 17:30:35 GMT
Author: gjm
Date: Fri Nov 30 17:30:34 2012
New Revision: 1415755

URL: http://svn.apache.org/viewvc?rev=1415755&view=rev
Log:
adding initial version of wiki documentation for widgets - towards #139

Added:
    incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets

Added: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets?rev=1415755&view=auto
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets
(added)
+++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/default-pages/BloodhoundWidgets
Fri Nov 30 17:30:34 2012
@@ -0,0 +1,323 @@
+= Bloodhound widgets =
+
+[[PageOutline]]
+
+[http://issues.apache.org/bloodhound Bloodhound] widgets are plugins to extend the Trac engine
with custom visual components written in Python. They are designed to insert dynamic HTML
data in any given context so as to display summarized information in a reduced space. Therefore
they are a generalization of WikiMacros and WikiProcessors as it is possible to rewrite them
all using [#API Bloodhound Widgets API]. Nonetheless the later are not aimed at replacing
any of the former as they are still used to [#WikiFormatting insert widgets using WikiFormatting].
Widgets development is recommended rather than macros due to their advantages.
+
+== Anatomy of a widget #overview
+
+Widgets are designed to look like a small version of a web page. From the top to the bottom
and from left to right the visual representation of a widget consists of the following parts.
+
+  - '''Title''' briefly describing what are widget contents about.
+  - '''Context navigation links''' pointing to pages where
+    users can find related information.
+  - '''Alternate download links''' included in ''Download'' drop down
+    menu allow users to download widget data in different formats.
+  - '''Contents pane''' is the area where widget contents are rendered
+  - '''Pagination links''' is displayed when there is a huge dataset
+    involved and only part of it can be displayed. They allow users to
+    request information in case they are interested in further details.
+
+=== Widget parameters #parameters
+
+Widget visualization may be customized by specifying arguments. For instance, in order to
insert a widget displaying the results of a ticket report it is mandatory to provide the identifier
of the target report. This is an example of a '''required parameter'''. If a value is not
provided for this kind of parameters then an [#error_handling error message] is displayed.
On the other hand '''optional parameters''' are those that may be ignored either because they
are related to a minor characteristic or a value can be considered by default under certain
circumstances. The line between both groups might be fuzzy sometimes because it is possible
that an ''optional parameter'' may be required depending on the values set to other parameters,
the state of widget rendering context , and maybe other factors.
+
+All parameters mentioned above have certain meaning for a particular widget. There is another
set of parameters used to customize its look and feel and other aspect present in all widgets.
They are known as '''meta-parameters'''. At present they are the following :
+
+  - '''altlinks''' is a boolean parameter controlling whether widget alternate
+    download links will be visible or hidden.
+  - '''ctxtnav''' is a boolean parameter controlling whether widget context
+    navigation links will be visible or hidden.
+  - '''id''' consisiting of an identifier for ''DOM'' element container
+  - '''title''' parameter may be used to display a user-defined title
+    rather than the one shown by default.
+
+There is no collision between parameters and meta-parameters. Hence, for instance, it's possible
for a widget to accept an argument named ''title'' even if there is a meta-parameter with
the same name.
+
+=== Widget context #context
+
+It is very important to mention that widgets can take advantage of context information used
to render parent web page. For instance, ''Timeline'' widget is able to detect whether it
is embedded in a page related to a resource. If so it filters events stream to show only those
related to that resource. That's only an example of how smart a widget can be.
+
+== Using widgets #usage
+
+Widgets encourage extreme reuse of visual components. This means that its scope spans far
beyond the boundaries of WikiFormatting, WikiMacros, and WikiProcessors. Therefore they are
helpful for Trac users as well as plugin developers. Both use cases are documented in this
section.
+
+=== Embedding widgets using Widget macro #WikiFormatting
+
+It's possible to embed widget contents everywhere WikiFormatting is supported. In order to
do so it is necessary to [WikiMacros call a macro] named '''Widget'''. Arguments supplied
in macro invocation having a name starting with ''wo_'' prefix (i.e. widget option) will be
considered as meta-parameters (e.g. value supplied for argument ''wo_id' in macro invocation
will be set to ''id' meta-parameter thus used to set widget identifier). All others will be
bound to required and optional parameters used to render its contents (e.g. value supplied
for argument ''title'' in macro invocation will be set to ''title'' parameter).
+
+[[MacroList(Widget)]]
+
+The first step to insert a widget is to search the [#reference list of available widgets]
and look for the one that renders the data the way you need. Once you succeed you should take
a look at its documentation in order to know of the parameters it accepts and expected results
in each case. Once all these details are understood the next step is to invoke '''Widget'''
macro. The following example illustrates the call needed to insert the top 10 active tickets
in milestone ''milestone1'' and hide ''Download'' drop down menu.
+
+{{{
+[[Widget(TicketQuery, wo_altlinks=false, query="milestone=milestone1&status=!closed",
max=10)]]
+}}}
+
+=== Widgets markup for plugin developers #genshi
+
+Widgets may also be inserted directly in [http://genshi.edgewall.org/wiki/Documentation/templates.html
Genshi templates] in order to design user interfaces quickly. Plugin developers should use
markup for this purpose. Let's consider the following sample template. If you are not familiar
with the subject , please read [http://genshi.edgewall.org/wiki/Documentation/xml-templates.html
XML templates reference].
+
+{{{
+#!xml
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:py="http://genshi.edgewall.org/"
+      xmlns:i18n="http://genshi.edgewall.org/i18n"
+      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 milestone1</title>
+  </head>
+  <body>
+    <bh:widget id="active" urn="TicketQuery" altlinks="false">
+      <bh:args>
+        <bh:arg name="query">milestone=milestone1&amp;status=!closed</bh:arg>
+        <bh:arg name="max">10</bh:arg>
+        <bh:arg name="title">Active tickets</bh:arg>
+      </bh:args>
+    </bh:widget>
+  </body>
+</html>
+}}}
+
+Analyzing sample markup from top to bottom it's possible to notice that the first step is
to declare ''Bloodhound'' dashboard XML namespace `http://issues.apache.org/bloodhound/wiki/Ui/Dashboard`.
In this case it is represented by the short prefix `bh`. This step is required as well as
the second. It consists of including `widget_macros.html` template. It contains all the foundations
of widgets agic. If you are interested in learning how everything works under-the-hood maybe
that's a good place to start ''';)'''.
+
+Now it is a good time to use widgets markup so as to insert some contents in the web page.
This is what `<bh:widget>` tag is for. Let's take a look at it. The value assigned to
`id` attribute indicates that this widget will have the `active` identifier set when it is
rendered. Script code in your template may use it to access its outermost ''div'' element
e.g. `jQuery('#active')`. Attribute `urn` is used to specify target widget name. In this case
`TicketQuery` widget is basically a table displaying the results of executing a ticket query.
All other attributes of `<bh:widget>` tag are considered as meta-parameters. Hence in
this case alternate download links (e.g. ''RSS Feed'', ''Comma-delimited Text'', ''Tab-delimited
Text'', and so on) will not be available.
+
+Moving forward it s the moment to analyze `<bh:args>` tag. It's only purpose is to
group some `<bh:arg>` tags containing specifications for widget parameters. Its description
is straightforward. Argument name is set in `name` attribute and value is its inner text.
As you can see in this particular example a table containing the first ''10'' active tickets
in milestone ''milestone1'' will be displayed.
+
+By the way, `query` argument could be a required parameter as it may seem that it makes no
sense to query tickets database without specifying query string describing the result set.
In practice this might not be the case due to the fact that Trac's query module uses a default
query string if missing. Something similar happens with `max` and `title` optional attributes.
+
+== Error handling #error_handling
+
+While rendering widgets there is a chance for errors to happen. If this is the case the parent
page still will be displayed. Actually the widget rendering engine will intercept exceptions
raised and instead of widget body it will show an informative error message containing :
+
+  - '''Widget name'''
+  - '''Exception type''' identifying the kind of error
+  - '''Log entry ID''' consisting of a [Acronym:GUID] identifying
+    a [TracLogging log entry] with all the details and context
+    information about the error.
+
+Every time you look for support (e.g. by contacting your administrator)  you have to provide
all these details , especially '''log entry ID'''.
+
+=== Getting detailed help #help
+The list of available macros and the full help can be obtained using the !WidgetDoc widget,
as seen [#reference below].
+
+A brief list can be obtained via ![[Widget(WidgetDoc)]]
+
+Detailed help on a specific widget can be obtained by passing its name as `urn` argument,
e.g. ![[Widget(WidgetDoc, urn=TicketQuery))]].
+
+=== Example #example
+
+A list of 3 most recently changed wiki pages starting with 'Trac':
+
+||= Widget macro call =||= Display =||
+{{{#!td
+  {{{
+  [[Widget(TicketQuery, wo_altlinks=false, query="status=!closed&col=id&col=summary",
max=2)]]
+  }}}
+}}}
+{{{#!td style="padding-left: 2em;"
+[[Widget(TicketQuery, wo_altlinks=false, query="status=!closed&col=id&col=summary",
max=2)]]
+}}}
+|-----------------------------------
+{{{#!td
+  {{{
+  [[Widget(WidgetDoc, urn=TicketQuery))]]
+  }}}
+}}}
+{{{#!td style="padding-left: 2em;"
+[[Widget(WidgetDoc, urn=TicketQuery))]]
+}}}
+|-----------------------------------
+{{{#!td
+  {{{
+  [[Widget(WidgetDoc))]]
+  }}}
+}}}
+{{{#!td style="padding-left: 2em"
+
+see [#reference below]
+
+}}}
+
+== Available widgets #reference
+
+''Note that the following list will only contain the macro documentation if you've not enabled
`-OO` optimizations, or not set the `PythonOptimize` option for [wiki:TracModPython mod_python].''
+
+[[Widget(WidgetDoc)]]
+
+== Widgets from around the world #directory
+
+The [http://trac-hacks.org/ Trac Hacks] site provides a wide collection of macros and other
Trac [TracPlugins plugins] contributed by the Trac community. If you're looking for new widgets,
or have written one that you'd like to share with the world, please don't hesitate to visit
that site.
+
+== Developing custom widgets #API
+Widgets, like Bloodhound itself, are written in the [http://python.org/ Python programming
language] and are developed as part of TracPlugins.
+
+For more information about developing widgets, see the [Bloodhound:Ui/Widgets development
resources] on ''Apache Software Foundation'' project site.
+
+Here is one simple example showing how to create a widget with Bloodhound 0.1.0 and Trac
1.0.
+
+=== Widget without arguments #widgetsimple
+
+Firstly you need to write an [http://genshi.edgewall.org/wiki/Documentation/xml-templates.html
XML Genshi template] to render widget data like shown below. In order to test this sample
quickly it should be saved in a `timestamp.html` file located in the TracEnvironment's `templates/`
directory. Nonetheless it is recommended to distribute templates by packaging them in [TracPlugins
plugins].
+
+{{{
+#!xml
+
+<div
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:py="http://genshi.edgewall.org/"
+    xmlns:xi="http://www.w3.org/2001/XInclude">
+  <b>format_datetime($time)</b>
+</div>
+}}}
+
+To test the following code, it should be saved in a `timestamp_sample.py` file located in
the TracEnvironment's `plugins/` directory.
+
+{{{
+#!python
+from datetime import datetime
+# Note: since Trac 0.11, datetime objects are used internally
+
+from bhdashboard.util import WidgetBase
+
+class TimeStampWidget(WidgetBase):
+    """Inserts the current time (in seconds)"""
+
+    revision = "$Rev$"
+    url = "$URL$"
+
+    def get_widget_params(self, name):
+        return {}
+
+    def render_widget(self, name, context, options):
+        t = datetime.now(utc)
+        return ( 'timestamp.html',
+                   {
+                        'title' : 'Timestamp',
+                        'data' : { 'time' : t },
+                    },
+                    context )
+
+}}}
+
+In this case widget name will be ''Timestamp''.
+
+=== Widget with arguments #widgetargs
+
+In first place you need to write an [http://genshi.edgewall.org/wiki/Documentation/xml-templates.html
XML Genshi template] to render widget data like shown below. In order to test this sample
quickly it should be saved in a `helloworld.html` file located in the TracEnvironment's `templates/`
directory. Nonetheless it is recommended to distribute templates by packaging them in [TracPlugins
plugins].
+
+{{{
+#!xml
+
+<div
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:py="http://genshi.edgewall.org/"
+    xmlns:xi="http://www.w3.org/2001/XInclude">
+  <p>Hello
+    <font size="$fontsize">
+      <strong py:strip="not highlight">$subject</strong>
+    </font> !
+  </p>
+  <h3>Arguments</h3>
+  <dl class="dl-horizontal">
+    <py:for each="k, v in args">
+      <dt>$k</dt>
+      <dd>$v</dd>
+    </py:for>
+  </dl>
+</div>
+}}}
+
+To test the following code, you should save it in a `helloworld_sample.py` file located in
the TracEnvironment's `plugins/` directory.
+
+{{{
+#!python
+
+from genshi.builder import tag
+
+from bhdashboard.util import WidgetBase
+
+class HelloWorldWidget(WikiWidgetBase):
+    """Simple HelloWorld widget.
+
+    Note that the name of the class is meaningful:
+     - it must end with "Widget"
+     - what comes before "Widget" ends up being the widget name
+
+    The documentation of the class (i.e. what you're reading)
+    will become the documentation of the widget, as shown by
+    the !WidgetDoc widget (usually used in the
+    BloodhoundWidgets page).
+    """
+
+    revision = "$Rev$"
+    url = "$URL$"
+
+    def get_widget_params(self, name):
+        """Return a dictionary containing arguments
+        specification for the widget with specified name.
+
+        `name` is the actual name of the macro
+        (no surprise, here it'll be `'HelloWorld'`),
+        """
+        return {
+                'subject' : {
+                        'desc' : """The subject of hello statement""",
+                        'required' : True,
+                    },
+                'size' : {
+                        'default' : 10,
+                        'desc' : """Optional font size""",
+                        'type' : int,
+                },
+                'highlight' : {
+                        'default' : false,
+                        'desc' : """Bold text for subject""",
+                        'type' : bool,
+                },
+            }
+
+    def render_widget(self, name, context, options):
+        """Return template, data and context that will be
+        used to render hello world message. Widget title will
+        always be `'Hello world'`. A link to project
+        home page will be inserted at its right side.
+        Immediately after hello message the items in
+        `options` map, including argument values, will be
+        listed.
+
+        `name` is the actual name of the macro
+        (no surprise, here it'll be `'HelloWorld'`),
+        `context` is the rendering context used to render the
+        parent page where widget is inserted.
+        `options` contains the arguments passed to insert
+        HelloWorld among other useful information.
+
+        Notice how `bind_params` method is used to retrieve
+        argument values.
+        """
+        subject, fontsize, highlight = self.bind_params(
+                name, options, 'subject', 'size', 'highlight')
+        return ( 'helloworld.html',
+                {
+                    'title' : 'Hello world',
+                    'data' : {
+                        'subject' : subject,
+                        'fontsize' : max(fontsize, 8),
+                        'highlight' : highlight,
+                        'args' : options,
+                    },
+                    'ctxtnav' : [
+                            tag.a('Project home',
+                                    href=context.req.href())],
+                },
+                context )
+
+}}}
+



Mime
View raw message