Changeset - 15e96b5a2685
[Not reviewed]
default
0 6 0
Marcin Kuzminski - 15 years ago 2010-06-26 18:42:13
marcin@python-works.com
autocomplete for repository managment of users
6 files changed with 487 insertions and 247 deletions:
0 comments (0 inline, 0 general)
pylons_app/controllers/repos.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# repos controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 7, 2010
 
admin controller for pylons
 
@author: marcink
 
"""
 
from operator import itemgetter
 
from pylons import request, response, session, tmpl_context as c, url, \
 
    app_globals as g
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 
from pylons_app.lib import helpers as h
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.utils import invalidate_cache
 
from pylons_app.model.repo_model import RepoModel
 
from pylons_app.model.hg_model import HgModel
 
from pylons_app.model.forms import RepoForm
 
from pylons_app.model.meta import Session
 
from datetime import datetime
 
import formencode
 
from formencode import htmlfill
 
import logging
 
import os
 
import shutil
 
log = logging.getLogger(__name__)
 

	
 
class ReposController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('repo', 'repos')
 
    @LoginRequired()
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(ReposController, self).__before__()
 
                
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        cached_repo_list = HgModel().get_repos()
 
        c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
 
        return render('admin/repos/repos.html')
 
    
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        # url('repos')
 
        repo_model = RepoModel()
 
        _form = RepoForm()()
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.create(form_result, c.hg_app_user)
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('created repository %s') % form_result['repo_name'],
 
                    category='success')
 
                                                             
 
        except formencode.Invalid as errors:
 
            c.form_errors = errors.error_dict
 
            c.new_repo = errors.value['repo_name']
 
            return htmlfill.render(
 
                 render('admin/repos/repo_add.html'),
 
                defaults=errors.value,
 
                encoding="UTF-8")        
 

	
 
        except Exception:
 
            h.flash(_('error occured during creation of repository %s') \
 
                    % form_result['repo_name'], category='error')
 
            
 
        return redirect('repos')
 

	
 
    def new(self, format='html'):
 
        """GET /repos/new: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        c.new_repo = h.repo_name_slug(new_repo)
 

	
 
        return render('admin/repos/repo_add.html')
 

	
 
    def update(self, id):
 
        """PUT /repos/id: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
        #    h.form(url('repo', id=ID),
 
        #           method='put')
 
        # url('repo', id=ID)
 
        repo_model = RepoModel()
 
        _form = RepoForm(edit=True)()
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.update(id, form_result)
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('Repository %s updated succesfully' % id), category='success')
 
                           
 
        except formencode.Invalid as errors:
 
            c.repo_info = repo_model.get(id)
 
            c.users_array = repo_model.get_users_js()
 
            errors.value.update({'user':c.repo_info.user.username})
 
            c.form_errors = errors.error_dict
 
            return htmlfill.render(
 
                 render('admin/repos/repo_edit.html'),
 
                defaults=errors.value,
 
                encoding="UTF-8")
 
        except Exception:
 
            h.flash(_('error occured during update of repository %s') \
 
                    % form_result['repo_name'], category='error')
 
        return redirect(url('repos'))
 
    
 
    def delete(self, id):
 
        """DELETE /repos/id: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
        #    h.form(url('repo', id=ID),
 
        #           method='delete')
 
        # url('repo', id=ID)
 
        
 
        repo_model = RepoModel()
 
        repo = repo_model.get(id)
 
        if not repo:
 
            h.flash(_('%s repository is not mapped to db perhaps' 
 
                      ' it was moved or renamed  from the filesystem'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % id, category='error')
 
        
 
            return redirect(url('repos'))
 
        try:
 
            repo_model.delete(repo)            
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('deleted repository %s') % id, category='success')
 
        except Exception:
 
            h.flash(_('An error occured during deletion of %s') % id,
 
                    category='error')
 
        
 
        return redirect(url('repos'))
 
        
 
    def show(self, id, format='html'):
 
        """GET /repos/id: Show a specific item"""
 
        # url('repo', id=ID)
 
        
 
    def edit(self, id, format='html'):
 
        """GET /repos/id/edit: Form to edit an existing item"""
 
        # url('edit_repo', id=ID)
 
        repo_model = RepoModel()
 
        c.repo_info = repo = repo_model.get(id)
 
        if not repo:
 
            h.flash(_('%s repository is not mapped to db perhaps' 
 
                      ' it was created or renamed from the filesystem'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % id, category='error')
 
        
 
            return redirect(url('repos'))        
 
        defaults = c.repo_info.__dict__
 
        defaults.update({'user':c.repo_info.user.username})
 
        
 
        c.users_array = repo_model.get_users_js()
 
        
 
        for p in c.repo_info.repo2perm:
 
            defaults.update({'perm_%s' % p.user.username: 
 
                             p.permission.permission_name})
 
                
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )          
pylons_app/model/repo_model.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# model for handling repositories actions
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on Jun 5, 2010
 
model for handling repositories actions
 
@author: marcink
 
"""
 
from pylons_app.model.meta import Session
 
from pylons_app.model.db import Repository, Repo2Perm, User, Permission
 
import shutil
 
import os
 
from datetime import datetime
 
from pylons_app.lib.utils import check_repo
 
from pylons import app_globals as g
 
import traceback
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
class RepoModel(object):
 
    
 
    def __init__(self):
 
        self.sa = Session()
 
    
 
    def get(self, id):
 
        return self.sa.query(Repository).get(id)
 
        
 
    def get_users_js(self):
 
        
 
        users = self.sa.query(User).all()
 
        u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
 
        users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
 
                                                    u.lastname, u.username) 
 
                                        for u in users])
 
        return users_array        
 
        
 
    
 
    def update(self, repo_id, form_data):
 
        try:
 
            if repo_id != form_data['repo_name']:
 
                self.__rename_repo(repo_id, form_data['repo_name'])
 
            cur_repo = self.sa.query(Repository).get(repo_id)
 
            for k, v in form_data.items():
 
                if k == 'user':
 
                    cur_repo.user_id = v
 
                else:
 
                    setattr(cur_repo, k, v)
 
            
 
            #update permissions
 
            for username, perm in form_data['perms_updates']:
 
                r2p = self.sa.query(Repo2Perm)\
 
                        .filter(Repo2Perm.user == self.sa.query(User)\
 
                                .filter(User.username == username).one())\
 
                        .filter(Repo2Perm.repository == repo_id).one()
 
                
 
                r2p.permission_id = self.sa.query(Permission).filter(
 
                                                Permission.permission_name == 
 
                                                perm).one().permission_id
 
                self.sa.add(r2p)
 
            
 
            for username, perm in form_data['perms_new']:
 
                r2p = Repo2Perm()
 
                r2p.repository = repo_id
 
                r2p.user = self.sa.query(User)\
 
                                .filter(User.username == username).one()
 
                
 
                r2p.permission_id = self.sa.query(Permission).filter(
 
                                                Permission.permission_name == 
 
                                                perm).one().permission_id
 
                self.sa.add(r2p)
 
                                    
 
            self.sa.add(cur_repo)
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise    
 
    
 
    def create(self, form_data, cur_user, just_db=False):
 
        try:
 
            repo_name = form_data['repo_name']
 
            new_repo = Repository()
 
            for k, v in form_data.items():
 
                setattr(new_repo, k, v)
 
                
 
            new_repo.user_id = cur_user.user_id
 
            self.sa.add(new_repo)
 

	
 
            #create default permission
 
            repo2perm = Repo2Perm()
 
            repo2perm.permission_id = self.sa.query(Permission)\
 
                    .filter(Permission.permission_name == 'repository.read')\
 
                    .one().permission_id
 
                        
 
            repo2perm.repository = repo_name
 
            repo2perm.user_id = self.sa.query(User)\
 
                    .filter(User.username == 'default').one().user_id 
 
            
 
            self.sa.add(repo2perm)
 
            self.sa.commit()
 
            if not just_db:
 
                self.__create_repo(repo_name)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise    
 
                     
 
    def delete(self, repo):
 
        try:
 
            self.sa.delete(repo)
 
            self.sa.commit()
 
            self.__delete_repo(repo.repo_name)
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 
       
 
    def __create_repo(self, repo_name):        
 
        repo_path = os.path.join(g.base_path, repo_name)
 
        if check_repo(repo_name, g.base_path):
 
            log.info('creating repo %s in %s', repo_name, repo_path)
 
            from vcs.backends.hg import MercurialRepository
 
            MercurialRepository(repo_path, create=True)
 

	
 
    def __rename_repo(self, old, new):
 
        log.info('renaming repoo from %s to %s', old, new)
 
        old_path = os.path.join(g.base_path, old)
 
        new_path = os.path.join(g.base_path, new)
 
        shutil.move(old_path, new_path)
 
    
 
    def __delete_repo(self, name):
 
        rm_path = os.path.join(g.base_path, name)
 
        log.info("Removing %s", rm_path)
 
        #disable hg 
 
        shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
 
        #disable repo
 
        shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
 
                                          % (datetime.today(), name)))
pylons_app/public/css/monoblue_custom.css
Show inline comments
 
/*** Initial Settings ***/
 
#mainhtml{
 
#mainhtml {
 
	margin: 15px 50px;
 
	background: #DBD4C6;
 
	font-family: sans-serif;
 
}
 
#mainhtml .breadcrumbs a:HOVER{
 
	text-decoration:  underline;
 

	
 
#mainhtml .breadcrumbs a:HOVER {
 
	text-decoration: underline;
 
}
 

	
 
a {
 
	color: #556CB5;
 
	text-decoration: none;
 
}
 
a:HOVER{
 

	
 
a:HOVER {
 
	text-decoration: underline;
 
}
 

	
 
/*** end of Initial Settings ***/ 
 

	
 
/*** ***/
 
.table_disp {
 
    border-left: 0px solid #666666;
 
    border-bottom: 1px solid #666666;
 
    border-right: 1px solid #666666;
 
    padding: 0px;
 
    margin: 0px;
 
    border-spacing: 0px;    
 
	border-left: 0px solid #666666;
 
	border-bottom: 1px solid #666666;
 
	border-right: 1px solid #666666;
 
	padding: 0px;
 
	margin: 0px;
 
	border-spacing: 0px;
 
}
 

	
 
.table_disp .header {
 
    border-top: 1px solid #666666;
 
    background-color: #556CB5;
 
    font-weight: bold;
 
    color: white;
 
    vertical-align: middle;
 
    padding: 3px 5px;
 
    text-align: left;
 
    font-size: 0.9em;
 
	border-top: 1px solid #666666;
 
	background-color: #556CB5;
 
	font-weight: bold;
 
	color: white;
 
	vertical-align: middle;
 
	padding: 3px 5px;
 
	text-align: left;
 
	font-size: 0.9em;
 
}
 

	
 
.table_disp .header td {
 
    padding: 4px;
 
    vertical-align: middle;
 
    border-top: 1px solid #AAAAAA;
 
    border-bottom: 2px solid #666666;
 
	padding: 4px;
 
	vertical-align: middle;
 
	border-top: 1px solid #AAAAAA;
 
	border-bottom: 2px solid #666666;
 
}
 

	
 
.table_disp td {
 
    border-left: 1px solid #AAAAAA;
 
    padding-left: 4px;
 
    padding-right: 4px;
 
	border-left: 1px solid #AAAAAA;
 
	padding-left: 4px;
 
	padding-right: 4px;
 
}
 

	
 
table tr.parity0:hover,table tr.parity1:hover {
 
    background: #D5E1E6;
 
	background: #D5E1E6;
 
}
 

	
 
table tr.parity0 {
 
    background: #EAEAE9;
 
	background: #EAEAE9;
 
}
 

	
 
table tr.parity1 {
 
    background: #FFFFFF;
 
	background: #FFFFFF;
 
}
 

	
 
/*** ***/ 
 

	
 
/** COMMON SETTINGS **/
 
.add_icon {
 
	background: url("/images/icons/add.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
.edit_icon {
 
	background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 

	
 
/*** ***/
 
.delete_icon {
 
	background: url("/images/icons/delete.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
/** common settings **/
 
.add_icon{
 
    background: url("/images/icons/add.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 

	
 
}
 
.edit_icon{
 
    background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
.action_button {
 
	border: 0px;
 
	display: block;
 
}
 

	
 
.delete_icon{
 
    background: url("/images/icons/delete.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 

	
 
.action_button:hover {
 
	border: 0px;
 
	font-style: italic;
 
	cursor: pointer;
 
}
 

	
 
.action_button{
 
    border:0px;
 
    display: block;
 
.flash_msg ul {
 
	margin: 0;
 
	padding: 25px 0px 0px 0px;
 
}
 
.action_button:hover{
 
    border:0px;
 
    font-style:italic;
 
    cursor: pointer;
 

	
 
.error_msg {
 
	background-color: #FFCFCF;
 
	background-image: url("/images/icons/error_msg.png");
 
	border: 1px solid #FF9595;
 
	color: #CC3300;
 
}
 

	
 
.flash_msg ul{
 
	margin:0;
 
	padding:25px 0px 0px 0px;
 
	
 
}
 
.error_msg {
 
	background-color:#FFCFCF;
 
	background-image: url("/images/icons/error_msg.png");
 
	border:1px solid #FF9595;
 
	color:#CC3300;
 
}
 
.warning_msg {
 
	background-color:#FFFBCC;
 
	background-color: #FFFBCC;
 
	background-image: url("/images/icons/warning_msg.png");
 
	border:1px solid #FFF35E;
 
	color:#C69E00;
 
	border: 1px solid #FFF35E;
 
	color: #C69E00;
 
}
 

	
 
.success_msg {
 
	background-color:#D5FFCF;
 
	background-color: #D5FFCF;
 
	background-image: url("/images/icons/success_msg.png");
 
	border:1px solid #97FF88;
 
	color:#009900;
 
	border: 1px solid #97FF88;
 
	color: #009900;
 
}
 

	
 
.notice_msg {
 
	background-color:#DCE3FF;
 
	background-color: #DCE3FF;
 
	background-image: url("/images/icons/notice_msg.png");
 
	border:1px solid #93A8FF;
 
	color:#556CB5;
 
	border: 1px solid #93A8FF;
 
	color: #556CB5;
 
}
 

	
 
.success_msg, .error_msg, .notice_msg, .warning_msg{
 
	background-position:10px center;
 
	background-repeat:no-repeat;
 
	font-size:12px;
 
	font-weight:bold;
 
	min-height:14px;
 
	line-height:14px;
 
	margin-bottom:0px;
 
	margin-top:0px;
 
	padding:3px 10px 3px 40px;
 
	display:block;
 
.success_msg,.error_msg,.notice_msg,.warning_msg {
 
	background-position: 10px center;
 
	background-repeat: no-repeat;
 
	font-size: 12px;
 
	font-weight: bold;
 
	min-height: 14px;
 
	line-height: 14px;
 
	margin-bottom: 0px;
 
	margin-top: 0px;
 
	padding: 3px 10px 3px 40px;
 
	display: block;
 
	overflow: auto;
 
}        
 
}
 

	
 
#msg_close {
 
	background:transparent url("icons/cross_grey_small.png")	no-repeat scroll 0 0;
 
	cursor:pointer;
 
	height:16px;
 
	position:absolute;
 
	right:5px;
 
	top:5px;
 
	width:16px;
 
	background: transparent url("icons/cross_grey_small.png") no-repeat
 
		scroll 0 0;
 
	cursor: pointer;
 
	height: 16px;
 
	position: absolute;
 
	right: 5px;
 
	top: 5px;
 
	width: 16px;
 
}
 

	
 
.error-message{
 
	color:#CC3300;
 
.error-message {
 
	color: #CC3300;
 
}
 
/**** Tooltip ****/
 
.yui-overlay,
 
.yui-panel-container {
 
    visibility:hidden;
 
    position:absolute;
 
    z-index: 2;
 

	
 
/**** TOOLTIP ****/
 
.yui-overlay,.yui-panel-container {
 
	visibility: hidden;
 
	position: absolute;
 
	z-index: 2;
 
}
 

	
 
.yui-tt {
 
    visibility:hidden;
 
    position:absolute;
 
    color:#666666;
 
    background-color:#FFFFFF;
 
    font-family:arial,helvetica,verdana,sans-serif;
 
    padding:8px;
 
    border:2px solid #556CB5;
 
    font:100% sans-serif;
 
    width:auto;
 
    opacity:1.0;
 
	visibility: hidden;
 
	position: absolute;
 
	color: #666666;
 
	background-color: #FFFFFF;
 
	font-family: arial, helvetica, verdana, sans-serif;
 
	padding: 8px;
 
	border: 2px solid #556CB5;
 
	font: 100% sans-serif;
 
	width: auto;
 
	opacity: 1.0;
 
}
 

	
 
.yui-tt-shadow {
 
    display: none;
 
	display: none;
 
}
 

	
 
/** END TOOLTIP **/ 
 

	
 
/** AUTOCOMPLETE **/ 
 

	
 
.ac{
 
	vertical-align: top;
 

	
 
}
 
.ac .match {
 
    font-weight:bold;
 
}
 

	
 
.ac .yui-ac {
 
	position: relative;
 
	font-family: arial;
 
	font-size: 100%;
 
}
 

	
 
.ac #perm_ac{
 
	width:15em;
 
}
 
/* styles for input field */
 
.ac .yui-ac-input {
 
	position: absolute;
 
	width: 100%;
 
}
 

	
 
/* styles for results container */
 
.ac .yui-ac-container {
 
	position: absolute;
 
	top: 1.6em;
 
	width: 100%;
 
}
 
/** end of Tooltip **/ 
 

	
 
/* styles for header/body/footer wrapper within container */
 
.ac .yui-ac-content {
 
	position: absolute;
 
	width: 100%;
 
	border: 1px solid #808080;
 
	background: #fff;
 
	overflow: hidden;
 
	z-index: 9050;
 
}
 

	
 
/* styles for container shadow */
 
.ac .yui-ac-shadow {
 
	position: absolute;
 
	margin: .3em;
 
	width: 100%;
 
	background: #000;
 
	-moz-opacity: 0.10;
 
	opacity: .10;
 
	filter: alpha(opacity = 10);
 
	z-index: 9049;
 
}
 

	
 
/* styles for results list */
 
.ac .yui-ac-content ul {
 
	margin: 0;
 
	padding: 0;
 
	width: 100%;
 
}
 

	
 
/* styles for result item */
 
.ac .yui-ac-content li {
 
	margin: 0;
 
	padding: 2px 5px;
 
	cursor: default;
 
	white-space: nowrap;
 
}
 

	
 
/* styles for prehighlighted result item */
 
.ac .yui-ac-content li.yui-ac-prehighlight {
 
	background: #B3D4FF;
 
}
 

	
 
/* styles for highlighted result item */
 
.ac .yui-ac-content li.yui-ac-highlight {
 
	background: #556CB5;
 
	color: #FFF;
 
}
 

	
 
/** END AUTOCOMPLETE **/
 
div#main {
 
	padding: 5px;
 
}
 

	
 
div#container {
 
	background: #FFFFFF;
 
	position: relative;
 
	color: #666;
 
}
 

	
 
div.page-header {
 
	padding: 50px 20px 0;
 
	background: #556cb5 top left repeat-x;
 
	position: relative;
 
}
 

	
 
div.page-header h1 {
 
	margin: 10px 0 30px;
 
	font-size: 1.8em;
 
	font-weight: bold;
 
	font-family: sans-serif;
 
	letter-spacing: 1px;
 
	color: #FFFFFF;
 
}
 

	
 
div.page-header h1 a {
 
	font-weight: bold;
 
	color: #FFFFFF;
 
}
 

	
 
div.page-header a {
 
	text-decoration: none;
 
}
 

	
 
div.page-header form {
 
	position: absolute;
 
	margin-bottom: 2px;
 
	bottom: 0;
 
	right: 20px;
 
}
 

	
 
div.page-header form label {
 
	color: #DDD;
 
}
 

	
 
div.page-header form input {
 
	padding: 2px;
 
	border: solid 1px #DDD;
 
}
 

	
 
div.page-header form dl {
 
	overflow: hidden;
 
}
 

	
 
div.page-header form dl dt {
 
	font-size: 1.2em;
 
}
 

	
 
div.page-header form dl dt,div.page-header form dl dd {
 
	margin: 0 0 0 5px;
 
	float: left;
 
	height: 24px;
 
	line-height: 20px;
 
}
 

	
 
ul.page-nav {
 
	margin: 10px 0 0 0;
 
	list-style-type: none;
 
	overflow: hidden;
 
	width: 800px;
 
	padding: 0;
 
}
 

	
 
ul.page-nav li {
 
	margin: 0 4px 0 0;
 
	float: left;
 
	height: 24px;
 
	font-size: 1.1em;
 
	line-height: 24px;
 
	text-align: center;
 
	background: #556CB5;
 
}
 

	
 
ul.page-nav li.current {
 
	background: #FFF;
 
	padding-right: 5px;
 
	padding-left: 5px;
 
}
 

	
 
ul.page-nav li.current a {
 
	color: #556CB5;
 
}
 

	
 
ul.page-nav li a {
 
	height: 24px;
 
	color: #FFF;
 
	padding-right: 5px;
 
	padding-left: 5px;
 
	display: block;
 
	text-decoration: none;
 
	font-weight: bold;
 
}
 

	
 
ul.page-nav li.logout a {
 
	color: #FDAC9D;
 
}
 

	
 
ul.page-nav li a:hover {
 
	background: #FFF;
 
	color: #556CB5;
 
}
 

	
 
ul.submenu {
 
	margin: 5px 0px -20px 0px;
 
	list-style-type: none;
 
}
 

	
 
ul.submenu li {
 
	margin: 0 10px 0 0;
 
	font-size: 0.9em;
 
	font-weight:bold;
 
	font-weight: bold;
 
	display: inline;
 
}
 

	
 
ul.submenu .repos {
 
    background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
   
 
	background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
ul.submenu .users {
 
    background: url("/images/icons/user_edit.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
	background: url("/images/icons/user_edit.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
ul.submenu .permissions {
 
    background: url("/images/icons/folder_key.png") no-repeat scroll 3px;
 
    height: 16px;
 
    padding-left: 20px;
 
    padding-top: 0px;
 
    text-align: left;
 
	background: url("/images/icons/folder_key.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
ul.submenu .current_submenu {
 
    border-bottom: 2px solid #556CB5;
 
	border-bottom: 2px solid #556CB5;
 
}
 

	
 
h2 {
 
	margin: 20px 0 10px;
 
	height: 30px;
 
	line-height: 30px;
 
	text-indent: 20px;
 
	background: #FFF;
 
	font-size: 1.2em;
 
	border-top: dotted 1px #D5E1E6;
 
	font-weight: bold;
 
	color:#556CB5;
 
	color: #556CB5;
 
}
 

	
 
h2.no-link {
 
	color: #006699;
 
}
 

	
 
h2.no-border {
 
	color: #FFF;
 
	background: #556CB5;
 
	border: 0;
 
}
 

	
 
h2 a {
 
	font-weight: bold;
 
	color: #006699;
 
}
 

	
 
div.page-path {
 
	text-align: right;
 
	padding: 20px 30px 10px 0;
 
	border: solid #d9d8d1;
 
	border-width: 0px 0px 1px;
 
	font-size: 1.2em;
 
}
 

	
 
div.page-footer {
 
	margin: 50px 0 0;
 
	position: relative;
 
	text-align: center;
 
	font-weight: bold;
 
	font-size: 90%;
 
}
 

	
 
div.page-footer p {
 
	position: relative;
 
	left: 20px;
 
	bottom: 5px;
 
	font-size: 1.2em;
 
}
 

	
 
ul.rss-logo {
 
	position: absolute;
 
	top: -10px;
 
	right: 20px;
 
	height: 20px;
 
	list-style-type: none;
 
}
 

	
 
ul.rss-logo li {
 
	display: inline;
 
}
 

	
 
ul.rss-logo li a {
 
	padding: 3px 6px;
 
	line-height: 10px;
 
	border: 1px solid;
 
	border-color: #fcc7a5 #7d3302 #3e1a01 #ff954e;
 
	color: #ffffff;
 
	background-color: #ff6600;
 
	font-weight: bold;
 
	font-family: sans-serif;
 
	font-size: 10px;
 
	text-align: center;
 
	text-decoration: none;
 
}
 

	
 
div.rss-logo li a:hover {
 
	background-color: #ee5500;
 
}
 

	
 
p.normal {
 
	margin: 20px 0 20px 30px;
 
	font-size: 1.2em;
 
}
 

	
 
span.logtags span {
 
	background-repeat: no-repeat;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
	font-weight: bold;
 
}
 

	
 
span.logtags span.tagtag {
 
	background-image: url("/images/icons/tag_green.png");
 
}
 

	
 
span.logtags span.branchtag {
 
	background-image: url("/images/icons/arrow_branch.png");
 
	color: #628F53;
 
}
 

	
 
span.logtags span.inbranchtag {
 
	background-image: url("/images/icons/arrow_branch.png");
 
}
 

	
 
div.diff pre {
 
	margin: 10px 0 0 0;
 
}
 

	
 
div.diff pre span {
 
	font-family: monospace;
 
	white-space: pre;
 
	font-size: 1.2em;
 
	padding: 3px 0;
 
}
 

	
 
td.source {
 
	white-space: pre;
 
	font-family: monospace;
 
	margin: 10px 30px 0;
 
	font-size: 1.2em;
 
	font-family: monospace;
 
}
 

	
 
div.source div.parity0,div.source div.parity1 {
 
	padding: 1px;
 
	font-size: 1.2em;
 
}
 

	
 
div.source div.parity0 {
 
	background: #F1F6F7;
 
}
 

	
 
div.source div.parity1 {
 
	background: #FFFFFF;
 
}
 

	
 
div.parity0:hover,div.parity1:hover {
 
	background: #D5E1E6;
 
}
 

	
 
.linenr {
 
	color: #999;
 
	text-align: right;
 
}
 

	
 
.lineno {
 
	text-align: right;
 
}
 

	
 
.lineno a {
 
	color: #999;
 
}
 

	
 
td.linenr {
 
	width: 60px;
 
}
 

	
 
div#powered-by {
 
	position: absolute;
 
	width: 75px;
 
	top: 15px;
 
	right: 20px;
 
	font-size: 1.2em;
 
}
 

	
 
div#powered-by a {
 
	color: #EEE;
 
	text-decoration: none;
 
}
 

	
 
div#powered-by a:hover {
 
	text-decoration: underline;
 
}
 

	
 
dl.overview {
 
	margin: 0 0 0 30px;
 
	font-size: 1.1em;
 
	overflow: hidden;
 
}
 

	
 
dl.overview dt,dl.overview dd {
 
	margin: 5px 0;
 
	float: left;
 
}
 

	
 
dl.overview dt {
 
	clear: left;
 
	font-weight: bold;
 
	width: 150px;
 
}
 

	
 
#clone_url{
 
    border: 0px;
 
#clone_url {
 
	border: 0px;
 
}
 
/** end of summary **/ 
 

	
 
/** chagelog **/
 
/** end of summary **/ /** chagelog **/
 
h3.changelog {
 
	margin: 20px 0 5px 30px;
 
	padding: 0 0 2px;
 
	font-size: 1.4em;
 
	border-bottom: dotted 1px #D5E1E6;
 
}
 

	
 
ul.changelog-entry {
 
	margin: 0 0 10px 30px;
 
	list-style-type: none;
 
	position: relative;
 
}
 

	
 
ul.changelog-entry li span.revdate {
 
	font-size: 1.1em;
 
}
 

	
 
ul.changelog-entry li.age {
 
	position: absolute;
 
	top: -25px;
 
	right: 10px;
 
	font-size: 1.4em;
 
	color: #CCC;
 
	font-weight: bold;
 
	font-style: italic;
 
}
 

	
 
ul.changelog-entry li span.name {
 
	font-size: 1.2em;
 
	font-weight: bold;
 
}
 

	
 
ul.changelog-entry li.description {
 
	margin: 10px 0 0;
 
	font-size: 1.1em;
 
}
 

	
 
/** end of changelog **/ 
 

	
 
/** file **/
 
/** end of changelog **/ /** file **/
 
p.files {
 
	margin: 0 0 0 20px;
 
	font-size: 2.0em;
 
	font-weight: bold;
 
}
 

	
 
/** end of file **/ 
 

	
 
/** changeset **/
 
#changeset_content{
 
	width:60%;
 
	float:left;
 
/** end of file **/ /** changeset **/
 
#changeset_content {
 
	width: 60%;
 
	float: left;
 
}
 

	
 
#changeset_content .container .wrapper{
 
#changeset_content .container .wrapper {
 
	width: 600px;
 
}
 
#changeset_content .container{
 
	border:1px solid #CCCCCC;
 
	height:120px;
 

	
 
#changeset_content .container {
 
	border: 1px solid #CCCCCC;
 
	height: 120px;
 
}
 

	
 
#changeset_content .container .left{
 
	float:left;
 
#changeset_content .container .left {
 
	float: left;
 
	width: 70%;
 
	padding-left: 5px;
 
}
 

	
 
#changeset_content .container .right{
 
	float:right;
 
#changeset_content .container .right {
 
	float: right;
 
	width: 25%;
 
	text-align: right;
 
}
 

	
 
#changeset_content .container .left .date{
 
	font-weight:bold;
 
#changeset_content .container .left .date {
 
	font-weight: bold;
 
}
 
#changeset_content .container .left .author{
 

	
 
#changeset_content .container .left .author {
 
	
 
}
 
#changeset_content .container .left .message{
 

	
 
#changeset_content .container .left .message {
 
	font-style: italic;
 
	color: #556CB5;
 
}
 

	
 
.cs_files{
 
.cs_files {
 
	width: 60%;
 
}
 

	
 
.cs_files .cs_added{
 
.cs_files .cs_added {
 
	background: url("/images/icons/page_white_add.png") no-repeat scroll 3px;
 
	/*background-color:#BBFFBB;*/
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;	
 
	text-align: left;
 
}
 
.cs_files .cs_changed{
 
	background: url("/images/icons/page_white_edit.png") no-repeat scroll 3px;
 

	
 
.cs_files .cs_changed {
 
	background: url("/images/icons/page_white_edit.png") no-repeat scroll
 
		3px;
 
	/*background-color: #FFDD88;*/
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;	
 
	text-align: left;
 
}
 
.cs_files .cs_removed{
 
	background: url("/images/icons/page_white_delete.png") no-repeat scroll 3px;
 

	
 
.cs_files .cs_removed {
 
	background: url("/images/icons/page_white_delete.png") no-repeat scroll
 
		3px;
 
	/*background-color: #FF8888;*/
 
	height: 16px;
 
	padding-left: 20px;
 
	margin-top: 7px;
 
	text-align: left;	
 
	text-align: left;
 
}
 

	
 
/** end of changeset **/ /** canvas **/
 
#graph_nodes {
 
	margin-top: 8px;
 
}
 

	
 
#graph {
 
	overflow: hidden;
 
}
 

	
 
/** end of changeset **/ 
 

	
 
/** canvas **/
 
#graph_nodes{
 
	margin-top:8px;
 
}
 
#graph{
 
	overflow: hidden;
 

	
 
}
 
#graph_nodes{
 
	width:160px;
 
	float:left;
 
#graph_nodes {
 
	width: 160px;
 
	float: left;
 
}
 

	
 
#graph_content{
 
	width:800px;
 
	float:left;
 
#graph_content {
 
	width: 800px;
 
	float: left;
 
}
 
#graph_content .container_header{
 
	border:1px solid #CCCCCC;
 
	height:30px;
 

	
 
#graph_content .container_header {
 
	border: 1px solid #CCCCCC;
 
	height: 30px;
 
	background: #EEEEEE;
 
}
 

	
 

	
 
#graph_content .container .wrapper{
 
#graph_content .container .wrapper {
 
	width: 600px;
 
}
 
#graph_content .container{
 

	
 
#graph_content .container {
 
	border-bottom: 1px solid #CCCCCC;
 
	border-left: 1px solid #CCCCCC;
 
	border-right: 1px solid #CCCCCC;
 
	height:120px;
 
	height: 120px;
 
}
 

	
 
#graph_content .container .left{
 
	float:left;
 
#graph_content .container .left {
 
	float: left;
 
	width: 70%;
 
	padding-left: 5px;
 
}
 

	
 
#graph_content .container .right{
 
	float:right;
 
#graph_content .container .right {
 
	float: right;
 
	width: 25%;
 
	text-align: right;
 
}
 
#graph_content .container .left .date{
 
	font-weight:bold;
 

	
 
#graph_content .container .left .date {
 
	font-weight: bold;
 
}
 
#graph_content .container .left .author{
 

	
 
#graph_content .container .left .author {
 
	
 
}
 
#graph_content .container .left .message{
 

	
 
#graph_content .container .left .message {
 
	font-size: 80%;
 
}
 

	
 
.right div{
 
.right div {
 
	clear: both;
 
}
 
.right .changes .added,.changed,.removed{
 
	border:1px solid #DDDDDD;
 
	display:block;
 
	float:right;
 
	font-size:0.75em;
 
	text-align:center;
 
	min-width:15px;
 

	
 
.right .changes .added,.changed,.removed {
 
	border: 1px solid #DDDDDD;
 
	display: block;
 
	float: right;
 
	font-size: 0.75em;
 
	text-align: center;
 
	min-width: 15px;
 
}
 
.right .changes .added{
 
	background:#BBFFBB; 
 

	
 
.right .changes .added {
 
	background: #BBFFBB;
 
}
 
.right .changes .changed{
 

	
 
.right .changes .changed {
 
	background: #FFDD88;
 
}
 
.right .changes .removed{
 

	
 
.right .changes .removed {
 
	background: #FF8888;
 
}
 

	
 
.right .merge{
 
.right .merge {
 
	vertical-align: top;
 
	font-size: 60%;
 
	font-weight: bold;
 
}
 
.right .merge img{
 
	vertical-align: bottom;	
 

	
 
.right .merge img {
 
	vertical-align: bottom;
 
}
 

	
 
.right .parent{
 
.right .parent {
 
	font-size: 90%;
 
	font-family: monospace;
 
}
 
/** end of canvas **/
 

	
 
/* FILE BROWSER */
 
/** end of canvas **/ /* FILE BROWSER */
 
div.browserblock {
 
    overflow: hidden;
 
    padding: 0px;
 
    border: 1px solid #ccc;
 
    background: #f8f8f8;
 
    font-size: 100%;
 
    line-height: 100%;
 
    /* new */
 
    line-height: 125%;
 
	overflow: hidden;
 
	padding: 0px;
 
	border: 1px solid #ccc;
 
	background: #f8f8f8;
 
	font-size: 100%;
 
	line-height: 100%;
 
	/* new */
 
	line-height: 125%;
 
}
 
div.browserblock .browser-header{
 

	
 
div.browserblock .browser-header {
 
	border-bottom: 1px solid #CCCCCC;
 
	background: #EEEEEE;
 
	color:blue;
 
	padding:10px 0 10px 0;
 
	color: blue;
 
	padding: 10px 0 10px 0;
 
}
 
div.browserblock .browser-header span{
 
	margin-left:25px;
 

	
 
div.browserblock .browser-header span {
 
	margin-left: 25px;
 
	font-weight: bold;
 
}
 
div.browserblock .browser-body{
 

	
 
div.browserblock .browser-body {
 
	background: #EEEEEE;
 
}
 

	
 
table.code-browser {
 
	border-collapse:collapse;
 
	border-collapse: collapse;
 
	width: 100%;
 
}
 
table.code-browser tr{
 
	margin:3px;	
 

	
 
table.code-browser tr {
 
	margin: 3px;
 
}
 

	
 
table.code-browser thead th {
 
	background-color: #EEEEEE;
 
	height: 20px;
 
	font-size: 1.1em;
 
	font-weight: bold;
 
	text-align: center;
 
	text-align: left;
 
	padding-left: 10px;
 
}
 

	
 
table.code-browser tbody tr {
 
	
 
}
 

	
 
table.code-browser tbody td {
 
	
 
	padding-left:10px;
 
	padding-left: 10px;
 
	height: 20px;
 
}
 

	
 
.info-table {
 
	background: none repeat scroll 0 0 #FAFAFA;
 
	border-bottom: 1px solid #DDDDDD;
 
	width: 100%;
 
}
 

	
 
.rss_logo {
 
	background: url("/images/icons/rss_16.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 

	
 
.atom_logo {
 
	background: url("/images/icons/atom.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	padding-top: 0px;
 
	text-align: left;
 
}
 
.archive_logo{
 

	
 
.archive_logo {
 
	background: url("/images/icons/compress.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	text-align: left;
 
}
 

	
 
.browser-file {
 
	background: url("/images/icons/document_16.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	text-align: left;
 
}
 

	
 
.browser-dir {
 
	background: url("/images/icons/folder_16.png") no-repeat scroll 3px;
 
	height: 16px;
 
	padding-left: 20px;
 
	text-align: left;
 
}
 

	
 
#repos_list {
 
	border: 1px solid #556CB5;
 
	background: #FFFFFF;
 
}
 
\ No newline at end of file
pylons_app/templates/admin/repos/repo_edit.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Repositories administration')}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${h.link_to(u'Admin',h.url('admin_home'))}
 
	 /  
 
	 ${_('Repos')}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('admin')}
 
	${self.submenu('repos')}
 
</%def>
 
<%def name="main()">
 
	<div>
 
        <h2>${_('Repositories')} - ${_('edit')}</h2>
 
        ${h.form(url('repo', id=c.repo_info.repo_name),method='put')}
 
        <table>
 
        	<tr>
 
        		<td>${_('Name')}</td>
 
        		<td>${h.text('repo_name')}</td>
 
        		<td>${self.get_form_error('repo_name')}</td>
 
        	</tr>
 
        	<tr>
 
        		<td>${_('Description')}</td>
 
        		<td>${h.textarea('description',cols=23,rows=5)}</td>
 
        		<td>${self.get_form_error('description')}</td>
 
        	</tr>
 
        	<tr>
 
        		<td>${_('Private')}</td>
 
        		<td>${h.checkbox('private')}</td>
 
        		<td>${self.get_form_error('private')}</td>
 
        	</tr>
 
        	<tr>
 
        		<td>${_('Owner')}</td>
 
        		<td>${h.text('user')}</td>
 
				<td class='ac'>
 
					<div id="perm_ac">
 
						${h.text('user',class_='yui-ac-input')}
 
						<div id="owner_container"></div>
 
					</div>
 
				</td>        		
 
        		<td>${self.get_form_error('user')}</td>
 
        	</tr>
 
        	<tr>
 
        		<td>${_('Permissions')}</td>
 
        		<td>
 
        			<table>
 
        				<tr>
 
        					<td>${_('none')}</td>
 
        					<td>${_('read')}</td>
 
        					<td>${_('write')}</td>
 
        					<td>${_('admin')}</td>
 
        					<td>${_('user')}</td>
 
        				</tr>
 
        				
 
        				%for r2p in c.repo_info.repo2perm:
 
	        				<tr>
 
	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.none')}</td>
 
	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.read')}</td>
 
	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.write')}</td>
 
	        					<td>${h.radio('perm_%s' % r2p.user.username,'repository.admin')}</td>
 
	        					<td>${r2p.user.username}</td>
 
	        				</tr>
 
						%endfor
 

	
 
						
 
						<%
 
							
 
							if not hasattr(c,'form_errors'):
 
								d = 'display:none;'
 
							else:
 
								d=''
 
						%>
 

	
 
        				<tr id="add_perm_input" style="${d}">
 
        					<td>${h.radio('perm_new_user','repository.none')}</td>
 
        					<td>${h.radio('perm_new_user','repository.read')}</td>
 
        					<td>${h.radio('perm_new_user','repository.write')}</td>
 
        					<td>${h.radio('perm_new_user','repository.admin')}</td>
 
        					<td>${h.text('perm_new_user_name',size=10)}</td>
 
        					<td class='ac'>
 
        						<div id="perm_ac">
 
        							${h.text('perm_new_user_name',class_='yui-ac-input')}
 
									<div id="perm_container"></div>
 
        						</div>
 
        					</td>
 
        					<td>${self.get_form_error('perm_new_user_name')}</td>     					
 
        				</tr>
 
        				<tr>
 
        					<td colspan="4">
 
        						<span id="add_perm" class="add_icon" style="cursor: pointer;">
 
        						${_('Add another user')}
 
        						</span>
 
        					</td>
 
        				</tr>
 
        			</table>
 
        		</td>
 
        		
 
        	</tr>
 
        	<tr>
 
        		<td></td>
 
        		<td>${h.submit('update','update')}</td>
 
        	</tr>
 
        	        	        	
 
        </table>
 
        ${h.end_form()}
 
        <script type="text/javascript">
 
        	YAHOO.util.Event.onDOMReady(function(){
 
				var D = YAHOO.util.Dom;
 
				YAHOO.util.Event.addListener('add_perm','click',function(){
 
					D.setStyle('add_perm_input','display','');
 
					D.setStyle('add_perm','opacity','0.6');
 
					D.setStyle('add_perm','cursor','default');
 
				});
 
            });
 
        </script>
 
		<script type="text/javascript">    
 
		YAHOO.example.FnMultipleFields = function(){
 
		    var myContacts = ${c.users_array|n}
 
		    
 
		    // Define a custom search function for the DataSource
 
		    var matchNames = function(sQuery) {
 
		        // Case insensitive matching
 
		        var query = sQuery.toLowerCase(),
 
		            contact,
 
		            i=0,
 
		            l=myContacts.length,
 
		            matches = [];
 
		        
 
		        // Match against each name of each contact
 
		        for(; i<l; i++) {
 
		            contact = myContacts[i];
 
		            if((contact.fname.toLowerCase().indexOf(query) > -1) ||
 
		                (contact.lname.toLowerCase().indexOf(query) > -1) ||
 
		                (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
 
		                matches[matches.length] = contact;
 
		            }
 
		        }
 
		
 
		        return matches;
 
		    };
 
		
 
		    // Use a FunctionDataSource
 
		    var oDS = new YAHOO.util.FunctionDataSource(matchNames);
 
		    oDS.responseSchema = {
 
		        fields: ["id", "fname", "lname", "nname"]
 
		    }
 
		
 
		    // Instantiate AutoComplete for perms
 
		    var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
 
		    oAC_perms.useShadow = false;
 
		    oAC_perms.resultTypeList = false;
 
		    
 
		    // Instantiate AutoComplete for owner
 
		 	var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
 
		 	oAC_owner.useShadow = false;
 
		 	oAC_owner.resultTypeList = false;
 
		    
 
		    
 
		    // Custom formatter to highlight the matching letters
 
		    var custom_formatter = function(oResultData, sQuery, sResultMatch) {
 
		        var query = sQuery.toLowerCase(),
 
		            fname = oResultData.fname,
 
		            lname = oResultData.lname,
 
		            nname = oResultData.nname || "", // Guard against null value
 
		            query = sQuery.toLowerCase(),
 
		            fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
		            lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
		            nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
		            displayfname, displaylname, displaynname;
 
		            
 
		        if(fnameMatchIndex > -1) {
 
		            displayfname = highlightMatch(fname, query, fnameMatchIndex);
 
		        }
 
		        else {
 
		            displayfname = fname;
 
		        }
 
		
 
		        if(lnameMatchIndex > -1) {
 
		            displaylname = highlightMatch(lname, query, lnameMatchIndex);
 
		        }
 
		        else {
 
		            displaylname = lname;
 
		        }
 
		
 
		        if(nnameMatchIndex > -1) {
 
		            displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
 
		        }
 
		        else {
 
		            displaynname = nname ? "(" + nname + ")" : "";
 
		        }
 
		
 
		        return displayfname + " " + displaylname + " " + displaynname;
 
		        
 
		    };
 
		    oAC_perms.formatResult = custom_formatter; 
 
		    oAC_owner.formatResult = custom_formatter;
 
		    			    
 
		    // Helper function for the formatter
 
		    var highlightMatch = function(full, snippet, matchindex) {
 
		        return full.substring(0, matchindex) + 
 
		                "<span class='match'>" + 
 
		                full.substr(matchindex, snippet.length) + 
 
		                "</span>" +
 
		                full.substring(matchindex + snippet.length);
 
		    };
 
		
 
		    var myHandler = function(sType, aArgs) {
 
		        var myAC = aArgs[0]; // reference back to the AC instance
 
		        var elLI = aArgs[1]; // reference to the selected LI element
 
		        var oData = aArgs[2]; // object literal of selected item's result data
 
		        myAC.getInputEl().value = oData.nname;
 
		    };
 

	
 
		    oAC_perms.itemSelectEvent.subscribe(myHandler);
 
		    oAC_owner.itemSelectEvent.subscribe(myHandler);
 
		    
 
		    return {
 
		        oDS: oDS,
 
		        oAC_perms: oAC_perms,
 
		        oAC_owner: oAC_owner, 
 
		    };
 
		}();
 
		    
 
		</script>        
 
    </div>
 
</%def>   
pylons_app/templates/base/base.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<!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" id="mainhtml">
 
<head>
 
    <link rel="icon" href="/images/hgicon.png" type="image/png" />
 
    <meta name="robots" content="index, nofollow"/>
 
    <title>${next.title()}</title>
 
    ##For future use yui reset for cross browser compatability.
 
    ##<link rel="stylesheet" href="/js/yui/reset-fonts-grids/reset-fonts-grids.css" type="text/css" />
 
    ${self.css()}
 
    ${self.js()}
 
</head>
 

	
 
<body class="mainbody">
 
<div id="container">
 
    <div class="page-header">
 
        <h1 class="breadcrumbs">${next.breadcrumbs()}</h1>
 
        ${self.page_nav()}
 
    <div class="flash_msg">
 
    <% messages = h.flash.pop_messages() %>
 
		% if messages:
 
		<ul id="flash-messages">
 
		    % for message in messages:
 
		    <li class="${message.category}_msg">${message}</li>
 
		    % endfor
 
		</ul>
 
		% endif
 
    </div>        
 
    <div id="main"> 
 
    	${next.main()}
 
    	<script type="text/javascript">${h.tooltip.activate()}</script>    	
 
    </div>
 
    <div class="page-footer">
 
        Hg App ${c.hg_app_version} &copy; 2010 by Marcin Kuzminski
 
    </div>   
 

	
 
    <div id="powered-by">
 
        <p>
 
        <a href="http://mercurial.selenic.com/" title="Mercurial">
 
            <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
 
        </p>
 
    </div>
 

	
 
    <div id="corner-top-left"></div>
 
    <div id="corner-top-right"></div>
 
    <div id="corner-bottom-left"></div>
 
    <div id="corner-bottom-right"></div>
 

	
 
</div>
 
</body>
 
</html>
 

	
 
### MAKO DEFS ### 
 

	
 
<%def name="page_nav()">
 
	${self.menu()}
 
	${self.submenu()}
 
</%def>
 

	
 
<%def name="menu(current)">
 
<% 
 
def is_current(selected):
 
	if selected == current:
 
		return "class='current'"
 
%>
 
		%if current not in ['home','admin']:
 
		##regular menu
 
	       <script type="text/javascript">
 
	       	YAHOO.util.Event.onDOMReady(function(){
 
				YAHOO.util.Event.addListener('repo_switcher','click',function(){
 
					if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
 
						YAHOO.util.Dom.setStyle('switch_repos','display','none');
 
						YAHOO.util.Dom.setStyle('repo_switcher','background','');
 
						YAHOO.util.Dom.removeClass('repo_switcher','selected');
 
						YAHOO.util.Dom.get('repo_switcher').removeAttribute('style');
 
					}
 
					else{
 
						YAHOO.util.Dom.setStyle('switch_repos','display','');
 
						YAHOO.util.Dom.setStyle('repo_switcher','background','#FFFFFF');
 
						YAHOO.util.Dom.setStyle('repo_switcher','color','#556CB5');
 
						YAHOO.util.Dom.addClass('repo_switcher','selected');
 
					}
 
					});
 
				YAHOO.util.Event.addListener('repos_list','change',function(e){
 
		            var wa = YAHOO.util.Dom.get('repos_list').value;
 
		        	
 
		            var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
 
			        window.location = url;
 
				})
 
	           });
 
	       	</script>       	
 
	        <ul class="page-nav">
 
				<li>
 
					<a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
 
					<div id="switch_repos" style="display:none;position: absolute;height: 25px">
 
						<select id="repos_list" size="=10" style="min-width: 150px">
 
						%for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
 
							<option value="${repo}">${repo}</option>
 
						%endfor
 
						</select>
 
					</div>			
 
				</li>
 
	            <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
 
				<li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>            
 
	            <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
 
	            <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
 
				<li>${h.link_to(_('settings'),h.url('edit_repo',id=c.repo_name))}</li>	        
 
	        </ul>
 
		%else:
 
		##Root menu
 
			<ul class="page-nav">
 
				<li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
 
				<li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
 
				<li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
 
			</ul>
 
		%endif    
 
		</div>
 
</%def>
 
<%def name="submenu(current=None)">
 
	<% 
 
	def is_current(selected):
 
		if selected == current:
 
			return "class='current_submenu'"
 
	%>
 
	%if current != None:
 
	<div>
 
    <ul class="submenu">
 
        <li ${is_current('repos')}>${h.link_to(u'repos',h.url('repos'),class_='repos')}</li>
 
        <li ${is_current('users')}>${h.link_to(u'users',h.url('users'),class_='users')}</li>
 
        <li ${is_current('permissions')}>${h.link_to(u'permissions',h.url('permissions'),class_='permissions')}</li>
 
    </ul>
 
    </div>
 
    %endif
 
</%def>
 

	
 

	
 
<%def name="css()">
 
<link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
 
</%def>
 

	
 
<%def name="js()">
 
<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
 
<script type="text/javascript" src="/js/yui/container/container-min.js"></script>
 
<script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
 
<script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
 
</%def>
 

	
 
<!-- DEFINITION OF FORM ERROR FETCHER -->
 
<%def name="get_form_error(element)">
 
	%if hasattr(c,'form_errors') and type(c.form_errors) == dict:
 
        %if c.form_errors.get(element,False):
 
            <span class="error-message">
 
                ${c.form_errors.get(element,'')}
 
            </span>
 
        %endif
 
	%endif           
 
</%def>
 
\ No newline at end of file
pylons_app/templates/login.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="base/base.html"/>
 
<%def name="title()">
 
    ${c.repos_prefix} Mercurial Repositories
 
</%def>
 
<%def name="breadcrumbs()">
 
	${c.repos_prefix} Mercurial Repositories
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('home')}
 
	&nbsp;
 
	</div>
 
</%def>
 
<%def name="main()">
 
        <div>
 
        <br />
 
        <h2>${_('Login')}</h2>
 
        <h2>${_('Login to hg app')}</h2>
 
        ${h.form(h.url.current())}
 
        <table>
 
            <tr>
 
                <td>${_('Username')}</td>
 
                <td>${h.text('username')}</td>
 
                <td>${self.get_form_error('username')}</td>
 
            </tr>
 
            <tr>
 
                <td>${_('Password')}</td>
 
                <td>${h.password('password')}</td>
 
                <td>${self.get_form_error('password')}</td> 
 
            </tr>
 
            <tr>
 
                <td></td>
 
                <td>${h.submit('login','login')}</td>
 
            </tr>            
 
        </table>
 
        ${h.end_form()}
 
        </div>
 
</%def>    
 

	
 

	
0 comments (0 inline, 0 general)