[Pysvnmanager-svn] SF.net SVN: pysvnmanager:[43] trunk/pysvnmanager
Status: Alpha
Brought to you by:
jiangx
From: <ji...@us...> - 2008-08-25 10:25:06
|
Revision: 43 http://pysvnmanager.svn.sourceforge.net/pysvnmanager/?rev=43&view=rev Author: jiangx Date: 2008-08-25 10:25:09 +0000 (Mon, 25 Aug 2008) Log Message: ----------- add controller/view for svn plugin management. Modified Paths: -------------- trunk/pysvnmanager/hooks/plugins/__init__.py trunk/pysvnmanager/model/hooks.py trunk/pysvnmanager/templates/authz/index.mako trunk/pysvnmanager/templates/base.mako trunk/pysvnmanager/templates/check/index.mako trunk/pysvnmanager/templates/role/index.mako trunk/pysvnmanager/tests/test_repos.py Added Paths: ----------- trunk/pysvnmanager/controllers/repos.py trunk/pysvnmanager/templates/repos/ trunk/pysvnmanager/templates/repos/hooks.mako trunk/pysvnmanager/tests/functional/test_repos.py Added: trunk/pysvnmanager/controllers/repos.py =================================================================== --- trunk/pysvnmanager/controllers/repos.py (rev 0) +++ trunk/pysvnmanager/controllers/repos.py 2008-08-25 10:25:09 UTC (rev 43) @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +import logging + +from pysvnmanager.lib.base import * +from pysvnmanager.model.svnauthz import * +from pysvnmanager.model import repos as _repos +from pysvnmanager.model import hooks as _hooks + + +log = logging.getLogger(__name__) + +class ReposController(BaseController): + requires_auth = True + + def __init__(self): + self.authz = SvnAuthz(cfg.authz_file) + self.login_as = session.get('user') + # Used as checked in user to rcs file. + self.authz.login_as = self.login_as + + self.repos_root = cfg.repos_root + self.repos = _repos.Repos(self.repos_root) + self.repos_list = self.repos.repos_list + + + def __before__(self, action): + super(ReposController, self).__before__(action) + if not self.authz.is_super_user(self.login_as): + return redirect_to(h.url_for(controller='security', action='failed')) + + def index(self): + return render('/repos/hooks.mako') + + def init_repos_list(self): + total = 0; + msg = '' + + # get javascript code for top_form's role_selector + msg += 'id[0]="%s";' % '...' + msg += 'name[0]="%s";\n' % _("Please choose...") + total += 1; + for reposname in self.repos_list: + msg += 'id[%d]="%s";' % (total, reposname) + msg += 'name[%d]="%s";\n' % (total, reposname) + total += 1; + msg += 'total=%d;\n' % total + msg += 'revision="%s";\n' % self.authz.version + return msg + + def get_plugin_list(self): + reposname = request.params.get('select') + h = _hooks.Hooks(self.repos_root + reposname) + total = 0; + msg = '' + + # get javascript code for top_form's role_selector + msg += 'id[0]="%s";' % '...' + msg += 'name[0]="%s";\n' % _("Please choose...") + total += 1; + for name in h.unapplied_plugins.keys(): + msg += 'id[%d]="%s";' % (total, name) + msg += 'name[%d]="%s";\n' % (total, h.plugins[name].name) + total += 1; + msg += 'total=%d;\n' % total + + return msg + + def get_remove_hook_form_content(self): + reposname = request.params.get('select') + h = _hooks.Hooks(self.repos_root + reposname) + msg = '' + if len(h.applied_plugins) > 0: + msg += "Installed hooks:" + msg += "<br>\n" + num = 0 + + for name in h.applied_plugins.keys(): + msg += '<input type="checkbox" name="pluginid_%(num)d" value="%(plugin)s">' % { + 'num': num, 'plugin': name, } + desc = h.plugins[name].description + detail = h.plugins[name].detail + msg += '%(plugin)s - %(desc)s' % { + 'plugin': name, 'name': h.plugins[name].name, 'desc': desc, } + if detail and detail != desc: + msg += ' - %(detail)s' % { 'detail': detail, } + msg += '<br>\n' + msg += '<input type="submit" name="remove_hook" value="Remove selected hooks">\n' + + return msg + + def get_hook_form(self): + reposname = request.params.get('repos') + pluginname = request.params.get('plugin') + h = _hooks.Hooks(self.repos_root + reposname) + + return h.plugins[pluginname].show_form() + + def apply_new_hook(self): + try: + d = request.params + reposname = d.get("_repos") + pluginname = d.get("_plugin") + h = _hooks.Hooks(self.repos_root + reposname) + plugin = h.plugins[pluginname] + plugin.set_plugin(d) + except Exception, e: + result = "Apply plugin '%(plugin)s on '%(repos)s' Failed. Error message:<br>\n%(msg)s" % { + "plugin": pluginname, "repos":reposname, "msg": e} + else: + result = "Apply plugin '%(plugin)s on '%(repos)s' success." % { + "plugin": pluginname, "repos":reposname} + return result + + def remove_hook(self): + try: + d = request.params + reposname = d.get("_repos") + h = _hooks.Hooks(self.repos_root + reposname) + for i in d.keys(): + if "pluginid_" in i: + pluginname = d[i] + plugin = h.plugins[pluginname] + plugin.delete_plugin() + except Exception, e: + result = "Delete plugin '%(plugin)s on '%(repos)s' Failed. Error message:<br>\n%(msg)s" % { + "plugin": pluginname, "repos":reposname, "msg": e} + else: + result = "Delete plugin '%(plugin)s on '%(repos)s' success." % { + "plugin": pluginname, "repos":reposname} + return result + + def create(self): + return render('/repos/create.mako') + + def remove(self): + return render('/repos/remove.mako') Modified: trunk/pysvnmanager/hooks/plugins/__init__.py =================================================================== --- trunk/pysvnmanager/hooks/plugins/__init__.py 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/hooks/plugins/__init__.py 2008-08-25 10:25:09 UTC (rev 43) @@ -89,6 +89,8 @@ def show(self): return self.description + detail = property(show) + def show_form(self): return self.description Modified: trunk/pysvnmanager/model/hooks.py =================================================================== --- trunk/pysvnmanager/model/hooks.py 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/model/hooks.py 2008-08-25 10:25:09 UTC (rev 43) @@ -48,12 +48,20 @@ self.plugins[m] = plugins.getHandler(m)(self.__repos_path) def __get_applied_plugins(self): - return [m for m in self.pluginnames if self.plugins[m].is_set()] + result={} + for k,v in self.plugins.iteritems(): + if v.is_set(): + result[k]=v + return result applied_plugins = property(__get_applied_plugins) def __get_unapplied_plugins(self): - return [m for m in self.pluginnames if not self.plugins[m].is_set()] + result={} + for k,v in self.plugins.iteritems(): + if not v.is_set(): + result[k]=v + return result unapplied_plugins = property(__get_unapplied_plugins) Modified: trunk/pysvnmanager/templates/authz/index.mako =================================================================== --- trunk/pysvnmanager/templates/authz/index.mako 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/templates/authz/index.mako 2008-08-25 10:25:09 UTC (rev 43) @@ -21,11 +21,6 @@ all_users.sort(); -function clean_message() -{ - document.getElementById('result').innerHTML = ''; -} - // Display repos list only. function show_init_form() { @@ -49,8 +44,6 @@ document.getElementById('action_box').style.visibility = 'hidden'; document.getElementById('action_box').style.position = 'absolute'; - - document.getElementById('result').innerHTML = ''; } // Display repos_list, admins_input, path_list. @@ -508,15 +501,12 @@ if (message) { message = '${_("Update ACL failed:")}' + message; - alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Update ACL successfully.")}'; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); if (document.main_form.repos_list.value == reposname) { repos_changed(); @@ -565,15 +555,12 @@ if (message) { message = '${_("Can not delete module ")}' + reposname + ':' + path + ' : ' + message; - alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Successfully delete module:")}' + reposname + ':' + path; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); repos_changed(); } } @@ -687,8 +674,6 @@ <table width='100%'> <tr> <td align='center'> - <div id='result'></div> - <br> <input type="hidden" name="reposname"> <input type="button" name="save_btn" value='${_("Save")}' onClick="save_authz(this.form)"> <input type="button" name="delete_btn" value='${_("Delete")}' onClick="delete_authz(this.form)"> Modified: trunk/pysvnmanager/templates/base.mako =================================================================== --- trunk/pysvnmanager/templates/base.mako 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/templates/base.mako 2008-08-25 10:25:09 UTC (rev 43) @@ -12,6 +12,11 @@ </div> ${self.nav_bar()} + + <div id="message_box" style="visibility:hidden;position:absolute" class=gainlayout> + <span id="message"></span> + <br><a class="clear-link" href="#" onClick="document.getElementById('message').innerHTML='';switch_message_box()">Clear message</a> + </div> ${next.body()} </body> @@ -27,6 +32,7 @@ <td>${h.link_to(_("Check permissions"), h.url_for(controller="check", id=None))}</td> <td>${h.link_to(_("Role management"), h.url(controller="role", id=None))}</td> <td>${h.link_to(_("ACL management"), h.url(controller="authz", id=None))}</td> + <td>${h.link_to(_("Repos management"), h.url(controller="repos", id=None))}</td> <td>${h.link_to(_("Logs"), h.url(controller="logs", id=None))}</td> <td>welcome ${session.get('user')}</td> <td>${h.link_to(_("Logout"), h.url(controller="logout", id=None))}</td> @@ -107,6 +113,28 @@ document.getElementById('popup_notices').style.visibility = 'hidden'; document.getElementById('popup_notices').style.display = 'none'; } + +function set_message_box(message) +{ + document.getElementById('message').innerHTML=message; + switch_message_box(); +} + +function switch_message_box() +{ + c=document.getElementById('message').innerHTML; + s=document.getElementById('message_box').style; + if (c) + { + s.visibility='visible'; + s.position = 'relative'; + } + else + { + s.visibility='hidden'; + s.position = 'absolute'; + } +} </script> </%def> Modified: trunk/pysvnmanager/templates/check/index.mako =================================================================== --- trunk/pysvnmanager/templates/check/index.mako 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/templates/check/index.mako 2008-08-25 10:25:09 UTC (rev 43) @@ -114,7 +114,7 @@ h.form_remote_tag( html={'id':'main_form'}, url=h.url(action='access_map'), - update=dict(success="acl_msg", failure="acl_error"), + update=dict(success="acl_msg", failure="message"), method='post', before='showNoticesPopup()', complete='hideNoticesPopup();'+h.visual_effect("Highlight", "acl_msg", duration=1), ) @@ -182,5 +182,4 @@ ## classic form: ${c.access_map_msg} <div id='acl_msg'></div> -<div id='acl_error'></div> Added: trunk/pysvnmanager/templates/repos/hooks.mako =================================================================== --- trunk/pysvnmanager/templates/repos/hooks.mako (rev 0) +++ trunk/pysvnmanager/templates/repos/hooks.mako 2008-08-25 10:25:09 UTC (rev 43) @@ -0,0 +1,254 @@ +## -*- coding: utf-8 -*- +<%inherit file="/base.mako" /> + +<%def name="head_tags()"> + <title>${_("Repos management")}</title> +</%def> + +<%def name="body_params()"> onload="init_repos_list()" </%def> + +<SCRIPT LANGUAGE="JavaScript"> + +// Display repos list only. +function show_init_form() +{ + document.getElementById('repos_list_box').style.visibility = 'visible'; + document.getElementById('repos_list_box').style.position = 'relative'; + + document.getElementById('new_hook_list_box').style.visibility = 'hidden'; + document.getElementById('new_hook_list_box').style.position = 'absolute'; + + document.getElementById('new_hook_setting_box').style.visibility = 'hidden'; + document.getElementById('new_hook_setting_box').style.position = 'absolute'; + + document.getElementById('remove_hook_box').style.visibility = 'visible'; + document.getElementById('remove_hook_box').style.position = 'relative'; +} + + +function init_repos_list() +{ + showNoticesPopup(); + new Ajax.Request( + '${h.url_for(controller="repos", action="init_repos_list")}', + {asynchronous:true, evalScripts:true, method:'post', + onComplete: + function(request) + {hideNoticesPopup();ajax_init_repos_list(request.responseText);} + }); +} + +function ajax_init_repos_list(code) +{ + var id = new Array(); + var name = new Array(); + var total = 0; + var revision = ''; + + repos_list = document.main_form.repos_list; + repos_list.options.length = 0; + + try { + eval(code); + for (var i=0; i < total; i++) + { + repos_list.options[i] = new Option(name[i], id[i]); + } + document.main_form.revision.value = revision; + } + catch(exception) { + alert(exception); + } + + repos_changed(); +} + +function repos_changed() +{ + var name = document.main_form.repos_list.value; + var params = {select:name}; + var revision = ''; + + if (name=='...'||name=='') + { + document.getElementById('remove_hook_form_content').innerHTML = ""; + show_init_form(); + } + else + { + showNoticesPopup(); + new Ajax.Request( + '${h.url_for(controller="repos", action="get_plugin_list")}', + {asynchronous:true, evalScripts:true, method:'post', + onComplete: + function(request) + {hideNoticesPopup();ajax_repos_changed(request.responseText);}, + parameters:params + }); + + new Ajax.Updater( + 'remove_hook_form_content', + '${h.url_for(controller="repos", action="get_remove_hook_form_content")}', + {asynchronous:true, evalScripts:true, method:'post', + onComplete: + function(request) + {hideNoticesPopup();}, + parameters:params + }); + } +} + +function ajax_repos_changed(code) +{ + var id = new Array(); + var name = new Array(); + var total = 0; + + unset_plugin_list = document.main_form.unset_plugin_list; + unset_plugin_list.options.length = 0; + + try { + eval(code); + if (total==1) + { + document.getElementById('new_hook_list_box').style.visibility = 'hidden'; + document.getElementById('new_hook_list_box').style.position = 'absolute'; + document.getElementById('new_hook_setting_box').style.visibility = 'hidden'; + document.getElementById('new_hook_setting_box').style.position = 'absolute'; + } + else + { + document.getElementById('new_hook_list_box').style.visibility = 'visible'; + document.getElementById('new_hook_list_box').style.position = 'relative'; + for (var i=0; i < total; i++) + { + unset_plugin_list.options[i] = new Option(name[i], id[i]); + } + } + } + catch(exception) { + alert(exception); + } + + path_changed(); +} + +function select_unset_hook_list() +{ + var reposname = document.main_form.repos_list.value; + var pluginname = document.main_form.unset_plugin_list.value; + var params = {repos:reposname, plugin:pluginname}; + + if (pluginname=='...'||pluginname=='') + { + document.getElementById('apply_new_hook_form_content').innerHTML = ""; + document.getElementById('new_hook_setting_box').style.visibility = 'hidden'; + document.getElementById('new_hook_setting_box').style.position = 'absolute'; + } + else + { + document.getElementById('new_hook_setting_box').style.visibility = 'visible'; + document.getElementById('new_hook_setting_box').style.position = 'relative'; + showNoticesPopup(); + new Ajax.Updater( + {success:'apply_new_hook_form_content',failure:'apply_new_hook_form_content'}, + '${h.url_for(controller="repos", action="get_hook_form")}', + {asynchronous:true, evalScripts:true, method:'post', + onComplete: + function(request) + {hideNoticesPopup();}, + parameters:params + }); + } +} + +function apply_new_hook_form_submit(form) +{ + var reposname = document.main_form.repos_list.value; + var pluginname = document.main_form.unset_plugin_list.value; + if (pluginname=='...'||pluginname==''||reposname=="..."||reposname=="") + { + alert("Bad repository or plugin name"); + return false; + } + form._repos.value = reposname; + form._plugin.value = pluginname; +} + +function remove_hook_form_submit(form) +{ + var reposname = document.main_form.repos_list.value; + if (reposname=="..."||reposname=="") + { + alert("Bad repository or plugin name"); + return false; + } + form._repos.value = reposname; +} + +</SCRIPT> + + +<h2>${_("Repos management")}</h2> + +<form name="main_form" method="post"> +<input type="hidden" name="revision" value="${c.revision}"> +<DIV style="position:relative;" class=gainlayout> + +<DIV id="repos_list_box" class=gainlayout> +${_("Repository:")} + <select name="repos_list" size="1" onChange='repos_changed()'> + </select> +<a href="#" onclick='#'>[+${_("Add repository")}]</a> +<a href="#" onclick='#'>[-${_("Remove repository")}]</a> +</DIV> + +<DIV id="new_hook_list_box" class=gainlayout style="visibility:hidden;position:absolute"> +${_("Available hooks:")} + <select name="unset_plugin_list" size="1" onChange='select_unset_hook_list()'> + </select> +</form> +</DIV> +<DIV id="new_hook_setting_box" class=gainlayout style="visibility:hidden;position:absolute"> +## <form name="apply_new_hook_form" method="post" action="${h.url_for(action='apply_new_hook')}" +## onSubmit="apply_new_hook_form_submit(this)"> +<% + context.write( + h.form_remote_tag( + html={'id':'apply_new_hook_form'}, + url=h.url(action='apply_new_hook'), + update=dict(success="message", failure="message"), + method='post', before='apply_new_hook_form_submit(this); showNoticesPopup()', + complete='hideNoticesPopup();switch_message_box();repos_changed()', + ) + ) + %> + <input type=hidden name="_repos" value=""> + <input type=hidden name="_plugin" value=""> + <div id="apply_new_hook_form_content"></div> + <input type="submit" name="apply" value="${_("Enable this hook")}"> +</form> +</DIV> + +<hr size='1'> + +<DIV id="remove_hook_box" class=gainlayout style="visibility:visible;position:relative"> +## <form name="remove_hook_form" method="post" action="${h.url_for(action='remove_hook')}" +## onSubmit="remove_hook_form_submit(this)"> +<% + context.write( + h.form_remote_tag( + html={'id':'remove_hook_form'}, + url=h.url(action='remove_hook'), + update=dict(success="message", failure="message"), + method='post', before='remove_hook_form_submit(this); showNoticesPopup()', + complete='hideNoticesPopup();switch_message_box();repos_changed()', + ) + ) + %> + <input type=hidden name="_repos" value=""> + <div id="remove_hook_form_content"></div> +</DIV> + +</DIV> + Modified: trunk/pysvnmanager/templates/role/index.mako =================================================================== --- trunk/pysvnmanager/templates/role/index.mako 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/templates/role/index.mako 2008-08-25 10:25:09 UTC (rev 43) @@ -355,8 +355,6 @@ else show_init_form(); - document.getElementById('result').innerHTML = ''; - if(name.charAt(0) == '@') { showNoticesPopup(); @@ -419,14 +417,12 @@ { message = '${_("Update group failed:")}' + message; alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Update group successfully.")}'; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); if (document.main_form.role_list.value == rolename) { role_changed(); @@ -469,15 +465,12 @@ if (message) { message = '${_("Delete group failed:")}' + message; - alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Delete group successfully.")}'; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); reset_main_form(); } } @@ -510,15 +503,12 @@ if (message) { message = '${_("Update alias failed:")}' + message; - alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Update alias successfully.")}'; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); if (document.main_form.role_list.value == aliasname) { role_changed(); @@ -560,15 +550,12 @@ if (message) { message = '${_("Delete alias failed:")}' + message; - alert(message); - document.getElementById('result').innerHTML = message; - document.getElementById('result').style.visibility = 'visible'; + set_message_box(message); } else { message = '${_("Delete alias successfully.")}'; - document.getElementById('result').innerHTML = message; - alert(message); + set_message_box(message); reset_main_form(); } } @@ -718,9 +705,6 @@ </DIV> -<div id='result' style="position:relative;" class=gainlayout> -</div> - <!-- begin: action_box --> <div id='action_box' style="position:relative;" class=gainlayout> <input type="hidden" name="rolename"> Added: trunk/pysvnmanager/tests/functional/test_repos.py =================================================================== --- trunk/pysvnmanager/tests/functional/test_repos.py (rev 0) +++ trunk/pysvnmanager/tests/functional/test_repos.py 2008-08-25 10:25:09 UTC (rev 43) @@ -0,0 +1,7 @@ +from pysvnmanager.tests import * + +class TestReposController(TestController): + + def test_index(self): + response = self.app.get(url_for(controller='repos')) + # Test response... Modified: trunk/pysvnmanager/tests/test_repos.py =================================================================== --- trunk/pysvnmanager/tests/test_repos.py 2008-08-25 10:22:44 UTC (rev 42) +++ trunk/pysvnmanager/tests/test_repos.py 2008-08-25 10:25:09 UTC (rev 43) @@ -87,7 +87,7 @@ myhooks = hooks.Hooks(self.repos_root + '/repos1') self.assert_(myhooks.pluginnames==['CaseInsensitive', 'EolStyleCheck'], myhooks.pluginnames) - self.assert_(myhooks.unapplied_plugins==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins) + self.assert_(myhooks.unapplied_plugins.keys()==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins.keys()) m = myhooks.plugins['CaseInsensitive'] self.assert_(m.name=="check case insensitive", m.name) @@ -98,18 +98,18 @@ m = myhooks.plugins['CaseInsensitive'] self.assert_(m.is_set()==False) - self.assert_(myhooks.applied_plugins==[], myhooks.applied_plugins) - self.assert_(myhooks.unapplied_plugins==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins) + self.assert_(myhooks.applied_plugins.keys()==[], myhooks.applied_plugins.keys()) + self.assert_(myhooks.unapplied_plugins.keys()==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins.keys()) m.set_plugin() self.assert_(m.is_set()==True) - self.assert_(myhooks.applied_plugins==['CaseInsensitive'], myhooks.applied_plugins) - self.assert_(myhooks.unapplied_plugins==['EolStyleCheck'], myhooks.unapplied_plugins) + self.assert_(myhooks.applied_plugins.keys()==['CaseInsensitive'], myhooks.applied_plugins.keys()) + self.assert_(myhooks.unapplied_plugins.keys()==['EolStyleCheck'], myhooks.unapplied_plugins.keys()) m.delete_plugin() self.assert_(m.is_set()==False) - self.assert_(myhooks.applied_plugins==[], myhooks.applied_plugins) - self.assert_(myhooks.unapplied_plugins==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins) + self.assert_(myhooks.applied_plugins.keys()==[], myhooks.applied_plugins.keys()) + self.assert_(myhooks.unapplied_plugins.keys()==['CaseInsensitive', 'EolStyleCheck'], myhooks.unapplied_plugins.keys()) if __name__ == '__main__': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |