Changeset - 3fe3285868d1
[Not reviewed]
beta
0 6 1
Marcin Kuzminski - 15 years ago 2011-02-25 18:47:09
marcin@python-works.com
implemented public journal for anonymous users, admin can control which repositories
are visible in such journal in admin panel
7 files changed with 184 insertions and 44 deletions:
0 comments (0 inline, 0 general)
rhodecode/config/routing.py
Show inline comments
 
"""
 
Routes configuration
 

	
 
The more specific and detailed routes should be defined first so they
 
may take precedent over the more generic routes. For more information
 
refer to the routes manual at http://routes.groovie.org/docs/
 
"""
 
from __future__ import with_statement
 
from routes import Mapper
 
from rhodecode.lib.utils import check_repo_fast as cr
 

	
 
def make_map(config):
 
    """Create, configure and return the routes Mapper"""
 
    routes_map = Mapper(directory=config['pylons.paths']['controllers'],
 
                 always_scan=config['debug'])
 
    routes_map.minimization = False
 
    routes_map.explicit = False
 

	
 
    def check_repo(environ, match_dict):
 
        """
 
        check for valid repository for proper 404 handling
 
        
 
        :param environ:
 
        :param match_dict:
 
        """
 
        repo_name = match_dict.get('repo_name')
 
        return not cr(repo_name, config['base_path'])
 

	
 
    # The ErrorController route (handles 404/500 error pages); it should
 
    # likely stay at the top, ensuring it can always be resolved
 
    routes_map.connect('/error/{action}', controller='error')
 
    routes_map.connect('/error/{action}/{id}', controller='error')
 

	
 
    #==========================================================================
 
    # CUSTOM ROUTES HERE
 
    #==========================================================================
 

	
 
    #MAIN PAGE
 
    routes_map.connect('home', '/', controller='home', action='index')
 
    routes_map.connect('bugtracker', "http://bitbucket.org/marcinkuzminski/rhodecode/issues", _static=True)
 
    routes_map.connect('gpl_license', "http://www.gnu.org/licenses/gpl.html", _static=True)
 
    #ADMIN REPOSITORY REST ROUTES
 
    with routes_map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
 
        m.connect("repos", "/repos",
 
             action="create", conditions=dict(method=["POST"]))
 
        m.connect("repos", "/repos",
 
             action="index", conditions=dict(method=["GET"]))
 
        m.connect("formatted_repos", "/repos.{format}",
 
             action="index",
 
            conditions=dict(method=["GET"]))
 
        m.connect("new_repo", "/repos/new",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("formatted_new_repo", "/repos/new.{format}",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("/repos/{repo_name:.*}",
 
             action="update", conditions=dict(method=["PUT"],
 
                                              function=check_repo))
 
        m.connect("/repos/{repo_name:.*}",
 
             action="delete", conditions=dict(method=["DELETE"],
 
                                              function=check_repo))
 
        m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
 
             action="edit", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("repo", "/repos/{repo_name:.*}",
 
             action="show", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
 
             action="show", conditions=dict(method=["GET"],
 
                                            function=check_repo))
 
        #ajax delete repo perm user
 
        m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
 
             action="delete_perm_user", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 
        #ajax delete repo perm users_group
 
        m.connect('delete_repo_users_group', "/repos_delete_users_group/{repo_name:.*}",
 
             action="delete_perm_users_group", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 

	
 
        #settings actions
 
        m.connect('repo_stats', "/repos_stats/{repo_name:.*}",
 
             action="repo_stats", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 
        m.connect('repo_cache', "/repos_cache/{repo_name:.*}",
 
             action="repo_cache", conditions=dict(method=["DELETE"],
 
                                                        function=check_repo))
 
        m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*}",
 
             action="repo_public_journal", conditions=dict(method=["PUT"],
 
                                                        function=check_repo))
 

	
 
    #ADMIN USER REST ROUTES
 
    routes_map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
 

	
 
    #ADMIN USER REST ROUTES
 
    routes_map.resource('users_group', 'users_groups', controller='admin/users_groups', path_prefix='/_admin')
 

	
 
    #ADMIN GROUP REST ROUTES
 
    routes_map.resource('group', 'groups', controller='admin/groups', path_prefix='/_admin')
 

	
 
    #ADMIN PERMISSIONS REST ROUTES
 
    routes_map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
 

	
 
    ##ADMIN LDAP SETTINGS
 
    routes_map.connect('ldap_settings', '/_admin/ldap', controller='admin/ldap_settings',
 
                action='ldap_settings', conditions=dict(method=["POST"]))
 
    routes_map.connect('ldap_home', '/_admin/ldap', controller='admin/ldap_settings',)
 

	
 

	
 
    #ADMIN SETTINGS REST ROUTES
 
    with routes_map.submapper(path_prefix='/_admin', controller='admin/settings') as m:
 
        m.connect("admin_settings", "/settings",
 
             action="create", conditions=dict(method=["POST"]))
 
        m.connect("admin_settings", "/settings",
 
             action="index", conditions=dict(method=["GET"]))
 
        m.connect("formatted_admin_settings", "/settings.{format}",
 
             action="index", conditions=dict(method=["GET"]))
 
        m.connect("admin_new_setting", "/settings/new",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("formatted_admin_new_setting", "/settings/new.{format}",
 
             action="new", conditions=dict(method=["GET"]))
 
        m.connect("/settings/{setting_id}",
 
             action="update", conditions=dict(method=["PUT"]))
 
        m.connect("/settings/{setting_id}",
 
             action="delete", conditions=dict(method=["DELETE"]))
 
        m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
 
             action="edit", conditions=dict(method=["GET"]))
 
        m.connect("formatted_admin_edit_setting", "/settings/{setting_id}.{format}/edit",
 
             action="edit", conditions=dict(method=["GET"]))
 
        m.connect("admin_setting", "/settings/{setting_id}",
 
             action="show", conditions=dict(method=["GET"]))
 
        m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
 
             action="show", conditions=dict(method=["GET"]))
 
        m.connect("admin_settings_my_account", "/my_account",
 
             action="my_account", conditions=dict(method=["GET"]))
 
        m.connect("admin_settings_my_account_update", "/my_account_update",
 
             action="my_account_update", conditions=dict(method=["PUT"]))
 
        m.connect("admin_settings_create_repository", "/create_repository",
 
             action="create_repository", conditions=dict(method=["GET"]))
 

	
 
    #ADMIN MAIN PAGES
 
    with routes_map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
 
        m.connect('admin_home', '', action='index')#main page
 
        m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
 
                  action='add_repo')
 

	
 

	
 
    #USER JOURNAL
 
    routes_map.connect('journal', '/_admin/journal', controller='journal',)
 
    routes_map.connect('public_journal', '/_admin/public_journal', controller='journal',
 
                       action="public_journal")
 
    routes_map.connect('toggle_following', '/_admin/toggle_following', controller='journal',
 
                action='toggle_following', conditions=dict(method=["POST"]))
 

	
 

	
 
    #SEARCH
 
    routes_map.connect('search', '/_admin/search', controller='search',)
 
    routes_map.connect('search_repo', '/_admin/search/{search_repo:.*}', controller='search')
 

	
 
    #LOGIN/LOGOUT/REGISTER/SIGN IN
 
    routes_map.connect('login_home', '/_admin/login', controller='login')
 
    routes_map.connect('logout_home', '/_admin/logout', controller='login', action='logout')
 
    routes_map.connect('register', '/_admin/register', controller='login', action='register')
 
    routes_map.connect('reset_password', '/_admin/password_reset', controller='login', action='password_reset')
 

	
 
    #FEEDS
 
    routes_map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
 
                controller='feed', action='rss',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
 
                controller='feed', action='atom',
 
                conditions=dict(function=check_repo))
 

	
 

	
 
    #REPOSITORY ROUTES
 
    routes_map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
 
                controller='changeset', revision='tip',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('raw_changeset_home', '/{repo_name:.*}/raw-changeset/{revision}',
 
                controller='changeset', action='raw_changeset', revision='tip',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('summary_home', '/{repo_name:.*}',
 
                controller='summary', conditions=dict(function=check_repo))
 
    routes_map.connect('summary_home', '/{repo_name:.*}/summary',
 
                controller='summary', conditions=dict(function=check_repo))
 
    routes_map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
 
                controller='shortlog', conditions=dict(function=check_repo))
 
    routes_map.connect('branches_home', '/{repo_name:.*}/branches',
 
                controller='branches', conditions=dict(function=check_repo))
 
    routes_map.connect('tags_home', '/{repo_name:.*}/tags',
 
                controller='tags', conditions=dict(function=check_repo))
 
    routes_map.connect('changelog_home', '/{repo_name:.*}/changelog',
 
                controller='changelog', conditions=dict(function=check_repo))
 
    routes_map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
 
                controller='files', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
 
                controller='files', action='diff', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('files_rawfile_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
 
                controller='files', action='rawfile', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('files_raw_home', '/{repo_name:.*}/raw/{revision}/{f_path:.*}',
 
                controller='files', action='raw', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
 
                controller='files', action='annotate', revision='tip', f_path='',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('files_archive_home', '/{repo_name:.*}/archive/{fname}',
 
                controller='files', action='archivefile',
 
                conditions=dict(function=check_repo))
 
    routes_map.connect('repo_settings_delete', '/{repo_name:.*}/settings',
 
                controller='settings', action="delete",
 
                conditions=dict(method=["DELETE"], function=check_repo))
 
    routes_map.connect('repo_settings_update', '/{repo_name:.*}/settings',
 
                controller='settings', action="update",
 
                conditions=dict(method=["PUT"], function=check_repo))
 
    routes_map.connect('repo_settings_home', '/{repo_name:.*}/settings',
 
                controller='settings', action='index',
 
                conditions=dict(function=check_repo))
 

	
 
    routes_map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
 
                controller='settings', action='fork_create',
 
                conditions=dict(function=check_repo, method=["POST"]))
 
    routes_map.connect('repo_fork_home', '/{repo_name:.*}/fork',
 
                controller='settings', action='fork',
 
                conditions=dict(function=check_repo))
 

	
 
    return routes_map
rhodecode/controllers/admin/repos.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.admin.repos
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
    
 
    Admin controller for RhodeCode
 
    
 
    :created_on: Apr 7, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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.
 

	
 
import logging
 
import traceback
 
import formencode
 
from operator import itemgetter
 
from formencode import htmlfill
 

	
 
from paste.httpexceptions import HTTPInternalServerError
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
 
from rhodecode.model.db import User
 
from rhodecode.lib.helpers import get_token
 
from rhodecode.model.db import User, Repository, UserFollowing
 
from rhodecode.model.forms import RepoForm
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.repo import RepoModel
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ReposController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    """
 
    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()
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(ReposController, self).__before__()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        cached_repo_list = ScmModel().get_repos()
 
        c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
 
        return render('admin/repos/repos.html')
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        """
 
        POST /repos: Create a new item"""
 
        # url('repos')
 
        repo_model = RepoModel()
 
        _form = RepoForm()()
 
        form_result = {}
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.create(form_result, c.rhodecode_user)
 
            h.flash(_('created repository %s') % form_result['repo_name'],
 
                    category='success')
 

	
 
            if request.POST.get('user_created'):
 
                action_logger(self.rhodecode_user, 'user_created_repo',
 
                              form_result['repo_name'], '', self.sa)
 
            else:
 
                action_logger(self.rhodecode_user, 'admin_created_repo',
 
                              form_result['repo_name'], '', self.sa)
 

	
 
        except formencode.Invalid, errors:
 
            c.new_repo = errors.value['repo_name']
 

	
 
            if request.POST.get('user_created'):
 
                r = render('admin/repos/repo_add_create_repository.html')
 
            else:
 
                r = render('admin/repos/repo_add.html')
 

	
 
            return htmlfill.render(
 
                r,
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            msg = _('error occurred during creation of repository %s') \
 
                    % form_result.get('repo_name')
 
            h.flash(msg, category='error')
 
        if request.POST.get('user_created'):
 
            return redirect(url('home'))
 
        return redirect(url('repos'))
 

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

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

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def update(self, repo_name):
 
        """PUT /repos/repo_name: Update an existing item"""
 
        """
 
        PUT /repos/repo_name: 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', repo_name=ID),
 
        #           method='put')
 
        # url('repo', repo_name=ID)
 
        repo_model = RepoModel()
 
        changed_name = repo_name
 
        _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
 

	
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.update(repo_name, form_result)
 
            invalidate_cache('get_repo_cached_%s' % repo_name)
 
            h.flash(_('Repository %s updated successfully' % repo_name),
 
                    category='success')
 
            changed_name = form_result['repo_name']
 
            action_logger(self.rhodecode_user, 'admin_updated_repo',
 
                              changed_name, '', self.sa)
 

	
 
        except formencode.Invalid, errors:
 
            c.repo_info = repo_model.get_by_repo_name(repo_name)
 

	
 
            if c.repo_info.stats:
 
                last_rev = c.repo_info.stats.stat_on_revision
 
            else:
 
                last_rev = 0
 
            c.stats_revision = last_rev
 
            repo, dbrepo = ScmModel().get(repo_name, retval='repo')
 
            c.repo_last_rev = repo.count() if repo.revisions else 0
 

	
 
            c.default_user_id = User.by_username('default').user_id
 
            c.in_public_journal = self.sa.query(UserFollowing)\
 
                .filter(UserFollowing.user_id == c.default_user_id)\
 
                .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
            if last_rev == 0:
 
                c.stats_percentage = 0
 
            else:
 
                c.stats_percentage = '%.2f' % ((float((last_rev)) /
 
                                                c.repo_last_rev) * 100)
 

	
 
            c.users_array = repo_model.get_users_js()
 
            c.users_groups_array = repo_model.get_users_groups_js()
 

	
 
            errors.value.update({'user':c.repo_info.user.username})
 
            return htmlfill.render(
 
                render('admin/repos/repo_edit.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('error occurred during update of repository %s') \
 
                    % repo_name, category='error')
 

	
 
        return redirect(url('edit_repo', repo_name=changed_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete(self, repo_name):
 
        """DELETE /repos/repo_name: Delete an existing item"""
 
        """
 
        DELETE /repos/repo_name: 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', repo_name=ID),
 
        #           method='delete')
 
        # url('repo', repo_name=ID)
 

	
 
        repo_model = RepoModel()
 
        repo = repo_model.get_by_repo_name(repo_name)
 
        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') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('repos'))
 
        try:
 
            action_logger(self.rhodecode_user, 'admin_deleted_repo',
 
                              repo_name, '', self.sa)
 
            repo_model.delete(repo)
 
            invalidate_cache('get_repo_cached_%s' % repo_name)
 
            h.flash(_('deleted repository %s') % repo_name, category='success')
 

	
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of %s') % repo_name,
 
                    category='error')
 

	
 
        return redirect(url('repos'))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_perm_user(self, repo_name):
 
        """DELETE an existing repository permission user
 
        """
 
        DELETE an existing repository permission user
 
        
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo_model = RepoModel()
 
            repo_model.delete_perm_user(request.POST, repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occurred during deletion of repository user'),
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_perm_users_group(self, repo_name):
 
        """DELETE an existing repository permission users group
 
        """
 
        DELETE an existing repository permission users group
 
        
 
        :param repo_name:
 
        """
 
        try:
 
            repo_model = RepoModel()
 
            repo_model.delete_perm_users_group(request.POST, repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occurred during deletion of repository'
 
                      ' users groups'),
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_stats(self, repo_name):
 
        """DELETE an existing repository statistics
 
        """
 
        DELETE an existing repository statistics
 
        
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo_model = RepoModel()
 
            repo_model.delete_stats(repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occurred during deletion of repository stats'),
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_cache(self, repo_name):
 
        """INVALIDATE existing repository cache
 
        """
 
        INVALIDATE existing repository cache
 
        
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            ScmModel().mark_for_invalidation(repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occurred during cache invalidation'),
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_public_journal(self, repo_name):
 
        """
 
        Set's this repository to be visible in public journal,
 
        in other words assing default user to follow this repo
 
        
 
        :param repo_name:
 
        """
 

	
 
        cur_token = request.POST.get('auth_token')
 
        token = get_token()
 
        if cur_token == token:
 
            try:
 
                repo_id = Repository.by_repo_name(repo_name).repo_id
 
                user_id = User.by_username('default').user_id
 
                self.scm_model.toggle_following_repo(repo_id, user_id)
 
                h.flash(_('Updated repository visibility in public journal'),
 
                        category='success')
 
            except:
 
                h.flash(_('An error occurred during setting this'
 
                          ' repository in public journal'),
 
                        category='error')
 

	
 
        else:
 
            h.flash(_('Token mismatch'), category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 

	
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def show(self, repo_name, format='html'):
 
        """GET /repos/repo_name: Show a specific item"""
 
        # url('repo', repo_name=ID)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def edit(self, repo_name, format='html'):
 
        """GET /repos/repo_name/edit: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        repo, dbrepo = ScmModel().get(repo_name, retval='repo')
 

	
 
        repo_model = RepoModel()
 
        c.repo_info = repo_model.get_by_repo_name(repo_name)
 

	
 
        if c.repo_info is None:
 
            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') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('repos'))
 

	
 
        c.default_user_id = User.by_username('default').user_id
 
        c.in_public_journal = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.default_user_id)\
 
            .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
        if c.repo_info.stats:
 
            last_rev = c.repo_info.stats.stat_on_revision
 
        else:
 
            last_rev = 0
 
        c.stats_revision = last_rev
 

	
 
        c.repo_last_rev = repo.count() if repo.revisions else 0
 

	
 
        if last_rev == 0 or c.repo_last_rev == 0:
 
            c.stats_percentage = 0
 
        else:
 
            c.stats_percentage = '%.2f' % ((float((last_rev)) /
 
                                            c.repo_last_rev) * 100)
 

	
 
        c.users_array = repo_model.get_users_js()
 
        c.users_groups_array = repo_model.get_users_groups_js()
 

	
 
        defaults = c.repo_info.get_dict()
 

	
 
        #fill owner
 
        if c.repo_info.user:
 
            defaults.update({'user':c.repo_info.user.username})
 
        else:
 
            replacement_user = self.sa.query(User)\
 
            .filter(User.admin == True).first().username
 
            defaults.update({'user':replacement_user})
 

	
 

	
 
        #fill repository users
 
        for p in c.repo_info.repo_to_perm:
 
            defaults.update({'u_perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        #fill repository groups
 
        for p in c.repo_info.users_group_to_perm:
 
            defaults.update({'g_perm_%s' % p.users_group.users_group_name:
 
                             p.permission.permission_name})
 

	
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
rhodecode/controllers/journal.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.journal
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Journal controller for pylons
 
    
 
    :created_on: Nov 21, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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.
 
import logging
 

	
 
from sqlalchemy import or_
 
from sqlalchemy.orm import joinedload, make_transient
 
from webhelpers.paginate import Page
 
from itertools import groupby
 

	
 
from paste.httpexceptions import HTTPInternalServerError
 
from pylons import request, tmpl_context as c
 

	
 
from rhodecode.lib.auth import LoginRequired, NotAnonymous
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.helpers import get_token
 
from rhodecode.model.db import UserLog, UserFollowing
 

	
 
log = logging.getLogger(__name__)
 

	
 
class JournalController(BaseController):
 

	
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def __before__(self):
 
        super(JournalController, self).__before__()
 

	
 
    @NotAnonymous()
 
    def index(self):
 
        # Return a rendered template
 
        p = int(request.params.get('page', 1))
 

	
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 

	
 
        repo_ids = [x.follows_repository.repo_id for x in c.following
 
                    if x.follows_repository is not None]
 
        user_ids = [x.follows_user.user_id for x in c.following
 
                    if x.follows_user is not None]
 

	
 
        filtering_criterion = None
 

	
 
        if repo_ids and user_ids:
 
            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
 
                        UserLog.user_id.in_(user_ids))
 
        if repo_ids and not user_ids:
 
            filtering_criterion = UserLog.repository_id.in_(repo_ids)
 
        if not repo_ids and user_ids:
 
            filtering_criterion = UserLog.user_id.in_(user_ids)
 
        if filtering_criterion is not None:
 
            journal = self.sa.query(UserLog)\
 
                .options(joinedload(UserLog.user))\
 
                .options(joinedload(UserLog.repository))\
 
                .filter(filtering_criterion)\
 
                .order_by(UserLog.action_date.desc())
 
        else:
 
            journal = []
 
        p = int(request.params.get('page', 1))
 
        journal = self._get_journal_data(c.following)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20)
 

	
 
        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
 

	
 
        c.journal_data = render('journal/journal_data.html')
 
        if request.params.get('partial'):
 
            return c.journal_data
 
        return render('journal/journal.html')
 

	
 

	
 
    def _get_daily_aggregate(self, journal):
 
        groups = []
 
        for k, g in groupby(journal, lambda x:x.action_as_day):
 
            user_group = []
 
            for k2, g2 in groupby(list(g), lambda x:x.user.email):
 
                l = list(g2)
 
                user_group.append((l[0].user, l))
 

	
 
            groups.append((k, user_group,))
 

	
 
        return groups
 

	
 

	
 
    def _get_journal_data(self, following_repos):
 
        repo_ids = [x.follows_repository.repo_id for x in following_repos
 
                    if x.follows_repository is not None]
 
        user_ids = [x.follows_user.user_id for x in following_repos
 
                    if x.follows_user is not None]
 

	
 
        filtering_criterion = None
 

	
 
        if repo_ids and user_ids:
 
            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
 
                        UserLog.user_id.in_(user_ids))
 
        if repo_ids and not user_ids:
 
            filtering_criterion = UserLog.repository_id.in_(repo_ids)
 
        if not repo_ids and user_ids:
 
            filtering_criterion = UserLog.user_id.in_(user_ids)
 
        if filtering_criterion is not None:
 
            journal = self.sa.query(UserLog)\
 
                .options(joinedload(UserLog.user))\
 
                .options(joinedload(UserLog.repository))\
 
                .filter(filtering_criterion)\
 
                .order_by(UserLog.action_date.desc())
 
        else:
 
            journal = []
 

	
 

	
 
        return journal
 

	
 
    @NotAnonymous()
 
    def toggle_following(self):
 
        cur_token = request.POST.get('auth_token')
 
        token = get_token()
 
        if cur_token == token:
 

	
 
            user_id = request.POST.get('follows_user_id')
 
            if user_id:
 
                try:
 
                    self.scm_model.toggle_following_user(user_id,
 
                                                    c.rhodecode_user.user_id)
 
                    return 'ok'
 
                except:
 
                    raise HTTPInternalServerError()
 

	
 
            repo_id = request.POST.get('follows_repo_id')
 
            if repo_id:
 
                try:
 
                    self.scm_model.toggle_following_repo(repo_id,
 
                                                    c.rhodecode_user.user_id)
 
                    return 'ok'
 
                except:
 
                    raise HTTPInternalServerError()
 

	
 

	
 
        log.debug('token mismatch %s vs %s', cur_token, token)
 
        raise HTTPInternalServerError()
 

	
 

	
 

	
 

	
 
    def public_journal(self):
 
        # Return a rendered template
 
        p = int(request.params.get('page', 1))
 

	
 
        c.following = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
 
            .options(joinedload(UserFollowing.follows_repository))\
 
            .all()
 

	
 
        journal = self._get_journal_data(c.following)
 

	
 
        c.journal_pager = Page(journal, page=p, items_per_page=20)
 

	
 
        c.journal_day_aggreagate = self._get_daily_aggregate(c.journal_pager)
 

	
 
        c.journal_data = render('journal/journal_data.html')
 
        if request.params.get('partial'):
 
            return c.journal_data
 
        return render('journal/public_journal.html')
rhodecode/public/css/style.css
Show inline comments
 
@@ -1798,384 +1798,398 @@ height:1%;
 
display:inline;
 
border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
 
border-style:solid;
 
border-width:1px;
 
padding:4px 6px;
 
}
 
 
.info_box span {
 
margin-left:3px;
 
margin-right:3px;
 
}
 
 
.info_box input#at_rev {
 
text-align:center;
 
padding:5px 3px 3px 2px;
 
}
 
 
.info_box input#view {
 
text-align:center;
 
padding:4px 3px 2px 2px;
 
}
 
 
.yui-overlay,.yui-panel-container {
 
visibility:hidden;
 
position:absolute;
 
z-index:2;
 
}
 
 
.yui-tt {
 
visibility:hidden;
 
position:absolute;
 
color:#666;
 
background-color:#FFF;
 
font-family:arial, helvetica, verdana, sans-serif;
 
border:2px solid #003367;
 
font:100% sans-serif;
 
width:auto;
 
opacity:1px;
 
padding:8px;
 
white-space: pre;
 
-webkit-border-radius: 8px 8px 8px 8px;
 
-khtml-border-radius: 8px 8px 8px 8px; 
 
-moz-border-radius: 8px 8px 8px 8px;
 
border-radius: 8px 8px 8px 8px;
 
}
 
 
.ac {
 
vertical-align:top;
 
}
 
 
.ac .yui-ac {
 
position:relative;
 
font-family:arial;
 
font-size:100%;
 
}
 
 
.ac .perm_ac {
 
width:15em;
 
}
 
 
.ac .yui-ac-input {
 
width:100%;
 
}
 
 
.ac .yui-ac-container {
 
position:absolute;
 
top:1.6em;
 
width:100%;
 
}
 
 
.ac .yui-ac-content {
 
position:absolute;
 
width:100%;
 
border:1px solid gray;
 
background:#fff;
 
overflow:hidden;
 
z-index:9050;
 
}
 
 
.ac .yui-ac-shadow {
 
position:absolute;
 
width:100%;
 
background:#000;
 
-moz-opacity:0.1px;
 
opacity:.10;
 
filter:alpha(opacity =   10);
 
z-index:9049;
 
margin:.3em;
 
}
 
 
.ac .yui-ac-content ul {
 
width:100%;
 
margin:0;
 
padding:0;
 
}
 
 
.ac .yui-ac-content li {
 
cursor:default;
 
white-space:nowrap;
 
margin:0;
 
padding:2px 5px;
 
}
 
 
.ac .yui-ac-content li.yui-ac-prehighlight {
 
background:#B3D4FF;
 
}
 
 
.ac .yui-ac-content li.yui-ac-highlight {
 
background:#556CB5;
 
color:#FFF;
 
}
 
 
.follow{
 
background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
height: 16px;
 
width: 20px;
 
cursor: pointer;
 
display: block;
 
float: right;
 
margin-top: 2px;
 
}
 
 
.following{
 
background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
height: 16px;
 
width: 20px;
 
cursor: pointer;
 
display: block;
 
float: right;
 
margin-top: 2px;
 
}
 
 
.currently_following{
 
padding-left: 10px;
 
padding-bottom:5px;
 
}
 
 
.add_icon {
 
background:url("../images/icons/add.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.edit_icon {
 
background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.delete_icon {
 
background:url("../images/icons/delete.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.refresh_icon {
 
background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.rss_icon {
 
background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.atom_icon {
 
background:url("../images/icons/atom.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
padding-top:1px;
 
text-align:left;
 
}
 
 
.archive_icon {
 
background:url("../images/icons/compress.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
.start_following_icon {
 
background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
.stop_following_icon {
 
background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
text-align:left;
 
padding-top:1px;
 
}
 
 
.action_button {
 
border:0;
 
display:block;
 
}
 
 
.action_button:hover {
 
border:0;
 
text-decoration:underline;
 
cursor:pointer;
 
}
 
 
#switch_repos {
 
position:absolute;
 
height:25px;
 
z-index:1;
 
}
 
 
#switch_repos select {
 
min-width:150px;
 
max-height:250px;
 
z-index:1;
 
}
 
 
.breadcrumbs {
 
border:medium none;
 
color:#FFF;
 
float:left;
 
text-transform:uppercase;
 
font-weight:700;
 
font-size:14px;
 
margin:0;
 
padding:11px 0 11px 10px;
 
}
 
 
.breadcrumbs a {
 
color:#FFF;
 
}
 
 
.flash_msg ul {
 
margin:0;
 
padding:0 0 10px;
 
}
 
 
.error_msg {
 
background-color:#FFCFCF;
 
background-image:url("../images/icons/error_msg.png");
 
border:1px solid #FF9595;
 
color:#C30;
 
}
 
 
.warning_msg {
 
background-color:#FFFBCC;
 
background-image:url("../images/icons/warning_msg.png");
 
border:1px solid #FFF35E;
 
color:#C69E00;
 
}
 
 
.success_msg {
 
background-color:#D5FFCF;
 
background-image:url("../images/icons/success_msg.png");
 
border:1px solid #97FF88;
 
color:#090;
 
}
 
 
.notice_msg {
 
background-color:#DCE3FF;
 
background-image:url("../images/icons/notice_msg.png");
 
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:700;
 
min-height:14px;
 
line-height:14px;
 
margin-bottom:0;
 
margin-top:0;
 
display:block;
 
overflow:auto;
 
padding:6px 10px 6px 40px;
 
}
 
 
#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;
 
}
 
 
div#legend_container table,div#legend_choices table {
 
width:auto !important;
 
}
 
 
table#permissions_manage {
 
width:0 !important;
 
}
 
 
table#permissions_manage span.private_repo_msg {
 
font-size:0.8em;
 
opacity:0.6px;
 
}
 
 
table#permissions_manage td.private_repo_msg {
 
font-size:0.8em;
 
}
 
 
table#permissions_manage tr#add_perm_input td {
 
vertical-align:middle;
 
}
 
 
div.gravatar {
 
background-color:#FFF;
 
border:1px solid #D0D0D0;
 
float:left;
 
margin-right:0.7em;
 
padding:2px 2px 0;
 
}
 
 
#header,#content,#footer {
 
min-width:1024px;
 
}
 
 
#content {
 
min-height:100%;
 
clear:both;
 
overflow:hidden;
 
padding:14px 30px;
 
}
 
 
#content div.box div.title div.search {
 
background:url("../images/title_link.png") no-repeat top left;
 
border-left:1px solid #316293;
 
}
 
 
#content div.box div.title div.search div.input input {
 
border:1px solid #316293;
 
}
 
 
#content div.box div.title div.search div.button input.ui-button {
 
background:#4e85bb url("../images/button_highlight.png") repeat-x;
 
border:1px solid #316293;
 
border-left:none;
 
color:#FFF;
 
}
 
 
#content div.box div.title div.search div.button input.ui-state-hover {
 
background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
 
border:1px solid #316293;
 
border-left:none;
 
color:#FFF;
 
}
 
 
#content div.box div.form div.fields div.field div.highlight .ui-button {
 
background:#4e85bb url("../images/button_highlight.png") repeat-x;
 
border-top:1px solid #5c91a4;
 
border-left:1px solid #2a6f89;
 
border-right:1px solid #2b7089;
 
border-bottom:1px solid #1a6480;
 
color:#fff;
 
}
 
 
#content div.box div.form div.fields div.field div.highlight .ui-state-hover {
 
background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
 
border-top:1px solid #78acbf;
 
border-left:1px solid #34819e;
 
border-right:1px solid #35829f;
 
border-bottom:1px solid #257897;
 
color:#fff;
 
}
 
 
ins,div.options a:hover {
 
text-decoration:none;
 
}
 
 
img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
 
border:none;
 
}
 
 
img.icon,.right .merge img {
 
vertical-align:bottom;
 
}
 
 
#header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
 
float:right;
 
margin:0;
rhodecode/templates/admin/repos/repo_edit.html
Show inline comments
 
@@ -113,227 +113,239 @@
 
                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 myUsers = ${c.users_array|n};
 
        	var myGroups = ${c.users_groups_array|n};
 
            
 
            // Define a custom search function for the DataSource of users
 
            var matchUsers = function(sQuery) {
 
                // Case insensitive matching
 
                var query = sQuery.toLowerCase();
 
                var i=0;
 
                var l=myUsers.length;
 
                var matches = [];
 
                
 
                // Match against each name of each contact
 
                for(; i<l; i++) {
 
                    contact = myUsers[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;
 
            };
 

	
 
            // Define a custom search function for the DataSource of usersGroups
 
            var matchGroups = function(sQuery) {
 
                // Case insensitive matching
 
                var query = sQuery.toLowerCase();
 
                var i=0;
 
                var l=myGroups.length;
 
                var matches = [];
 
                
 
                // Match against each name of each contact
 
                for(; i<l; i++) {
 
                    matched_group = myGroups[i];
 
                    if(matched_group.grname.toLowerCase().indexOf(query) > -1) {
 
                        matches[matches.length] = matched_group;
 
                    }
 
                }
 
                return matches;
 
            };         
 
            
 
            //match all
 
            var matchAll = function(sQuery){
 
            	u = matchUsers(sQuery);
 
            	g = matchGroups(sQuery);
 
            	return u.concat(g);
 
            };
 
            
 
            // DataScheme for members
 
            var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
 
            memberDS.responseSchema = {
 
                fields: ["id", "fname", "lname", "nname", "grname", "grmembers"]
 
            };
 

	
 
            // DataScheme for owner
 
            var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 
            ownerDS.responseSchema = {
 
                fields: ["id", "fname", "lname", "nname"]
 
            };          
 
            
 
            // Instantiate AutoComplete for perms
 
            var membersAC = new YAHOO.widget.AutoComplete("perm_new_member_name", "perm_container", memberDS);
 
            membersAC.useShadow = false;
 
            membersAC.resultTypeList = false;
 
            
 
            // Instantiate AutoComplete for owner
 
            var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
 
            ownerAC.useShadow = false;
 
            ownerAC.resultTypeList = false;
 
            
 

	
 
            // Helper highlight 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);
 
            };
 
            
 
            // Custom formatter to highlight the matching letters
 
            var custom_formatter = function(oResultData, sQuery, sResultMatch) {
 
            	var query = sQuery.toLowerCase();
 
            	
 
            	if (oResultData.grname != undefined){
 
            		var grname = oResultData.grname;
 
            		var grmembers = oResultData.grmembers;
 
            		var grnameMatchIndex = grname.toLowerCase().indexOf(query);
 
            		var grprefix = "${_('Group')}: ";
 
            		var grsuffix = " ("+grmembers+"  ${_('members')})";
 
            		
 
            		if (grnameMatchIndex > -1){
 
            			return grprefix+highlightMatch(grname,query,grnameMatchIndex)+grsuffix;
 
            		}
 
            		
 
            		return grprefix+oResultData.grname+grsuffix;
 
            	}
 
            	else if(oResultData.fname != undefined){
 
	                
 
	                var fname = oResultData.fname,
 
	                    lname = oResultData.lname,
 
	                    nname = oResultData.nname || "", // Guard against null value
 
	                    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;
 
            	}
 
            	else{
 
            		return '';
 
            	}
 
            };
 
            membersAC.formatResult = custom_formatter; 
 
            ownerAC.formatResult = custom_formatter;
 
                            
 
            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
 
                
 
                //fill the autocomplete with value
 
                if(oData.nname != undefined){
 
                	//users
 
                	myAC.getInputEl().value = oData.nname;
 
                	YUD.get('perm_new_member_type').value = 'user';
 
                }
 
                else{
 
                	//groups
 
                	myAC.getInputEl().value = oData.grname;
 
                	YUD.get('perm_new_member_type').value = 'users_group';
 
                }
 
                
 
            };
 

	
 
            membersAC.itemSelectEvent.subscribe(myHandler);
 
            ownerAC.itemSelectEvent.subscribe(myHandler);
 
            
 
            return {
 
                memberDS: memberDS,
 
                ownerDS:  ownerDS,
 
                membersAC: membersAC,
 
                ownerAC: ownerAC, 
 
            };
 
        }();
 
            
 
        </script>      
 

	
 
</div>
 

	
 
<div class="box box-right">
 
    <div class="title">
 
        <h5>${_('Administration')}</h5>    
 
    </div>
 
    
 
        <h3>${_('Statistics')}</h3>
 
        
 
        ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
 
        <div class="form">
 
           <div class="fields">
 
               ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('Confirm to remove current statistics');")}
 
               
 
               <div class="field">
 
               <ul>
 
                    <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
 
                    <li>${_('Percentage of stats gathered')}: ${c.stats_percentage} %</li>
 
               </ul>
 
               </div>
 
               
 
           </div>
 
        </div>                    
 
        ${h.end_form()}
 
        
 
        <h3>${_('Cache')}</h3>
 
        ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
 
        <div class="form">
 
           <div class="fields">
 
               ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('Confirm to invalidate repository cache');")}
 
           </div>
 
        </div>                    
 
        ${h.end_form()}
 
        
 
        <h3>${_('Public journal')}</h3>
 
        ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
 
        <div class="form">
 
            <div class="fields">
 
                ${h.hidden('auth_token',str(h.get_token()))}
 
                %if c.in_public_journal:
 
                    ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")}
 
                %else:
 
		            ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")}
 
		        %endif
 
	         </div>        
 
        </div>
 
        ${h.end_form()}
 
        
 
        <h3>${_('Delete')}</h3>
 
        ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
 
        <div class="form">
 
           <div class="fields">
 
               ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
 
           </div>
 
        </div>                    
 
        ${h.end_form()}
 
    
 
</div>
 

	
 

	
 
</%def> 
 
\ No newline at end of file
rhodecode/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>
 
    <title>${next.title()}</title>
 
    <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
 
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 
    <meta name="robots" content="index, nofollow"/>
 
    <!-- stylesheets -->
 
    ${self.css()}
 
    <!-- scripts -->
 
    ${self.js()}
 
%if c.ga_code:
 
<script type="text/javascript">
 

	
 
  var _gaq = _gaq || [];
 
  _gaq.push(['_setAccount', '${c.ga_code}']);
 
  _gaq.push(['_trackPageview']);
 

	
 
  (function() {
 
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 
  })();
 

	
 

	
 
</script>
 
%endif
 
</head>
 
<body>
 
    <!-- header -->
 
    <div id="header">
 
        <!-- user -->
 
        <ul id="logged-user">
 
	            <li class="first">
 
	                <div class="gravatar">
 
	                    <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,20)}" />
 
	                </div>
 
		            <div class="account">
 
		            %if c.rhodecode_user.username == 'default':
 
                        %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')(): 
 
                            ${h.link_to('anonymous',h.url('register'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
                        %else:
 
                            ${h.link_to('anonymous',h.url('#'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
                        %endif		            
 
                        
 
		                <a href="${h.url('public_journal')}">${_('Public journal')}</a>   
 
                    %else:                        		            
 
		            	${h.link_to(c.rhodecode_user.username,h.url('admin_settings_my_account'),title='%s %s'%(c.rhodecode_user.name,c.rhodecode_user.lastname))}
 
		            %endif
 
		            </div>	
 
	            </li>
 
	            <li>
 
	               <a href="${h.url('home')}">${_('Home')}</a>
 
	            </li>
 
	            %if c.rhodecode_user.username != 'default':
 
                <li>
 
                   <a href="${h.url('journal')}">${_('Journal')}</a> 
 
                   ##(${c.unread_journal})</a>
 
                </li>
 
                %endif
 
                %if c.rhodecode_user.username == 'default':
 
                    <li class="last highlight">${h.link_to(u'Login',h.url('login_home'))}</li>
 
                %else:
 
                    <li class="last highlight">${h.link_to(u'Log Out',h.url('logout_home'))}</li>
 
                %endif
 
        </ul>
 
        <!-- end user -->
 
        <div id="header-inner" class="title top-left-rounded-corner top-right-rounded-corner">
 
            <!-- logo -->
 
            <div id="logo">
 
                <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
 
            </div>
 
            <!-- end logo -->
 
            <!-- menu -->
 
            ${self.page_nav()}
 
            <!-- quick -->
 
        </div>
 
    </div>     
 
    <!-- end header -->
 
    
 
	<!-- CONTENT -->
 
	<div id="content"> 
 
        <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()}
 
	    </div>
 
	</div> 
 
    <!-- END CONTENT -->
 

	
 
	<!-- footer -->
 
	<div id="footer">
 
	   <div id="footer-inner" class="title bottom-left-rounded-corner bottom-right-rounded-corner">
 
	       <div>
 
	           <p class="footer-link">${h.link_to(_('Submit a bug'),h.url('bugtracker'))}</p>
 
		       <p class="footer-link">${h.link_to(_('GPL license'),h.url('gpl_license'))}</p>
 
		       <p>RhodeCode ${c.rhodecode_version} &copy; 2010-2011 by Marcin Kuzminski</p>
 
	       </div>
 
	   </div>
 
        <script type="text/javascript">
 
        function tooltip_activate(){
 
        ${h.tooltip.activate()}
 
        }
 
        tooltip_activate();
 
        </script>
 
	</div>
 
	<!-- end footer -->
 
</body>
 

	
 
</html>
 

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

	
 
<%def name="menu(current=None)">
 
		<% 
 
		def is_current(selected):
 
			if selected == current:
 
				return h.literal('class="current"')
 
		%>
 
		%if current not in ['home','admin']:           		
 
		   ##REGULAR MENU            
 
	        <ul id="quick">
 
				<!-- repo switcher -->
 
				<li>
 
					<a id="repo_switcher" title="${_('Switch repository')}" href="#">
 
                    <span class="icon">
 
                        <img src="${h.url("/images/icons/database.png")}" alt="${_('Products')}" />
 
                    </span>
 
                    <span>&darr;</span>					
 
					</a>
 
					<ul class="repo_switcher">
 
                        %for repo in c.cached_repo_list:
 
                        
 
                          %if repo['dbrepo']['private']:
 
                             <li><img src="${h.url("/images/icons/lock.png")}" alt="${_('Private repository')}" class="repo_switcher_type"/>${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['dbrepo']['repo_type'])}</li>
 
                          %else:
 
                             <li><img src="${h.url("/images/icons/lock_open.png")}" alt="${_('Public repository')}" class="repo_switcher_type" />${h.link_to(repo['repo'].name,h.url('summary_home',repo_name=repo['repo'].name),class_="%s" % repo['dbrepo']['repo_type'])}</li>
 
                          %endif  
 
                        %endfor					
 
					</ul>			
 
				</li>
 
				
 
	            <li ${is_current('summary')}>
 
	               <a title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
 
	               <span class="icon">
 
	                   <img src="${h.url("/images/icons/clipboard_16.png")}" alt="${_('Summary')}" />
 
	               </span>
 
	               <span>${_('Summary')}</span>                 
 
	               </a>	            
 
	            </li>
 
                ##<li ${is_current('shortlog')}>
 
                ##   <a title="${_('Shortlog')}" href="${h.url('shortlog_home',repo_name=c.repo_name)}">
 
                ##   <span class="icon">
 
                ##       <img src="${h.url("/images/icons/application_view_list.png")}" alt="${_('Shortlog')}" />
 
                ##   </span>
 
                ##   <span>${_('Shortlog')}</span>                 
 
                ##   </a>             
 
                ##</li>	            
 
                <li ${is_current('changelog')}>
 
                   <a title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
 
                   <span class="icon">
 
                       <img src="${h.url("/images/icons/time.png")}" alt="${_('Changelog')}" />
 
                   </span>
 
                   <span>${_('Changelog')}</span>                 
 
                   </a>             
 
                </li>   	
 
                
 
                <li ${is_current('switch_to')}>
 
                   <a title="${_('Switch to')}" href="#">
 
                   <span class="icon">
 
                       <img src="${h.url("/images/icons/arrow_switch.png")}" alt="${_('Switch to')}" />
 
                   </span>
 
                   <span>${_('Switch to')}</span>                 
 
                   </a>    
 
                    <ul>
 
                        <li>
 
                            ${h.link_to('%s (%s)' % (_('branches'),len(c.rhodecode_repo.branches.values()),),h.url('branches_home',repo_name=c.repo_name),class_='branches childs')}
 
                            <ul>
 
                            %if c.rhodecode_repo.branches.values():
 
						        %for cnt,branch in enumerate(c.rhodecode_repo.branches.items()):
 
						            <li>${h.link_to('%s - %s' % (branch[0],h.short_id(branch[1])),h.url('files_home',repo_name=c.repo_name,revision=branch[1]))}</li>
 
						        %endfor
 
						    %else:
 
						    	<li>${h.link_to(_('There are no branches yet'),'#')}</li>
 
						    %endif
 
                            </ul>                        
 
                        </li>
 
                        <li>
 
                            ${h.link_to('%s (%s)' % (_('tags'),len(c.rhodecode_repo.tags.values()),),h.url('tags_home',repo_name=c.repo_name),class_='tags childs')}
 
                            <ul>
 
                            %if c.rhodecode_repo.tags.values():
 
                                %for cnt,tag in enumerate(c.rhodecode_repo.tags.items()):
 
                                 <li>${h.link_to('%s - %s' % (tag[0],h.short_id(tag[1])),h.url('files_home',repo_name=c.repo_name,revision=tag[1]))}</li>
 
                                %endfor
 
                            %else:
 
                            	<li>${h.link_to(_('There are no tags yet'),'#')}</li>
 
                            %endif
 
                            </ul>                        
 
                        </li>                        
 
                    </ul>
 
                </li>
 
                <li ${is_current('files')}>
 
                   <a title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
 
                   <span class="icon">
 
                       <img src="${h.url("/images/icons/file.png")}" alt="${_('Files')}" />
 
                   </span>
 
                   <span>${_('Files')}</span>                 
 
                   </a>             
 
                </li>                            
 
				
 
                <li ${is_current('options')}>
 
                   <a title="${_('Options')}" href="#">
 
                   <span class="icon">
 
                       <img src="${h.url("/images/icons/table_gear.png")}" alt="${_('Admin')}" />
 
                   </span>
 
                   <span>${_('Options')}</span>                 
 
                   </a>
 
                   <ul>
 
                   %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
 
                     %if h.HasPermissionAll('hg.admin')('access settings on repository'):
 
                         <li>${h.link_to(_('settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
 
                     %else:
 
                         <li>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
 
                     %endif
 
                   %endif
 
                   	<li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
 
                   	<li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
 
                    
 
                    %if h.HasPermissionAll('hg.admin')('access admin main page'):
 
                    <li>
 
                       ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}  
 
                        <%def name="admin_menu()">
 
                        <ul>
 
                            <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
 
                            <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
 
                            <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
 
                            <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
 
                            <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
 
                            <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
 
                            <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>        
 
                        </ul>
 
                        </%def>
 
                        
 
                        ${admin_menu()}
 
                    </li>
 
                    %endif
 

	
 
                   </ul>             
 
                </li>
 
                
 
                <li>
 
                    <a title="${_('Followers')}" href="#">
 
                    <span class="icon_short">
 
                        <img src="${h.url("/images/icons/heart.png")}" alt="${_('Followers')}" />
 
                    </span>
 
                    <span id="current_followers_count" class="short">${c.repository_followers}</span>
 
                    </a>
 
                </li>
 
                <li>
 
                    <a title="${_('Forks')}" href="#">
 
                    <span class="icon_short">
 
                        <img src="${h.url("/images/icons/arrow_divide.png")}" alt="${_('Forks')}" />
 
                    </span>
 
                    <span class="short">${c.repository_forks}</span>
 
                    </a>
 
                </li>                
 
                
 
                
 
                
 
	        </ul>
 
		%else:
 
		    ##ROOT MENU
 
            <ul id="quick">
 
                <li>
 
                    <a title="${_('Home')}"  href="${h.url('home')}">
 
                    <span class="icon">
 
                        <img src="${h.url("/images/icons/home_16.png")}" alt="${_('Home')}" />
 
                    </span>
 
                    <span>${_('Home')}</span>                 
 
                    </a>        
 
                </li>
 
                %if c.rhodecode_user.username != 'default':
 
                <li>
 
                    <a title="${_('Journal')}"  href="${h.url('journal')}">
 
                    <span class="icon">
 
                        <img src="${h.url("/images/icons/book.png")}" alt="${_('Journal')}" />
 
                    </span>
 
                    <span>${_('Journal')}</span>                 
 
                    </a>        
 
                </li>
 
                %endif          
 
                <li>
 
                    <a title="${_('Search')}"  href="${h.url('search')}">
 
                    <span class="icon">
 
                        <img src="${h.url("/images/icons/search_16.png")}" alt="${_('Search')}" />
 
                    </span>
 
                    <span>${_('Search')}</span>                 
 
                    </a>        
 
                </li>
 
                
 
				%if h.HasPermissionAll('hg.admin')('access admin main page'):
 
                <li ${is_current('admin')}>
 
                   <a title="${_('Admin')}" href="${h.url('admin_home')}">
 
                   <span class="icon">
 
                       <img src="${h.url("/images/icons/cog_edit.png")}" alt="${_('Admin')}" />
 
                   </span>
 
                   <span>${_('Admin')}</span>                 
 
                   </a>
 
                    ${admin_menu()}
 
                </li>
 
				%endif
 
			</ul>
 
		%endif    
 
</%def>
 

	
 

	
 
<%def name="css()">
 
<link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
 
<link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css')}"  />
 
<link rel="stylesheet" type="text/css" href="${h.url('/css/diff.css')}"  />
 
</%def>
 

	
 
<%def name="js()">
 
##<script type="text/javascript" src="${h.url('/js/yui/utilities/utilities.js')}"></script>
 
##<script type="text/javascript" src="${h.url('/js/yui/container/container.js')}"></script>
 
##<script type="text/javascript" src="${h.url('/js/yui/datasource/datasource.js')}"></script>
 
##<script type="text/javascript" src="${h.url('/js/yui/autocomplete/autocomplete.js')}"></script>
 
##<script type="text/javascript" src="${h.url('/js/yui/selector/selector-min.js')}"></script>
 

	
 
<script type="text/javascript" src="${h.url('/js/yui2a.js')}"></script>
 
<!--[if IE]><script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script><![endif]-->
 
<script type="text/javascript" src="${h.url('/js/yui.flot.js')}"></script>
 

	
 
<script type="text/javascript">
 
var base_url  = "${h.url('toggle_following')}";
 
var YUC = YAHOO.util.Connect;
 
var YUD = YAHOO.util.Dom;
 
var YUE = YAHOO.util.Event;
 

	
 
function onSuccess(target){
 
	
 
	var f = YUD.get(target.id);
 
	var f_cnt = YUD.get('current_followers_count');
 
	
 
    if(f.getAttribute('class')=='follow'){
 
        f.setAttribute('class','following');
 
        f.setAttribute('title',"${_('Stop following this repository')}");
 
        
 
        if(f_cnt){
 
            var cnt = Number(f_cnt.innerHTML)+1;
 
            f_cnt.innerHTML = cnt;
 
        }
 
        
 
    }
 
    else{
 
        f.setAttribute('class','follow');
 
        f.setAttribute('title',"${_('Start following this repository')}");
 
        if(f_cnt){
 
            var cnt = Number(f_cnt.innerHTML)+1;
 
            f_cnt.innerHTML = cnt;
 
        }      
 
    }
 
}
 

	
 
function toggleFollowingUser(fallows_user_id,token){
 
function toggleFollowingUser(target,fallows_user_id,token,user_id){
 
    args = 'follows_user_id='+fallows_user_id;
 
    args+= '&amp;auth_token='+token;
 
    if(user_id != undefined){
 
    	args+="&amp;user_id="+user_id;
 
    }
 
    YUC.asyncRequest('POST',base_url,{
 
        success:function(o){
 
        	onSuccess();
 
        	onSuccess(target);
 
        }
 
    },args); return false;
 
}
 

	
 
function toggleFollowingRepo(target,fallows_repo_id,token){
 
function toggleFollowingRepo(target,fallows_repo_id,token,user_id){
 

	
 
    args = 'follows_repo_id='+fallows_repo_id;
 
    args+= '&amp;auth_token='+token;
 
    if(user_id != undefined){
 
        args+="&amp;user_id="+user_id;
 
    }    
 
    YUC.asyncRequest('POST',base_url,{
 
        success:function(o){
 
        	onSuccess(target);
 
        }
 
    },args); return false;
 
}    
 
</script>
 

	
 
</%def>
 

	
 
<%def name="breadcrumbs()">
 
    <div class="breadcrumbs">
 
    ${self.breadcrumbs_links()}
 
    </div>
 
</%def>
 
\ No newline at end of file
rhodecode/templates/journal/public_journal.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 
<%def name="title()">
 
    ${_('Journal')} - ${c.rhodecode_name}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${c.rhodecode_name}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('home')}
 
</%def>
 
<%def name="main()">
 
	
 
    <div class="box">
 
	    <!-- box / title -->
 
	    <div class="title">
 
	        <h5>${_('Public Journal')}</h5>
 
	    </div>
 
		<script type="text/javascript">
 
		function show_more_event(){
 
		YUE.on(YUD.getElementsByClassName('show_more'),'click',function(e){
 
		    var el = e.target;
 
		    YUD.setStyle(YUD.get(el.id.substring(1)),'display','');
 
		    YUD.setStyle(el.parentNode,'display','none');
 
		});
 
		}
 
		</script> 	    
 
	    <div id="journal">${c.journal_data}</div>
 
    </div>
 
     
 
</%def>    
0 comments (0 inline, 0 general)