Changeset - 1ab38cd72704
[Not reviewed]
default
0 11 0
domruf - 9 years ago 2016-09-20 20:01:59
dominikruf@gmail.com
template: use Bootstrap tooltips and popover instead of handmade tooltips

Based on work from Andrew Shadura <andrew@shadura.me>.

Further modified by Mads Kiilerich.

show_changeset_tooltip is merged into tooltip_activate.
11 files changed with 195 insertions and 131 deletions:
0 comments (0 inline, 0 general)
kallithea/controllers/changeset.py
Show inline comments
 
@@ -63,157 +63,157 @@ def _update_with_GET(params, GET):
 
    for k in ['diff1', 'diff2', 'diff']:
 
        params[k] += GET.getall(k)
 

	
 

	
 
def anchor_url(revision, path, GET):
 
    fid = h.FID(revision, path)
 
    return h.url.current(anchor=fid, **dict(GET))
 

	
 

	
 
def get_ignore_ws(fid, GET):
 
    ig_ws_global = GET.get('ignorews')
 
    ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid))
 
    if ig_ws:
 
        try:
 
            return int(ig_ws[0].split(':')[-1])
 
        except ValueError:
 
            raise HTTPBadRequest()
 
    return ig_ws_global
 

	
 

	
 
def _ignorews_url(GET, fileid=None):
 
    fileid = str(fileid) if fileid else None
 
    params = defaultdict(list)
 
    _update_with_GET(params, GET)
 
    lbl = _('Show whitespace')
 
    ig_ws = get_ignore_ws(fileid, GET)
 
    ln_ctx = get_line_ctx(fileid, GET)
 
    # global option
 
    if fileid is None:
 
        if ig_ws is None:
 
            params['ignorews'] += [1]
 
            lbl = _('Ignore whitespace')
 
        ctx_key = 'context'
 
        ctx_val = ln_ctx
 
    # per file options
 
    else:
 
        if ig_ws is None:
 
            params[fileid] += ['WS:1']
 
            lbl = _('Ignore whitespace')
 

	
 
        ctx_key = fileid
 
        ctx_val = 'C:%s' % ln_ctx
 
    # if we have passed in ln_ctx pass it along to our params
 
    if ln_ctx:
 
        params[ctx_key] += [ctx_val]
 

	
 
    params['anchor'] = fileid
 
    icon = h.literal('<i class="icon-strike"></i>')
 
    return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
 
    return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
 

	
 

	
 
def get_line_ctx(fid, GET):
 
    ln_ctx_global = GET.get('context')
 
    if fid:
 
        ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid))
 
    else:
 
        _ln_ctx = filter(lambda k: k.startswith('C'), GET)
 
        ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx  else ln_ctx_global
 
        if ln_ctx:
 
            ln_ctx = [ln_ctx]
 

	
 
    if ln_ctx:
 
        retval = ln_ctx[0].split(':')[-1]
 
    else:
 
        retval = ln_ctx_global
 

	
 
    try:
 
        return int(retval)
 
    except Exception:
 
        return 3
 

	
 

	
 
def _context_url(GET, fileid=None):
 
    """
 
    Generates url for context lines
 

	
 
    :param fileid:
 
    """
 

	
 
    fileid = str(fileid) if fileid else None
 
    ig_ws = get_ignore_ws(fileid, GET)
 
    ln_ctx = (get_line_ctx(fileid, GET) or 3) * 2
 

	
 
    params = defaultdict(list)
 
    _update_with_GET(params, GET)
 

	
 
    # global option
 
    if fileid is None:
 
        if ln_ctx > 0:
 
            params['context'] += [ln_ctx]
 

	
 
        if ig_ws:
 
            ig_ws_key = 'ignorews'
 
            ig_ws_val = 1
 

	
 
    # per file option
 
    else:
 
        params[fileid] += ['C:%s' % ln_ctx]
 
        ig_ws_key = fileid
 
        ig_ws_val = 'WS:%s' % 1
 

	
 
    if ig_ws:
 
        params[ig_ws_key] += [ig_ws_val]
 

	
 
    lbl = _('Increase diff context to %(num)s lines') % {'num': ln_ctx}
 

	
 
    params['anchor'] = fileid
 
    icon = h.literal('<i class="icon-sort"></i>')
 
    return h.link_to(icon, h.url.current(**params), title=lbl, class_='tooltip')
 
    return h.link_to(icon, h.url.current(**params), title=lbl, **{'data-toggle': 'tooltip'})
 

	
 

	
 
# Could perhaps be nice to have in the model but is too high level ...
 
def create_comment(text, status, f_path, line_no, revision=None, pull_request_id=None, closing_pr=None):
 
    """Comment functionality shared between changesets and pullrequests"""
 
    f_path = f_path or None
 
    line_no = line_no or None
 

	
 
    comment = ChangesetCommentsModel().create(
 
        text=text,
 
        repo=c.db_repo.repo_id,
 
        author=c.authuser.user_id,
 
        revision=revision,
 
        pull_request=pull_request_id,
 
        f_path=f_path,
 
        line_no=line_no,
 
        status_change=ChangesetStatus.get_status_lbl(status) if status else None,
 
        closing_pr=closing_pr,
 
    )
 

	
 
    return comment
 

	
 

	
 
class ChangesetController(BaseRepoController):
 

	
 
    def __before__(self):
 
        super(ChangesetController, self).__before__()
 
        c.affected_files_cut_off = 60
 

	
 
    def __load_data(self):
 
        repo_model = RepoModel()
 
        c.users_array = repo_model.get_users_js()
 
        c.user_groups_array = repo_model.get_user_groups_js()
 

	
 
    def _index(self, revision, method):
 
        c.pull_request = None
 
        c.anchor_url = anchor_url
 
        c.ignorews_url = _ignorews_url
 
        c.context_url = _context_url
 
        c.fulldiff = fulldiff = request.GET.get('fulldiff')
 
        #get ranges of revisions if preset
 
        rev_range = revision.split('...')[:2]
 
        enable_comments = True
 
        c.cs_repo = c.db_repo
 
        try:
 
            if len(rev_range) == 2:
 
                enable_comments = False
 
                rev_start = rev_range[0]
kallithea/lib/helpers.py
Show inline comments
 
@@ -266,109 +266,108 @@ def pygmentize_annotation(repo_name, fil
 

	
 
        def hsv_to_rgb(h, s, v):
 
            if s == 0.0:
 
                return v, v, v
 
            i = int(h * 6.0)  # XXX assume int() truncates!
 
            f = (h * 6.0) - i
 
            p = v * (1.0 - s)
 
            q = v * (1.0 - s * f)
 
            t = v * (1.0 - s * (1.0 - f))
 
            i = i % 6
 
            if i == 0:
 
                return v, t, p
 
            if i == 1:
 
                return q, v, p
 
            if i == 2:
 
                return p, v, t
 
            if i == 3:
 
                return p, q, v
 
            if i == 4:
 
                return t, p, v
 
            if i == 5:
 
                return v, p, q
 

	
 
        golden_ratio = 0.618033988749895
 
        h = 0.22717784590367374
 

	
 
        for _unused in xrange(n):
 
            h += golden_ratio
 
            h %= 1
 
            HSV_tuple = [h, 0.95, 0.95]
 
            RGB_tuple = hsv_to_rgb(*HSV_tuple)
 
            yield map(lambda x: str(int(x * 256)), RGB_tuple)
 

	
 
    cgenerator = gen_color()
 

	
 
    def get_color_string(cs):
 
        if cs in color_dict:
 
            col = color_dict[cs]
 
        else:
 
            col = color_dict[cs] = cgenerator.next()
 
        return "color: rgb(%s)! important;" % (', '.join(col))
 

	
 
    def url_func(repo_name):
 

	
 
        def _url_func(changeset):
 
            author = escape(changeset.author)
 
            date = changeset.date
 
            message = escape(changeset.message)
 
            tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
 
                            " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
 
                            "</b> %s<br/></div>") % (author, date, message)
 
            tooltip_html = ("<b>Author:</b> %s<br/>"
 
                            "<b>Date:</b> %s</b><br/>"
 
                            "<b>Message:</b> %s") % (author, date, message)
 

	
 
            lnk_format = show_id(changeset)
 
            uri = link_to(
 
                    lnk_format,
 
                    url('changeset_home', repo_name=repo_name,
 
                        revision=changeset.raw_id),
 
                    style=get_color_string(changeset.raw_id),
 
                    class_='safe-html-title',
 
                    title=tooltip_html,
 
                    **{'data-toggle': 'tooltip'}
 
                    **{'data-toggle': 'popover',
 
                       'data-content': tooltip_html}
 
                  )
 

	
 
            uri += '\n'
 
            return uri
 
        return _url_func
 

	
 
    return literal(markup_whitespace(annotate_highlight(filenode, url_func(repo_name), **kwargs)))
 

	
 

	
 
class _Message(object):
 
    """A message returned by ``Flash.pop_messages()``.
 

	
 
    Converting the message to a string returns the message text. Instances
 
    also have the following attributes:
 

	
 
    * ``message``: the message text.
 
    * ``category``: the category specified when the message was created.
 
    """
 

	
 
    def __init__(self, category, message):
 
        self.category = category
 
        self.message = message
 

	
 
    def __str__(self):
 
        return self.message
 

	
 
    __unicode__ = __str__
 

	
 
    def __html__(self):
 
        return escape(safe_unicode(self.message))
 

	
 
class Flash(_Flash):
 

	
 
    def __call__(self, message, category=None, ignore_duplicate=False, logf=None):
 
        """
 
        Show a message to the user _and_ log it through the specified function
 

	
 
        category: notice (default), warning, error, success
 
        logf: a custom log function - such as log.debug
 

	
 
        logf defaults to log.info, unless category equals 'success', in which
 
        case logf defaults to log.debug.
 
        """
 
        if logf is None:
 
            logf = log.info
 
            if category == 'success':
 
                logf = log.debug
 

	
 
@@ -523,97 +522,97 @@ def action_parser(user_log, feed=False, 
 
    This helper will action_map the specified string action into translated
 
    fancy names with icons and links
 

	
 
    :param user_log: user log instance
 
    :param feed: use output for feeds (no html and fancy icons)
 
    :param parse_cs: parse Changesets into VCS instances
 
    """
 

	
 
    action = user_log.action
 
    action_params = ' '
 

	
 
    x = action.split(':')
 

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

	
 
    def get_cs_links():
 
        revs_limit = 3  # display this amount always
 
        revs_top_limit = 50  # show upto this amount of changesets hidden
 
        revs_ids = action_params.split(',')
 
        deleted = user_log.repository is None
 
        if deleted:
 
            return ','.join(revs_ids)
 

	
 
        repo_name = user_log.repository.repo_name
 

	
 
        def lnk(rev, repo_name):
 
            lazy_cs = False
 
            title_ = None
 
            url_ = '#'
 
            if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict):
 
                if rev.op and rev.ref_name:
 
                    if rev.op == 'delete_branch':
 
                        lbl = _('Deleted branch: %s') % rev.ref_name
 
                    elif rev.op == 'tag':
 
                        lbl = _('Created tag: %s') % rev.ref_name
 
                    else:
 
                        lbl = 'Unknown operation %s' % rev.op
 
                else:
 
                    lazy_cs = True
 
                    lbl = rev.short_id[:8]
 
                    url_ = url('changeset_home', repo_name=repo_name,
 
                               revision=rev.raw_id)
 
            else:
 
                # changeset cannot be found - it might have been stripped or removed
 
                lbl = rev[:12]
 
                title_ = _('Changeset %s not found') % lbl
 
            if parse_cs:
 
                return link_to(lbl, url_, title=title_, class_='tooltip')
 
                return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'})
 
            return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '',
 
                           **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name})
 

	
 
        def _get_op(rev_txt):
 
            _op = None
 
            _name = rev_txt
 
            if len(rev_txt.split('=>')) == 2:
 
                _op, _name = rev_txt.split('=>')
 
            return _op, _name
 

	
 
        revs = []
 
        if len(filter(lambda v: v != '', revs_ids)) > 0:
 
            repo = None
 
            for rev in revs_ids[:revs_top_limit]:
 
                _op, _name = _get_op(rev)
 

	
 
                # we want parsed changesets, or new log store format is bad
 
                if parse_cs:
 
                    try:
 
                        if repo is None:
 
                            repo = user_log.repository.scm_instance
 
                        _rev = repo.get_changeset(rev)
 
                        revs.append(_rev)
 
                    except ChangesetDoesNotExistError:
 
                        log.error('cannot find revision %s in this repo', rev)
 
                        revs.append(rev)
 
                else:
 
                    _rev = AttributeDict({
 
                        'short_id': rev[:12],
 
                        'raw_id': rev,
 
                        'message': '',
 
                        'op': _op,
 
                        'ref_name': _name
 
                    })
 
                    revs.append(_rev)
 
        cs_links = [" " + ', '.join(
 
            [lnk(rev, repo_name) for rev in revs[:revs_limit]]
 
        )]
 
        _op1, _name1 = _get_op(revs_ids[0])
 
        _op2, _name2 = _get_op(revs_ids[-1])
 

	
 
        _rev = '%s...%s' % (_name1, _name2)
 

	
 
        compare_view = (
 
            ' <div class="compare_view" data-toggle="tooltip" title="%s">'
 
            '<a href="%s">%s</a> </div>' % (
 
                _('Show all combined changesets %s->%s') % (
 
                    revs_ids[0][:12], revs_ids[-1][:12]
kallithea/public/css/style.css
Show inline comments
 
@@ -2579,127 +2579,96 @@ table.code-browser i[class^='icon-'] {
 

	
 
#path_unlock {
 
    color: red;
 
    font-size: 1.2em;
 
    padding-left: 4px;
 
}
 

	
 
.info_box span {
 
    margin-left: 3px;
 
    margin-right: 3px;
 
}
 

	
 
.info_box .rev {
 
    color: #577632;
 
    font-size: 1.6em;
 
    font-weight: bold;
 
    vertical-align: sub;
 
}
 

	
 
.info_box input#at_rev,
 
.info_box input#size {
 
    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-size: 12px;
 
    margin: 0;
 
    padding: 1px 5px 1px;
 
}
 

	
 
.info_box input#view {
 
    text-align: center;
 
    padding: 4px 3px 2px 2px;
 
}
 

	
 
.info_box_elem {
 
    display: inline-block;
 
    padding: 0 2px;
 
}
 

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

	
 
#tip-box {
 
    position: absolute;
 

	
 
    background-color: #FFF;
 
    border: 2px solid #577632;
 
    font: 100% sans-serif;
 
    width: auto;
 
    opacity: 1;
 
    padding: 8px;
 

	
 
    white-space: pre-wrap;
 
    border-radius: 8px 8px 8px 8px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
    z-index: 100000;
 
}
 

	
 
.hl-tip-box {
 
    z-index: 1;
 
    position: absolute;
 
    color: #666;
 
    background-color: #FFF;
 
    border: 2px solid #577632;
 
    font: 100% sans-serif;
 
    width: auto;
 
    opacity: 1;
 
    padding: 8px;
 
    white-space: pre-wrap;
 
    border-radius: 8px 8px 8px 8px;
 
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
 
}
 

	
 

	
 
.mentions-container {
 
    width: 90% !important;
 
}
 
.mentions-container .yui-ac-content {
 
    width: 100% !important;
 
}
 

	
 
.ac {
 
    vertical-align: top;
 
}
 

	
 
.ac .yui-ac {
 
    position: inherit;
 
    font-size: 100%;
 
}
 

	
 
.ac .perm_ac {
 
    width: 20em;
 
}
 

	
 
.ac .yui-ac-input {
 
    width: 100%;
 
}
 

	
 
.ac .yui-ac-container {
 
    position: absolute;
 
    top: 1.6em;
 
    width: auto;
 
}
 

	
 
.ac .yui-ac-content {
 
    position: absolute;
 
    border: 1px solid gray;
 
    background: #fff;
 
    z-index: 9050;
 
}
 

	
 
.ac .yui-ac-shadow {
 
    position: absolute;
 
    width: 100%;
 
    background: #000;
 
    opacity: .10;
 
    z-index: 9049;
 
    margin: .3em;
 
}
 

	
 
.ac .yui-ac-content ul {
 
@@ -2938,97 +2907,97 @@ nav.navbar, #content, #footer {
 
.panel-body.settings > ul.nav-stacked {
 
    float: left;
 
    width: 150px;
 
    margin: 20px;
 
    color: #393939;
 
    font-weight: 700;
 
}
 

	
 
.panel-body.settings > ul.nav-stacked a {
 
    color: inherit;
 
}
 

	
 
.panel-body.settings > ul.nav-stacked li.active {
 
    list-style-type: disc
 
}
 

	
 
.panel-body.settings > div,
 
.panel-body.settings > form {
 
    float: left;
 
    width: 750px;
 
    margin: 10px 0 0 0;
 
    border-left: 1px solid #DDDDDD;
 
}
 

	
 
.panel-body > div,
 
.panel-body > form {
 
    padding: 0 20px 10px;
 
}
 

	
 
/* make .btn inputs and buttons and divs look the same */
 
button.btn,
 
input.btn {
 
    font-family: inherit;
 
    font-size: inherit;
 
    line-height: inherit;
 
}
 

	
 
.btn::-moz-focus-inner {
 
    border: 0;
 
    padding: 0;
 
}
 

	
 
.btn.badge {
 
    cursor: default !important;
 
}
 

	
 
input[disabled].btn,
 
.btn.disabled {
 
    color: #999;
 
    opacity: 0.5;
 
}
 

	
 
.label,
 
.btn.btn-sm {
 
    padding: 3px 8px;
 
}
 

	
 
.btn.btn-xs {
 
    padding: 1px 5px;
 
}
 

	
 
.btn:focus {
 
    outline: none;
 
}
 
.btn:hover {
 
    text-decoration: none;
 
    color: #515151;
 
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
 
}
 
.btn.badge:hover {
 
    box-shadow: none !important;
 
}
 
.btn.disabled:hover {
 
    background-position: 0;
 
    color: #999;
 
    text-decoration: none;
 
    box-shadow: none !important;
 
}
 

	
 
.label.label-danger,
 
.btn.btn-danger {
 
    color: #fff !important;
 
    background-color: #c43c35;
 
    background-repeat: repeat-x;
 
    background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
 
    border-color: #c43c35 #c43c35 #882a25;
 
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
}
 

	
 
.label.label-primary,
 
.btn.btn-primary {
 
    color: #fff !important;
 
    background-color: #339bb9;
 
    background-repeat: repeat-x;
 
    background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
 
    border-color: #339bb9 #339bb9 #22697d;
 
    border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
 
}
 
@@ -4389,48 +4358,189 @@ body table.dataTable thead .sorting_desc
 
}
 

	
 
.dataTables_wrapper .dataTables_right {
 
  float: right;
 
}
 

	
 
.dataTables_wrapper .dataTables_right > div {
 
  padding-left: 30px;
 
}
 

	
 
.dataTables_wrapper .dataTables_info {
 
  clear: none;
 
  padding-top: 1em;
 
}
 

	
 
.dataTables_wrapper .dataTables_paginate {
 
  padding-top: 0;
 
}
 

	
 
.dataTables_wrapper .dataTables_paginate > a.paginate_button {
 
  padding-top: 1em;
 
  border: 0 !important;
 
}
 

	
 
.text-muted {
 
    color: #777777;
 
}
 

	
 
.grid_edit a {
 
    text-decoration: none;
 
}
 

	
 
.changes_txt {
 
    clear: both;
 
}
 

	
 
.text-nowrap {
 
    white-space: nowrap;
 
}
 

	
 
div.codeblock div.code-header div.author {
 
    height: auto;
 
    min-height: 25px;
 
}
 

	
 
ul.user_group_member li {
 
    clear: both;
 
}
 

	
 
.tooltip {
 
    position: absolute;
 
    z-index: 1070;
 
    display: block;
 
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
 
    font-size: 12px;
 
    font-style: normal;
 
    font-weight: 400;
 
    line-height: 1.42857143;
 
    text-align: left;
 
    text-align: start;
 
    text-decoration: none;
 
    text-shadow: none;
 
    text-transform: none;
 
    letter-spacing: normal;
 
    word-break: normal;
 
    word-spacing: normal;
 
    word-wrap: normal;
 
    white-space: normal;
 
}
 
.tooltip-arrow {
 
    position: absolute;
 
    width: 0;
 
    height: 0;
 
    border-color: transparent;
 
    border-style: solid;
 
}
 
.tooltip-inner {
 
    max-width: 200px;
 
    padding: 3px 8px;
 
    color: #fff;
 
    text-align: center;
 
    background-color: #000;
 
    border-radius: 4px;
 
}
 

	
 
.tooltip.top {
 
    padding: 5px 0;
 
    margin-top: -3px;
 
}
 
.tooltip.top .tooltip-arrow {
 
    bottom: 0;
 
    left: 50%;
 
    margin-left: -5px;
 
    border-width: 5px 5px 0;
 
    border-top-color: #000;
 
}
 

	
 
.tooltip.bottom {
 
    padding: 5px 0;
 
    margin-top: 3px;
 
}
 
.tooltip.bottom .tooltip-arrow {
 
    top: 0;
 
    left: 50%;
 
    margin-left: -5px;
 
    border-width: 0 5px 5px;
 
    border-bottom-color: #000;
 
}
 

	
 

	
 
.popover {
 
    position: absolute;
 
    top: 0;
 
    left: 0;
 
    z-index: 1060;
 
    max-width: 276px;
 
    padding: 1px;
 
    background-color: #fff;
 
    background-clip: padding-box;
 
    border: 1px solid #ccc;
 
    border: 1px solid rgba(0,0,0,.2);
 
    border-radius: 6px;
 
    box-shadow: 0 5px 10px rgba(0,0,0,.2);
 
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
 
    font-size: 12px;
 
    font-style: normal;
 
    font-weight: 400;
 
    line-height: 1.42857143;
 
    text-align: left;
 
    text-align: start;
 
    text-decoration: none;
 
    text-shadow: none;
 
    text-transform: none;
 
    letter-spacing: normal;
 
    word-break: normal;
 
    word-spacing: normal;
 
    word-wrap: normal;
 
    white-space: normal;
 
}
 

	
 
.popover > .arrow {
 
    border-width: 11px;
 
}
 
.popover > .arrow,
 
.popover > .arrow::after {
 
    position: absolute;
 
    display: block;
 
    width: 0;
 
    height: 0;
 
    border-color: transparent;
 
    border-style: solid;
 
}
 

	
 
.popover-title {
 
    padding: 8px 14px;
 
    margin: 0;
 
    font-size: 14px;
 
    background-color: #f7f7f7;
 
    border-bottom: 1px solid #ebebeb;
 
    border-radius: 5px 5px 0 0;
 
}
 

	
 
.popover-content {
 
    padding: 9px 14px;
 
}
 

	
 
.popover.top {
 
    margin-top: -10px;
 
}
 
.popover.top > .arrow {
 
    bottom: -11px;
 
    left: 50%;
 
    margin-left: -11px;
 
    border-top-color: #999;
 
    border-top-color: rgba(0,0,0,.25);
 
    border-bottom-width: 0;
 
}
 

	
 
.popover.bottom {
 
    margin-top: 10px;
 
}
 
.popover.bottom > .arrow {
 
    top: -11px;
 
    left: 50%;
 
    margin-left: -11px;
 
    border-top-width: 0;
 
    border-bottom-color: #999;
 
    border-bottom-color: rgba(0,0,0,.25);
 
}
kallithea/public/js/base.js
Show inline comments
 
@@ -366,230 +366,191 @@ function asynchtml(url, $target, success
 
                if (textStatus == "abort")
 
                    return;
 
                $target.html('<span class="error_red">ERROR: {0}</span>'.format(textStatus));
 
                $target.css('opacity','1.0');
 
            })
 
        ;
 
};
 

	
 
var ajaxGET = function(url, success, failure) {
 
    if(failure === undefined) {
 
        failure = function(jqXHR, textStatus, errorThrown) {
 
                if (textStatus != "abort")
 
                    alert("Ajax GET error: " + textStatus);
 
            };
 
    }
 
    return $.ajax({url: url, headers: {'X-PARTIAL-XHR': '1'}, cache: false})
 
        .done(success)
 
        .fail(failure);
 
};
 

	
 
var ajaxPOST = function(url, postData, success, failure) {
 
    postData['_authentication_token'] = _authentication_token;
 
    var postData = _toQueryString(postData);
 
    if(failure === undefined) {
 
        failure = function(jqXHR, textStatus, errorThrown) {
 
                if (textStatus != "abort")
 
                    alert("Error posting to server: " + textStatus);
 
            };
 
    }
 
    return $.ajax({url: url, data: postData, type: 'POST', headers: {'X-PARTIAL-XHR': '1'}, cache: false})
 
        .done(success)
 
        .fail(failure);
 
};
 

	
 

	
 
/**
 
 * activate .show_more links
 
 * the .show_more must have an id that is the the id of an element to hide prefixed with _
 
 * the parentnode will be displayed
 
 */
 
var show_more_event = function(){
 
    $('.show_more').click(function(e){
 
        var el = e.currentTarget;
 
        $('#' + el.id.substring(1)).hide();
 
        $(el.parentNode).show();
 
    });
 
};
 

	
 
/**
 
 * activate .lazy-cs mouseover for showing changeset tooltip
 
 */
 
var show_changeset_tooltip = function(){
 
    $('.lazy-cs').mouseover(function(e){
 
        var $target = $(e.currentTarget);
 
        var rid = $target.data('raw_id');
 
        var repo_name = $target.data('repo_name');
 
        if(rid && !$target.hasClass('tooltip')){
 
            _show_tooltip(e, _TM['loading ...']);
 
            var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": rid});
 
            ajaxGET(url, function(json){
 
                    $target.addClass('tooltip');
 
                    _show_tooltip(e, json['message']);
 
                    _activate_tooltip($target);
 
                });
 
        }
 
    });
 
};
 

	
 
var _onSuccessFollow = function(target){
 
    var $target = $(target);
 
    var $f_cnt = $('#current_followers_count');
 
    if ($target.hasClass('follow')) {
 
        $target.removeClass('follow').addClass('following');
 
        $target.prop('title', _TM['Stop following this repository']);
 
        if ($f_cnt.html()) {
 
            var cnt = Number($f_cnt.html())+1;
 
            $f_cnt.html(cnt);
 
        }
 
    } else {
 
        $target.removeClass('following').addClass('follow');
 
        $target.prop('title', _TM['Start following this repository']);
 
        if ($f_cnt.html()) {
 
            var cnt = Number($f_cnt.html())-1;
 
            $f_cnt.html(cnt);
 
        }
 
    }
 
}
 

	
 
var toggleFollowingRepo = function(target, follows_repository_id){
 
    var args = 'follows_repository_id=' + follows_repository_id;
 
    args += '&amp;_authentication_token=' + _authentication_token;
 
    $.post(TOGGLE_FOLLOW_URL, args, function(data){
 
            _onSuccessFollow(target);
 
        });
 
    return false;
 
};
 

	
 
var showRepoSize = function(target, repo_name){
 
    var args = '_authentication_token=' + _authentication_token;
 

	
 
    if(!$("#" + target).hasClass('loaded')){
 
        $("#" + target).html(_TM['Loading ...']);
 
        var url = pyroutes.url('repo_size', {"repo_name":repo_name});
 
        $.post(url, args, function(data) {
 
            $("#" + target).html(data);
 
            $("#" + target).addClass('loaded');
 
        });
 
    }
 
    return false;
 
};
 

	
 
/**
 
 * tooltips
 
 * load tooltips dynamically based on data attributes, used for .lazy-cs changeset links
 
 */
 

	
 
var tooltip_activate = function(){
 
    $(document).ready(_init_tooltip);
 
};
 

	
 
var _activate_tooltip = function($tt){
 
    $tt.mouseover(_show_tooltip);
 
    $tt.mousemove(_move_tooltip);
 
    $tt.mouseout(_close_tooltip);
 
};
 
var get_changeset_tooltip = function() {
 
    var $target = $(this);
 
    var tooltip = $target.data('tooltip');
 
    if (!tooltip) {
 
        var raw_id = $target.data('raw_id');
 
        var repo_name = $target.data('repo_name');
 
        var url = pyroutes.url('changeset_info', {"repo_name": repo_name, "revision": raw_id});
 

	
 
var _init_tooltip = function(){
 
    var $tipBox = $('#tip-box');
 
    if(!$tipBox.length){
 
        $tipBox = $('<div id="tip-box"></div>');
 
        $(document.body).append($tipBox);
 
        $.ajax(url, {
 
            async: false,
 
            success: function(data) {
 
                tooltip = data["message"];
 
    }
 

	
 
    $tipBox.hide();
 
    $tipBox.css('position', 'absolute');
 
    $tipBox.css('max-width', '600px');
 

	
 
    _activate_tooltip($('[data-toggle="tooltip"]'));
 
        });
 
        $target.data('tooltip', tooltip);
 
    }
 
    return tooltip;
 
};
 

	
 
var _show_tooltip = function(e, tipText, safe){
 
    e.stopImmediatePropagation();
 
    var el = e.currentTarget;
 
    var $el = $(el);
 
    if(tipText){
 
        // just use it
 
    } else if(el.tagName.toLowerCase() === 'img'){
 
        tipText = el.alt ? el.alt : '';
 
/**
 
 * activate tooltips and popups
 
 */
 
var tooltip_activate = function(){
 
    function placement(p, e){
 
        if(e.getBoundingClientRect().top > 2*$(window).height()/3){
 
            return 'top';
 
    } else {
 
        tipText = el.title ? el.title : '';
 
        safe = safe || $el.hasClass("safe-html-title");
 
            return 'bottom';
 
        }
 
    }
 

	
 
    if(tipText !== ''){
 
        // save org title
 
        $el.attr('tt_title', tipText);
 
        // reset title to not show org tooltips
 
        $el.prop('title', '');
 

	
 
        var $tipBox = $('#tip-box');
 
        if (safe) {
 
            $tipBox.html(tipText);
 
        } else {
 
            $tipBox.text(tipText);
 
        }
 
        $tipBox.css('display', 'block');
 
    }
 
    $(document).ready(function(){
 
        $('[data-toggle="tooltip"]').tooltip({
 
            placement: placement
 
        });
 
        $('[data-toggle="popover"]').popover({
 
            html: true,
 
            container: 'body',
 
            placement: placement,
 
            trigger: 'hover',
 
            template: '<div class="popover cs-popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
 
        });
 
        $('.lazy-cs').tooltip({
 
            title: get_changeset_tooltip,
 
            placement: placement
 
        });
 
    });
 
};
 

	
 
var _move_tooltip = function(e){
 
    e.stopImmediatePropagation();
 
    var $tipBox = $('#tip-box');
 
    $tipBox.css('top', (e.pageY + 15) + 'px');
 
    $tipBox.css('left', (e.pageX + 15) + 'px');
 
};
 

	
 
var _close_tooltip = function(e){
 
    e.stopImmediatePropagation();
 
    var $tipBox = $('#tip-box');
 
    $tipBox.hide();
 
    var el = e.currentTarget;
 
    $(el).prop('title', $(el).attr('tt_title'));
 
};
 

	
 
/**
 
 * Quick filter widget
 
 *
 
 * @param target: filter input target
 
 * @param nodes: list of nodes in html we want to filter.
 
 * @param display_element function that takes current node from nodes and
 
 *    does hide or show based on the node
 
 */
 
var q_filter = (function() {
 
    var _namespace = {};
 
    var namespace = function (target) {
 
        if (!(target in _namespace)) {
 
            _namespace[target] = {};
 
        }
 
        return _namespace[target];
 
    };
 
    return function (target, $nodes, display_element) {
 
        var $nodes = $nodes;
 
        var $q_filter_field = $('#' + target);
 
        var F = namespace(target);
 

	
 
        $q_filter_field.keyup(function (e) {
 
            clearTimeout(F.filterTimeout);
 
            F.filterTimeout = setTimeout(F.updateFilter, 600);
 
        });
 

	
 
        F.filterTimeout = null;
 

	
 
        F.updateFilter = function () {
 
            // Reset timeout
 
            F.filterTimeout = null;
 

	
 
            var obsolete = [];
 

	
 
            var req = $q_filter_field.val().toLowerCase();
 

	
 
            var showing = 0;
 
            $nodes.each(function () {
 
                var n = this;
 
                var target_element = display_element(n);
 
                if (req && n.innerHTML.toLowerCase().indexOf(req) == -1) {
 
                    $(target_element).hide();
 
                }
 
                else {
 
                    $(target_element).show();
 
                    showing += 1;
 
                }
kallithea/templates/admin/admin_log.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
%if c.users_log:
 
<table class="table">
 
    <tr>
 
        <th class="left">${_('Username')}</th>
 
        <th class="left">${_('Action')}</th>
 
        <th class="left">${_('Repository')}</th>
 
        <th class="left">${_('Date')}</th>
 
        <th class="left">${_('From IP')}</th>
 
    </tr>
 

	
 
    %for cnt,l in enumerate(c.users_log):
 
    <tr class="parity${cnt%2}">
 
        <td>
 
        %if l.user is not None:
 
          ${h.link_to(l.user.username,h.url('edit_user', id=l.user.user_id))}
 
        %else:
 
          ${l.username}
 
        %endif
 
        </td>
 
        <td>${h.action_parser(l)[0]()}
 
            <div class="journal_action_params">
 
                ${h.literal(h.action_parser(l)[1]())}
 
            </div>
 
        </td>
 
        <td>
 
            %if l.repository is not None:
 
              ${h.link_to(l.repository.repo_name,h.url('summary_home',repo_name=l.repository.repo_name))}
 
            %else:
 
              ${l.repository_name}
 
            %endif
 
        </td>
 

	
 
        <td>${h.fmt_date(l.action_date)}</td>
 
        <td>${l.user_ip}</td>
 
    </tr>
 
    %endfor
 
</table>
 

	
 
<script type="text/javascript">
 
  $(document).ready(function(){
 
    var $user_log = $('#user_log');
 
    $user_log.on('click','.pager_link',function(e){
 
      asynchtml(e.target.href, $user_log, function(){
 
        show_more_event();
 
        tooltip_activate();
 
        show_changeset_tooltip();
 
      });
 
      e.preventDefault();
 
    });
 
    $user_log.on('click','.show_more',function(e){
 
      var el = e.target;
 
      $('#'+el.id.substring(1)).show();
 
      $(el.parentNode).hide();
 
    });
 
  });
 
</script>
 

	
 
<ul class="pagination">
 
    ${c.users_log.pager()}
 
</ul>
 
%else:
 
    ${_('No actions yet')}
 
%endif
kallithea/templates/base/root.html
Show inline comments
 
@@ -36,97 +36,96 @@
 
                'Collapse Diff': "${_('Collapse Diff')}",
 
                'Expand Diff': "${_('Expand Diff')}",
 
                'Failed to revoke permission': "${_('Failed to revoke permission')}",
 
                'Confirm to revoke permission for {0}: {1} ?': "${_('Confirm to revoke permission for {0}: {1} ?')}",
 
                'Enabled': "${_('Enabled')}",
 
                'Disabled': "${_('Disabled')}",
 
                'Select changeset': "${_('Select changeset')}",
 
                'Specify changeset': "${_('Specify changeset')}",
 
                'MSG_SORTASC': "${_('Click to sort ascending')}",
 
                'MSG_SORTDESC': "${_('Click to sort descending')}",
 
                'MSG_EMPTY': "${_('No records found.')}",
 
                'MSG_ERROR': "${_('Data error.')}",
 
                'MSG_LOADING': "${_('Loading...')}"
 
            };
 
            var _TM = TRANSLATION_MAP;
 

	
 
            var TOGGLE_FOLLOW_URL  = "${h.url('toggle_following')}";
 

	
 
            var REPO_NAME = "";
 
            %if hasattr(c, 'repo_name'):
 
                var REPO_NAME = "${c.repo_name}";
 
            %endif
 

	
 
            var _authentication_token = "${h.authentication_token()}";
 
        </script>
 
        <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/jquery.min.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/jquery.dataTables.min.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
 
        <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
 
        ## EXTRA FOR JS
 
        <%block name="js_extra"/>
 
        <script type="text/javascript">
 
            (function(window,undefined){
 
                var History = window.History; // Note: We are using a capital H instead of a lower h
 
                if ( !History.enabled ) {
 
                     // History.js is disabled for this browser.
 
                     // This is because we can optionally choose to support HTML4 browsers or not.
 
                    return false;
 
                }
 
            })(window);
 

	
 
            $(document).ready(function(){
 
              tooltip_activate();
 
              show_more_event();
 
              show_changeset_tooltip();
 
              // routes registration
 
              pyroutes.register('home', "${h.url('home')}", []);
 
              pyroutes.register('new_gist', "${h.url('new_gist')}", []);
 
              pyroutes.register('gists', "${h.url('gists')}", []);
 
              pyroutes.register('new_repo', "${h.url('new_repo')}", []);
 

	
 
              pyroutes.register('summary_home', "${h.url('summary_home', repo_name='%(repo_name)s')}", ['repo_name']);
 
              pyroutes.register('changelog_home', "${h.url('changelog_home', repo_name='%(repo_name)s')}", ['repo_name']);
 
              pyroutes.register('files_home', "${h.url('files_home', repo_name='%(repo_name)s',revision='%(revision)s',f_path='%(f_path)s')}", ['repo_name', 'revision', 'f_path']);
 
              pyroutes.register('edit_repo', "${h.url('edit_repo', repo_name='%(repo_name)s')}", ['repo_name']);
 
              pyroutes.register('edit_repo_perms', "${h.url('edit_repo_perms', repo_name='%(repo_name)s')}", ['repo_name']);
 
              pyroutes.register('pullrequest_home', "${h.url('pullrequest_home', repo_name='%(repo_name)s')}", ['repo_name']);
 

	
 
              pyroutes.register('toggle_following', "${h.url('toggle_following')}");
 
              pyroutes.register('changeset_info', "${h.url('changeset_info', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
 
              pyroutes.register('repo_size', "${h.url('repo_size', repo_name='%(repo_name)s')}", ['repo_name']);
 
              pyroutes.register('repo_refs_data', "${h.url('repo_refs_data', repo_name='%(repo_name)s')}", ['repo_name']);
 
             });
 
        </script>
 

	
 
        <%block name="head_extra"/>
 
    </head>
 
    <body>
 
      <nav class="navbar navbar-inverse">
 
        <div>
 
          <div class="navbar-header" id="logo">
 
            <a class="navbar-brand" href="${h.url('home')}">
 
                <img class="pull-left" src="${h.url('/images/kallithea-logo.svg')}" alt="Kallithea"/>
 
                  %if c.site_name:
 
                    <span class="branding">${c.site_name}</span>
 
                  %endif
 
            </a>
 
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
 
              <span class="sr-only">Toggle navigation</span>
 
              <span class="icon-bar"></span>
 
              <span class="icon-bar"></span>
 
              <span class="icon-bar"></span>
 
            </button>
 
          </div>
 
          <div id="navbar" class="navbar-collapse collapse">
 
            <%block name="header_menu"/>
 
          </div>
 
        </div>
 
      </nav>
 

	
 
      ${next.body()}
 

	
 
      %if c.ga_code:
kallithea/templates/data_table/_dt_elements.html
Show inline comments
 
## DATA TABLE RE USABLE ELEMENTS
 
## usage:
 
## <%namespace name="dt" file="/data_table/_dt_elements.html"/>
 

	
 
<%namespace name="base" file="/base/base.html"/>
 

	
 
<%def name="repo_name(name,rtype,rstate,private,fork_of,short_name=False,admin=False)">
 
    <%
 
    def get_name(name,short_name=short_name):
 
      if short_name:
 
        return name.split('/')[-1]
 
      else:
 
        return name
 
    %>
 
  <div class="dt_repo ${'dt_repo_pending' if rstate == 'repo_state_pending' else ''}">
 
    ##NAME
 
    <a href="${h.url('edit_repo' if admin else 'summary_home', repo_name=name)}">
 

	
 
    ##TYPE OF REPO
 
    ${base.repotag(rtype)}
 

	
 
    ##PRIVATE/PUBLIC
 
    %if private and c.visual.show_private_icon:
 
      <i class="icon-keyhole-circled" title="${_('Private repository')}"></i>
 
    %elif not private and c.visual.show_public_icon:
 
      <i class="icon-globe" title="${_('Public repository')}"></i>
 
    %else:
 
      <span style="margin: 0px 8px 0px 8px"></span>
 
    %endif
 
    <span class="dt_repo_name">${get_name(name)}</span>
 
    </a>
 
    %if fork_of:
 
      <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}"><i class="icon-fork"></i></a>
 
    %endif
 
    %if rstate == 'repo_state_pending':
 
      <i class="icon-wrench" title="${_('Repository creation in progress...')}"></i>
 
    %endif
 
  </div>
 
</%def>
 

	
 
<%def name="last_change(last_change)">
 
  <span data-toggle="tooltip" title="${h.fmt_date(last_change)}" date="${last_change}">${h.age(last_change)}</span>
 
</%def>
 

	
 
<%def name="revision(name,rev,tip,author,last_msg)">
 
  <div>
 
  %if rev >= 0:
 
      <a data-toggle="tooltip" title="${'%s:\n\n%s' % (h.escape(author), h.escape(last_msg))}" class="revision-link safe-html-title" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
 
      <a data-toggle="popover" title="${author | entity}" data-content="${last_msg | entity}" class="hash" href="${h.url('changeset_home',repo_name=name,revision=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a>
 
  %else:
 
      ${_('No changesets yet')}
 
  %endif
 
  </div>
 
</%def>
 

	
 
<%def name="rss(name)">
 
  %if c.authuser.username != 'default':
 
    <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
 
  %else:
 
    <a title="${_('Subscribe to %s rss feed')% name}" href="${h.url('rss_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
 
  %endif
 
</%def>
 

	
 
<%def name="atom(name)">
 
  %if c.authuser.username != 'default':
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name,api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
 
  %else:
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${h.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
 
  %endif
 
</%def>
 

	
 
<%def name="repo_actions(repo_name, super_user=True)">
 
  <div>
 
    <div class="grid_edit pull-left">
 
      <a href="${h.url('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
 
        <i class="icon-pencil"></i> ${h.submit('edit_%s' % repo_name,_('Edit'),class_="btn btn-default btn-xs")}
 
      </a>
 
    </div>
 
    <div class="grid_delete pull-left">
 
      ${h.form(h.url('delete_repo', repo_name=repo_name))}
 
        <i class="icon-minus-circled" style="color:#FF4444"></i>
 
        ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-default btn-xs",
 
        onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
 
      ${h.end_form()}
 
    </div>
 
  </div>
 
</%def>
 

	
 
<%def name="repo_state(repo_state)">
 
  <div>
 
    %if repo_state == u'repo_state_pending':
 
        <div class="label label-info">${_('Creating')}</div>
 
    %elif repo_state == u'repo_state_created':
 
        <div class="label label-success">${_('Created')}</div>
 
    %else:
 
        <div class="label label-danger" title="${repo_state}">invalid</div>
 
    %endif
kallithea/templates/files/files_source.html
Show inline comments
 
<div id="node_history" style="padding: 0px 0px 10px 0px">
 
    <div>
 
        <div class="pull-left">
 
        ${h.form(h.url('files_diff_home',repo_name=c.repo_name,f_path=c.f_path),method='get')}
 
        ${h.hidden('diff2',c.changeset.raw_id)}
 
        ${h.hidden('diff1')}
 
        ${h.submit('diff',_('Diff to Revision'),class_="btn btn-default btn-sm")}
 
        ${h.submit('show_rev',_('Show at Revision'),class_="btn btn-default btn-sm")}
 
        ${h.hidden('annotate', c.annotate)}
 
        ${h.link_to(_('Show Full History'),h.url('changelog_file_home',repo_name=c.repo_name, revision=c.changeset.raw_id, f_path=c.f_path),class_="btn btn-default btn-sm")}
 
        ${h.link_to(_('Show Authors'),'#',class_="btn btn-default btn-sm" ,id="show_authors")}
 
        ${h.end_form()}
 
        </div>
 
        <div id="file_authors" class="file_author" style="clear:both; display: none"></div>
 
    </div>
 
    <div style="clear:both"></div>
 
</div>
 

	
 

	
 
<div id="body" class="codeblock">
 
    <div class="code-header">
 
        <div class="stats">
 
        <div class="pull-left">
 
            <div class="left img"><i class="icon-doc-inv"></i></div>
 
            <div class="left item"><pre data-toggle="tooltip" title="${h.fmt_date(c.changeset.date)}">${h.link_to(h.show_id(c.changeset),h.url('changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</pre></div>
 
            <div class="left item"><pre>${h.format_byte_size(c.file.size,binary=True)}</pre></div>
 
            <div class="left item last"><pre>${c.file.mimetype}</pre></div>
 
        </div>
 
        <div class="pull-right buttons">
 
              %if c.annotate:
 
                ${h.link_to(_('Show Source'),    h.url('files_home',         repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
 
              %else:
 
                ${h.link_to(_('Show Annotation'),h.url('files_annotate_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
 
              %endif
 
              ${h.link_to(_('Show as Raw'),h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
 
              ${h.link_to(_('Download as Raw'),h.url('files_rawfile_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path),class_="btn btn-default btn-xs")}
 
              %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
 
               %if c.on_branch_head and not c.file.is_binary:
 
                ${h.link_to(_('Edit on Branch: %s') % c.changeset.branch, h.url('files_edit_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-default btn-xs")}
 
                ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
 
               %elif c.on_branch_head and c.file.is_binary:
 
                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing binary files not allowed'))}
 
                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing binary files not allowed'),**{'data-toggle':'tooltip'})}
 
                ${h.link_to(_('Delete'), h.url('files_delete_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path, anchor='edit'),class_="btn btn-danger btn-xs")}
 
               %else:
 
                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled tooltip", title=_('Editing files allowed only when on branch head revision'))}
 
                ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled tooltip", title=_('Deleting files allowed only when on branch head revision'))}
 
                ${h.link_to(_('Edit'), '#', class_="btn btn-default btn-xs disabled", title=_('Editing files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
 
                ${h.link_to(_('Delete'), '#', class_="btn btn-danger btn-xs disabled", title=_('Deleting files allowed only when on branch head revision'),**{'data-toggle':'tooltip'})}
 
               %endif
 
              %endif
 
        </div>
 
        </div>
 
        <div class="author">
 
            ${h.gravatar_div(h.email_or_none(c.changeset.author), size=16)}
 
            <div title="${c.changeset.author}" class="user">${h.person(c.changeset.author)}</div>
 
        </div>
 
        <div class="commit">${h.urlify_text(c.changeset.message,c.repo_name)}</div>
 
    </div>
 
    <div class="code-body">
 
      %if c.file.is_browser_compatible_image():
 
        <img src="${h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path)}" class="img-preview"/>
 
      %elif c.file.is_binary:
 
        <div style="padding:5px">
 
          ${_('Binary file (%s)') % c.file.mimetype}
 
        </div>
 
      %else:
 
        %if c.file.size < c.cut_off_limit or c.fulldiff:
 
            %if c.annotate:
 
              ${h.pygmentize_annotation(c.repo_name,c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
 
            %else:
 
              ${h.pygmentize(c.file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
 
            %endif
 
        %else:
 
            <h4>
 
            ${_('File is too big to display.')}
 
            %if c.annotate:
 
              ${h.link_to(_('Show full annotation anyway.'), h.url.current(fulldiff=1, **request.GET.mixed()))}
 
            %else:
 
              ${h.link_to(_('Show as raw.'), h.url('files_raw_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=c.f_path))}
 
            %endif
 
            </h4>
 
        %endif
 
      %endif
 
    </div>
 
</div>
 

	
 
<script>
 
    $(document).ready(function(){
 
        // fake html5 history state
 
        var _State = {
 
           url: "${h.url.current()}",
 
           data: {
 
             node_list_url: node_list_url.replace('__REV__',"${c.changeset.raw_id}").replace('__FPATH__', "${h.safe_unicode(c.file.path)}"),
 
             url_base: url_base.replace('__REV__',"${c.changeset.raw_id}"),
 
             rev:"${c.changeset.raw_id}",
 
             f_path: "${h.safe_unicode(c.file.path)}"
kallithea/templates/followers/followers.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%block name="title">
 
    ${_('%s Followers') % c.repo_name}
 
</%block>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Followers')}
 
</%def>
 

	
 
<%block name="header_menu">
 
    ${self.menu('repositories')}
 
</%block>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('followers')}
 
<div class="panel panel-primary">
 
    <div class="panel-heading clearfix">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <div class="panel-body">
 
        <div id="followers">
 
            <%include file='followers_data.html'/>
 
        </div>
 
    </div>
 
</div>
 
<script type="text/javascript">
 
  $(document).ready(function(){
 
    var $followers = $('#followers');
 
    $followers.on('click','.pager_link',function(e){
 
        asynchtml(e.target.href, $followers, function(){
 
            show_more_event();
 
            tooltip_activate();
 
            show_changeset_tooltip();
 
        });
 
        e.preventDefault();
 
    });
 
  });
 
</script>
 
</%def>
kallithea/templates/forks/forks.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%block name="title">
 
    ${_('%s Forks') % c.repo_name}
 
</%block>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${_('Forks')}
 
</%def>
 

	
 
<%block name="header_menu">
 
    ${self.menu('repositories')}
 
</%block>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('showforks')}
 
<div class="panel panel-primary">
 
    <div class="panel-heading clearfix">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <div class="panel-body">
 
        <div id="forks">
 
            <%include file='forks_data.html'/>
 
        </div>
 
    </div>
 
</div>
 
<script type="text/javascript">
 
  $(document).ready(function(){
 
      var $forks = $('#forks');
 
      $forks.on('click','.pager_link',function(e){
 
          asynchtml(e.target.href, $forks, function(){
 
              show_more_event();
 
              tooltip_activate();
 
              show_changeset_tooltip();
 
          });
 
          e.preventDefault();
 
      });
 
  });
 
</script>
 
</%def>
kallithea/templates/journal/journal.html
Show inline comments
 
@@ -17,74 +17,72 @@
 
<%block name="head_extra">
 
  <link href="${h.url('journal_atom', api_key=c.authuser.api_key)}" rel="alternate" title="${_('ATOM journal feed')}" type="application/atom+xml" />
 
  <link href="${h.url('journal_rss', api_key=c.authuser.api_key)}" rel="alternate" title="${_('RSS journal feed')}" type="application/rss+xml" />
 
</%block>
 

	
 
<%def name="main()">
 
    <div class="panel panel-primary">
 
        <div class="panel-heading clearfix">
 
            <div class="pull-left">
 
                ${self.breadcrumbs()}
 
            </div>
 
            <div class="pull-right panel-title">
 
                <a href="${h.url('my_account_watched')}"><i class="icon-eye"></i> ${_('Watched Repositories')}</a>
 
                <a href="${h.url('my_account_repos')}"><i class="icon-database"></i> ${_('My Repositories')}</a>
 
                <a id="refresh" href="${h.url('journal')}"><i class="icon-arrows-cw"></i></a>
 
                <a href="${h.url('journal_atom', api_key=c.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
 
            </div>
 
        </div>
 
        <div id="journal" class="panel-body">
 
            <%include file='journal_data.html'/>
 
        </div>
 
    </div>
 

	
 
<script type="text/javascript">
 

	
 
    $('#j_filter').click(function(){
 
        var $jfilter = $('#j_filter');
 
        if($jfilter.hasClass('initial')){
 
            $jfilter.val('');
 
        }
 
    });
 
    var fix_j_filter_width = function(len){
 
        $('#j_filter').css('width', Math.max(80, len*6.50)+'px');
 
    };
 
    $('#j_filter').keyup(function(){
 
        fix_j_filter_width($('#j_filter').val().length);
 
    });
 
    $('#filter_form').submit(function(e){
 
        e.preventDefault();
 
        var val = $('#j_filter').val();
 
        window.location = "${url.current(filter='__FILTER__')}".replace('__FILTER__',val);
 
    });
 
    fix_j_filter_width($('#j_filter').val().length);
 

	
 
    $('#refresh').click(function(e){
 
        asynchtml("${h.url.current(filter=c.search_term)}", $("#journal"), function(){
 
            show_more_event();
 
            tooltip_activate();
 
            show_changeset_tooltip();
 
            });
 
        e.preventDefault();
 
    });
 

	
 
</script>
 

	
 
<script type="text/javascript">
 
    $(document).ready(function(){
 
        var $journal = $('#journal');
 
        $journal.on('click','.pager_link',function(e){
 
            asynchtml(e.target.href, $journal, function(){
 
                show_more_event();
 
                tooltip_activate();
 
                show_changeset_tooltip();
 
            });
 
            e.preventDefault();
 
        });
 
        $('#journal').on('click','.show_more',function(e){
 
            var el = e.target;
 
            $('#'+el.id.substring(1)).show();
 
            $(el.parentNode).hide();
 
        });
 
    });
 
</script>
 
</%def>
0 comments (0 inline, 0 general)