incubator-bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From g..@apache.org
Subject svn commit: r1294673 - in /incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct: __init__.py htdocs/ product_admin.py templates/ templates/admin_products.html
Date Tue, 28 Feb 2012 14:40:35 GMT
Author: gjm
Date: Tue Feb 28 14:40:35 2012
New Revision: 1294673

URL: http://svn.apache.org/viewvc?rev=1294673&view=rev
Log:
adding a basic product admin panel

Added:
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/htdocs/
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py   (with
props)
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
  (with props)
Modified:
    incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py

Modified: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py?rev=1294673&r1=1294672&r2=1294673&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py (original)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/__init__.py Tue Feb 28
14:40:35 2012
@@ -18,4 +18,5 @@
 
 """multiproduct module"""
 from model import MultiProductEnvironmentProvider
+from product_admin import ProductAdminPanel
 from ticket_web_ui import ProductTicketModule

Added: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py?rev=1294673&view=auto
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py (added)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py Tue Feb
28 14:40:35 2012
@@ -0,0 +1,140 @@
+
+#  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.
+
+"""Admin panels for product management"""
+
+from trac.core import *
+from trac.config import *
+from trac.perm import PermissionSystem
+from trac.admin.api import IAdminPanelProvider
+from trac.perm import IPermissionRequestor
+from trac.ticket.admin import TicketAdminPanel, _save_config
+from trac.resource import ResourceNotFound
+from model import Product
+from trac.util.translation import _, N_, gettext
+from trac.web.chrome import Chrome, add_notice, add_warning
+
+class ProductAdminPanel(TicketAdminPanel):
+    """The Product Admin Panel"""
+    _type = 'products'
+    _label = ('Product','Products')
+    
+    def _render_admin_panel(self, req, cat, page, product):
+        req.perm.require('PRODUCT_VIEW')
+        
+        name = req.args.get('name')
+        description = req.args.get('description','')
+        prefix = req.args.get('prefix') if product is None else product
+        owner = req.args.get('owner')
+        keys = {'prefix':prefix}
+        field_data = {'name':name,
+                      'description':description,
+                      'owner':owner,
+                      }
+        
+        # Detail view?
+        if product:
+            prod = Product(self.env, keys)
+            if req.method == 'POST':
+                if req.args.get('save'):
+                    req.perm.require('PRODUCT_MODIFY')
+                    prod.update_field_dict(field_data)
+                    prod.update()
+                    add_notice(req, _('Your changes have been saved.'))
+                    req.redirect(req.href.admin(cat, page))
+                elif req.args.get('cancel'):
+                    req.redirect(req.href.admin(cat, page))
+            
+            Chrome(self.env).add_wiki_toolbars(req)
+            data = {'view': 'detail', 'product': prod}
+        else:
+            default = self.config.get('ticket', 'default_product')
+            if req.method == 'POST':
+                # Add Product
+                if req.args.get('add') and req.args.get('prefix'):
+                    req.perm.require('PRODUCT_CREATE')
+                    try:
+                        prod = Product(self.env, keys)
+                    except ResourceNotFound:
+                        prod = Product(self.env)
+                        prod.update_field_dict(keys)
+                        prod.update_field_dict(field_data)
+                        prod.insert()
+                        add_notice(req, _('The product "%(id)s" has been '
+                                          'added.', id=prefix))
+                        req.redirect(req.href.admin(cat, page))
+                    else:
+                        if prod.prefix is None:
+                            raise TracError(_('Invalid product id.'))
+                        raise TracError(_("Product %(id)s already exists.",
+                                          id=prefix))
+                
+                # Remove product
+                elif req.args.get('remove'):
+                    req.perm.require('PRODUCT_DELETE')
+                    sel = req.args.get('sel')
+                    if not sel:
+                        raise TracError(_('No product selected'))
+                    if not isinstance(sel, list):
+                        sel = [sel]
+                    with self.env.db_transaction:
+                        for prefix in sel:
+                            prod = Product(self.env, {'prefix':prefix})
+                            prod.delete()
+                    add_notice(req, _("The selected products have been "
+                                      "removed."))
+                    req.redirect(req.href.admin(cat, page))
+                
+                # Set default product
+                elif req.args.get('apply'):
+                    prefix = req.args.get('default')
+                    if prefix and prefix != default:
+                        self.log.info("Setting default product to %s",
+                                      prefix)
+                        self.config.set('ticket', 'default_product',
+                                        prefix)
+                        _save_config(self.config, req, self.log)
+                        req.redirect(req.href.admin(cat, page))
+            
+            products = Product.select(self.env)
+            data = {'view': 'list',
+                    'products': products,
+                    'default': default}
+        if self.config.getbool('ticket', 'restrict_owner'):
+            perm = PermissionSystem(self.env)
+            def valid_owner(username):
+                return perm.get_user_permissions(username).get('TICKET_MODIFY')
+            data['owners'] = [username for username, name, email
+                              in self.env.get_known_users()
+                              if valid_owner(username)]
+            data['owners'].insert(0, '')
+            data['owners'].sort()
+        else:
+            data['owners'] = None
+        return 'admin_products.html', data
+
+class ProductPermissions(Component):
+    """Product extensions to permissions"""
+    implements(IPermissionRequestor)
+    
+    # IPermissionRequestor methods
+    def get_permission_actions(self):
+        acts = ['PRODUCT_CREATE', 'PRODUCT_DELETE', 'PRODUCT_MODIFY',
+                'PRODUCT_VIEW']
+        return acts + [('PRODUCT_ADMIN', acts)] + [('ROADMAP_ADMIN', acts)]
+

Propchange: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/product_admin.py
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html?rev=1294673&view=auto
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
(added)
+++ incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
Tue Feb 28 14:40:35 2012
@@ -0,0 +1,142 @@
+<!--
+  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.
+-->
+
+<!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:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/"
+      xmlns:i18n="http://genshi.edgewall.org/i18n">
+  <xi:include href="admin.html" />
+  <head>
+    <title>Products</title>
+  </head>
+
+  <body>
+    <h2>Manage Products</h2>
+
+    <py:def function="owner_field(default_owner='')">
+      <div class="field">
+        <label>Owner: <br />
+          <py:choose>
+            <select py:when="owners" size="1" id="owner" name="owner">
+              <option py:for="owner in owners"
+                      selected="${owner==default_owner or None}" value="$owner">$owner</option>
+              <option py:if="default_owner and default_owner not in owners"
+                      selected="selected" value="$default_owner">$default_owner</option>
+            </select>
+            <input py:otherwise="" type="text" name="owner" value="$default_owner" />
+          </py:choose>
+        </label>
+      </div>
+    </py:def>
+
+    <py:choose test="view">
+      <form py:when="'detail'" class="mod" id="modifyproduct" method="post" action="">
+        <fieldset>
+          <legend>Modify Product:</legend>
+          <div class="field">
+            <label>Prefix:<br /><input type="text" name="prefix" value="$product.prefix"/></label>
+          </div>
+          <div class="field">
+            <label>Name:<br /><input type="text" name="name" value="$product.name"/></label>
+          </div>
+          ${owner_field(product.owner)}
+          <div class="field">
+            <fieldset class="iefix">
+              <label for="description" i18n:msg="">
+                Description (you may use
+                <a tabindex="42" href="${href.wiki('WikiFormatting')}">WikiFormatting</a>
+                here):
+              </label>
+              <p>
+                <textarea id="description" name="description" class="wikitext trac-resizable"
+                          rows="6" cols="60">
+$product.description</textarea>
+              </p>
+            </fieldset>
+          </div>
+          <div class="buttons">
+            <input type="submit" name="cancel" value="${_('Cancel')}" />
+            <input type="submit" name="save" value="${_('Save')}" />
+          </div>
+        </fieldset>
+      </form>
+
+      <py:otherwise>
+        <form class="addnew" id="addproduct" method="post" action="">
+          <fieldset>
+            <legend>Add Product:</legend>
+            <div class="field">
+              <label>Prefix:<br /><input type="text" name="prefix" /></label>
+            </div>
+            <div class="field">
+              <label>Name:<br /><input type="text" name="name" /></label>
+            </div>
+            ${owner_field()}
+            <div class="buttons">
+              <input type="submit" name="add" value="${_('Add')}"/>
+            </div>
+          </fieldset>
+        </form>
+
+        <py:choose>
+          <form py:when="products" id="product_table" method="post" action="">
+            <table class="listing" id="prodlist">
+              <thead>
+                <tr><th class="sel">&nbsp;</th>
+                  <th>Prefix</th><th>Name</th><th>Owner</th><th>Default</th>
+                </tr>
+              </thead>
+              <tbody>
+                <tr py:for="prod in products">
+                  <td class="sel"><input type="checkbox" name="sel" value="$prod.prefix"
/></td>
+                  <td class="prefix">
+                    <a href="${panel_href(prod.prefix)}">$prod.prefix</a>
+                  </td>
+                  <td class="name">$prod.name</td>
+                  <td class="owner">$prod.owner</td>
+                  <td class="default">
+                    <input type="radio" name="default" value="$prod.prefix"
+                           checked="${prod.prefix==default or None}" />
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+            <div class="buttons">
+              <input type="submit" name="remove" value="${_('Remove selected items')}"
/>
+              <input type="submit" name="apply" value="${_('Apply changes')}" />
+            </div>
+            <p class="help">
+              You can remove all items from this list to completely hide this
+              field from the user interface.
+            </p>
+          </form>
+
+          <p py:otherwise="" class="help">
+            As long as you don't add any items to the list, this field
+            will remain completely hidden from the user interface.
+          </p>
+        </py:choose>
+      </py:otherwise>
+    </py:choose>
+  </body>
+
+</html>

Propchange: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/bloodhound/trunk/bloodhound_multiproduct/multiproduct/templates/admin_products.html
------------------------------------------------------------------------------
    svn:mime-type = text/html



Mime
View raw message