##// END OF EJS Templates
Added lightweight dashboard option. ref #500
marcink -
r2936:62e493c7 beta
parent child Browse files
Show More
@@ -185,18 +185,23 b' class SettingsController(BaseController)'
185 sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
185 sett1 = RhodeCodeSetting.get_by_name_or_create('show_public_icon')
186 sett1.app_settings_value = \
186 sett1.app_settings_value = \
187 form_result['rhodecode_show_public_icon']
187 form_result['rhodecode_show_public_icon']
188 Session().add(sett1)
188
189
189 sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
190 sett2 = RhodeCodeSetting.get_by_name_or_create('show_private_icon')
190 sett2.app_settings_value = \
191 sett2.app_settings_value = \
191 form_result['rhodecode_show_private_icon']
192 form_result['rhodecode_show_private_icon']
193 Session().add(sett2)
192
194
193 sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
195 sett3 = RhodeCodeSetting.get_by_name_or_create('stylify_metatags')
194 sett3.app_settings_value = \
196 sett3.app_settings_value = \
195 form_result['rhodecode_stylify_metatags']
197 form_result['rhodecode_stylify_metatags']
198 Session().add(sett3)
196
199
197 Session().add(sett1)
200 sett4 = RhodeCodeSetting.get_by_name_or_create('lightweight_dashboard')
198 Session().add(sett2)
201 sett4.app_settings_value = \
199 Session().add(sett3)
202 form_result['rhodecode_lightweight_dashboard']
203 Session().add(sett4)
204
200 Session().commit()
205 Session().commit()
201 set_rhodecode_config(config)
206 set_rhodecode_config(config)
202 h.flash(_('Updated visualisation settings'),
207 h.flash(_('Updated visualisation settings'),
@@ -26,11 +26,16 b''
26 import logging
26 import logging
27
27
28 from pylons import tmpl_context as c, request
28 from pylons import tmpl_context as c, request
29 from pylons.i18n.translation import _
29 from webob.exc import HTTPBadRequest
30 from webob.exc import HTTPBadRequest
30
31
32 import rhodecode
33 from rhodecode.lib import helpers as h
34 from rhodecode.lib.ext_json import json
31 from rhodecode.lib.auth import LoginRequired
35 from rhodecode.lib.auth import LoginRequired
32 from rhodecode.lib.base import BaseController, render
36 from rhodecode.lib.base import BaseController, render
33 from rhodecode.model.db import Repository
37 from rhodecode.model.db import Repository
38 from sqlalchemy.sql.expression import func
34
39
35 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
36
41
@@ -42,9 +47,55 b' class HomeController(BaseController):'
42 super(HomeController, self).__before__()
47 super(HomeController, self).__before__()
43
48
44 def index(self):
49 def index(self):
45 c.repos_list = self.scm_model.get_repos()
46 c.groups = self.scm_model.get_repos_groups()
50 c.groups = self.scm_model.get_repos_groups()
47 c.group = None
51 c.group = None
52
53 if c.visual.lightweight_dashboard is False:
54 c.repos_list = self.scm_model.get_repos()
55 ## lightweight version of dashboard
56 else:
57 c.repos_list = Repository.query()\
58 .filter(Repository.group_id == None)\
59 .order_by(func.lower(Repository.repo_name))\
60 .all()
61 repos_data = []
62 total_records = len(c.repos_list)
63
64 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
65 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
66
67 quick_menu = lambda repo_name: (template.get_def("quick_menu")
68 .render(repo_name, _=_, h=h, c=c))
69 repo_lnk = lambda name, rtype, private, fork_of: (
70 template.get_def("repo_name")
71 .render(name, rtype, private, fork_of, short_name=False,
72 admin=False, _=_, h=h, c=c))
73 rss_lnk = lambda repo_name: (template.get_def("rss")
74 .render(repo_name, _=_, h=h, c=c))
75 atom_lnk = lambda repo_name: (template.get_def("atom")
76 .render(repo_name, _=_, h=h, c=c))
77
78 for repo in c.repos_list:
79 repos_data.append({
80 "menu": quick_menu(repo.repo_name),
81 "raw_name": repo.repo_name.lower(),
82 "name": repo_lnk(repo.repo_name, repo.repo_type,
83 repo.private, repo.fork),
84 "last_change": h.age(repo.last_db_change),
85 "desc": repo.description,
86 "owner": h.person(repo.user.username),
87 "rss": rss_lnk(repo.repo_name),
88 "atom": atom_lnk(repo.repo_name),
89 })
90
91 c.data = json.dumps({
92 "totalRecords": total_records,
93 "startIndex": 0,
94 "sort": "name",
95 "dir": "asc",
96 "records": repos_data
97 })
98
48 return render('/index.html')
99 return render('/index.html')
49
100
50 def repo_switcher(self):
101 def repo_switcher(self):
@@ -245,6 +245,7 b' class BaseController(WSGIController):'
245 c.visual.show_public_icon = str2bool(config.get('rhodecode_show_public_icon'))
245 c.visual.show_public_icon = str2bool(config.get('rhodecode_show_public_icon'))
246 c.visual.show_private_icon = str2bool(config.get('rhodecode_show_private_icon'))
246 c.visual.show_private_icon = str2bool(config.get('rhodecode_show_private_icon'))
247 c.visual.stylify_metatags = str2bool(config.get('rhodecode_stylify_metatags'))
247 c.visual.stylify_metatags = str2bool(config.get('rhodecode_stylify_metatags'))
248 c.visual.lightweight_dashboard = str2bool(config.get('rhodecode_lightweight_dashboard'))
248
249
249 c.repo_name = get_repo_slug(request)
250 c.repo_name = get_repo_slug(request)
250 c.backends = BACKENDS.keys()
251 c.backends = BACKENDS.keys()
@@ -42,7 +42,7 b' from webhelpers.html.tags import _set_in'
42 from rhodecode.lib.annotate import annotate_highlight
42 from rhodecode.lib.annotate import annotate_highlight
43 from rhodecode.lib.utils import repo_name_slug
43 from rhodecode.lib.utils import repo_name_slug
44 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
44 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
45 get_changeset_safe, datetime_to_time, time_to_datetime
45 get_changeset_safe, datetime_to_time, time_to_datetime, AttributeDict
46 from rhodecode.lib.markup_renderer import MarkupRenderer
46 from rhodecode.lib.markup_renderer import MarkupRenderer
47 from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError
47 from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError
48 from rhodecode.lib.vcs.backends.base import BaseChangeset
48 from rhodecode.lib.vcs.backends.base import BaseChangeset
@@ -856,6 +856,10 b' class Repository(Base, BaseModel):'
856 Session().add(repo)
856 Session().add(repo)
857 Session().commit()
857 Session().commit()
858
858
859 @property
860 def last_db_change(self):
861 return self.updated_on
862
859 #==========================================================================
863 #==========================================================================
860 # SCM PROPERTIES
864 # SCM PROPERTIES
861 #==========================================================================
865 #==========================================================================
@@ -254,6 +254,8 b' def ApplicationVisualisationForm():'
254 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
254 rhodecode_show_private_icon = v.StringBoolean(if_missing=False)
255 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
255 rhodecode_stylify_metatags = v.StringBoolean(if_missing=False)
256
256
257 rhodecode_lightweight_dashboard = v.StringBoolean(if_missing=False)
258
257 return _ApplicationVisualisationForm
259 return _ApplicationVisualisationForm
258
260
259
261
@@ -115,6 +115,7 b' class CachedRepoList(object):'
115 tmp_d = {}
115 tmp_d = {}
116 tmp_d['name'] = dbr.repo_name
116 tmp_d['name'] = dbr.repo_name
117 tmp_d['name_sort'] = tmp_d['name'].lower()
117 tmp_d['name_sort'] = tmp_d['name'].lower()
118 tmp_d['raw_name'] = tmp_d['name'].lower()
118 tmp_d['description'] = dbr.description
119 tmp_d['description'] = dbr.description
119 tmp_d['description_sort'] = tmp_d['description'].lower()
120 tmp_d['description_sort'] = tmp_d['description'].lower()
120 tmp_d['last_change'] = last_change
121 tmp_d['last_change'] = last_change
@@ -149,6 +150,7 b' class SimpleCachedRepoList(CachedRepoLis'
149 tmp_d = {}
150 tmp_d = {}
150 tmp_d['name'] = dbr.repo_name
151 tmp_d['name'] = dbr.repo_name
151 tmp_d['name_sort'] = tmp_d['name'].lower()
152 tmp_d['name_sort'] = tmp_d['name'].lower()
153 tmp_d['raw_name'] = tmp_d['name'].lower()
152 tmp_d['description'] = dbr.description
154 tmp_d['description'] = dbr.description
153 tmp_d['description_sort'] = tmp_d['description'].lower()
155 tmp_d['description_sort'] = tmp_d['description'].lower()
154 tmp_d['dbrepo'] = dbr.get_dict()
156 tmp_d['dbrepo'] = dbr.get_dict()
@@ -122,6 +122,17 b''
122 <!-- fields -->
122 <!-- fields -->
123
123
124 <div class="fields">
124 <div class="fields">
125 <div class="field">
126 <div class="label label-checkbox">
127 <label>${_('General')}:</label>
128 </div>
129 <div class="checkboxes">
130 <div class="checkbox">
131 ${h.checkbox('rhodecode_lightweight_dashboard','True')}
132 <label for="rhodecode_lightweight_dashboard">${_('Use lightweight dashboard')}</label>
133 </div>
134 </div>
135 </div>
125
136
126 <div class="field">
137 <div class="field">
127 <div class="label label-checkbox">
138 <div class="label label-checkbox">
@@ -76,8 +76,8 b''
76 ${h.link_to(get_name(name),h.url('summary_home',repo_name=name),class_="repo_name")}
76 ${h.link_to(get_name(name),h.url('summary_home',repo_name=name),class_="repo_name")}
77 %endif
77 %endif
78 %if fork_of:
78 %if fork_of:
79 <a href="${h.url('summary_home',repo_name=fork_of)}">
79 <a href="${h.url('summary_home',repo_name=fork_of.repo_name)}">
80 <img class="icon" alt="${_('fork')}" title="${_('Fork of')} ${fork_of}" src="${h.url('/images/icons/arrow_divide.png')}"/></a>
80 <img class="icon" alt="${_('fork')}" title="${_('Fork of')} ${fork_of.repo_name}" src="${h.url('/images/icons/arrow_divide.png')}"/></a>
81 %endif
81 %endif
82 </div>
82 </div>
83 </%def>
83 </%def>
@@ -94,6 +94,22 b''
94 </div>
94 </div>
95 </%def>
95 </%def>
96
96
97 <%def name="rss(name)">
98 %if c.rhodecode_user.username != 'default':
99 <a title="${_('Subscribe to %s rss feed')% name}" class="rss_icon" href="${h.url('rss_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"></a>
100 %else:
101 <a title="${_('Subscribe to %s rss feed')% name}" class="rss_icon" href="${h.url('rss_feed_home',repo_name=name)}"></a>
102 %endif
103 </%def>
104
105 <%def name="atom(name)">
106 %if c.rhodecode_user.username != 'default':
107 <a title="${_('Subscribe to %s atom feed')% name}" class="atom_icon" href="${h.url('atom_feed_home',repo_name=name,api_key=c.rhodecode_user.api_key)}"></a>
108 %else:
109 <a title="${_('Subscribe to %s atom feed')% name}" class="atom_icon" href="${h.url('atom_feed_home',repo_name=name)}"></a>
110 %endif
111 </%def>
112
97 <%def name="user_gravatar(email, size=24)">
113 <%def name="user_gravatar(email, size=24)">
98 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(email, size)}"/> </div>
114 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(email, size)}"/> </div>
99 </%def>
115 </%def>
@@ -59,10 +59,11 b''
59 <div id="welcome" style="display:none;text-align:center">
59 <div id="welcome" style="display:none;text-align:center">
60 <h1><a href="${h.url('home')}">${c.rhodecode_name} ${c.rhodecode_version}</a></h1>
60 <h1><a href="${h.url('home')}">${c.rhodecode_name} ${c.rhodecode_version}</a></h1>
61 </div>
61 </div>
62 <%cnt=0%>
63 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
64 % if c.visual.lightweight_dashboard is False:
65 ## old full detailed version
62 <div id='repos_list_wrap' class="yui-skin-sam">
66 <div id='repos_list_wrap' class="yui-skin-sam">
63 <%cnt=0%>
64 <%namespace name="dt" file="/data_table/_dt_elements.html"/>
65
66 <table id="repos_list">
67 <table id="repos_list">
67 <thead>
68 <thead>
68 <tr>
69 <tr>
@@ -85,7 +86,7 b''
85 </td>
86 </td>
86 ##REPO NAME AND ICONS
87 ##REPO NAME AND ICONS
87 <td class="reponame">
88 <td class="reponame">
88 ${dt.repo_name(repo['name'],repo['dbrepo']['repo_type'],repo['dbrepo']['private'],repo['dbrepo_fork'].get('repo_name'),pageargs.get('short_repo_names'))}
89 ${dt.repo_name(repo['name'],repo['dbrepo']['repo_type'],repo['dbrepo']['private'],h.AttributeDict(repo['dbrepo_fork']),pageargs.get('short_repo_names'))}
89 </td>
90 </td>
90 ##DESCRIPTION
91 ##DESCRIPTION
91 <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
92 <td><span class="tooltip" title="${h.tooltip(repo['description'])}">
@@ -106,38 +107,33 b''
106 ##
107 ##
107 <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
108 <td title="${repo['contact']}">${h.person(repo['contact'])}</td>
108 <td>
109 <td>
109 %if c.rhodecode_user.username != 'default':
110 ${dt.rss(repo['name'])}
110 <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon" href="${h.url('rss_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
111 %else:
112 <a title="${_('Subscribe to %s rss feed')%repo['name']}" class="rss_icon" href="${h.url('rss_feed_home',repo_name=repo['name'])}"></a>
113 %endif:
114 </td>
111 </td>
115 <td>
112 <td>
116 %if c.rhodecode_user.username != 'default':
113 ${dt.atom(repo['name'])}
117 <a title="${_('Subscribe to %s atom feed')%repo['name']}" class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'],api_key=c.rhodecode_user.api_key)}"></a>
118 %else:
119 <a title="${_('Subscribe to %s atom feed')%repo['name']}" class="atom_icon" href="${h.url('atom_feed_home',repo_name=repo['name'])}"></a>
120 %endif:
121 </td>
114 </td>
122 </tr>
115 </tr>
123 %endfor
116 %endfor
124 </tbody>
117 </tbody>
125 </table>
118 </table>
126 </div>
119 </div>
120 % else:
121 ## lightweight version
122 <div class="yui-skin-sam" id="repos_list_wrap"></div>
123 <div id="user-paginator" style="padding: 0px 0px 0px 0px"></div>
124 % endif
127 </div>
125 </div>
128 </div>
126 </div>
127 % if c.visual.lightweight_dashboard is False:
129 <script>
128 <script>
130 YUD.get('repo_count').innerHTML = ${cnt+1 if cnt else 0};
129 YUD.get('repo_count').innerHTML = ${cnt+1 if cnt else 0};
131 var func = function(node){
130 var func = function(node){
132 return node.parentNode.parentNode.parentNode.parentNode;
131 return node.parentNode.parentNode.parentNode.parentNode;
133 }
132 }
134
133
135 var sort_by = "name";
136 var sort_dir = "asc";
137
138 // groups table sorting
134 // groups table sorting
139 var myColumnDefs = [
135 var myColumnDefs = [
140 {key:"name",label:"${_('Group Name')}",sortable:true,
136 {key:"name",label:"${_('Group name')}",sortable:true,
141 sortOptions: { sortFunction: groupNameSort }},
137 sortOptions: { sortFunction: groupNameSort }},
142 {key:"desc",label:"${_('Description')}",sortable:true},
138 {key:"desc",label:"${_('Description')}",sortable:true},
143 ];
139 ];
@@ -152,13 +148,25 b''
152 ]
148 ]
153 };
149 };
154
150
155 var myDataTable = new YAHOO.widget.DataTable("groups_list_wrap", myColumnDefs, myDataSource,
151 var myDataTable = new YAHOO.widget.DataTable("groups_list_wrap", myColumnDefs, myDataSource,{
156 {
152 sortedBy:{key:"name",dir:"asc"},
157 sortedBy:{key:"name",dir:"asc"},
153 paginator: new YAHOO.widget.Paginator({
158 MSG_SORTASC:"${_('Click to sort ascending')}",
154 rowsPerPage: 5,
159 MSG_SORTDESC:"${_('Click to sort descending')}"
155 alwaysVisible: false,
160 }
156 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
161 );
157 pageLinks: 5,
158 containerClass: 'pagination-wh',
159 currentPageClass: 'pager_curpage',
160 pageLinkClass: 'pager_link',
161 nextPageLinkLabel: '&gt;',
162 previousPageLinkLabel: '&lt;',
163 firstPageLinkLabel: '&lt;&lt;',
164 lastPageLinkLabel: '&gt;&gt;',
165 containers:['user-paginator']
166 }),
167 MSG_SORTASC:"${_('Click to sort ascending')}",
168 MSG_SORTDESC:"${_('Click to sort descending')}"
169 });
162
170
163 // main table sorting
171 // main table sorting
164 var myColumnDefs = [
172 var myColumnDefs = [
@@ -182,6 +190,7 b''
182 myDataSource.responseSchema = {
190 myDataSource.responseSchema = {
183 fields: [
191 fields: [
184 {key:"menu"},
192 {key:"menu"},
193 //{key:"raw_name"},
185 {key:"name"},
194 {key:"name"},
186 {key:"desc"},
195 {key:"desc"},
187 {key:"last_change"},
196 {key:"last_change"},
@@ -194,7 +203,7 b''
194
203
195 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
204 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
196 {
205 {
197 sortedBy:{key:sort_by,dir:sort_dir},
206 sortedBy:{key:"name",dir:"asc"},
198 MSG_SORTASC:"${_('Click to sort ascending')}",
207 MSG_SORTASC:"${_('Click to sort ascending')}",
199 MSG_SORTDESC:"${_('Click to sort descending')}",
208 MSG_SORTDESC:"${_('Click to sort descending')}",
200 MSG_EMPTY:"${_('No records found.')}",
209 MSG_EMPTY:"${_('No records found.')}",
@@ -209,3 +218,115 b''
209 });
218 });
210
219
211 </script>
220 </script>
221 % else:
222 <script>
223 //var url = "${h.url('formatted_users', format='json')}";
224 var data = ${c.data|n};
225 var myDataSource = new YAHOO.util.DataSource(data);
226 myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
227
228 myDataSource.responseSchema = {
229 resultsList: "records",
230 fields: [
231 {key:"menu"},
232 {key:"raw_name"},
233 {key:"name"},
234 {key:"desc"},
235 //{key:"last_change"},
236 {key:"owner"},
237 {key:"rss"},
238 {key:"atom"},
239 ]
240 };
241 myDataSource.doBeforeCallback = function(req,raw,res,cb) {
242 // This is the filter function
243 var data = res.results || [],
244 filtered = [],
245 i,l;
246
247 if (req) {
248 req = req.toLowerCase();
249 for (i = 0; i<data.length; i++) {
250 var pos = data[i].raw_name.toLowerCase().indexOf(req)
251 if (pos != -1) {
252 filtered.push(data[i]);
253 }
254 }
255 res.results = filtered;
256 }
257 YUD.get('repo_count').innerHTML = res.results.length;
258 return res;
259 }
260
261 // main table sorting
262 var myColumnDefs = [
263 {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
264 {key:"name",label:"${_('Name')}",sortable:true,
265 sortOptions: { sortFunction: nameSort }},
266 {key:"desc",label:"${_('Description')}",sortable:true},
267 //{key:"last_change",label:"${_('Last Change')}",sortable:true,
268 // sortOptions: { sortFunction: ageSort }},
269 {key:"owner",label:"${_('Owner')}",sortable:true},
270 {key:"rss",label:"",sortable:false},
271 {key:"atom",label:"",sortable:false},
272 ];
273
274 var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
275 sortedBy:{key:"name",dir:"asc"},
276 paginator: new YAHOO.widget.Paginator({
277 rowsPerPage: 15,
278 alwaysVisible: false,
279 template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
280 pageLinks: 5,
281 containerClass: 'pagination-wh',
282 currentPageClass: 'pager_curpage',
283 pageLinkClass: 'pager_link',
284 nextPageLinkLabel: '&gt;',
285 previousPageLinkLabel: '&lt;',
286 firstPageLinkLabel: '&lt;&lt;',
287 lastPageLinkLabel: '&gt;&gt;',
288 containers:['user-paginator']
289 }),
290
291 MSG_SORTASC:"${_('Click to sort ascending')}",
292 MSG_SORTDESC:"${_('Click to sort descending')}",
293 MSG_EMPTY:"${_('No records found.')}",
294 MSG_ERROR:"${_('Data error.')}",
295 MSG_LOADING:"${_('Loading...')}",
296 }
297 );
298 myDataTable.subscribe('postRenderEvent',function(oArgs) {
299 tooltip_activate();
300 quick_repo_menu();
301 });
302
303 var filterTimeout = null;
304
305 updateFilter = function () {
306 // Reset timeout
307 filterTimeout = null;
308
309 // Reset sort
310 var state = myDataTable.getState();
311 state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
312
313 // Get filtered data
314 myDataSource.sendRequest(YUD.get('q_filter').value,{
315 success : myDataTable.onDataReturnInitializeTable,
316 failure : myDataTable.onDataReturnInitializeTable,
317 scope : myDataTable,
318 argument: state
319 });
320
321 };
322 YUE.on('q_filter','click',function(){
323 YUD.get('q_filter').value = '';
324 });
325
326 YUE.on('q_filter','keyup',function (e) {
327 clearTimeout(filterTimeout);
328 filterTimeout = setTimeout(updateFilter,600);
329 });
330 </script>
331 % endif
332 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now