@@ -0,0 +1,38 | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2018-2019 RhodeCode GmbH | |||
|
4 | # | |||
|
5 | # This program is free software: you can redistribute it and/or modify | |||
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU Affero General Public License | |||
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | from rhodecode.config import routing_links | |||
|
21 | ||||
|
22 | ||||
|
23 | def includeme(config): | |||
|
24 | ||||
|
25 | config.add_route( | |||
|
26 | name='hovercard_user', | |||
|
27 | pattern='/_hovercard/user/{user_id}') | |||
|
28 | ||||
|
29 | config.add_route( | |||
|
30 | name='hovercard_user_group', | |||
|
31 | pattern='/_hovercard/user_group/{user_group_id}') | |||
|
32 | ||||
|
33 | config.add_route( | |||
|
34 | name='hovercard_commit', | |||
|
35 | pattern='/_hovercard/commit/{repo_name}/{user_id}') | |||
|
36 | ||||
|
37 | # Scan module for configuration decorators. | |||
|
38 | config.scan('.views', ignore='.tests') |
@@ -0,0 +1,71 | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | # Copyright (C) 2016-2019 RhodeCode GmbH | |||
|
4 | # | |||
|
5 | # This program is free software: you can redistribute it and/or modify | |||
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |||
|
7 | # (only), as published by the Free Software Foundation. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU Affero General Public License | |||
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
16 | # | |||
|
17 | # This program is dual-licensed. If you wish to learn more about the | |||
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |||
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |||
|
20 | ||||
|
21 | import re | |||
|
22 | import logging | |||
|
23 | import collections | |||
|
24 | ||||
|
25 | from pyramid.view import view_config | |||
|
26 | ||||
|
27 | from rhodecode.apps._base import BaseAppView | |||
|
28 | from rhodecode.lib import helpers as h | |||
|
29 | from rhodecode.lib.auth import ( | |||
|
30 | LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, CSRFRequired) | |||
|
31 | from rhodecode.lib.codeblocks import filenode_as_lines_tokens | |||
|
32 | from rhodecode.lib.index import searcher_from_config | |||
|
33 | from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int | |||
|
34 | from rhodecode.lib.ext_json import json | |||
|
35 | from rhodecode.lib.vcs.nodes import FileNode | |||
|
36 | from rhodecode.model.db import ( | |||
|
37 | func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup) | |||
|
38 | from rhodecode.model.repo import RepoModel | |||
|
39 | from rhodecode.model.repo_group import RepoGroupModel | |||
|
40 | from rhodecode.model.scm import RepoGroupList, RepoList | |||
|
41 | from rhodecode.model.user import UserModel | |||
|
42 | from rhodecode.model.user_group import UserGroupModel | |||
|
43 | ||||
|
44 | log = logging.getLogger(__name__) | |||
|
45 | ||||
|
46 | ||||
|
47 | class HoverCardsView(BaseAppView): | |||
|
48 | ||||
|
49 | def load_default_context(self): | |||
|
50 | c = self._get_local_tmpl_context() | |||
|
51 | return c | |||
|
52 | ||||
|
53 | @LoginRequired() | |||
|
54 | @view_config( | |||
|
55 | route_name='hovercard_user', request_method='GET', xhr=True, | |||
|
56 | renderer='rhodecode:templates/hovercards/hovercard_user.mako') | |||
|
57 | def hovercard_user(self): | |||
|
58 | c = self.load_default_context() | |||
|
59 | user_id = self.request.matchdict['user_id'] | |||
|
60 | c.user = User.get_or_404(user_id) | |||
|
61 | return self._get_template_context(c) | |||
|
62 | ||||
|
63 | @LoginRequired() | |||
|
64 | @view_config( | |||
|
65 | route_name='hovercard_user_group', request_method='GET', xhr=True, | |||
|
66 | renderer='rhodecode:templates/hovercards/hovercard_user_group.mako') | |||
|
67 | def hovercard_user_group(self): | |||
|
68 | c = self.load_default_context() | |||
|
69 | user_group_id = self.request.matchdict['user_group_id'] | |||
|
70 | c.user_group = UserGroup.get_or_404(user_group_id) | |||
|
71 | return self._get_template_context(c) |
@@ -0,0 +1,460 | |||||
|
1 | /* This is the core CSS of Tooltipster */ | |||
|
2 | ||||
|
3 | /* GENERAL STRUCTURE RULES (do not edit this section) */ | |||
|
4 | ||||
|
5 | .tooltipster-base { | |||
|
6 | /* this ensures that a constrained height set by functionPosition, | |||
|
7 | if greater that the natural height of the tooltip, will be enforced | |||
|
8 | in browsers that support display:flex */ | |||
|
9 | display: flex; | |||
|
10 | pointer-events: none; | |||
|
11 | /* this may be overriden in JS for fixed position origins */ | |||
|
12 | position: absolute; | |||
|
13 | } | |||
|
14 | ||||
|
15 | .tooltipster-box { | |||
|
16 | /* see .tooltipster-base. flex-shrink 1 is only necessary for IE10- | |||
|
17 | and flex-basis auto for IE11- (at least) */ | |||
|
18 | flex: 1 1 auto; | |||
|
19 | } | |||
|
20 | ||||
|
21 | .tooltipster-content { | |||
|
22 | /* prevents an overflow if the user adds padding to the div */ | |||
|
23 | box-sizing: border-box; | |||
|
24 | /* these make sure we'll be able to detect any overflow */ | |||
|
25 | max-height: 100%; | |||
|
26 | max-width: 100%; | |||
|
27 | overflow: auto; | |||
|
28 | } | |||
|
29 | ||||
|
30 | .tooltipster-ruler { | |||
|
31 | /* these let us test the size of the tooltip without overflowing the window */ | |||
|
32 | bottom: 0; | |||
|
33 | left: 0; | |||
|
34 | overflow: hidden; | |||
|
35 | position: fixed; | |||
|
36 | right: 0; | |||
|
37 | top: 0; | |||
|
38 | visibility: hidden; | |||
|
39 | } | |||
|
40 | ||||
|
41 | /* ANIMATIONS */ | |||
|
42 | ||||
|
43 | /* Open/close animations */ | |||
|
44 | ||||
|
45 | /* fade */ | |||
|
46 | ||||
|
47 | .tooltipster-fade { | |||
|
48 | opacity: 0; | |||
|
49 | -webkit-transition-property: opacity; | |||
|
50 | -moz-transition-property: opacity; | |||
|
51 | -o-transition-property: opacity; | |||
|
52 | -ms-transition-property: opacity; | |||
|
53 | transition-property: opacity; | |||
|
54 | } | |||
|
55 | .tooltipster-fade.tooltipster-show { | |||
|
56 | opacity: 1; | |||
|
57 | } | |||
|
58 | ||||
|
59 | /* grow */ | |||
|
60 | ||||
|
61 | .tooltipster-grow { | |||
|
62 | -webkit-transform: scale(0,0); | |||
|
63 | -moz-transform: scale(0,0); | |||
|
64 | -o-transform: scale(0,0); | |||
|
65 | -ms-transform: scale(0,0); | |||
|
66 | transform: scale(0,0); | |||
|
67 | -webkit-transition-property: -webkit-transform; | |||
|
68 | -moz-transition-property: -moz-transform; | |||
|
69 | -o-transition-property: -o-transform; | |||
|
70 | -ms-transition-property: -ms-transform; | |||
|
71 | transition-property: transform; | |||
|
72 | -webkit-backface-visibility: hidden; | |||
|
73 | } | |||
|
74 | .tooltipster-grow.tooltipster-show { | |||
|
75 | -webkit-transform: scale(1,1); | |||
|
76 | -moz-transform: scale(1,1); | |||
|
77 | -o-transform: scale(1,1); | |||
|
78 | -ms-transform: scale(1,1); | |||
|
79 | transform: scale(1,1); | |||
|
80 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); | |||
|
81 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
82 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
83 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
84 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
85 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
86 | } | |||
|
87 | ||||
|
88 | /* swing */ | |||
|
89 | ||||
|
90 | .tooltipster-swing { | |||
|
91 | opacity: 0; | |||
|
92 | -webkit-transform: rotateZ(4deg); | |||
|
93 | -moz-transform: rotateZ(4deg); | |||
|
94 | -o-transform: rotateZ(4deg); | |||
|
95 | -ms-transform: rotateZ(4deg); | |||
|
96 | transform: rotateZ(4deg); | |||
|
97 | -webkit-transition-property: -webkit-transform, opacity; | |||
|
98 | -moz-transition-property: -moz-transform; | |||
|
99 | -o-transition-property: -o-transform; | |||
|
100 | -ms-transition-property: -ms-transform; | |||
|
101 | transition-property: transform; | |||
|
102 | } | |||
|
103 | .tooltipster-swing.tooltipster-show { | |||
|
104 | opacity: 1; | |||
|
105 | -webkit-transform: rotateZ(0deg); | |||
|
106 | -moz-transform: rotateZ(0deg); | |||
|
107 | -o-transform: rotateZ(0deg); | |||
|
108 | -ms-transform: rotateZ(0deg); | |||
|
109 | transform: rotateZ(0deg); | |||
|
110 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 1); | |||
|
111 | -webkit-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); | |||
|
112 | -moz-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); | |||
|
113 | -ms-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); | |||
|
114 | -o-transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); | |||
|
115 | transition-timing-function: cubic-bezier(0.230, 0.635, 0.495, 2.4); | |||
|
116 | } | |||
|
117 | ||||
|
118 | /* fall */ | |||
|
119 | ||||
|
120 | .tooltipster-fall { | |||
|
121 | -webkit-transition-property: top; | |||
|
122 | -moz-transition-property: top; | |||
|
123 | -o-transition-property: top; | |||
|
124 | -ms-transition-property: top; | |||
|
125 | transition-property: top; | |||
|
126 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); | |||
|
127 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
128 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
129 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
130 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
131 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
132 | } | |||
|
133 | .tooltipster-fall.tooltipster-initial { | |||
|
134 | top: 0 !important; | |||
|
135 | } | |||
|
136 | .tooltipster-fall.tooltipster-show { | |||
|
137 | } | |||
|
138 | .tooltipster-fall.tooltipster-dying { | |||
|
139 | -webkit-transition-property: all; | |||
|
140 | -moz-transition-property: all; | |||
|
141 | -o-transition-property: all; | |||
|
142 | -ms-transition-property: all; | |||
|
143 | transition-property: all; | |||
|
144 | top: 0 !important; | |||
|
145 | opacity: 0; | |||
|
146 | } | |||
|
147 | ||||
|
148 | /* slide */ | |||
|
149 | ||||
|
150 | .tooltipster-slide { | |||
|
151 | -webkit-transition-property: left; | |||
|
152 | -moz-transition-property: left; | |||
|
153 | -o-transition-property: left; | |||
|
154 | -ms-transition-property: left; | |||
|
155 | transition-property: left; | |||
|
156 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1); | |||
|
157 | -webkit-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
158 | -moz-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
159 | -ms-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
160 | -o-transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
161 | transition-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1.15); | |||
|
162 | } | |||
|
163 | .tooltipster-slide.tooltipster-initial { | |||
|
164 | left: -40px !important; | |||
|
165 | } | |||
|
166 | .tooltipster-slide.tooltipster-show { | |||
|
167 | } | |||
|
168 | .tooltipster-slide.tooltipster-dying { | |||
|
169 | -webkit-transition-property: all; | |||
|
170 | -moz-transition-property: all; | |||
|
171 | -o-transition-property: all; | |||
|
172 | -ms-transition-property: all; | |||
|
173 | transition-property: all; | |||
|
174 | left: 0 !important; | |||
|
175 | opacity: 0; | |||
|
176 | } | |||
|
177 | ||||
|
178 | /* Update animations */ | |||
|
179 | ||||
|
180 | /* We use animations rather than transitions here because | |||
|
181 | transition durations may be specified in the style tag due to | |||
|
182 | animationDuration, and we try to avoid collisions and the use | |||
|
183 | of !important */ | |||
|
184 | ||||
|
185 | /* fade */ | |||
|
186 | ||||
|
187 | @keyframes tooltipster-fading { | |||
|
188 | 0% { | |||
|
189 | opacity: 0; | |||
|
190 | } | |||
|
191 | 100% { | |||
|
192 | opacity: 1; | |||
|
193 | } | |||
|
194 | } | |||
|
195 | ||||
|
196 | .tooltipster-update-fade { | |||
|
197 | animation: tooltipster-fading 400ms; | |||
|
198 | } | |||
|
199 | ||||
|
200 | /* rotate */ | |||
|
201 | ||||
|
202 | @keyframes tooltipster-rotating { | |||
|
203 | 25% { | |||
|
204 | transform: rotate(-2deg); | |||
|
205 | } | |||
|
206 | 75% { | |||
|
207 | transform: rotate(2deg); | |||
|
208 | } | |||
|
209 | 100% { | |||
|
210 | transform: rotate(0); | |||
|
211 | } | |||
|
212 | } | |||
|
213 | ||||
|
214 | .tooltipster-update-rotate { | |||
|
215 | animation: tooltipster-rotating 600ms; | |||
|
216 | } | |||
|
217 | ||||
|
218 | /* scale */ | |||
|
219 | ||||
|
220 | @keyframes tooltipster-scaling { | |||
|
221 | 50% { | |||
|
222 | transform: scale(1.1); | |||
|
223 | } | |||
|
224 | 100% { | |||
|
225 | transform: scale(1); | |||
|
226 | } | |||
|
227 | } | |||
|
228 | ||||
|
229 | .tooltipster-update-scale { | |||
|
230 | animation: tooltipster-scaling 600ms; | |||
|
231 | } | |||
|
232 | ||||
|
233 | /** | |||
|
234 | * DEFAULT STYLE OF THE SIDETIP PLUGIN | |||
|
235 | * | |||
|
236 | * All styles are "namespaced" with .tooltipster-sidetip to prevent | |||
|
237 | * conflicts between plugins. | |||
|
238 | */ | |||
|
239 | ||||
|
240 | /* .tooltipster-box */ | |||
|
241 | ||||
|
242 | .tooltipster-sidetip .tooltipster-box { | |||
|
243 | background: #565656; | |||
|
244 | border: 2px solid black; | |||
|
245 | border-radius: 4px; | |||
|
246 | } | |||
|
247 | ||||
|
248 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-box { | |||
|
249 | margin-top: 8px; | |||
|
250 | } | |||
|
251 | ||||
|
252 | .tooltipster-sidetip.tooltipster-left .tooltipster-box { | |||
|
253 | margin-right: 8px; | |||
|
254 | } | |||
|
255 | ||||
|
256 | .tooltipster-sidetip.tooltipster-right .tooltipster-box { | |||
|
257 | margin-left: 8px; | |||
|
258 | } | |||
|
259 | ||||
|
260 | .tooltipster-sidetip.tooltipster-top .tooltipster-box { | |||
|
261 | margin-bottom: 8px; | |||
|
262 | } | |||
|
263 | ||||
|
264 | /* .tooltipster-content */ | |||
|
265 | ||||
|
266 | .tooltipster-sidetip .tooltipster-content { | |||
|
267 | color: white; | |||
|
268 | line-height: 18px; | |||
|
269 | padding: 6px 14px; | |||
|
270 | } | |||
|
271 | ||||
|
272 | /* .tooltipster-arrow : will keep only the zone of .tooltipster-arrow-uncropped that | |||
|
273 | corresponds to the arrow we want to display */ | |||
|
274 | ||||
|
275 | .tooltipster-sidetip .tooltipster-arrow { | |||
|
276 | overflow: hidden; | |||
|
277 | position: absolute; | |||
|
278 | } | |||
|
279 | ||||
|
280 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow { | |||
|
281 | height: 10px; | |||
|
282 | /* half the width, for centering */ | |||
|
283 | margin-left: -10px; | |||
|
284 | top: 0; | |||
|
285 | width: 20px; | |||
|
286 | } | |||
|
287 | ||||
|
288 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow { | |||
|
289 | height: 20px; | |||
|
290 | margin-top: -10px; | |||
|
291 | right: 0; | |||
|
292 | /* top 0 to keep the arrow from overflowing .tooltipster-base when it has not | |||
|
293 | been positioned yet */ | |||
|
294 | top: 0; | |||
|
295 | width: 10px; | |||
|
296 | } | |||
|
297 | ||||
|
298 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow { | |||
|
299 | height: 20px; | |||
|
300 | margin-top: -10px; | |||
|
301 | left: 0; | |||
|
302 | /* same as .tooltipster-left .tooltipster-arrow */ | |||
|
303 | top: 0; | |||
|
304 | width: 10px; | |||
|
305 | } | |||
|
306 | ||||
|
307 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow { | |||
|
308 | bottom: 0; | |||
|
309 | height: 10px; | |||
|
310 | margin-left: -10px; | |||
|
311 | width: 20px; | |||
|
312 | } | |||
|
313 | ||||
|
314 | /* common rules between .tooltipster-arrow-background and .tooltipster-arrow-border */ | |||
|
315 | ||||
|
316 | .tooltipster-sidetip .tooltipster-arrow-background, .tooltipster-sidetip .tooltipster-arrow-border { | |||
|
317 | height: 0; | |||
|
318 | position: absolute; | |||
|
319 | width: 0; | |||
|
320 | } | |||
|
321 | ||||
|
322 | /* .tooltipster-arrow-background */ | |||
|
323 | ||||
|
324 | .tooltipster-sidetip .tooltipster-arrow-background { | |||
|
325 | border: 10px solid transparent; | |||
|
326 | } | |||
|
327 | ||||
|
328 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-background { | |||
|
329 | border-bottom-color: #565656; | |||
|
330 | left: 0; | |||
|
331 | top: 3px; | |||
|
332 | } | |||
|
333 | ||||
|
334 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-background { | |||
|
335 | border-left-color: #565656; | |||
|
336 | left: -3px; | |||
|
337 | top: 0; | |||
|
338 | } | |||
|
339 | ||||
|
340 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-background { | |||
|
341 | border-right-color: #565656; | |||
|
342 | left: 3px; | |||
|
343 | top: 0; | |||
|
344 | } | |||
|
345 | ||||
|
346 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-background { | |||
|
347 | border-top-color: #565656; | |||
|
348 | left: 0; | |||
|
349 | top: -3px; | |||
|
350 | } | |||
|
351 | ||||
|
352 | /* .tooltipster-arrow-border */ | |||
|
353 | ||||
|
354 | .tooltipster-sidetip .tooltipster-arrow-border { | |||
|
355 | border: 10px solid transparent; | |||
|
356 | left: 0; | |||
|
357 | top: 0; | |||
|
358 | } | |||
|
359 | ||||
|
360 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-border { | |||
|
361 | border-bottom-color: black; | |||
|
362 | } | |||
|
363 | ||||
|
364 | .tooltipster-sidetip.tooltipster-left .tooltipster-arrow-border { | |||
|
365 | border-left-color: black; | |||
|
366 | } | |||
|
367 | ||||
|
368 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-border { | |||
|
369 | border-right-color: black; | |||
|
370 | } | |||
|
371 | ||||
|
372 | .tooltipster-sidetip.tooltipster-top .tooltipster-arrow-border { | |||
|
373 | border-top-color: black; | |||
|
374 | } | |||
|
375 | ||||
|
376 | /* tooltipster-arrow-uncropped */ | |||
|
377 | ||||
|
378 | .tooltipster-sidetip .tooltipster-arrow-uncropped { | |||
|
379 | position: relative; | |||
|
380 | } | |||
|
381 | ||||
|
382 | .tooltipster-sidetip.tooltipster-bottom .tooltipster-arrow-uncropped { | |||
|
383 | top: -10px; | |||
|
384 | } | |||
|
385 | ||||
|
386 | .tooltipster-sidetip.tooltipster-right .tooltipster-arrow-uncropped { | |||
|
387 | left: -10px; | |||
|
388 | } | |||
|
389 | ||||
|
390 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-box { | |||
|
391 | border: none; | |||
|
392 | border-radius: 5px; | |||
|
393 | background: #fff; | |||
|
394 | box-shadow: 0 0 5px 3px rgba(0, 0, 0, .1) | |||
|
395 | } | |||
|
396 | ||||
|
397 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-box { | |||
|
398 | margin-top: 6px | |||
|
399 | } | |||
|
400 | ||||
|
401 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-box { | |||
|
402 | margin-right: 6px | |||
|
403 | } | |||
|
404 | ||||
|
405 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-box { | |||
|
406 | margin-left: 6px | |||
|
407 | } | |||
|
408 | ||||
|
409 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-box { | |||
|
410 | margin-bottom: 6px | |||
|
411 | } | |||
|
412 | ||||
|
413 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-content { | |||
|
414 | color: #8d8d8d | |||
|
415 | } | |||
|
416 | ||||
|
417 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow { | |||
|
418 | height: 6px; | |||
|
419 | margin-left: -6px; | |||
|
420 | width: 12px | |||
|
421 | } | |||
|
422 | ||||
|
423 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow, .tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow { | |||
|
424 | height: 12px; | |||
|
425 | margin-left: 0; | |||
|
426 | margin-top: -6px; | |||
|
427 | width: 6px | |||
|
428 | } | |||
|
429 | ||||
|
430 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-background { | |||
|
431 | display: none | |||
|
432 | } | |||
|
433 | ||||
|
434 | .tooltipster-sidetip.tooltipster-shadow .tooltipster-arrow-border { | |||
|
435 | border: 6px solid transparent | |||
|
436 | } | |||
|
437 | ||||
|
438 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-border { | |||
|
439 | border-bottom-color: #fff | |||
|
440 | } | |||
|
441 | ||||
|
442 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-left .tooltipster-arrow-border { | |||
|
443 | border-left-color: #fff | |||
|
444 | } | |||
|
445 | ||||
|
446 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-border { | |||
|
447 | border-right-color: #fff | |||
|
448 | } | |||
|
449 | ||||
|
450 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-top .tooltipster-arrow-border { | |||
|
451 | border-top-color: #fff | |||
|
452 | } | |||
|
453 | ||||
|
454 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-bottom .tooltipster-arrow-uncropped { | |||
|
455 | top: -6px | |||
|
456 | } | |||
|
457 | ||||
|
458 | .tooltipster-sidetip.tooltipster-shadow.tooltipster-right .tooltipster-arrow-uncropped { | |||
|
459 | left: -6px | |||
|
460 | } No newline at end of file |
@@ -0,0 +1,24 | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |||
|
3 | ||||
|
4 | <div class="user-hovercard"> | |||
|
5 | <div class="user-hovercard-header"> | |||
|
6 | ||||
|
7 | </div> | |||
|
8 | ||||
|
9 | <div class="user-hovercard-icon"> | |||
|
10 | ${base.gravatar(c.user.email, 64)} | |||
|
11 | </div> | |||
|
12 | ||||
|
13 | <div class="user-hovercard-name"> | |||
|
14 | <strong>${c.user.full_name_or_username}</strong> <br/> | |||
|
15 | <code>@${h.link_to_user(c.user.username)}</code> | |||
|
16 | ||||
|
17 | <div class="user-hovercard-bio">${dt.render_description(c.user.description, c.visual.stylify_metatags)}</div> | |||
|
18 | </div> | |||
|
19 | ||||
|
20 | <div class="user-hovercard-footer"> | |||
|
21 | ||||
|
22 | </div> | |||
|
23 | ||||
|
24 | </div> |
@@ -0,0 +1,24 | |||||
|
1 | <%namespace name="base" file="/base/base.mako"/> | |||
|
2 | <%namespace name="dt" file="/data_table/_dt_elements.mako"/> | |||
|
3 | ||||
|
4 | <div class="user-group-hovercard"> | |||
|
5 | <div class="user-group-hovercard-header"> | |||
|
6 | ||||
|
7 | </div> | |||
|
8 | ||||
|
9 | <div class="user-group-hovercard-icon"> | |||
|
10 | ${base.user_group_icon(c.user_group, 64)} | |||
|
11 | </div> | |||
|
12 | ||||
|
13 | <div class="user-group-hovercard-name"> | |||
|
14 | <strong><a href="${h.route_path('user_group_profile', user_group_name=c.user_group.users_group_name)}">${c.user_group.users_group_name}</a></strong> <br/> | |||
|
15 | Members: ${len(c.user_group.members)} | |||
|
16 | ||||
|
17 | <div class="user-group-hovercard-bio">${dt.render_description(c.user_group.user_group_description, c.visual.stylify_metatags)}</div> | |||
|
18 | </div> | |||
|
19 | ||||
|
20 | <div class="user-group-hovercard-footer"> | |||
|
21 | ||||
|
22 | </div> | |||
|
23 | ||||
|
24 | </div> |
@@ -282,6 +282,7 def includeme(config): | |||||
282 | # apps |
|
282 | # apps | |
283 | if load_all: |
|
283 | if load_all: | |
284 | config.include('rhodecode.apps._base') |
|
284 | config.include('rhodecode.apps._base') | |
|
285 | config.include('rhodecode.apps.hovercards') | |||
285 | config.include('rhodecode.apps.ops') |
|
286 | config.include('rhodecode.apps.ops') | |
286 | config.include('rhodecode.apps.admin') |
|
287 | config.include('rhodecode.apps.admin') | |
287 | config.include('rhodecode.apps.channelstream') |
|
288 | config.include('rhodecode.apps.channelstream') |
@@ -899,10 +899,9 def person_by_id(id_, show_attr="usernam | |||||
899 | return id_ |
|
899 | return id_ | |
900 |
|
900 | |||
901 |
|
901 | |||
902 | def gravatar_with_user(request, author, show_disabled=False): |
|
902 | def gravatar_with_user(request, author, show_disabled=False, tooltip=False): | |
903 | _render = request.get_partial_renderer( |
|
903 | _render = request.get_partial_renderer('rhodecode:templates/base/base.mako') | |
904 | 'rhodecode:templates/base/base.mako') |
|
904 | return _render('gravatar_with_user', author, show_disabled=show_disabled, tooltip=tooltip) | |
905 | return _render('gravatar_with_user', author, show_disabled=show_disabled) |
|
|||
906 |
|
905 | |||
907 |
|
906 | |||
908 | tags_paterns = OrderedDict(( |
|
907 | tags_paterns = OrderedDict(( | |
@@ -1625,7 +1624,7 def _process_url_func(match_obj, repo_na | |||||
1625 |
|
1624 | |||
1626 | if link_format == 'html': |
|
1625 | if link_format == 'html': | |
1627 | tmpl = ( |
|
1626 | tmpl = ( | |
1628 | '%(pref)s<a class="%(cls)s" href="%(url)s">' |
|
1627 | '%(pref)s<a class="tooltip %(cls)s" href="%(url)s" title="%(title)s">' | |
1629 | '%(issue-prefix)s%(id-repr)s' |
|
1628 | '%(issue-prefix)s%(id-repr)s' | |
1630 | '</a>') |
|
1629 | '</a>') | |
1631 | elif link_format == 'rst': |
|
1630 | elif link_format == 'rst': | |
@@ -1643,7 +1642,7 def _process_url_func(match_obj, repo_na | |||||
1643 | 'id': issue_id, |
|
1642 | 'id': issue_id, | |
1644 | 'repo': repo_name, |
|
1643 | 'repo': repo_name, | |
1645 | 'repo_name': repo_name_cleaned, |
|
1644 | 'repo_name': repo_name_cleaned, | |
1646 | 'group_name': parent_group_name |
|
1645 | 'group_name': parent_group_name, | |
1647 | } |
|
1646 | } | |
1648 | # named regex variables |
|
1647 | # named regex variables | |
1649 | named_vars.update(match_obj.groupdict()) |
|
1648 | named_vars.update(match_obj.groupdict()) | |
@@ -1660,6 +1659,7 def _process_url_func(match_obj, repo_na | |||||
1660 | 'id-repr': issue_id, |
|
1659 | 'id-repr': issue_id, | |
1661 | 'issue-prefix': entry['pref'], |
|
1660 | 'issue-prefix': entry['pref'], | |
1662 | 'serv': entry['url'], |
|
1661 | 'serv': entry['url'], | |
|
1662 | 'title': entry['desc'] | |||
1663 | } |
|
1663 | } | |
1664 | if return_raw_data: |
|
1664 | if return_raw_data: | |
1665 | return { |
|
1665 | return { |
@@ -26,6 +26,7 | |||||
26 | @import 'panels-bootstrap'; |
|
26 | @import 'panels-bootstrap'; | |
27 | @import 'panels'; |
|
27 | @import 'panels'; | |
28 | @import 'deform'; |
|
28 | @import 'deform'; | |
|
29 | @import 'tooltips'; | |||
29 |
|
30 | |||
30 | //--- BASE ------------------// |
|
31 | //--- BASE ------------------// | |
31 | .noscript-error { |
|
32 | .noscript-error { | |
@@ -2775,31 +2776,31 form.markup-form { | |||||
2775 |
|
2776 | |||
2776 | .dropzone, |
|
2777 | .dropzone, | |
2777 | .dropzone-pure { |
|
2778 | .dropzone-pure { | |
2778 |
|
|
2779 | border: 2px dashed @grey5; | |
2779 |
|
|
2780 | border-radius: 5px; | |
2780 |
|
|
2781 | background: white; | |
2781 |
|
|
2782 | min-height: 200px; | |
2782 |
|
|
2783 | padding: 54px; | |
2783 |
|
2784 | |||
2784 | .dz-message { |
|
2785 | .dz-message { | |
2785 |
|
|
2786 | font-weight: 700; | |
2786 |
|
|
2787 | text-align: center; | |
2787 |
|
|
2788 | margin: 2em 0; | |
2788 | } |
|
2789 | } | |
2789 |
|
2790 | |||
2790 | } |
|
2791 | } | |
2791 |
|
2792 | |||
2792 | .dz-preview { |
|
2793 | .dz-preview { | |
2793 |
|
|
2794 | margin: 10px 0 !important; | |
2794 |
|
|
2795 | position: relative; | |
2795 |
|
|
2796 | vertical-align: top; | |
2796 |
|
|
2797 | padding: 10px; | |
2797 |
|
|
2798 | border-bottom: 1px solid @grey5; | |
2798 | } |
|
2799 | } | |
2799 |
|
2800 | |||
2800 | .dz-filename { |
|
2801 | .dz-filename { | |
2801 |
|
|
2802 | font-weight: 700; | |
2802 |
|
|
2803 | float: left; | |
2803 | } |
|
2804 | } | |
2804 |
|
2805 | |||
2805 | .dz-sending { |
|
2806 | .dz-sending { | |
@@ -2807,15 +2808,90 form.markup-form { | |||||
2807 | } |
|
2808 | } | |
2808 |
|
2809 | |||
2809 | .dz-response { |
|
2810 | .dz-response { | |
2810 | clear:both |
|
2811 | clear: both | |
2811 | } |
|
2812 | } | |
2812 |
|
2813 | |||
2813 | .dz-filename-size { |
|
2814 | .dz-filename-size { | |
2814 |
|
|
2815 | float: right | |
2815 | } |
|
2816 | } | |
2816 |
|
2817 | |||
2817 | .dz-error-message { |
|
2818 | .dz-error-message { | |
2818 |
|
|
2819 | color: @alert2; | |
2819 |
|
|
2820 | padding-top: 10px; | |
2820 |
|
|
2821 | clear: both; | |
|
2822 | } | |||
|
2823 | ||||
|
2824 | ||||
|
2825 | .user-hovercard { | |||
|
2826 | padding: 5px; | |||
|
2827 | } | |||
|
2828 | ||||
|
2829 | .user-hovercard-icon { | |||
|
2830 | display: inline; | |||
|
2831 | padding: 0; | |||
|
2832 | box-sizing: content-box; | |||
|
2833 | border-radius: 50%; | |||
|
2834 | float: left; | |||
|
2835 | } | |||
|
2836 | ||||
|
2837 | .user-hovercard-name { | |||
|
2838 | float: right; | |||
|
2839 | vertical-align: top; | |||
|
2840 | padding-left: 10px; | |||
|
2841 | min-width: 150px; | |||
|
2842 | } | |||
|
2843 | ||||
|
2844 | .user-hovercard-bio { | |||
|
2845 | clear: both; | |||
|
2846 | padding-top: 10px; | |||
|
2847 | } | |||