##// END OF EJS Templates
base-grid-view: allow specifing custom mapping for sort columns.
marcink -
r1649:1c00b1d7 default
parent child Browse files
Show More
@@ -1,191 +1,189 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import time
22 22 import logging
23 23 from pylons import tmpl_context as c
24 24 from pyramid.httpexceptions import HTTPFound
25 25
26 26 from rhodecode.lib import helpers as h
27 27 from rhodecode.lib.utils2 import StrictAttributeDict, safe_int
28 28 from rhodecode.model import repo
29 29 from rhodecode.model.db import User
30 30 from rhodecode.model.scm import ScmModel
31 31
32 32 log = logging.getLogger(__name__)
33 33
34 34
35 35 ADMIN_PREFIX = '/_admin'
36 36 STATIC_FILE_PREFIX = '/_static'
37 37
38 38
39 39 class TemplateArgs(StrictAttributeDict):
40 40 pass
41 41
42 42
43 43 class BaseAppView(object):
44 44
45 45 def __init__(self, context, request):
46 46 self.request = request
47 47 self.context = context
48 48 self.session = request.session
49 49 self._rhodecode_user = request.user # auth user
50 50 self._rhodecode_db_user = self._rhodecode_user.get_instance()
51 51 self._maybe_needs_password_change(
52 52 request.matched_route.name, self._rhodecode_db_user)
53 53
54 54 def _maybe_needs_password_change(self, view_name, user_obj):
55 55 log.debug('Checking if user %s needs password change on view %s',
56 56 user_obj, view_name)
57 57 skip_user_views = [
58 58 'logout', 'login',
59 59 'my_account_password', 'my_account_password_update'
60 60 ]
61 61
62 62 if not user_obj:
63 63 return
64 64
65 65 if user_obj.username == User.DEFAULT_USER:
66 66 return
67 67
68 68 now = time.time()
69 69 should_change = user_obj.user_data.get('force_password_change')
70 70 change_after = safe_int(should_change) or 0
71 71 if should_change and now > change_after:
72 72 log.debug('User %s requires password change', user_obj)
73 73 h.flash('You are required to change your password', 'warning',
74 74 ignore_duplicate=True)
75 75
76 76 if view_name not in skip_user_views:
77 77 raise HTTPFound(
78 78 self.request.route_path('my_account_password'))
79 79
80 80 def _get_local_tmpl_context(self):
81 81 c = TemplateArgs()
82 82 c.auth_user = self.request.user
83 83 return c
84 84
85 85 def _register_global_c(self, tmpl_args):
86 86 """
87 87 Registers attributes to pylons global `c`
88 88 """
89 89 # TODO(marcink): remove once pyramid migration is finished
90 90 for k, v in tmpl_args.items():
91 91 setattr(c, k, v)
92 92
93 93 def _get_template_context(self, tmpl_args):
94 94 self._register_global_c(tmpl_args)
95 95
96 96 local_tmpl_args = {
97 97 'defaults': {},
98 98 'errors': {},
99 99 }
100 100 local_tmpl_args.update(tmpl_args)
101 101 return local_tmpl_args
102 102
103 103 def load_default_context(self):
104 104 """
105 105 example:
106 106
107 107 def load_default_context(self):
108 108 c = self._get_local_tmpl_context()
109 109 c.custom_var = 'foobar'
110 110 self._register_global_c(c)
111 111 return c
112 112 """
113 113 raise NotImplementedError('Needs implementation in view class')
114 114
115 115
116 116 class RepoAppView(BaseAppView):
117 117
118 118 def __init__(self, context, request):
119 119 super(RepoAppView, self).__init__(context, request)
120 120 self.db_repo = request.db_repo
121 121 self.db_repo_name = self.db_repo.repo_name
122 122 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
123 123
124 124 def _get_local_tmpl_context(self):
125 125 c = super(RepoAppView, self)._get_local_tmpl_context()
126 126 # register common vars for this type of view
127 127 c.rhodecode_db_repo = self.db_repo
128 128 c.repo_name = self.db_repo_name
129 129 c.repository_pull_requests = self.db_repo_pull_requests
130 130 return c
131 131
132 132
133 133 class DataGridAppView(object):
134 134 """
135 135 Common class to have re-usable grid rendering components
136 136 """
137 137
138 def _extract_ordering(self, request):
138 def _extract_ordering(self, request, column_map=None):
139 column_map = column_map or {}
139 140 column_index = safe_int(request.GET.get('order[0][column]'))
140 141 order_dir = request.GET.get(
141 142 'order[0][dir]', 'desc')
142 143 order_by = request.GET.get(
143 144 'columns[%s][data][sort]' % column_index, 'name_raw')
144 145
145 146 # translate datatable to DB columns
146 order_by = {
147 'first_name': 'name',
148 'last_name': 'lastname',
149 }.get(order_by) or order_by
147 order_by = column_map.get(order_by) or order_by
150 148
151 149 search_q = request.GET.get('search[value]')
152 150 return search_q, order_by, order_dir
153 151
154 152 def _extract_chunk(self, request):
155 153 start = safe_int(request.GET.get('start'), 0)
156 154 length = safe_int(request.GET.get('length'), 25)
157 155 draw = safe_int(request.GET.get('draw'))
158 156 return draw, start, length
159 157
160 158
161 159 class RepoRoutePredicate(object):
162 160 def __init__(self, val, config):
163 161 self.val = val
164 162
165 163 def text(self):
166 164 return 'repo_route = %s' % self.val
167 165
168 166 phash = text
169 167
170 168 def __call__(self, info, request):
171 169 repo_name = info['match']['repo_name']
172 170 repo_model = repo.RepoModel()
173 171 by_name_match = repo_model.get_by_repo_name(repo_name, cache=True)
174 172 # if we match quickly from database, short circuit the operation,
175 173 # and validate repo based on the type.
176 174 if by_name_match:
177 175 # register this as request object we can re-use later
178 176 request.db_repo = by_name_match
179 177 return True
180 178
181 179 by_id_match = repo_model.get_repo_by_id(repo_name)
182 180 if by_id_match:
183 181 request.db_repo = by_id_match
184 182 return True
185 183
186 184 return False
187 185
188 186
189 187 def includeme(config):
190 188 config.add_route_predicate(
191 189 'repo_route', RepoRoutePredicate)
General Comments 0
You need to be logged in to leave comments. Login now