##// END OF EJS Templates
added settings rest controllers for admin, updated routes with easier submodule handling
marcink -
r346:51362853 default
parent child Browse files
Show More
@@ -0,0 +1,93 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # settings controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20 """
21 Created on July 14, 2010
22 settings controller for pylons
23 @author: marcink
24 """
25 from formencode import htmlfill
26 from pylons import request, session, tmpl_context as c, url
27 from pylons.controllers.util import abort, redirect
28 from pylons.i18n.translation import _
29 from pylons_app.lib import helpers as h
30 from pylons_app.lib.auth import LoginRequired, HasPermissionAllDecorator
31 from pylons_app.lib.base import BaseController, render
32 from pylons_app.model.db import User, UserLog
33 from pylons_app.model.forms import UserForm
34 from pylons_app.model.user_model import UserModel
35 import formencode
36 import logging
37
38 log = logging.getLogger(__name__)
39
40
41 class SettingsController(BaseController):
42 """REST Controller styled on the Atom Publishing Protocol"""
43 # To properly map this controller, ensure your config/routing.py
44 # file has a resource setup:
45 # map.resource('setting', 'settings', controller='admin/settings',
46 # path_prefix='/admin', name_prefix='admin_')
47
48
49 @LoginRequired()
50 #@HasPermissionAllDecorator('hg.admin')
51 def __before__(self):
52 c.admin_user = session.get('admin_user')
53 c.admin_username = session.get('admin_username')
54 super(SettingsController, self).__before__()
55
56 def index(self, format='html'):
57 """GET /admin/settings: All items in the collection"""
58 # url('admin_settings')
59 return render('admin/settings/settings.html')
60
61 def create(self):
62 """POST /admin/settings: Create a new item"""
63 # url('admin_settings')
64
65 def new(self, format='html'):
66 """GET /admin/settings/new: Form to create a new item"""
67 # url('admin_new_setting')
68
69 def update(self, id):
70 """PUT /admin/settings/id: Update an existing item"""
71 # Forms posted to this method should contain a hidden field:
72 # <input type="hidden" name="_method" value="PUT" />
73 # Or using helpers:
74 # h.form(url('admin_setting', id=ID),
75 # method='put')
76 # url('admin_setting', id=ID)
77
78 def delete(self, id):
79 """DELETE /admin/settings/id: Delete an existing item"""
80 # Forms posted to this method should contain a hidden field:
81 # <input type="hidden" name="_method" value="DELETE" />
82 # Or using helpers:
83 # h.form(url('admin_setting', id=ID),
84 # method='delete')
85 # url('admin_setting', id=ID)
86
87 def show(self, id, format='html'):
88 """GET /admin/settings/id: Show a specific item"""
89 # url('admin_setting', id=ID)
90
91 def edit(self, id, format='html'):
92 """GET /admin/settings/id/edit: Form to edit an existing item"""
93 # url('admin_edit_setting', id=ID)
@@ -0,0 +1,21 b''
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
3
4 <%def name="title()">
5 ${_('Settings administration')}
6 </%def>
7 <%def name="breadcrumbs()">
8 ${h.link_to(u'Admin',h.url('admin_home'))}
9 /
10 ${_('Settings')}
11 </%def>
12 <%def name="page_nav()">
13 ${self.menu('admin')}
14 ${self.submenu('settings')}
15 </%def>
16 <%def name="main()">
17 <div>
18 <h2>${_('Settings administration')}</h2>
19
20 </div>
21 </%def>
@@ -0,0 +1,43 b''
1 from pylons_app.tests import *
2
3 class TestSettingsController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url('admin_settings'))
7 # Test response...
8
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_admin_settings', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('admin_settings'))
14
15 def test_new(self):
16 response = self.app.get(url('admin_new_setting'))
17
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_admin_new_setting', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('admin_setting', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('admin_setting', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('admin_setting', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('admin_setting', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('admin_setting', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_admin_setting', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('admin_edit_setting', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_admin_edit_setting', id=1, format='xml'))
@@ -0,0 +1,43 b''
1 from pylons_app.tests import *
2
3 class TestSettingsHgController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url('admin_settings_hg'))
7 # Test response...
8
9 def test_index_as_xml(self):
10 response = self.app.get(url('formatted_admin_settings_hg', format='xml'))
11
12 def test_create(self):
13 response = self.app.post(url('admin_settings_hg'))
14
15 def test_new(self):
16 response = self.app.get(url('admin_new_setting_hg'))
17
18 def test_new_as_xml(self):
19 response = self.app.get(url('formatted_admin_new_setting_hg', format='xml'))
20
21 def test_update(self):
22 response = self.app.put(url('admin_setting_hg', id=1))
23
24 def test_update_browser_fakeout(self):
25 response = self.app.post(url('admin_setting_hg', id=1), params=dict(_method='put'))
26
27 def test_delete(self):
28 response = self.app.delete(url('admin_setting_hg', id=1))
29
30 def test_delete_browser_fakeout(self):
31 response = self.app.post(url('admin_setting_hg', id=1), params=dict(_method='delete'))
32
33 def test_show(self):
34 response = self.app.get(url('admin_setting_hg', id=1))
35
36 def test_show_as_xml(self):
37 response = self.app.get(url('formatted_admin_setting_hg', id=1, format='xml'))
38
39 def test_edit(self):
40 response = self.app.get(url('admin_edit_setting_hg', id=1))
41
42 def test_edit_as_xml(self):
43 response = self.app.get(url('formatted_admin_edit_setting_hg', id=1, format='xml'))
@@ -1,128 +1,129 b''
1 """Routes configuration
1 """Routes configuration
2
2
3 The more specific and detailed routes should be defined first so they
3 The more specific and detailed routes should be defined first so they
4 may take precedent over the more generic routes. For more information
4 may take precedent over the more generic routes. For more information
5 refer to the routes manual at http://routes.groovie.org/docs/
5 refer to the routes manual at http://routes.groovie.org/docs/
6 """
6 """
7 from routes import Mapper
7 from routes import Mapper
8 from pylons_app.lib.utils import check_repo_fast as cr
8 from pylons_app.lib.utils import check_repo_fast as cr
9
9
10 def make_map(config):
10 def make_map(config):
11 """Create, configure and return the routes Mapper"""
11 """Create, configure and return the routes Mapper"""
12 map = Mapper(directory=config['pylons.paths']['controllers'],
12 map = Mapper(directory=config['pylons.paths']['controllers'],
13 always_scan=config['debug'])
13 always_scan=config['debug'])
14 map.minimization = False
14 map.minimization = False
15 map.explicit = False
15 map.explicit = False
16
16
17 # The ErrorController route (handles 404/500 error pages); it should
17 # The ErrorController route (handles 404/500 error pages); it should
18 # likely stay at the top, ensuring it can always be resolved
18 # likely stay at the top, ensuring it can always be resolved
19 map.connect('/error/{action}', controller='error')
19 map.connect('/error/{action}', controller='error')
20 map.connect('/error/{action}/{id}', controller='error')
20 map.connect('/error/{action}/{id}', controller='error')
21
21
22 # CUSTOM ROUTES HERE
22 # CUSTOM ROUTES HERE
23 map.connect('hg_home', '/', controller='hg', action='index')
23 map.connect('hg_home', '/', controller='hg', action='index')
24
24
25 def check_repo(environ, match_dict):
25 def check_repo(environ, match_dict):
26 """
26 """
27 check for valid repository for proper 404 handling
27 check for valid repository for proper 404 handling
28 @param environ:
28 @param environ:
29 @param match_dict:
29 @param match_dict:
30 """
30 """
31 repo_name = match_dict.get('repo_name')
31 repo_name = match_dict.get('repo_name')
32 return not cr(repo_name, config['base_path'])
32 return not cr(repo_name, config['base_path'])
33
33
34 #REST routes
34 #REST routes
35 with map.submapper(path_prefix='/_admin', controller='pylons_app.controllers.admin.repos:ReposController') as m:
35 with map.submapper(path_prefix='/_admin', controller='admin/repos') as m:
36 m.connect("repos", "/repos",
36 m.connect("repos", "/repos",
37 action="create", conditions=dict(method=["POST"]))
37 action="create", conditions=dict(method=["POST"]))
38 m.connect("repos", "/repos",
38 m.connect("repos", "/repos",
39 action="index", conditions=dict(method=["GET"]))
39 action="index", conditions=dict(method=["GET"]))
40 m.connect("formatted_repos", "/repos.{format}",
40 m.connect("formatted_repos", "/repos.{format}",
41 action="index",
41 action="index",
42 conditions=dict(method=["GET"]))
42 conditions=dict(method=["GET"]))
43 m.connect("new_repo", "/repos/new",
43 m.connect("new_repo", "/repos/new",
44 action="new", conditions=dict(method=["GET"]))
44 action="new", conditions=dict(method=["GET"]))
45 m.connect("formatted_new_repo", "/repos/new.{format}",
45 m.connect("formatted_new_repo", "/repos/new.{format}",
46 action="new", conditions=dict(method=["GET"]))
46 action="new", conditions=dict(method=["GET"]))
47 m.connect("/repos/{repo_name:.*}",
47 m.connect("/repos/{repo_name:.*}",
48 action="update", conditions=dict(method=["PUT"],
48 action="update", conditions=dict(method=["PUT"],
49 function=check_repo))
49 function=check_repo))
50 m.connect("/repos/{repo_name:.*}",
50 m.connect("/repos/{repo_name:.*}",
51 action="delete", conditions=dict(method=["DELETE"],
51 action="delete", conditions=dict(method=["DELETE"],
52 function=check_repo))
52 function=check_repo))
53 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
53 m.connect("edit_repo", "/repos/{repo_name:.*}/edit",
54 action="edit", conditions=dict(method=["GET"],
54 action="edit", conditions=dict(method=["GET"],
55 function=check_repo))
55 function=check_repo))
56 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
56 m.connect("formatted_edit_repo", "/repos/{repo_name:.*}.{format}/edit",
57 action="edit", conditions=dict(method=["GET"],
57 action="edit", conditions=dict(method=["GET"],
58 function=check_repo))
58 function=check_repo))
59 m.connect("repo", "/repos/{repo_name:.*}",
59 m.connect("repo", "/repos/{repo_name:.*}",
60 action="show", conditions=dict(method=["GET"],
60 action="show", conditions=dict(method=["GET"],
61 function=check_repo))
61 function=check_repo))
62 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
62 m.connect("formatted_repo", "/repos/{repo_name:.*}.{format}",
63 action="show", conditions=dict(method=["GET"],
63 action="show", conditions=dict(method=["GET"],
64 function=check_repo))
64 function=check_repo))
65 #ajax delete repo perm user
65 #ajax delete repo perm user
66 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
66 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*}",
67 action="delete_perm_user", conditions=dict(method=["DELETE"],
67 action="delete_perm_user", conditions=dict(method=["DELETE"],
68 function=check_repo))
68 function=check_repo))
69
69
70 map.resource('user', 'users', controller='pylons_app.controllers.admin.users:UsersController', path_prefix='/_admin')
70 map.resource('user', 'users', controller='admin/users', path_prefix='/_admin')
71 map.resource('permission', 'permissions', controller='pylons_app.controllers.admin.permissions:PermissionsController', path_prefix='/_admin')
71 map.resource('permission', 'permissions', controller='admin/permissions', path_prefix='/_admin')
72 map.resource('setting', 'settings', controller='admin/settings', path_prefix='/_admin', name_prefix='admin_')
72
73
73 #ADMIN
74 #ADMIN
74 with map.submapper(path_prefix='/_admin', controller='pylons_app.controllers.admin.admin:AdminController') as m:
75 with map.submapper(path_prefix='/_admin', controller='admin/admin') as m:
75 m.connect('admin_home', '', action='index')#main page
76 m.connect('admin_home', '', action='index')#main page
76 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
77 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
77 action='add_repo')
78 action='add_repo')
78
79
79 #FEEDS
80 #FEEDS
80 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
81 map.connect('rss_feed_home', '/{repo_name:.*}/feed/rss',
81 controller='feed', action='rss',
82 controller='feed', action='rss',
82 conditions=dict(function=check_repo))
83 conditions=dict(function=check_repo))
83 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
84 map.connect('atom_feed_home', '/{repo_name:.*}/feed/atom',
84 controller='feed', action='atom',
85 controller='feed', action='atom',
85 conditions=dict(function=check_repo))
86 conditions=dict(function=check_repo))
86
87
87 #LOGIN/LOGOUT
88 #LOGIN/LOGOUT
88 map.connect('login_home', '/login', controller='login')
89 map.connect('login_home', '/login', controller='login')
89 map.connect('logout_home', '/logout', controller='login', action='logout')
90 map.connect('logout_home', '/logout', controller='login', action='logout')
90
91
91 #OTHERS
92 #OTHERS
92 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
93 map.connect('changeset_home', '/{repo_name:.*}/changeset/{revision}',
93 controller='changeset', revision='tip',
94 controller='changeset', revision='tip',
94 conditions=dict(function=check_repo))
95 conditions=dict(function=check_repo))
95 map.connect('summary_home', '/{repo_name:.*}/summary',
96 map.connect('summary_home', '/{repo_name:.*}/summary',
96 controller='summary', conditions=dict(function=check_repo))
97 controller='summary', conditions=dict(function=check_repo))
97 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
98 map.connect('shortlog_home', '/{repo_name:.*}/shortlog',
98 controller='shortlog', conditions=dict(function=check_repo))
99 controller='shortlog', conditions=dict(function=check_repo))
99 map.connect('branches_home', '/{repo_name:.*}/branches',
100 map.connect('branches_home', '/{repo_name:.*}/branches',
100 controller='branches', conditions=dict(function=check_repo))
101 controller='branches', conditions=dict(function=check_repo))
101 map.connect('tags_home', '/{repo_name:.*}/tags',
102 map.connect('tags_home', '/{repo_name:.*}/tags',
102 controller='tags', conditions=dict(function=check_repo))
103 controller='tags', conditions=dict(function=check_repo))
103 map.connect('changelog_home', '/{repo_name:.*}/changelog',
104 map.connect('changelog_home', '/{repo_name:.*}/changelog',
104 controller='changelog', conditions=dict(function=check_repo))
105 controller='changelog', conditions=dict(function=check_repo))
105 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
106 map.connect('files_home', '/{repo_name:.*}/files/{revision}/{f_path:.*}',
106 controller='files', revision='tip', f_path='',
107 controller='files', revision='tip', f_path='',
107 conditions=dict(function=check_repo))
108 conditions=dict(function=check_repo))
108 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
109 map.connect('files_diff_home', '/{repo_name:.*}/diff/{f_path:.*}',
109 controller='files', action='diff', revision='tip', f_path='',
110 controller='files', action='diff', revision='tip', f_path='',
110 conditions=dict(function=check_repo))
111 conditions=dict(function=check_repo))
111 map.connect('files_raw_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
112 map.connect('files_raw_home', '/{repo_name:.*}/rawfile/{revision}/{f_path:.*}',
112 controller='files', action='rawfile', revision='tip', f_path='',
113 controller='files', action='rawfile', revision='tip', f_path='',
113 conditions=dict(function=check_repo))
114 conditions=dict(function=check_repo))
114 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
115 map.connect('files_annotate_home', '/{repo_name:.*}/annotate/{revision}/{f_path:.*}',
115 controller='files', action='annotate', revision='tip', f_path='',
116 controller='files', action='annotate', revision='tip', f_path='',
116 conditions=dict(function=check_repo))
117 conditions=dict(function=check_repo))
117 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
118 map.connect('files_archive_home', '/{repo_name:.*}/archive/{revision}/{fileformat}',
118 controller='files', action='archivefile', revision='tip',
119 controller='files', action='archivefile', revision='tip',
119 conditions=dict(function=check_repo))
120 conditions=dict(function=check_repo))
120 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
121 map.connect('repo_settings_update', '/{repo_name:.*}/settings',
121 controller='settings', action="update",
122 controller='settings', action="update",
122 conditions=dict(method=["PUT"], function=check_repo))
123 conditions=dict(method=["PUT"], function=check_repo))
123 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
124 map.connect('repo_settings_home', '/{repo_name:.*}/settings',
124 controller='settings', action='index',
125 controller='settings', action='index',
125 conditions=dict(function=check_repo))
126 conditions=dict(function=check_repo))
126
127
127
128
128 return map
129 return map
@@ -1,45 +1,45 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Users administration')}
5 ${_('Users administration')}
6 </%def>
6 </%def>
7 <%def name="breadcrumbs()">
7 <%def name="breadcrumbs()">
8 ${h.link_to(u'Admin',h.url('admin_home'))}
8 ${h.link_to(u'Admin',h.url('admin_home'))}
9 /
9 /
10 ${_('Users')}
10 ${_('Users')}
11 </%def>
11 </%def>
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 ${self.submenu('users')}
14 ${self.submenu('users')}
15 </%def>
15 </%def>
16 <%def name="main()">
16 <%def name="main()">
17 <div>
17 <div>
18 <h2>${_('Mercurial users')}</h2>
18 <h2>${_('Users administration')}</h2>
19 <table class="table_disp">
19 <table class="table_disp">
20 <tr class="header">
20 <tr class="header">
21 <td>${_('username')}</td>
21 <td>${_('username')}</td>
22 <td>${_('name')}</td>
22 <td>${_('name')}</td>
23 <td>${_('lastname')}</td>
23 <td>${_('lastname')}</td>
24 <td>${_('active')}</td>
24 <td>${_('active')}</td>
25 <td>${_('admin')}</td>
25 <td>${_('admin')}</td>
26 <td>${_('action')}</td>
26 <td>${_('action')}</td>
27 </tr>
27 </tr>
28 %for user in c.users_list:
28 %for user in c.users_list:
29 <tr>
29 <tr>
30 <td>${h.link_to(user.username,h.url('edit_user', id=user.user_id))}</td>
30 <td>${h.link_to(user.username,h.url('edit_user', id=user.user_id))}</td>
31 <td>${user.name}</td>
31 <td>${user.name}</td>
32 <td>${user.lastname}</td>
32 <td>${user.lastname}</td>
33 <td>${user.active}</td>
33 <td>${user.active}</td>
34 <td>${user.admin}</td>
34 <td>${user.admin}</td>
35 <td>
35 <td>
36 ${h.form(url('user', id=user.user_id),method='delete')}
36 ${h.form(url('user', id=user.user_id),method='delete')}
37 ${h.submit('remove','delete',class_="delete_icon action_button")}
37 ${h.submit('remove','delete',class_="delete_icon action_button")}
38 ${h.end_form()}
38 ${h.end_form()}
39 </td>
39 </td>
40 </tr>
40 </tr>
41 %endfor
41 %endfor
42 </table>
42 </table>
43 <span class="add_icon">${h.link_to(u'add user',h.url('new_user'))}</span>
43 <span class="add_icon">${h.link_to(u'add user',h.url('new_user'))}</span>
44 </div>
44 </div>
45 </%def>
45 </%def>
@@ -1,164 +1,164 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 <head>
4 <head>
5 <link rel="icon" href="/images/hgicon.png" type="image/png" />
5 <link rel="icon" href="/images/hgicon.png" type="image/png" />
6 <meta name="robots" content="index, nofollow"/>
6 <meta name="robots" content="index, nofollow"/>
7 <title>${next.title()}</title>
7 <title>${next.title()}</title>
8 ##For future use yui reset for cross browser compatability.
8 ##For future use yui reset for cross browser compatability.
9 ##<link rel="stylesheet" href="/js/yui/reset-fonts-grids/reset-fonts-grids.css" type="text/css" />
9 ##<link rel="stylesheet" href="/js/yui/reset-fonts-grids/reset-fonts-grids.css" type="text/css" />
10 ${self.css()}
10 ${self.css()}
11 ${self.js()}
11 ${self.js()}
12 </head>
12 </head>
13
13
14 <body class="mainbody">
14 <body class="mainbody">
15 <div id="container">
15 <div id="container">
16 <div class="page-header">
16 <div class="page-header">
17 <h1 class="breadcrumbs">${next.breadcrumbs()}</h1>
17 <h1 class="breadcrumbs">${next.breadcrumbs()}</h1>
18 ${self.page_nav()}
18 ${self.page_nav()}
19 <div class="flash_msg">
19 <div class="flash_msg">
20 <% messages = h.flash.pop_messages() %>
20 <% messages = h.flash.pop_messages() %>
21 % if messages:
21 % if messages:
22 <ul id="flash-messages">
22 <ul id="flash-messages">
23 % for message in messages:
23 % for message in messages:
24 <li class="${message.category}_msg">${message}</li>
24 <li class="${message.category}_msg">${message}</li>
25 % endfor
25 % endfor
26 </ul>
26 </ul>
27 % endif
27 % endif
28 </div>
28 </div>
29 <div id="main">
29 <div id="main">
30 ${next.main()}
30 ${next.main()}
31 <script type="text/javascript">${h.tooltip.activate()}</script>
31 <script type="text/javascript">${h.tooltip.activate()}</script>
32 </div>
32 </div>
33 <div class="page-footer">
33 <div class="page-footer">
34 Hg App ${c.hg_app_version} &copy; 2010 by Marcin Kuzminski
34 Hg App ${c.hg_app_version} &copy; 2010 by Marcin Kuzminski
35 </div>
35 </div>
36
36
37 <div id="powered-by">
37 <div id="powered-by">
38 <p>
38 <p>
39 <a href="http://mercurial.selenic.com/" title="Mercurial">
39 <a href="http://mercurial.selenic.com/" title="Mercurial">
40 <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
40 <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
41 </p>
41 </p>
42 </div>
42 </div>
43
43
44 <div id="corner-top-left"></div>
44 <div id="corner-top-left"></div>
45 <div id="corner-top-right"></div>
45 <div id="corner-top-right"></div>
46 <div id="corner-bottom-left"></div>
46 <div id="corner-bottom-left"></div>
47 <div id="corner-bottom-right"></div>
47 <div id="corner-bottom-right"></div>
48
48
49 </div>
49 </div>
50 </body>
50 </body>
51 </html>
51 </html>
52
52
53 ### MAKO DEFS ###
53 ### MAKO DEFS ###
54
54
55 <%def name="page_nav()">
55 <%def name="page_nav()">
56 ${self.menu()}
56 ${self.menu()}
57 ${self.submenu()}
57 ${self.submenu()}
58 </%def>
58 </%def>
59
59
60 <%def name="menu(current)">
60 <%def name="menu(current)">
61 <%
61 <%
62 def is_current(selected):
62 def is_current(selected):
63 if selected == current:
63 if selected == current:
64 return "class='current'"
64 return "class='current'"
65 %>
65 %>
66 %if current not in ['home','admin']:
66 %if current not in ['home','admin']:
67 ##regular menu
67 ##regular menu
68 <script type="text/javascript">
68 <script type="text/javascript">
69 YAHOO.util.Event.onDOMReady(function(){
69 YAHOO.util.Event.onDOMReady(function(){
70 YAHOO.util.Event.addListener('repo_switcher','click',function(){
70 YAHOO.util.Event.addListener('repo_switcher','click',function(){
71 if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
71 if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
72 YAHOO.util.Dom.setStyle('switch_repos','display','none');
72 YAHOO.util.Dom.setStyle('switch_repos','display','none');
73 YAHOO.util.Dom.setStyle('repo_switcher','background','');
73 YAHOO.util.Dom.setStyle('repo_switcher','background','');
74 YAHOO.util.Dom.removeClass('repo_switcher','selected');
74 YAHOO.util.Dom.removeClass('repo_switcher','selected');
75 YAHOO.util.Dom.get('repo_switcher').removeAttribute('style');
75 YAHOO.util.Dom.get('repo_switcher').removeAttribute('style');
76 }
76 }
77 else{
77 else{
78 YAHOO.util.Dom.setStyle('switch_repos','display','');
78 YAHOO.util.Dom.setStyle('switch_repos','display','');
79 YAHOO.util.Dom.setStyle('repo_switcher','background','#FFFFFF');
79 YAHOO.util.Dom.setStyle('repo_switcher','background','#FFFFFF');
80 YAHOO.util.Dom.setStyle('repo_switcher','color','#556CB5');
80 YAHOO.util.Dom.setStyle('repo_switcher','color','#556CB5');
81 YAHOO.util.Dom.addClass('repo_switcher','selected');
81 YAHOO.util.Dom.addClass('repo_switcher','selected');
82 }
82 }
83 });
83 });
84 YAHOO.util.Event.addListener('repos_list','change',function(e){
84 YAHOO.util.Event.addListener('repos_list','change',function(e){
85 var wa = YAHOO.util.Dom.get('repos_list').value;
85 var wa = YAHOO.util.Dom.get('repos_list').value;
86
86
87 var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
87 var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
88 window.location = url;
88 window.location = url;
89 })
89 })
90 });
90 });
91 </script>
91 </script>
92 <ul class="page-nav">
92 <ul class="page-nav">
93 <li>
93 <li>
94 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
94 <a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
95 <div id="switch_repos" style="display:none;position: absolute;height: 25px">
95 <div id="switch_repos" style="display:none;position: absolute;height: 25px">
96 <select id="repos_list" size="=10" style="min-width: 150px">
96 <select id="repos_list" size="=10" style="min-width: 150px">
97 %for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
97 %for repo in sorted(x.name.lower() for x in c.cached_repo_list.values()):
98 <option value="${repo}">${repo}</option>
98 <option value="${repo}">${repo}</option>
99 %endfor
99 %endfor
100 </select>
100 </select>
101 </div>
101 </div>
102 </li>
102 </li>
103 <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
103 <li ${is_current('summary')}>${h.link_to(_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
104 <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
104 <li ${is_current('shortlog')}>${h.link_to(_('shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</li>
105 <li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>
105 <li ${is_current('changelog')}>${h.link_to(_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>
106 <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
106 <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
107 <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
107 <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
108 <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
108 <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
109 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
109 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
110 <li ${is_current('settings')}>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name))}</li>
110 <li ${is_current('settings')}>${h.link_to(_('settings'),h.url('repo_settings_home',repo_name=c.repo_name))}</li>
111 %endif
111 %endif
112 </ul>
112 </ul>
113 %else:
113 %else:
114 ##Root menu
114 ##Root menu
115 <ul class="page-nav">
115 <ul class="page-nav">
116 <li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
116 <li ${is_current('home')}>${h.link_to(_('Home'),h.url('/'))}</li>
117 %if h.HasPermissionAll('hg.admin')('access admin main page'):
117 %if h.HasPermissionAll('hg.admin')('access admin main page'):
118 <li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
118 <li ${is_current('admin')}>${h.link_to(_('Admin'),h.url('admin_home'))}</li>
119 %endif
119 %endif
120 <li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
120 <li class="logout">${h.link_to(u'Logout',h.url('logout_home'))}</li>
121 </ul>
121 </ul>
122 %endif
122 %endif
123 </div>
123 </div>
124 </%def>
124 </%def>
125 <%def name="submenu(current=None)">
125 <%def name="submenu(current=None)">
126 <%
126 <%
127 def is_current(selected):
127 def is_current(selected):
128 if selected == current:
128 if selected == current:
129 return "class='current_submenu'"
129 return "class='current_submenu'"
130 %>
130 %>
131 %if current != None:
131 %if current != None:
132 <div>
132 <div>
133 <ul class="submenu">
133 <ul class="submenu">
134 <li ${is_current('repos')}>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
134 <li ${is_current('repos')}>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
135 <li ${is_current('users')}>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
135 <li ${is_current('users')}>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
136 ##commented<li ${is_current('permissions')}>${h.link_to(_('permissions'),h.url('permissions'),class_='permissions')}</li>
136 ##commented<li ${is_current('permissions')}>${h.link_to(_('permissions'),h.url('permissions'),class_='permissions')}</li>
137 ##commented<li ${is_current('settings')}>${h.link_to(_('settings'),h.url('hgapp_settings'),class_='settings')}</li>
137 <li ${is_current('settings')}>${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
138 </ul>
138 </ul>
139 </div>
139 </div>
140 %endif
140 %endif
141 </%def>
141 </%def>
142
142
143
143
144 <%def name="css()">
144 <%def name="css()">
145 <link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
145 <link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
146 </%def>
146 </%def>
147
147
148 <%def name="js()">
148 <%def name="js()">
149 <script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
149 <script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
150 <script type="text/javascript" src="/js/yui/container/container-min.js"></script>
150 <script type="text/javascript" src="/js/yui/container/container-min.js"></script>
151 <script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
151 <script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
152 <script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
152 <script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
153 </%def>
153 </%def>
154
154
155 <!-- DEFINITION OF FORM ERROR FETCHER -->
155 <!-- DEFINITION OF FORM ERROR FETCHER -->
156 <%def name="get_form_error(element)">
156 <%def name="get_form_error(element)">
157 %if hasattr(c,'form_errors') and type(c.form_errors) == dict:
157 %if hasattr(c,'form_errors') and type(c.form_errors) == dict:
158 %if c.form_errors.get(element,False):
158 %if c.form_errors.get(element,False):
159 <span class="error-message">
159 <span class="error-message">
160 ${c.form_errors.get(element,'')}
160 ${c.form_errors.get(element,'')}
161 </span>
161 </span>
162 %endif
162 %endif
163 %endif
163 %endif
164 </%def> No newline at end of file
164 </%def>
General Comments 0
You need to be logged in to leave comments. Login now