Mercurial > kallithea
changeset 2674:a221706dab50 beta
merged + fixed pull request #62: Implemented metatags and visualisation options.
- new tag lang
- fixed found issues
- added simple test
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Fri, 27 Jul 2012 01:21:07 +0200 |
parents | d5e42c00f3c1 |
children | 31265f80cf8b |
files | rhodecode/controllers/admin/repos.py rhodecode/controllers/admin/settings.py rhodecode/controllers/admin/users.py rhodecode/lib/base.py rhodecode/lib/helpers.py rhodecode/lib/utils2.py rhodecode/model/db.py rhodecode/model/forms.py rhodecode/public/css/style.css rhodecode/templates/admin/settings/settings.html rhodecode/templates/data_table/_dt_elements.html rhodecode/templates/index_base.html rhodecode/templates/journal/journal.html rhodecode/templates/repo_switcher_list.html rhodecode/templates/summary/summary.html rhodecode/tests/test_libs.py |
diffstat | 16 files changed, 288 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/rhodecode/controllers/admin/repos.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/controllers/admin/repos.py Fri Jul 27 01:21:07 2012 +0200 @@ -144,20 +144,21 @@ template = _tmpl_lookup.get_template('data_table/_dt_elements.html') quick_menu = lambda repo_name: (template.get_def("quick_menu") - .render(repo_name, _=_, h=h)) + .render(repo_name, _=_, h=h, c=c)) repo_lnk = lambda name, rtype, private, fork_of: ( template.get_def("repo_name") - .render(name, rtype, private, fork_of, short_name=False, - admin=True, _=_, h=h)) + .render(name, rtype, private, fork_of, short_name=False, + admin=True, _=_, h=h, c=c)) repo_actions = lambda repo_name: (template.get_def("repo_actions") - .render(repo_name, _=_, h=h)) + .render(repo_name, _=_, h=h, c=c)) for repo in c.repos_list: repos_data.append({ "menu": quick_menu(repo.repo_name), "raw_name": repo.repo_name, - "name": repo_lnk(repo.repo_name, repo.repo_type, repo.private, repo.fork), + "name": repo_lnk(repo.repo_name, repo.repo_type, + repo.private, repo.fork), "desc": repo.description, "owner": repo.user.username, "action": repo_actions(repo.repo_name),
--- a/rhodecode/controllers/admin/settings.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/controllers/admin/settings.py Fri Jul 27 01:21:07 2012 +0200 @@ -45,7 +45,7 @@ from rhodecode.model.db import RhodeCodeUi, Repository, RepoGroup, \ RhodeCodeSetting, PullRequest, PullRequestReviewers from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \ - ApplicationUiSettingsForm + ApplicationUiSettingsForm, ApplicationVisualisationForm from rhodecode.model.scm import ScmModel from rhodecode.model.user import UserModel from rhodecode.model.db import User @@ -143,15 +143,15 @@ ) try: - sett1 = RhodeCodeSetting.get_by_name('title') + sett1 = RhodeCodeSetting.get_by_name_or_create('title') sett1.app_settings_value = form_result['rhodecode_title'] Session().add(sett1) - sett2 = RhodeCodeSetting.get_by_name('realm') + sett2 = RhodeCodeSetting.get_by_name_or_create('realm') sett2.app_settings_value = form_result['rhodecode_realm'] Session().add(sett2) - sett3 = RhodeCodeSetting.get_by_name('ga_code') + sett3 = RhodeCodeSetting.get_by_name_or_create('ga_code') sett3.app_settings_value = form_result['rhodecode_ga_code'] Session().add(sett3) @@ -165,6 +165,47 @@ 'application settings'), category='error') + if setting_id == 'visual': + + application_form = ApplicationVisualisationForm()() + try: + form_result = application_form.to_python(dict(request.POST)) + except formencode.Invalid, errors: + return htmlfill.render( + render('admin/settings/settings.html'), + defaults=errors.value, + errors=errors.error_dict or {}, + prefix_error=False, + encoding="UTF-8" + ) + + try: + sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon') + sett1.app_settings_value = \ + form_result['rhodecode_show_public_icon'] + + sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon') + sett2.app_settings_value = \ + form_result['rhodecode_show_private_icon'] + + sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags') + sett3.app_settings_value = \ + form_result['rhodecode_stylify_metatags'] + + Session().add(sett1) + Session().add(sett2) + Session().add(sett3) + Session().commit() + set_rhodecode_config(config) + h.flash(_('Updated visualisation settings'), + category='success') + + except Exception: + log.error(traceback.format_exc()) + h.flash(_('error occurred during updating ' + 'visualisation settings'), + category='error') + if setting_id == 'vcs': application_form = ApplicationUiSettingsForm()() try:
--- a/rhodecode/controllers/admin/users.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/controllers/admin/users.py Fri Jul 27 01:21:07 2012 +0200 @@ -78,15 +78,15 @@ grav_tmpl = lambda user_email, size: ( template.get_def("user_gravatar") - .render(user_email, size, _=_, h=h)) + .render(user_email, size, _=_, h=h, c=c)) user_lnk = lambda user_id, username: ( template.get_def("user_name") - .render(user_id, username, _=_, h=h)) + .render(user_id, username, _=_, h=h, c=c)) user_actions = lambda user_id, username: ( template.get_def("user_actions") - .render(user_id, username, _=_, h=h)) + .render(user_id, username, _=_, h=h, c=c)) for user in c.users_list: users_data.append({
--- a/rhodecode/lib/base.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/lib/base.py Fri Jul 27 01:21:07 2012 +0200 @@ -17,7 +17,7 @@ from rhodecode import __version__, BACKENDS -from rhodecode.lib.utils2 import str2bool, safe_unicode +from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ HasPermissionAnyMiddleware, CookieStoreWrapper from rhodecode.lib.utils import get_repo_slug, invalidate_cache @@ -158,7 +158,7 @@ log.debug('proto is %s and SSL is required BAD REQUEST !' % org_proto) return False - return True + return True def __call__(self, environ, start_response): start = time.time() @@ -178,6 +178,12 @@ c.rhodecode_name = config.get('rhodecode_title') c.use_gravatar = str2bool(config.get('use_gravatar')) c.ga_code = config.get('rhodecode_ga_code') + # Visual options + c.visual = AttributeDict({}) + c.visual.show_public_icon = str2bool(config.get('rhodecode_show_public_icon')) + c.visual.show_private_icon = str2bool(config.get('rhodecode_show_private_icon')) + c.visual.stylify_metatags = str2bool(config.get('rhodecode_stylify_metatags')) + c.repo_name = get_repo_slug(request) c.backends = BACKENDS.keys() c.unread_notifications = NotificationModel()\
--- a/rhodecode/lib/helpers.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/lib/helpers.py Fri Jul 27 01:21:07 2012 +0200 @@ -9,6 +9,7 @@ import urllib import math import logging +import re from datetime import datetime from pygments.formatters.html import HtmlFormatter @@ -430,6 +431,26 @@ return _author +def desc_stylize(value): + """ + converts tags from value into html equivalent + + :param value: + """ + value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', + '<div class="metatag" tag="see">see => \\1 </div>', value) + value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', + '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value) + value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z\-\/]*)\]', + '<div class="metatag" tag="\\1">\\1 => <a href="/\\2">\\2</a></div>', value) + value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/]*)\]', + '<div class="metatag" tag="lang">\\2</div>', value) + value = re.sub(r'\[([a-z]+)\]', + '<div class="metatag" tag="\\1">\\1</div>', value) + + return value + + def bool2icon(value): """Returns True/False values represented as small html image of true/false icons
--- a/rhodecode/lib/utils2.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/lib/utils2.py Fri Jul 27 01:21:07 2012 +0200 @@ -443,3 +443,9 @@ usrs.add(username) return sorted(list(usrs), key=lambda k: k.lower()) + +class AttributeDict(dict): + def __getattr__(self, attr): + return self.get(attr, None) + __setattr__ = dict.__setitem__ + __delattr__ = dict.__delitem__
--- a/rhodecode/model/db.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/model/db.py Fri Jul 27 01:21:07 2012 +0200 @@ -182,9 +182,16 @@ ) @classmethod - def get_by_name(cls, ldap_key): + def get_by_name(cls, key): return cls.query()\ - .filter(cls.app_settings_name == ldap_key).scalar() + .filter(cls.app_settings_name == key).scalar() + + @classmethod + def get_by_name_or_create(cls, key): + res = cls.get_by_name(key) + if not res: + res = cls(key) + return res @classmethod def get_app_settings(cls, cache=False): @@ -589,8 +596,8 @@ users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all') stats = relationship('Statistics', cascade='all', uselist=False) - followers = relationship('UserFollowing', - primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', + followers = relationship('UserFollowing', + primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all') logs = relationship('UserLog') @@ -1547,7 +1554,7 @@ self._revisions = ':'.join(val) author = relationship('User', lazy='joined') - reviewers = relationship('PullRequestReviewers', + reviewers = relationship('PullRequestReviewers', cascade="all, delete, delete-orphan") org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
--- a/rhodecode/model/forms.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/model/forms.py Fri Jul 27 01:21:07 2012 +0200 @@ -242,23 +242,30 @@ return _ApplicationSettingsForm +def ApplicationVisualisationForm(): + class _ApplicationVisualisationForm(formencode.Schema): + allow_extra_fields = True + filter_extra_fields = False + rhodecode_show_public_icon = v.StringBoolean(if_missing=False) + rhodecode_show_private_icon = v.StringBoolean(if_missing=False) + rhodecode_stylify_metatags = v.StringBoolean(if_missing=False) + + return _ApplicationVisualisationForm + + def ApplicationUiSettingsForm(): class _ApplicationUiSettingsForm(formencode.Schema): allow_extra_fields = True filter_extra_fields = False - web_push_ssl = v.OneOf(['true', 'false'], if_missing='false') + web_push_ssl = v.StringBoolean(if_missing=False) paths_root_path = All( v.ValidPath(), v.UnicodeString(strip=True, min=1, not_empty=True) ) - hooks_changegroup_update = v.OneOf(['True', 'False'], - if_missing=False) - hooks_changegroup_repo_size = v.OneOf(['True', 'False'], - if_missing=False) - hooks_changegroup_push_logger = v.OneOf(['True', 'False'], - if_missing=False) - hooks_preoutgoing_pull_logger = v.OneOf(['True', 'False'], - if_missing=False) + hooks_changegroup_update = v.StringBoolean(if_missing=False) + hooks_changegroup_repo_size = v.StringBoolean(if_missing=False) + hooks_changegroup_push_logger = v.StringBoolean(if_missing=False) + hooks_preoutgoing_pull_logger = v.StringBoolean(if_missing=False) return _ApplicationUiSettingsForm @@ -268,7 +275,7 @@ allow_extra_fields = True filter_extra_fields = True overwrite_default = v.StringBoolean(if_missing=False) - anonymous = v.OneOf(['True', 'False'], if_missing=False) + anonymous = v.StringBoolean(if_missing=False) default_perm = v.OneOf(perms_choices) default_register = v.OneOf(register_choices) default_create = v.OneOf(create_choices)
--- a/rhodecode/public/css/style.css Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/public/css/style.css Fri Jul 27 01:21:07 2012 +0200 @@ -1827,6 +1827,81 @@ } +#summary .metatag { + display: inline-block; + padding: 3px 5px; + margin-bottom: 3px; + margin-right: 1px; + border-radius: 5px; +} + +#content div.box #summary p { + margin-bottom: -5px; + width: 600px; + white-space: pre-wrap; +} + +#content div.box #summary p:last-child { + margin-bottom: 9px; +} + +#content div.box #summary p:first-of-type { + margin-top: 9px; +} + + .metatag { + display: inline-block; + margin-right: 1px; + -webkit-border-radius: 4px 4px 4px 4px; + -khtml-border-radius: 4px 4px 4px 4px; + -moz-border-radius: 4px 4px 4px 4px; + border-radius: 4px 4px 4px 4px; + + border: solid 1px #9CF; + padding: 2px 3px 2px 3px !important; + background-color: #DEF; +} + +.metatag[tag="dead"] { + background-color: #E44; +} + +.metatag[tag="stale"] { + background-color: #EA4; +} + +.metatag[tag="featured"] { + background-color: #AEA; +} + +.metatag[tag="requires"] { + background-color: #9CF; +} + +.metatag[tag="recommends"] { + background-color: #BDF; +} + +.metatag[tag="lang"] { + background-color: #FAF474; +} + +.metatag[tag="license"] { + border: solid 1px #9CF; + background-color: #DEF; + target-new: tab !important; +} +.metatag[tag="see"] { + border: solid 1px #CBD; + background-color: #EDF; +} + +a.metatag[tag="license"]:hover { + background-color: #003367; + color: #FFF; + text-decoration: none; +} + #summary .desc { white-space: pre; width: 100%;
--- a/rhodecode/templates/admin/settings/settings.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/admin/settings/settings.html Fri Jul 27 01:21:07 2012 +0200 @@ -116,6 +116,63 @@ </div> ${h.end_form()} + <h3>${_('Visualisation settings')}</h3> + ${h.form(url('admin_setting', setting_id='visual'),method='put')} + <div class="form"> + <!-- fields --> + + <div class="fields"> + + <div class="field"> + <div class="label label-checkbox"> + <label>${_('Icons')}:</label> + </div> + <div class="checkboxes"> + <div class="checkbox"> + ${h.checkbox('rhodecode_show_public_icon','True')} + <label for="rhodecode_show_public_icon">${_('Show public repo icon on repositories')}</label> + </div> + <div class="checkbox"> + ${h.checkbox('rhodecode_show_private_icon','True')} + <label for="rhodecode_show_private_icon">${_('Show private repo icon on repositories')}</label> + </div> + </div> + </div> + + <div class="field"> + <div class="label label-checkbox"> + <label>${_('Meta-Tagging')}:</label> + </div> + <div class="checkboxes"> + <div class="checkbox"> + ${h.checkbox('rhodecode_stylify_metatags','True')} + <label for="rhodecode_stylify_metatags">${_('Stylify recognised metatags:')}</label> + </div> + <div style="padding-left: 20px;"> + <ul> <!-- Fix style here --> + <li>[featured] <span class="metatag" tag="featured">featured</span></li> + <li>[stale] <span class="metatag" tag="stale">stale</span></li> + <li>[dead] <span class="metatag" tag="dead">dead</span></li> + <li>[lang => lang] <span class="metatag" tag="lang" >lang</span></li> + <li>[license => License] <span class="metatag" tag="license"><a href="http://www.opensource.org/licenses/License" >License</a></span></li> + <li>[requires => Repo] <span class="metatag" tag="requires" >requires => <a href="#" >Repo</a></span></li> + <li>[recommends => Repo] <span class="metatag" tag="recommends" >recommends => <a href="#" >Repo</a></span></li> + <li>[see => URI] <span class="metatag" tag="see">see => <a href="#">URI</a> </span></li> + </ul> + </div> + </div> + </div> + + <div class="buttons"> + ${h.submit('save',_('Save settings'),class_="ui-btn large")} + ${h.reset('reset',_('Reset'),class_="ui-btn large")} + </div> + + </div> + </div> + ${h.end_form()} + + <h3>${_('VCS settings')}</h3> ${h.form(url('admin_setting', setting_id='vcs'),method='put')} <div class="form">
--- a/rhodecode/templates/data_table/_dt_elements.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/data_table/_dt_elements.html Fri Jul 27 01:21:07 2012 +0200 @@ -63,10 +63,10 @@ %endif ##PRIVATE/PUBLIC - %if private: - <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/> - %else: - <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/> + %if private and c.visual.show_private_icon: + <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/> + %elif not private and c.visual.show_public_icon: + <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/> %endif ##NAME @@ -108,4 +108,3 @@ <%def name="user_name(user_id, username)"> ${h.link_to(username,h.url('edit_user', id=user_id))} </%def> -
--- a/rhodecode/templates/index_base.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/index_base.html Fri Jul 27 01:21:07 2012 +0200 @@ -41,7 +41,11 @@ ${h.link_to(gr.name,url('repos_group_home',group_name=gr.group_name))} </div> </td> - <td>${gr.group_description}</td> + %if c.visual.stylify_metatags: + <td>${h.desc_stylize(gr.group_description)}</td> + %else: + <td>${gr.group_description}</td> + %endif ## this is commented out since for multi nested repos can be HEAVY! ## in number of executed queries during traversing uncomment at will ##<td><b>${gr.repositories_recursive_count}</b></td> @@ -85,7 +89,11 @@ </td> ##DESCRIPTION <td><span class="tooltip" title="${h.tooltip(repo['description'])}"> + %if c.visual.stylify_metatags: + ${h.urlify_text(h.desc_stylize(h.truncate(repo['description'],60)))}</span> + %else: ${h.truncate(repo['description'],60)}</span> + %endif </td> ##LAST CHANGE DATE <td>
--- a/rhodecode/templates/journal/journal.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/journal/journal.html Fri Jul 27 01:21:07 2012 +0200 @@ -128,9 +128,9 @@ <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/> %endif - %if entry.follows_repository.private: + %if entry.follows_repository.private and c.visual.show_private_icon: <img class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="${h.url('/images/icons/lock.png')}"/> - %else: + %elif not entry.follows_repository.private and c.visual.show_public_icon: <img class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="${h.url('/images/icons/lock_open.png')}"/> %endif <span class="watched_repo">
--- a/rhodecode/templates/repo_switcher_list.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/repo_switcher_list.html Fri Jul 27 01:21:07 2012 +0200 @@ -6,12 +6,12 @@ %for repo in c.repos_list: - %if repo['dbrepo']['private']: + %if repo['dbrepo']['private'] and c.visual.show_private_icon: <li> <img src="${h.url('/images/icons/lock.png')}" alt="${_('Private repository')}" class="repo_switcher_type"/> ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])} </li> - %else: + %elif not repo['dbrepo']['private'] and c.visual.show_public_icon: <li> <img src="${h.url('/images/icons/lock_open.png')}" alt="${_('Public repository')}" class="repo_switcher_type" /> ${h.link_to(repo['name'],h.url('summary_home',repo_name=repo['name']),class_="repo_name %s" % repo['dbrepo']['repo_type'])}
--- a/rhodecode/templates/summary/summary.html Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/templates/summary/summary.html Fri Jul 27 01:21:07 2012 +0200 @@ -104,7 +104,11 @@ <div class="label-summary"> <label>${_('Description')}:</label> </div> - <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div> + %if c.visual.stylify_metatags: + <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(h.desc_stylize(c.dbrepo.description))}</div> + %else: + <div class="input ${summary(c.show_stats)} desc">${h.urlify_text(c.dbrepo.description)}</div> + %endif </div> <div class="field">
--- a/rhodecode/tests/test_libs.py Fri Jul 27 01:06:50 2012 +0200 +++ b/rhodecode/tests/test_libs.py Fri Jul 27 01:21:07 2012 +0200 @@ -131,3 +131,19 @@ self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month-1] + 2))), u'1 month and 2 days ago') self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago') + + def test_tag_exctrator(self): + sample = ( + "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]" + "[requires] [stale] [see<>=>] [see => http://url.com]" + "[requires => url] [lang => python] [just a tag]" + "[,d] [ => ULR ] [obsolete] [desc]]" + ) + from rhodecode.lib.helpers import desc_stylize + res = desc_stylize(sample) + self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res) + self.assertTrue('<div class="metatag" tag="obsolete">obsolete</div>' in res) + self.assertTrue('<div class="metatag" tag="stale">stale</div>' in res) + self.assertTrue('<div class="metatag" tag="lang">python</div>' in res) + self.assertTrue('<div class="metatag" tag="requires">requires => <a href="/url">url</a></div>' in res) + self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res)