Changeset - c96651aebd8a
[Not reviewed]
beta
0 3 0
Marcin Kuzminski - 15 years ago 2011-02-15 19:45:15
marcin@python-works.com
fixed journal look & feel
3 files changed with 46 insertions and 30 deletions:
0 comments (0 inline, 0 general)
rhodecode/lib/helpers.py
Show inline comments
 
@@ -387,206 +387,207 @@ def _age(curdate):
 

	
 
    age = datetime.now() - curdate
 
    age_seconds = (age.days * agescales[2][1]) + age.seconds
 
    pos = 1
 
    for scale in agescales:
 
        if scale[1] <= age_seconds:
 
            if pos == 6:pos = 5
 
            return time_ago_in_words(curdate, agescales[pos][0]) + ' ' + _('ago')
 
        pos += 1
 

	
 
    return _('just now')
 

	
 
age = lambda  x:_age(x)
 
capitalize = lambda x: x.capitalize()
 
email = util.email
 
email_or_none = lambda x: util.email(x) if util.email(x) != x else None
 
person = lambda x: _person(x)
 
short_id = lambda x: x[:12]
 

	
 

	
 
def bool2icon(value):
 
    """Returns True/False values represented as small html image of true/false
 
    icons
 
    
 
    :param value: bool value
 
    """
 

	
 
    if value is True:
 
        return HTML.tag('img', src=url("/images/icons/accept.png"),
 
                        alt=_('True'))
 

	
 
    if value is False:
 
        return HTML.tag('img', src=url("/images/icons/cancel.png"),
 
                        alt=_('False'))
 

	
 
    return value
 

	
 

	
 
def action_parser(user_log):
 
    """This helper will map the specified string action into translated
 
    fancy names with icons and links
 
    
 
    :param user_log: user log instance
 
    """
 

	
 
    action = user_log.action
 
    action_params = ' '
 

	
 
    x = action.split(':')
 

	
 
    if len(x) > 1:
 
        action, action_params = x
 

	
 
    def get_cs_links():
 
        revs_limit = 5 #display this amount always
 
        revs_top_limit = 50 #show upto this amount of changesets hidden
 
        revs = action_params.split(',')
 
        repo_name = user_log.repository.repo_name
 

	
 
        from rhodecode.model.scm import ScmModel
 
        repo, dbrepo = ScmModel().get(repo_name, retval='repo',
 
                                      invalidation_list=[])
 

	
 
        message = lambda rev: get_changeset_safe(repo, rev).message
 

	
 
        cs_links = " " + ', '.join ([link_to(rev,
 
                url('changeset_home',
 
                repo_name=repo_name,
 
                revision=rev), title=tooltip(message(rev)),
 
                class_='tooltip') for rev in revs[:revs_limit] ])
 

	
 
        compare_view = (' <div class="compare_view tooltip" title="%s">'
 
                        '<a href="%s">%s</a> '
 
                        '</div>' % (_('Show all combined changesets %s->%s' \
 
                                      % (revs[0], revs[-1])),
 
                                    url('changeset_home', repo_name=repo_name,
 
                                        revision='%s...%s' % (revs[0], revs[-1])
 
                                    ),
 
                                    _('compare view'))
 
                        )
 

	
 
        if len(revs) > revs_limit:
 
            uniq_id = revs[0]
 
            html_tmpl = ('<span> %s '
 
            '<a class="show_more" id="_%s" href="#more">%s</a> '
 
            '%s</span>')
 
            cs_links += html_tmpl % (_('and'), uniq_id, _('%s more') \
 
                                        % (len(revs) - revs_limit),
 
                                        _('revisions'))
 

	
 
            html_tmpl = '<span id="%s" style="display:none"> %s </span>'
 
            cs_links += html_tmpl % (uniq_id, ', '.join([link_to(rev,
 
                url('changeset_home',
 
                repo_name=repo_name, revision=rev),
 
                title=message(rev), class_='tooltip')
 
                for rev in revs[revs_limit:revs_top_limit]]))
 
        cs_links += _(' into')
 
        if len(revs) > 1:
 
            cs_links += compare_view
 
        return cs_links
 

	
 
    def get_fork_name():
 
        repo_name = action_params
 
        return str(link_to(action_params, url('summary_home',
 
                                          repo_name=repo_name,)))
 

	
 
    map = {'user_deleted_repo':(_('[deleted] repository'), None),
 
           'user_created_repo':(_('[created] repository'), None),
 
           'user_forked_repo':(_('[forked] repository as:'), get_fork_name),
 
           'user_updated_repo':(_('[updated] repository'), None),
 
           'admin_deleted_repo':(_('[delete] repository'), None),
 
           'admin_created_repo':(_('[created] repository'), None),
 
           'admin_forked_repo':(_('[forked] repository'), None),
 
           'admin_updated_repo':(_('[updated] repository'), None),
 
           'push':(_('[pushed]'), get_cs_links),
 
           'pull':(_('[pulled]'), None),
 
           'push':(_('[pushed] into'), get_cs_links),
 
           'pull':(_('[pulled] into'), None),
 
           'started_following_repo':(_('[started following] repository'), None),
 
           'stopped_following_repo':(_('[stopped following] repository'), None),
 
            }
 

	
 
    action_str = map.get(action, action)
 
    action = action_str[0].replace('[', '<span class="journal_highlight">')\
 
                   .replace(']', '</span>')
 
    action_params_func = lambda :""
 

	
 
    if action_str[1] is not None:
 
        action = action + " " + action_str[1]()
 
        action_params_func = action_str[1]
 

	
 
    return literal(action)
 
    return [literal(action), action_params_func]
 

	
 
def action_parser_icon(user_log):
 
    action = user_log.action
 
    action_params = None
 
    x = action.split(':')
 

	
 
    if len(x) > 1:
 
        action, action_params = x
 

	
 
    tmpl = """<img src="%s/%s" alt="%s"/>"""
 
    map = {'user_deleted_repo':'database_delete.png',
 
           'user_created_repo':'database_add.png',
 
           'user_forked_repo':'arrow_divide.png',
 
           'user_updated_repo':'database_edit.png',
 
           'admin_deleted_repo':'database_delete.png',
 
           'admin_created_repo':'database_add.png',
 
           'admin_forked_repo':'arrow_divide.png',
 
           'admin_updated_repo':'database_edit.png',
 
           'push':'script_add.png',
 
           'pull':'down_16.png',
 
           'started_following_repo':'heart_add.png',
 
           'stopped_following_repo':'heart_delete.png',
 
            }
 
    return literal(tmpl % ((url('/images/icons/')),
 
                           map.get(action, action), action))
 

	
 

	
 
#==============================================================================
 
# PERMS
 
#==============================================================================
 
from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
 
HasRepoPermissionAny, HasRepoPermissionAll
 

	
 
#==============================================================================
 
# GRAVATAR URL
 
#==============================================================================
 
import hashlib
 
import urllib
 
from pylons import request
 

	
 
def gravatar_url(email_address, size=30):
 
    ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme')
 
    default = 'identicon'
 
    baseurl_nossl = "http://www.gravatar.com/avatar/"
 
    baseurl_ssl = "https://secure.gravatar.com/avatar/"
 
    baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
 

	
 

	
 
    # construct the url
 
    gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
 
    gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
 

	
 
    return gravatar_url
 

	
 
def safe_unicode(str):
 
    """safe unicode function. In case of UnicodeDecode error we try to return
 
    unicode with errors replace, if this failes we return unicode with 
 
    string_escape decoding """
 

	
 
    try:
 
        u_str = unicode(str)
 
    except UnicodeDecodeError:
 
        try:
 
            u_str = unicode(str, 'utf-8', 'replace')
 
        except UnicodeDecodeError:
 
            #incase we have a decode error just represent as byte string
 
            u_str = unicode(str(str).encode('string_escape'))
 

	
 
    return u_str
 

	
 
def changed_tooltip(nodes):
 
    if nodes:
 
        pref = ': <br/> '
 
        suf = ''
 
        if len(nodes) > 30:
 
            suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
 
        return literal(pref + '<br/> '.join([x.path for x in nodes[:30]]) + suf)
 
    else:
 
        return ': ' + _('No Files')
rhodecode/public/css/style.css
Show inline comments
 
@@ -1320,227 +1320,240 @@ background:#FFF;
 
border-top:1px solid #b3b3b3;
 
border-left:1px solid #b3b3b3;
 
border-right:1px solid #eaeaea;
 
border-bottom:1px solid #eaeaea;
 
color:#000;
 
font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
 
font-size:11px;
 
margin:0;
 
padding:7px 7px 6px;
 
}
 
 
#login div.form div.fields div.buttons {
 
clear:both;
 
overflow:hidden;
 
border-top:1px solid #DDD;
 
text-align:right;
 
margin:0;
 
padding:10px 0 0;
 
}
 
 
#login div.form div.links {
 
clear:both;
 
overflow:hidden;
 
margin:10px 0 0;
 
padding:0 0 2px;
 
}
 
 
#register div.title {
 
clear:both;
 
overflow:hidden;
 
position:relative;
 
background:#003367 url("../images/header_inner.png") repeat-x;
 
margin:0 auto;
 
padding:0;
 
}
 
 
#register div.inner {
 
background:#FFF;
 
border-top:none;
 
border-bottom:none;
 
margin:0 auto;
 
padding:20px;
 
}
 
 
#register div.form div.fields div.field div.label {
 
width:135px;
 
float:left;
 
text-align:right;
 
margin:2px 10px 0 0;
 
padding:5px 0 0 5px;
 
}
 
 
#register div.form div.fields div.field div.input input {
 
width:300px;
 
background:#FFF;
 
border-top:1px solid #b3b3b3;
 
border-left:1px solid #b3b3b3;
 
border-right:1px solid #eaeaea;
 
border-bottom:1px solid #eaeaea;
 
color:#000;
 
font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
 
font-size:11px;
 
margin:0;
 
padding:7px 7px 6px;
 
}
 
 
#register div.form div.fields div.buttons {
 
clear:both;
 
overflow:hidden;
 
border-top:1px solid #DDD;
 
text-align:left;
 
margin:0;
 
padding:10px 0 0 150px;
 
}
 
 
#register div.form div.fields div.buttons div.highlight input.ui-button {
 
background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
 
color:#FFF;
 
border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
 
border-style:solid;
 
border-width:1px;
 
}
 
 
#register div.form div.activation_msg {
 
padding-top:4px;
 
padding-bottom:4px;
 
}
 
 
#journal .journal_day{
 
font-size:20px;
 
padding:10px 0px;
 
border-bottom:2px solid #DDD;
 
margin-left:10px;
 
margin-right:10px;
 
}
 
 
#journal .journal_container{
 
padding:5px;
 
clear:both;
 
margin:0px 5px 0px 10px;
 
}
 
 
#journal .journal_action_container{
 
padding-left:38px;
 
}
 
 
#journal .journal_user{
 
color: #747474;
 
font-size: 14px;
 
font-weight: bold;
 
height: 30px;
 
}
 
#journal .journal_icon{
 
clear: both;
 
float: left;
 
padding-left: 36px;
 
padding-right: 4px;
 
padding-top: 3px;
 
}
 
#journal .journal_action{
 
padding-top:4px;
 
min-height:2px;
 
float:left
 
}
 
#journal .journal_action_params{
 
clear: left;
 
padding-left: 22px;
 
}
 
#journal .journal_repo{
 
float: left;
 
margin-left: 6px;
 
padding-top: 3px;
 
}
 
#journal .date{
 
clear: both;
 
color: #777777;
 
font-size: 11px;
 
padding-left: 56px;
 
padding-left: 22px;
 
}
 
#journal .journal_repo .journal_repo_name{
 
font-weight: bold;
 
font-size: 1.1em;
 
}
 
#journal .compare_view{
 
padding: 5px 0px 5px 3px;
 
padding: 5px 0px 5px 0px;
 
width: 95px;
 
}
 
.journal_highlight{
 
font-weight: bold;
 
padding: 0 2px;
 
vertical-align: bottom;
 
}
 
.trending_language_tbl,.trending_language_tbl td {
 
border:0 !important;
 
margin:0 !important;
 
padding:0 !important;
 
}
 
 
.trending_language {
 
background-color:#003367;
 
color:#FFF;
 
display:block;
 
min-width:20px;
 
text-decoration:none;
 
height:12px;
 
margin-bottom:4px;
 
margin-left:5px;
 
white-space:pre;
 
padding:3px;
 
}
 
 
h3.files_location {
 
font-size:1.8em;
 
font-weight:700;
 
border-bottom:none !important;
 
margin:10px 0 !important;
 
}
 
 
#files_data dl dt {
 
float:left;
 
width:115px;
 
margin:0 !important;
 
padding:5px;
 
}
 
 
#files_data dl dd {
 
margin:0 !important;
 
padding:5px !important;
 
}
 
 
#changeset_content {
 
border:1px solid #CCC;
 
padding:5px;
 
}
 
#changeset_compare_view_content{
 
border:1px solid #CCC;
 
padding:5px;
 
}
 
 
#changeset_content .container {
 
min-height:120px;
 
font-size:1.2em;
 
overflow:hidden;
 
}
 
 
#changeset_compare_view_content .compare_view_commits{
 
width: auto !important;
 
}
 
 
#changeset_compare_view_content .compare_view_commits td{
 
padding:0px 0px 0px 12px !important;
 
}
 
 
#changeset_content .container .right {
 
float:right;
 
width:25%;
 
text-align:right;
 
}
 
 
#changeset_content .container .left .message {
 
font-style:italic;
 
color:#556CB5;
 
white-space:pre-wrap;
 
}
 
 
.cs_files .cur_cs{
 
margin:10px 2px;
 
font-weight: bold;
 
}
 
 
.cs_files .cs_added {
 
background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
 
height:16px;
 
padding-left:20px;
 
margin-top:7px;
 
text-align:left;
 
}
 
 
.cs_files .cs_changed {
 
background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
 
height:16px;
rhodecode/templates/journal/journal_data.html
Show inline comments
 
## -*- coding: utf-8 -*-
 

	
 
%if c.journal_day_aggreagate:
 
    %for day,items in c.journal_day_aggreagate:
 
    <div class="journal_day">${day}</div>
 
        % for user,entries in items:
 
        <div style="padding:10px">
 
            <div class="gravatar">
 
                <img alt="gravatar" src="${h.gravatar_url(user.email,24)}"/>
 
            </div>
 
            <div class="journal_user">${user.name} ${user.lastname}</div>
 
            % for entry in entries:
 
            <div class="journal_icon"> ${h.action_parser_icon(entry)}</div>
 
            <div class="journal_action">${h.action_parser(entry)}</div>
 
            <div class="journal_repo">
 
                <span class="journal_repo_name">
 
                %if entry.repository is not None:
 
                  ${h.link_to(entry.repository.repo_name,
 
                              h.url('summary_home',repo_name=entry.repository.repo_name))}
 
                %else:
 
                  ${entry.repository_name}
 
                %endif             
 
                </span>
 
            </div>
 
            <div class="date"><span class="tooltip" title="${entry.action_date}">${h.age(entry.action_date)}</span></div>
 
            %endfor
 
        </div>
 
        <div style="clear:both;border-bottom:1px dashed #DDD;padding:3px 3px;margin:0px 10px 0px 10px"></div>
 
	        <div class="journal_container">
 
	            <div class="gravatar">
 
	                <img alt="gravatar" src="${h.gravatar_url(user.email,24)}"/>
 
	            </div>
 
	            <div class="journal_user">${user.name} ${user.lastname}</div>
 
	            <div class="journal_action_container">
 
	            % for entry in entries:
 
		            <div class="journal_icon"> ${h.action_parser_icon(entry)}</div>
 
		            <div class="journal_action">${h.action_parser(entry)[0]}</div>
 
		            <div class="journal_repo">
 
		                <span class="journal_repo_name">
 
		                %if entry.repository is not None:
 
		                  ${h.link_to(entry.repository.repo_name,
 
		                              h.url('summary_home',repo_name=entry.repository.repo_name))}
 
		                %else:
 
		                  ${entry.repository_name}
 
		                %endif             
 
		                </span>
 
		            </div>
 
		            <div class="journal_action_params">${h.literal(h.action_parser(entry)[1]())}</div>
 
		            <div class="date"><span class="tooltip" title="${entry.action_date}">${h.age(entry.action_date)}</span></div>
 
	            %endfor
 
	            </div>
 
	        </div>
 
        %endfor
 
    %endfor
 
    
 
<div class="pagination-wh pagination-left">
 
<script type="text/javascript">
 
  var data_div = 'journal';
 
  YAHOO.util.Event.onDOMReady(function(){
 
    YAHOO.util.Event.addListener(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
 
            YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});});
 
</script>
 
${c.journal_pager.pager('$link_previous ~2~ $link_next',     
 
onclick="""YAHOO.util.Connect.asyncRequest('GET','$partial_url',{
 
success:function(o){YAHOO.util.Dom.get(data_div).innerHTML=o.responseText;
 
show_more_event();
 
tooltip_activate();
 
YUE.on(YAHOO.util.Dom.getElementsByClassName('pager_link'),"click",function(){
 
        YAHOO.util.Dom.setStyle(data_div,'opacity','0.3');});       
 
YAHOO.util.Dom.setStyle(data_div,'opacity','1');}},null); return false;""")}
 
</div>
 
    
 
%else:
 
    ${_('No entries yet')}
 
%endif
 
            
 
<script type="text/javascript">
 
show_more_event();
 
</script>
 
\ No newline at end of file
0 comments (0 inline, 0 general)