##// END OF EJS Templates
ui: changed status icons to <i> elements instead of div.
marcink -
r3883:698bb7ce default
parent child Browse files
Show More
@@ -1,586 +1,581 b''
1 // comments.less
1 // comments.less
2 // For use in RhodeCode applications;
2 // For use in RhodeCode applications;
3 // see style guide documentation for guidelines.
3 // see style guide documentation for guidelines.
4
4
5
5
6 // Comments
6 // Comments
7 @comment-outdated-opacity: 0.6;
7 @comment-outdated-opacity: 0.6;
8
8
9 .comments {
9 .comments {
10 width: 100%;
10 width: 100%;
11 }
11 }
12
12
13 .comments-heading {
13 .comments-heading {
14 margin-bottom: -1px;
14 margin-bottom: -1px;
15 background: @grey6;
15 background: @grey6;
16 display: block;
16 display: block;
17 padding: 10px 0px;
17 padding: 10px 0px;
18 font-size: 18px
18 font-size: 18px
19 }
19 }
20
20
21 tr.inline-comments div {
21 tr.inline-comments div {
22 max-width: 100%;
22 max-width: 100%;
23
23
24 p {
24 p {
25 white-space: normal;
25 white-space: normal;
26 }
26 }
27
27
28 code, pre, .code, dd {
28 code, pre, .code, dd {
29 overflow-x: auto;
29 overflow-x: auto;
30 width: 1062px;
30 width: 1062px;
31 }
31 }
32
32
33 dd {
33 dd {
34 width: auto;
34 width: auto;
35 }
35 }
36 }
36 }
37
37
38 #injected_page_comments {
38 #injected_page_comments {
39 .comment-previous-link,
39 .comment-previous-link,
40 .comment-next-link,
40 .comment-next-link,
41 .comment-links-divider {
41 .comment-links-divider {
42 display: none;
42 display: none;
43 }
43 }
44 }
44 }
45
45
46 .add-comment {
46 .add-comment {
47 margin-bottom: 10px;
47 margin-bottom: 10px;
48 }
48 }
49 .hide-comment-button .add-comment {
49 .hide-comment-button .add-comment {
50 display: none;
50 display: none;
51 }
51 }
52
52
53 .comment-bubble {
53 .comment-bubble {
54 color: @grey4;
54 color: @grey4;
55 margin-top: 4px;
55 margin-top: 4px;
56 margin-right: 30px;
56 margin-right: 30px;
57 visibility: hidden;
57 visibility: hidden;
58 }
58 }
59
59
60 .comment-label {
60 .comment-label {
61 float: left;
61 float: left;
62
62
63 padding: 0.4em 0.4em;
63 padding: 0.4em 0.4em;
64 margin: 3px 5px 0px -10px;
64 margin: 3px 5px 0px -10px;
65 display: inline-block;
65 display: inline-block;
66 min-height: 0;
66 min-height: 0;
67
67
68 text-align: center;
68 text-align: center;
69 font-size: 10px;
69 font-size: 10px;
70 line-height: .8em;
70 line-height: .8em;
71
71
72 font-family: @text-italic;
72 font-family: @text-italic;
73 font-style: italic;
73 font-style: italic;
74 background: #fff none;
74 background: #fff none;
75 color: @grey4;
75 color: @grey4;
76 border: 1px solid @grey4;
76 border: 1px solid @grey4;
77 white-space: nowrap;
77 white-space: nowrap;
78
78
79 text-transform: uppercase;
79 text-transform: uppercase;
80 min-width: 40px;
80 min-width: 40px;
81
81
82 &.todo {
82 &.todo {
83 color: @color5;
83 color: @color5;
84 font-style: italic;
84 font-style: italic;
85 font-weight: @text-bold-italic-weight;
85 font-weight: @text-bold-italic-weight;
86 font-family: @text-bold-italic;
86 font-family: @text-bold-italic;
87 }
87 }
88
88
89 .resolve {
89 .resolve {
90 cursor: pointer;
90 cursor: pointer;
91 text-decoration: underline;
91 text-decoration: underline;
92 }
92 }
93
93
94 .resolved {
94 .resolved {
95 text-decoration: line-through;
95 text-decoration: line-through;
96 color: @color1;
96 color: @color1;
97 }
97 }
98 .resolved a {
98 .resolved a {
99 text-decoration: line-through;
99 text-decoration: line-through;
100 color: @color1;
100 color: @color1;
101 }
101 }
102 .resolve-text {
102 .resolve-text {
103 color: @color1;
103 color: @color1;
104 margin: 2px 8px;
104 margin: 2px 8px;
105 font-family: @text-italic;
105 font-family: @text-italic;
106 font-style: italic;
106 font-style: italic;
107 }
107 }
108 }
108 }
109
109
110 .has-spacer-after {
110 .has-spacer-after {
111 &:after {
111 &:after {
112 content: ' | ';
112 content: ' | ';
113 color: @grey5;
113 color: @grey5;
114 }
114 }
115 }
115 }
116
116
117 .has-spacer-before {
117 .has-spacer-before {
118 &:before {
118 &:before {
119 content: ' | ';
119 content: ' | ';
120 color: @grey5;
120 color: @grey5;
121 }
121 }
122 }
122 }
123
123
124 .comment {
124 .comment {
125
125
126 &.comment-general {
126 &.comment-general {
127 border: 1px solid @grey5;
127 border: 1px solid @grey5;
128 padding: 5px 5px 5px 5px;
128 padding: 5px 5px 5px 5px;
129 }
129 }
130
130
131 margin: @padding 0;
131 margin: @padding 0;
132 padding: 4px 0 0 0;
132 padding: 4px 0 0 0;
133 line-height: 1em;
133 line-height: 1em;
134
134
135 .rc-user {
135 .rc-user {
136 min-width: 0;
136 min-width: 0;
137 margin: 0px .5em 0 0;
137 margin: 0px .5em 0 0;
138
138
139 .user {
139 .user {
140 display: inline;
140 display: inline;
141 }
141 }
142 }
142 }
143
143
144 .meta {
144 .meta {
145 position: relative;
145 position: relative;
146 width: 100%;
146 width: 100%;
147 border-bottom: 1px solid @grey5;
147 border-bottom: 1px solid @grey5;
148 margin: -5px 0px;
148 margin: -5px 0px;
149 line-height: 24px;
149 line-height: 24px;
150
150
151 &:hover .permalink {
151 &:hover .permalink {
152 visibility: visible;
152 visibility: visible;
153 color: @rcblue;
153 color: @rcblue;
154 }
154 }
155 }
155 }
156
156
157 .author,
157 .author,
158 .date {
158 .date {
159 display: inline;
159 display: inline;
160
160
161 &:after {
161 &:after {
162 content: ' | ';
162 content: ' | ';
163 color: @grey5;
163 color: @grey5;
164 }
164 }
165 }
165 }
166
166
167 .author-general img {
167 .author-general img {
168 top: 3px;
168 top: 3px;
169 }
169 }
170 .author-inline img {
170 .author-inline img {
171 top: 3px;
171 top: 3px;
172 }
172 }
173
173
174 .status-change,
174 .status-change,
175 .permalink,
175 .permalink,
176 .changeset-status-lbl {
176 .changeset-status-lbl {
177 display: inline;
177 display: inline;
178 }
178 }
179
179
180 .permalink {
180 .permalink {
181 visibility: hidden;
181 visibility: hidden;
182 }
182 }
183
183
184 .comment-links-divider {
184 .comment-links-divider {
185 display: inline;
185 display: inline;
186 }
186 }
187
187
188 .comment-links-block {
188 .comment-links-block {
189 float:right;
189 float:right;
190 text-align: right;
190 text-align: right;
191 min-width: 85px;
191 min-width: 85px;
192
192
193 [class^="icon-"]:before,
193 [class^="icon-"]:before,
194 [class*=" icon-"]:before {
194 [class*=" icon-"]:before {
195 margin-left: 0;
195 margin-left: 0;
196 margin-right: 0;
196 margin-right: 0;
197 }
197 }
198 }
198 }
199
199
200 .comment-previous-link {
200 .comment-previous-link {
201 display: inline-block;
201 display: inline-block;
202
202
203 .arrow_comment_link{
203 .arrow_comment_link{
204 cursor: pointer;
204 cursor: pointer;
205 i {
205 i {
206 font-size:10px;
206 font-size:10px;
207 }
207 }
208 }
208 }
209 .arrow_comment_link.disabled {
209 .arrow_comment_link.disabled {
210 cursor: default;
210 cursor: default;
211 color: @grey5;
211 color: @grey5;
212 }
212 }
213 }
213 }
214
214
215 .comment-next-link {
215 .comment-next-link {
216 display: inline-block;
216 display: inline-block;
217
217
218 .arrow_comment_link{
218 .arrow_comment_link{
219 cursor: pointer;
219 cursor: pointer;
220 i {
220 i {
221 font-size:10px;
221 font-size:10px;
222 }
222 }
223 }
223 }
224 .arrow_comment_link.disabled {
224 .arrow_comment_link.disabled {
225 cursor: default;
225 cursor: default;
226 color: @grey5;
226 color: @grey5;
227 }
227 }
228 }
228 }
229
229
230 .flag_status {
231 display: inline-block;
232 margin: -2px .5em 0 .25em
233 }
234
235 .delete-comment {
230 .delete-comment {
236 display: inline-block;
231 display: inline-block;
237 color: @rcblue;
232 color: @rcblue;
238
233
239 &:hover {
234 &:hover {
240 cursor: pointer;
235 cursor: pointer;
241 }
236 }
242 }
237 }
243
238
244 .text {
239 .text {
245 clear: both;
240 clear: both;
246 .border-radius(@border-radius);
241 .border-radius(@border-radius);
247 .box-sizing(border-box);
242 .box-sizing(border-box);
248
243
249 .markdown-block p,
244 .markdown-block p,
250 .rst-block p {
245 .rst-block p {
251 margin: .5em 0 !important;
246 margin: .5em 0 !important;
252 // TODO: lisa: This is needed because of other rst !important rules :[
247 // TODO: lisa: This is needed because of other rst !important rules :[
253 }
248 }
254 }
249 }
255
250
256 .pr-version {
251 .pr-version {
257 float: left;
252 float: left;
258 margin: 0px 4px;
253 margin: 0px 4px;
259 }
254 }
260 .pr-version-inline {
255 .pr-version-inline {
261 float: left;
256 float: left;
262 margin: 0px 4px;
257 margin: 0px 4px;
263 }
258 }
264 .pr-version-num {
259 .pr-version-num {
265 font-size: 10px;
260 font-size: 10px;
266 }
261 }
267 }
262 }
268
263
269 @comment-padding: 5px;
264 @comment-padding: 5px;
270
265
271 .general-comments {
266 .general-comments {
272 .comment-outdated {
267 .comment-outdated {
273 opacity: @comment-outdated-opacity;
268 opacity: @comment-outdated-opacity;
274 }
269 }
275 }
270 }
276
271
277 .inline-comments {
272 .inline-comments {
278 border-radius: @border-radius;
273 border-radius: @border-radius;
279 .comment {
274 .comment {
280 margin: 0;
275 margin: 0;
281 border-radius: @border-radius;
276 border-radius: @border-radius;
282 }
277 }
283 .comment-outdated {
278 .comment-outdated {
284 opacity: @comment-outdated-opacity;
279 opacity: @comment-outdated-opacity;
285 }
280 }
286
281
287 .comment-inline {
282 .comment-inline {
288 background: white;
283 background: white;
289 padding: @comment-padding @comment-padding;
284 padding: @comment-padding @comment-padding;
290 border: @comment-padding solid @grey6;
285 border: @comment-padding solid @grey6;
291
286
292 .text {
287 .text {
293 border: none;
288 border: none;
294 }
289 }
295 .meta {
290 .meta {
296 border-bottom: 1px solid @grey6;
291 border-bottom: 1px solid @grey6;
297 margin: -5px 0px;
292 margin: -5px 0px;
298 line-height: 24px;
293 line-height: 24px;
299 }
294 }
300 }
295 }
301 .comment-selected {
296 .comment-selected {
302 border-left: 6px solid @comment-highlight-color;
297 border-left: 6px solid @comment-highlight-color;
303 }
298 }
304 .comment-inline-form {
299 .comment-inline-form {
305 padding: @comment-padding;
300 padding: @comment-padding;
306 display: none;
301 display: none;
307 }
302 }
308 .cb-comment-add-button {
303 .cb-comment-add-button {
309 margin: @comment-padding;
304 margin: @comment-padding;
310 }
305 }
311 /* hide add comment button when form is open */
306 /* hide add comment button when form is open */
312 .comment-inline-form-open ~ .cb-comment-add-button {
307 .comment-inline-form-open ~ .cb-comment-add-button {
313 display: none;
308 display: none;
314 }
309 }
315 .comment-inline-form-open {
310 .comment-inline-form-open {
316 display: block;
311 display: block;
317 }
312 }
318 /* hide add comment button when form but no comments */
313 /* hide add comment button when form but no comments */
319 .comment-inline-form:first-child + .cb-comment-add-button {
314 .comment-inline-form:first-child + .cb-comment-add-button {
320 display: none;
315 display: none;
321 }
316 }
322 /* hide add comment button when no comments or form */
317 /* hide add comment button when no comments or form */
323 .cb-comment-add-button:first-child {
318 .cb-comment-add-button:first-child {
324 display: none;
319 display: none;
325 }
320 }
326 /* hide add comment button when only comment is being deleted */
321 /* hide add comment button when only comment is being deleted */
327 .comment-deleting:first-child + .cb-comment-add-button {
322 .comment-deleting:first-child + .cb-comment-add-button {
328 display: none;
323 display: none;
329 }
324 }
330 }
325 }
331
326
332
327
333 .show-outdated-comments {
328 .show-outdated-comments {
334 display: inline;
329 display: inline;
335 color: @rcblue;
330 color: @rcblue;
336 }
331 }
337
332
338 // Comment Form
333 // Comment Form
339 div.comment-form {
334 div.comment-form {
340 margin-top: 20px;
335 margin-top: 20px;
341 }
336 }
342
337
343 .comment-form strong {
338 .comment-form strong {
344 display: block;
339 display: block;
345 margin-bottom: 15px;
340 margin-bottom: 15px;
346 }
341 }
347
342
348 .comment-form textarea {
343 .comment-form textarea {
349 width: 100%;
344 width: 100%;
350 height: 100px;
345 height: 100px;
351 font-family: @text-monospace;
346 font-family: @text-monospace;
352 }
347 }
353
348
354 form.comment-form {
349 form.comment-form {
355 margin-top: 10px;
350 margin-top: 10px;
356 margin-left: 10px;
351 margin-left: 10px;
357 }
352 }
358
353
359 .comment-inline-form .comment-block-ta,
354 .comment-inline-form .comment-block-ta,
360 .comment-form .comment-block-ta,
355 .comment-form .comment-block-ta,
361 .comment-form .preview-box {
356 .comment-form .preview-box {
362 .border-radius(@border-radius);
357 .border-radius(@border-radius);
363 .box-sizing(border-box);
358 .box-sizing(border-box);
364 background-color: white;
359 background-color: white;
365 }
360 }
366
361
367 .comment-form-submit {
362 .comment-form-submit {
368 margin-top: 5px;
363 margin-top: 5px;
369 margin-left: 525px;
364 margin-left: 525px;
370 }
365 }
371
366
372 .file-comments {
367 .file-comments {
373 display: none;
368 display: none;
374 }
369 }
375
370
376 .comment-form .preview-box.unloaded,
371 .comment-form .preview-box.unloaded,
377 .comment-inline-form .preview-box.unloaded {
372 .comment-inline-form .preview-box.unloaded {
378 height: 50px;
373 height: 50px;
379 text-align: center;
374 text-align: center;
380 padding: 20px;
375 padding: 20px;
381 background-color: white;
376 background-color: white;
382 }
377 }
383
378
384 .comment-footer {
379 .comment-footer {
385 position: relative;
380 position: relative;
386 width: 100%;
381 width: 100%;
387 min-height: 42px;
382 min-height: 42px;
388
383
389 .status_box,
384 .status_box,
390 .cancel-button {
385 .cancel-button {
391 float: left;
386 float: left;
392 display: inline-block;
387 display: inline-block;
393 }
388 }
394
389
395 .action-buttons {
390 .action-buttons {
396 float: right;
391 float: right;
397 display: inline-block;
392 display: inline-block;
398 }
393 }
399
394
400 .action-buttons-extra {
395 .action-buttons-extra {
401 display: inline-block;
396 display: inline-block;
402 }
397 }
403 }
398 }
404
399
405 .comment-form {
400 .comment-form {
406
401
407 .comment {
402 .comment {
408 margin-left: 10px;
403 margin-left: 10px;
409 }
404 }
410
405
411 .comment-help {
406 .comment-help {
412 color: @grey4;
407 color: @grey4;
413 padding: 5px 0 5px 0;
408 padding: 5px 0 5px 0;
414 }
409 }
415
410
416 .comment-title {
411 .comment-title {
417 padding: 5px 0 5px 0;
412 padding: 5px 0 5px 0;
418 }
413 }
419
414
420 .comment-button {
415 .comment-button {
421 display: inline-block;
416 display: inline-block;
422 }
417 }
423
418
424 .comment-button-input {
419 .comment-button-input {
425 margin-right: 0;
420 margin-right: 0;
426 }
421 }
427
422
428 .comment-footer {
423 .comment-footer {
429 margin-bottom: 110px;
424 margin-bottom: 110px;
430 margin-top: 10px;
425 margin-top: 10px;
431 }
426 }
432 }
427 }
433
428
434
429
435 .comment-form-login {
430 .comment-form-login {
436 .comment-help {
431 .comment-help {
437 padding: 0.7em; //same as the button
432 padding: 0.7em; //same as the button
438 }
433 }
439
434
440 div.clearfix {
435 div.clearfix {
441 clear: both;
436 clear: both;
442 width: 100%;
437 width: 100%;
443 display: block;
438 display: block;
444 }
439 }
445 }
440 }
446
441
447 .comment-type {
442 .comment-type {
448 margin: 0px;
443 margin: 0px;
449 border-radius: inherit;
444 border-radius: inherit;
450 border-color: @grey6;
445 border-color: @grey6;
451 }
446 }
452
447
453 .preview-box {
448 .preview-box {
454 min-height: 105px;
449 min-height: 105px;
455 margin-bottom: 15px;
450 margin-bottom: 15px;
456 background-color: white;
451 background-color: white;
457 .border-radius(@border-radius);
452 .border-radius(@border-radius);
458 .box-sizing(border-box);
453 .box-sizing(border-box);
459 }
454 }
460
455
461 .add-another-button {
456 .add-another-button {
462 margin-left: 10px;
457 margin-left: 10px;
463 margin-top: 10px;
458 margin-top: 10px;
464 margin-bottom: 10px;
459 margin-bottom: 10px;
465 }
460 }
466
461
467 .comment .buttons {
462 .comment .buttons {
468 float: right;
463 float: right;
469 margin: -1px 0px 0px 0px;
464 margin: -1px 0px 0px 0px;
470 }
465 }
471
466
472 // Inline Comment Form
467 // Inline Comment Form
473 .injected_diff .comment-inline-form,
468 .injected_diff .comment-inline-form,
474 .comment-inline-form {
469 .comment-inline-form {
475 background-color: white;
470 background-color: white;
476 margin-top: 10px;
471 margin-top: 10px;
477 margin-bottom: 20px;
472 margin-bottom: 20px;
478 }
473 }
479
474
480 .inline-form {
475 .inline-form {
481 padding: 10px 7px;
476 padding: 10px 7px;
482 }
477 }
483
478
484 .inline-form div {
479 .inline-form div {
485 max-width: 100%;
480 max-width: 100%;
486 }
481 }
487
482
488 .overlay {
483 .overlay {
489 display: none;
484 display: none;
490 position: absolute;
485 position: absolute;
491 width: 100%;
486 width: 100%;
492 text-align: center;
487 text-align: center;
493 vertical-align: middle;
488 vertical-align: middle;
494 font-size: 16px;
489 font-size: 16px;
495 background: none repeat scroll 0 0 white;
490 background: none repeat scroll 0 0 white;
496
491
497 &.submitting {
492 &.submitting {
498 display: block;
493 display: block;
499 opacity: 0.5;
494 opacity: 0.5;
500 z-index: 100;
495 z-index: 100;
501 }
496 }
502 }
497 }
503 .comment-inline-form .overlay.submitting .overlay-text {
498 .comment-inline-form .overlay.submitting .overlay-text {
504 margin-top: 5%;
499 margin-top: 5%;
505 }
500 }
506
501
507 .comment-inline-form .clearfix,
502 .comment-inline-form .clearfix,
508 .comment-form .clearfix {
503 .comment-form .clearfix {
509 .border-radius(@border-radius);
504 .border-radius(@border-radius);
510 margin: 0px;
505 margin: 0px;
511 }
506 }
512
507
513 .comment-inline-form .comment-footer {
508 .comment-inline-form .comment-footer {
514 margin: 10px 0px 0px 0px;
509 margin: 10px 0px 0px 0px;
515 }
510 }
516
511
517 .hide-inline-form-button {
512 .hide-inline-form-button {
518 margin-left: 5px;
513 margin-left: 5px;
519 }
514 }
520 .comment-button .hide-inline-form {
515 .comment-button .hide-inline-form {
521 background: white;
516 background: white;
522 }
517 }
523
518
524 .comment-area {
519 .comment-area {
525 padding: 8px 12px;
520 padding: 8px 12px;
526 border: 1px solid @grey5;
521 border: 1px solid @grey5;
527 .border-radius(@border-radius);
522 .border-radius(@border-radius);
528
523
529 .resolve-action {
524 .resolve-action {
530 padding: 1px 0px 0px 6px;
525 padding: 1px 0px 0px 6px;
531 }
526 }
532
527
533 }
528 }
534
529
535 .comment-area-header .nav-links {
530 .comment-area-header .nav-links {
536 display: flex;
531 display: flex;
537 flex-flow: row wrap;
532 flex-flow: row wrap;
538 -webkit-flex-flow: row wrap;
533 -webkit-flex-flow: row wrap;
539 width: 100%;
534 width: 100%;
540 }
535 }
541
536
542 .comment-area-footer {
537 .comment-area-footer {
543 display: flex;
538 display: flex;
544 }
539 }
545
540
546 .comment-footer .toolbar {
541 .comment-footer .toolbar {
547
542
548 }
543 }
549
544
550 .nav-links {
545 .nav-links {
551 padding: 0;
546 padding: 0;
552 margin: 0;
547 margin: 0;
553 list-style: none;
548 list-style: none;
554 height: auto;
549 height: auto;
555 border-bottom: 1px solid @grey5;
550 border-bottom: 1px solid @grey5;
556 }
551 }
557 .nav-links li {
552 .nav-links li {
558 display: inline-block;
553 display: inline-block;
559 list-style-type: none;
554 list-style-type: none;
560 }
555 }
561
556
562 .nav-links li a.disabled {
557 .nav-links li a.disabled {
563 cursor: not-allowed;
558 cursor: not-allowed;
564 }
559 }
565
560
566 .nav-links li.active a {
561 .nav-links li.active a {
567 border-bottom: 2px solid @rcblue;
562 border-bottom: 2px solid @rcblue;
568 color: #000;
563 color: #000;
569 font-weight: 600;
564 font-weight: 600;
570 }
565 }
571 .nav-links li a {
566 .nav-links li a {
572 display: inline-block;
567 display: inline-block;
573 padding: 0px 10px 5px 10px;
568 padding: 0px 10px 5px 10px;
574 margin-bottom: -1px;
569 margin-bottom: -1px;
575 font-size: 14px;
570 font-size: 14px;
576 line-height: 28px;
571 line-height: 28px;
577 color: #8f8f8f;
572 color: #8f8f8f;
578 border-bottom: 2px solid transparent;
573 border-bottom: 2px solid transparent;
579 }
574 }
580
575
581 .toolbar-text {
576 .toolbar-text {
582 float: left;
577 float: left;
583 margin: -5px 0px 0px 0px;
578 margin: -5px 0px 0px 0px;
584 font-size: 12px;
579 font-size: 12px;
585 }
580 }
586
581
@@ -1,2854 +1,2823 b''
1 //Primary CSS
1 //Primary CSS
2
2
3 //--- IMPORTS ------------------//
3 //--- IMPORTS ------------------//
4
4
5 @import 'helpers';
5 @import 'helpers';
6 @import 'mixins';
6 @import 'mixins';
7 @import 'rcicons';
7 @import 'rcicons';
8 @import 'variables';
8 @import 'variables';
9 @import 'bootstrap-variables';
9 @import 'bootstrap-variables';
10 @import 'form-bootstrap';
10 @import 'form-bootstrap';
11 @import 'codemirror';
11 @import 'codemirror';
12 @import 'legacy_code_styles';
12 @import 'legacy_code_styles';
13 @import 'readme-box';
13 @import 'readme-box';
14 @import 'progress-bar';
14 @import 'progress-bar';
15
15
16 @import 'type';
16 @import 'type';
17 @import 'alerts';
17 @import 'alerts';
18 @import 'buttons';
18 @import 'buttons';
19 @import 'tags';
19 @import 'tags';
20 @import 'code-block';
20 @import 'code-block';
21 @import 'examples';
21 @import 'examples';
22 @import 'login';
22 @import 'login';
23 @import 'main-content';
23 @import 'main-content';
24 @import 'select2';
24 @import 'select2';
25 @import 'comments';
25 @import 'comments';
26 @import 'panels-bootstrap';
26 @import 'panels-bootstrap';
27 @import 'panels';
27 @import 'panels';
28 @import 'deform';
28 @import 'deform';
29
29
30 //--- BASE ------------------//
30 //--- BASE ------------------//
31 .noscript-error {
31 .noscript-error {
32 top: 0;
32 top: 0;
33 left: 0;
33 left: 0;
34 width: 100%;
34 width: 100%;
35 z-index: 101;
35 z-index: 101;
36 text-align: center;
36 text-align: center;
37 font-size: 120%;
37 font-size: 120%;
38 color: white;
38 color: white;
39 background-color: @alert2;
39 background-color: @alert2;
40 padding: 5px 0 5px 0;
40 padding: 5px 0 5px 0;
41 font-weight: @text-semibold-weight;
41 font-weight: @text-semibold-weight;
42 font-family: @text-semibold;
42 font-family: @text-semibold;
43 }
43 }
44
44
45 html {
45 html {
46 display: table;
46 display: table;
47 height: 100%;
47 height: 100%;
48 width: 100%;
48 width: 100%;
49 }
49 }
50
50
51 body {
51 body {
52 display: table-cell;
52 display: table-cell;
53 width: 100%;
53 width: 100%;
54 }
54 }
55
55
56 //--- LAYOUT ------------------//
56 //--- LAYOUT ------------------//
57
57
58 .hidden{
58 .hidden{
59 display: none !important;
59 display: none !important;
60 }
60 }
61
61
62 .box{
62 .box{
63 float: left;
63 float: left;
64 width: 100%;
64 width: 100%;
65 }
65 }
66
66
67 .browser-header {
67 .browser-header {
68 clear: both;
68 clear: both;
69 }
69 }
70 .main {
70 .main {
71 clear: both;
71 clear: both;
72 padding:0 0 @pagepadding;
72 padding:0 0 @pagepadding;
73 height: auto;
73 height: auto;
74
74
75 &:after { //clearfix
75 &:after { //clearfix
76 content:"";
76 content:"";
77 clear:both;
77 clear:both;
78 width:100%;
78 width:100%;
79 display:block;
79 display:block;
80 }
80 }
81 }
81 }
82
82
83 .action-link{
83 .action-link{
84 margin-left: @padding;
84 margin-left: @padding;
85 padding-left: @padding;
85 padding-left: @padding;
86 border-left: @border-thickness solid @border-default-color;
86 border-left: @border-thickness solid @border-default-color;
87 }
87 }
88
88
89 input + .action-link, .action-link.first{
89 input + .action-link, .action-link.first{
90 border-left: none;
90 border-left: none;
91 }
91 }
92
92
93 .action-link.last{
93 .action-link.last{
94 margin-right: @padding;
94 margin-right: @padding;
95 padding-right: @padding;
95 padding-right: @padding;
96 }
96 }
97
97
98 .action-link.active,
98 .action-link.active,
99 .action-link.active a{
99 .action-link.active a{
100 color: @grey4;
100 color: @grey4;
101 }
101 }
102
102
103 .action-link.disabled {
103 .action-link.disabled {
104 color: @grey4;
104 color: @grey4;
105 cursor: inherit;
105 cursor: inherit;
106 }
106 }
107
107
108 .clipboard-action {
108 .clipboard-action {
109 cursor: pointer;
109 cursor: pointer;
110 color: @grey4;
110 color: @grey4;
111 margin-left: 5px;
111 margin-left: 5px;
112
112
113 &:hover {
113 &:hover {
114 color: @grey2;
114 color: @grey2;
115 }
115 }
116 }
116 }
117
117
118 ul.simple-list{
118 ul.simple-list{
119 list-style: none;
119 list-style: none;
120 margin: 0;
120 margin: 0;
121 padding: 0;
121 padding: 0;
122 }
122 }
123
123
124 .main-content {
124 .main-content {
125 padding-bottom: @pagepadding;
125 padding-bottom: @pagepadding;
126 }
126 }
127
127
128 .wide-mode-wrapper {
128 .wide-mode-wrapper {
129 max-width:4000px !important;
129 max-width:4000px !important;
130 }
130 }
131
131
132 .wrapper {
132 .wrapper {
133 position: relative;
133 position: relative;
134 max-width: @wrapper-maxwidth;
134 max-width: @wrapper-maxwidth;
135 margin: 0 auto;
135 margin: 0 auto;
136 }
136 }
137
137
138 #content {
138 #content {
139 clear: both;
139 clear: both;
140 padding: 0 @contentpadding;
140 padding: 0 @contentpadding;
141 }
141 }
142
142
143 .advanced-settings-fields{
143 .advanced-settings-fields{
144 input{
144 input{
145 margin-left: @textmargin;
145 margin-left: @textmargin;
146 margin-right: @padding/2;
146 margin-right: @padding/2;
147 }
147 }
148 }
148 }
149
149
150 .cs_files_title {
150 .cs_files_title {
151 margin: @pagepadding 0 0;
151 margin: @pagepadding 0 0;
152 }
152 }
153
153
154 input.inline[type="file"] {
154 input.inline[type="file"] {
155 display: inline;
155 display: inline;
156 }
156 }
157
157
158 .error_page {
158 .error_page {
159 margin: 10% auto;
159 margin: 10% auto;
160
160
161 h1 {
161 h1 {
162 color: @grey2;
162 color: @grey2;
163 }
163 }
164
164
165 .alert {
165 .alert {
166 margin: @padding 0;
166 margin: @padding 0;
167 }
167 }
168
168
169 .error-branding {
169 .error-branding {
170 color: @grey4;
170 color: @grey4;
171 font-weight: @text-semibold-weight;
171 font-weight: @text-semibold-weight;
172 font-family: @text-semibold;
172 font-family: @text-semibold;
173 }
173 }
174
174
175 .error_message {
175 .error_message {
176 font-family: @text-regular;
176 font-family: @text-regular;
177 }
177 }
178
178
179 .sidebar {
179 .sidebar {
180 min-height: 275px;
180 min-height: 275px;
181 margin: 0;
181 margin: 0;
182 padding: 0 0 @sidebarpadding @sidebarpadding;
182 padding: 0 0 @sidebarpadding @sidebarpadding;
183 border: none;
183 border: none;
184 }
184 }
185
185
186 .main-content {
186 .main-content {
187 position: relative;
187 position: relative;
188 margin: 0 @sidebarpadding @sidebarpadding;
188 margin: 0 @sidebarpadding @sidebarpadding;
189 padding: 0 0 0 @sidebarpadding;
189 padding: 0 0 0 @sidebarpadding;
190 border-left: @border-thickness solid @grey5;
190 border-left: @border-thickness solid @grey5;
191
191
192 @media (max-width:767px) {
192 @media (max-width:767px) {
193 clear: both;
193 clear: both;
194 width: 100%;
194 width: 100%;
195 margin: 0;
195 margin: 0;
196 border: none;
196 border: none;
197 }
197 }
198 }
198 }
199
199
200 .inner-column {
200 .inner-column {
201 float: left;
201 float: left;
202 width: 29.75%;
202 width: 29.75%;
203 min-height: 150px;
203 min-height: 150px;
204 margin: @sidebarpadding 2% 0 0;
204 margin: @sidebarpadding 2% 0 0;
205 padding: 0 2% 0 0;
205 padding: 0 2% 0 0;
206 border-right: @border-thickness solid @grey5;
206 border-right: @border-thickness solid @grey5;
207
207
208 @media (max-width:767px) {
208 @media (max-width:767px) {
209 clear: both;
209 clear: both;
210 width: 100%;
210 width: 100%;
211 border: none;
211 border: none;
212 }
212 }
213
213
214 ul {
214 ul {
215 padding-left: 1.25em;
215 padding-left: 1.25em;
216 }
216 }
217
217
218 &:last-child {
218 &:last-child {
219 margin: @sidebarpadding 0 0;
219 margin: @sidebarpadding 0 0;
220 border: none;
220 border: none;
221 }
221 }
222
222
223 h4 {
223 h4 {
224 margin: 0 0 @padding;
224 margin: 0 0 @padding;
225 font-weight: @text-semibold-weight;
225 font-weight: @text-semibold-weight;
226 font-family: @text-semibold;
226 font-family: @text-semibold;
227 }
227 }
228 }
228 }
229 }
229 }
230 .error-page-logo {
230 .error-page-logo {
231 width: 130px;
231 width: 130px;
232 height: 160px;
232 height: 160px;
233 }
233 }
234
234
235 // HEADER
235 // HEADER
236 .header {
236 .header {
237
237
238 // TODO: johbo: Fix login pages, so that they work without a min-height
238 // TODO: johbo: Fix login pages, so that they work without a min-height
239 // for the header and then remove the min-height. I chose a smaller value
239 // for the header and then remove the min-height. I chose a smaller value
240 // intentionally here to avoid rendering issues in the main navigation.
240 // intentionally here to avoid rendering issues in the main navigation.
241 min-height: 49px;
241 min-height: 49px;
242 min-width: 1024px;
242 min-width: 1024px;
243
243
244 position: relative;
244 position: relative;
245 vertical-align: bottom;
245 vertical-align: bottom;
246 padding: 0 @header-padding;
246 padding: 0 @header-padding;
247 background-color: @grey1;
247 background-color: @grey1;
248 color: @grey5;
248 color: @grey5;
249
249
250 .title {
250 .title {
251 overflow: visible;
251 overflow: visible;
252 }
252 }
253
253
254 &:before,
254 &:before,
255 &:after {
255 &:after {
256 content: "";
256 content: "";
257 clear: both;
257 clear: both;
258 width: 100%;
258 width: 100%;
259 }
259 }
260
260
261 // TODO: johbo: Avoids breaking "Repositories" chooser
261 // TODO: johbo: Avoids breaking "Repositories" chooser
262 .select2-container .select2-choice .select2-arrow {
262 .select2-container .select2-choice .select2-arrow {
263 display: none;
263 display: none;
264 }
264 }
265 }
265 }
266
266
267 #header-inner {
267 #header-inner {
268 &.title {
268 &.title {
269 margin: 0;
269 margin: 0;
270 }
270 }
271 &:before,
271 &:before,
272 &:after {
272 &:after {
273 content: "";
273 content: "";
274 clear: both;
274 clear: both;
275 }
275 }
276 }
276 }
277
277
278 // Gists
278 // Gists
279 #files_data {
279 #files_data {
280 clear: both; //for firefox
280 clear: both; //for firefox
281 padding-top: 10px;
281 padding-top: 10px;
282 }
282 }
283
283
284 #gistid {
284 #gistid {
285 margin-right: @padding;
285 margin-right: @padding;
286 }
286 }
287
287
288 // Global Settings Editor
288 // Global Settings Editor
289 .textarea.editor {
289 .textarea.editor {
290 float: left;
290 float: left;
291 position: relative;
291 position: relative;
292 max-width: @texteditor-width;
292 max-width: @texteditor-width;
293
293
294 select {
294 select {
295 position: absolute;
295 position: absolute;
296 top:10px;
296 top:10px;
297 right:0;
297 right:0;
298 }
298 }
299
299
300 .CodeMirror {
300 .CodeMirror {
301 margin: 0;
301 margin: 0;
302 }
302 }
303
303
304 .help-block {
304 .help-block {
305 margin: 0 0 @padding;
305 margin: 0 0 @padding;
306 padding:.5em;
306 padding:.5em;
307 background-color: @grey6;
307 background-color: @grey6;
308 &.pre-formatting {
308 &.pre-formatting {
309 white-space: pre;
309 white-space: pre;
310 }
310 }
311 }
311 }
312 }
312 }
313
313
314 ul.auth_plugins {
314 ul.auth_plugins {
315 margin: @padding 0 @padding @legend-width;
315 margin: @padding 0 @padding @legend-width;
316 padding: 0;
316 padding: 0;
317
317
318 li {
318 li {
319 margin-bottom: @padding;
319 margin-bottom: @padding;
320 line-height: 1em;
320 line-height: 1em;
321 list-style-type: none;
321 list-style-type: none;
322
322
323 .auth_buttons .btn {
323 .auth_buttons .btn {
324 margin-right: @padding;
324 margin-right: @padding;
325 }
325 }
326
326
327 }
327 }
328 }
328 }
329
329
330
330
331 // My Account PR list
331 // My Account PR list
332
332
333 #show_closed {
333 #show_closed {
334 margin: 0 1em 0 0;
334 margin: 0 1em 0 0;
335 }
335 }
336
336
337 #pull_request_list_table {
337 #pull_request_list_table {
338 .closed {
338 .closed {
339 background-color: @grey6;
339 background-color: @grey6;
340 }
340 }
341
341
342 .state-creating,
342 .state-creating,
343 .state-updating,
343 .state-updating,
344 .state-merging
344 .state-merging
345 {
345 {
346 background-color: @grey6;
346 background-color: @grey6;
347 }
347 }
348
348
349 .td-status {
349 .td-status {
350 padding-left: .5em;
350 padding-left: .5em;
351 }
351 }
352 .log-container .truncate {
352 .log-container .truncate {
353 height: 2.75em;
353 height: 2.75em;
354 white-space: pre-line;
354 white-space: pre-line;
355 }
355 }
356 table.rctable .user {
356 table.rctable .user {
357 padding-left: 0;
357 padding-left: 0;
358 }
358 }
359 table.rctable {
359 table.rctable {
360 td.td-description,
360 td.td-description,
361 .rc-user {
361 .rc-user {
362 min-width: auto;
362 min-width: auto;
363 }
363 }
364 }
364 }
365 }
365 }
366
366
367 // Pull Requests
367 // Pull Requests
368
368
369 .pullrequests_section_head {
369 .pullrequests_section_head {
370 display: block;
370 display: block;
371 clear: both;
371 clear: both;
372 margin: @padding 0;
372 margin: @padding 0;
373 font-weight: @text-bold-weight;
373 font-weight: @text-bold-weight;
374 font-family: @text-bold;
374 font-family: @text-bold;
375 }
375 }
376
376
377 .pr-origininfo, .pr-targetinfo {
377 .pr-origininfo, .pr-targetinfo {
378 position: relative;
378 position: relative;
379
379
380 .tag {
380 .tag {
381 display: inline-block;
381 display: inline-block;
382 margin: 0 1em .5em 0;
382 margin: 0 1em .5em 0;
383 }
383 }
384
384
385 .clone-url {
385 .clone-url {
386 display: inline-block;
386 display: inline-block;
387 margin: 0 0 .5em 0;
387 margin: 0 0 .5em 0;
388 padding: 0;
388 padding: 0;
389 line-height: 1.2em;
389 line-height: 1.2em;
390 }
390 }
391 }
391 }
392
392
393 .pr-mergeinfo {
393 .pr-mergeinfo {
394 min-width: 95% !important;
394 min-width: 95% !important;
395 padding: 0 !important;
395 padding: 0 !important;
396 border: 0;
396 border: 0;
397 }
397 }
398 .pr-mergeinfo-copy {
398 .pr-mergeinfo-copy {
399 padding: 0 0;
399 padding: 0 0;
400 }
400 }
401
401
402 .pr-pullinfo {
402 .pr-pullinfo {
403 min-width: 95% !important;
403 min-width: 95% !important;
404 padding: 0 !important;
404 padding: 0 !important;
405 border: 0;
405 border: 0;
406 }
406 }
407 .pr-pullinfo-copy {
407 .pr-pullinfo-copy {
408 padding: 0 0;
408 padding: 0 0;
409 }
409 }
410
410
411
411
412 #pr-title-input {
412 #pr-title-input {
413 width: 72%;
413 width: 72%;
414 font-size: 1em;
414 font-size: 1em;
415 margin: 0;
415 margin: 0;
416 padding: 0 0 0 @padding/4;
416 padding: 0 0 0 @padding/4;
417 line-height: 1.7em;
417 line-height: 1.7em;
418 color: @text-color;
418 color: @text-color;
419 letter-spacing: .02em;
419 letter-spacing: .02em;
420 font-weight: @text-bold-weight;
420 font-weight: @text-bold-weight;
421 font-family: @text-bold;
421 font-family: @text-bold;
422 }
422 }
423
423
424 #pullrequest_title {
424 #pullrequest_title {
425 width: 100%;
425 width: 100%;
426 box-sizing: border-box;
426 box-sizing: border-box;
427 }
427 }
428
428
429 #pr_open_message {
429 #pr_open_message {
430 border: @border-thickness solid #fff;
430 border: @border-thickness solid #fff;
431 border-radius: @border-radius;
431 border-radius: @border-radius;
432 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
432 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
433 text-align: left;
433 text-align: left;
434 overflow: hidden;
434 overflow: hidden;
435 }
435 }
436
436
437 .pr-submit-button {
437 .pr-submit-button {
438 float: right;
438 float: right;
439 margin: 0 0 0 5px;
439 margin: 0 0 0 5px;
440 }
440 }
441
441
442 .pr-spacing-container {
442 .pr-spacing-container {
443 padding: 20px;
443 padding: 20px;
444 clear: both
444 clear: both
445 }
445 }
446
446
447 #pr-description-input {
447 #pr-description-input {
448 margin-bottom: 0;
448 margin-bottom: 0;
449 }
449 }
450
450
451 .pr-description-label {
451 .pr-description-label {
452 vertical-align: top;
452 vertical-align: top;
453 }
453 }
454
454
455 .perms_section_head {
455 .perms_section_head {
456 min-width: 625px;
456 min-width: 625px;
457
457
458 h2 {
458 h2 {
459 margin-bottom: 0;
459 margin-bottom: 0;
460 }
460 }
461
461
462 .label-checkbox {
462 .label-checkbox {
463 float: left;
463 float: left;
464 }
464 }
465
465
466 &.field {
466 &.field {
467 margin: @space 0 @padding;
467 margin: @space 0 @padding;
468 }
468 }
469
469
470 &:first-child.field {
470 &:first-child.field {
471 margin-top: 0;
471 margin-top: 0;
472
472
473 .label {
473 .label {
474 margin-top: 0;
474 margin-top: 0;
475 padding-top: 0;
475 padding-top: 0;
476 }
476 }
477
477
478 .radios {
478 .radios {
479 padding-top: 0;
479 padding-top: 0;
480 }
480 }
481 }
481 }
482
482
483 .radios {
483 .radios {
484 position: relative;
484 position: relative;
485 width: 505px;
485 width: 505px;
486 }
486 }
487 }
487 }
488
488
489 //--- MODULES ------------------//
489 //--- MODULES ------------------//
490
490
491
491
492 // Server Announcement
492 // Server Announcement
493 #server-announcement {
493 #server-announcement {
494 width: 95%;
494 width: 95%;
495 margin: @padding auto;
495 margin: @padding auto;
496 padding: @padding;
496 padding: @padding;
497 border-width: 2px;
497 border-width: 2px;
498 border-style: solid;
498 border-style: solid;
499 .border-radius(2px);
499 .border-radius(2px);
500 font-weight: @text-bold-weight;
500 font-weight: @text-bold-weight;
501 font-family: @text-bold;
501 font-family: @text-bold;
502
502
503 &.info { border-color: @alert4; background-color: @alert4-inner; }
503 &.info { border-color: @alert4; background-color: @alert4-inner; }
504 &.warning { border-color: @alert3; background-color: @alert3-inner; }
504 &.warning { border-color: @alert3; background-color: @alert3-inner; }
505 &.error { border-color: @alert2; background-color: @alert2-inner; }
505 &.error { border-color: @alert2; background-color: @alert2-inner; }
506 &.success { border-color: @alert1; background-color: @alert1-inner; }
506 &.success { border-color: @alert1; background-color: @alert1-inner; }
507 &.neutral { border-color: @grey3; background-color: @grey6; }
507 &.neutral { border-color: @grey3; background-color: @grey6; }
508 }
508 }
509
509
510 // Fixed Sidebar Column
510 // Fixed Sidebar Column
511 .sidebar-col-wrapper {
511 .sidebar-col-wrapper {
512 padding-left: @sidebar-all-width;
512 padding-left: @sidebar-all-width;
513
513
514 .sidebar {
514 .sidebar {
515 width: @sidebar-width;
515 width: @sidebar-width;
516 margin-left: -@sidebar-all-width;
516 margin-left: -@sidebar-all-width;
517 }
517 }
518 }
518 }
519
519
520 .sidebar-col-wrapper.scw-small {
520 .sidebar-col-wrapper.scw-small {
521 padding-left: @sidebar-small-all-width;
521 padding-left: @sidebar-small-all-width;
522
522
523 .sidebar {
523 .sidebar {
524 width: @sidebar-small-width;
524 width: @sidebar-small-width;
525 margin-left: -@sidebar-small-all-width;
525 margin-left: -@sidebar-small-all-width;
526 }
526 }
527 }
527 }
528
528
529
529
530 // FOOTER
530 // FOOTER
531 #footer {
531 #footer {
532 padding: 0;
532 padding: 0;
533 text-align: center;
533 text-align: center;
534 vertical-align: middle;
534 vertical-align: middle;
535 color: @grey2;
535 color: @grey2;
536 font-size: 11px;
536 font-size: 11px;
537
537
538 p {
538 p {
539 margin: 0;
539 margin: 0;
540 padding: 1em;
540 padding: 1em;
541 line-height: 1em;
541 line-height: 1em;
542 }
542 }
543
543
544 .server-instance { //server instance
544 .server-instance { //server instance
545 display: none;
545 display: none;
546 }
546 }
547
547
548 .title {
548 .title {
549 float: none;
549 float: none;
550 margin: 0 auto;
550 margin: 0 auto;
551 }
551 }
552 }
552 }
553
553
554 button.close {
554 button.close {
555 padding: 0;
555 padding: 0;
556 cursor: pointer;
556 cursor: pointer;
557 background: transparent;
557 background: transparent;
558 border: 0;
558 border: 0;
559 .box-shadow(none);
559 .box-shadow(none);
560 -webkit-appearance: none;
560 -webkit-appearance: none;
561 }
561 }
562
562
563 .close {
563 .close {
564 float: right;
564 float: right;
565 font-size: 21px;
565 font-size: 21px;
566 font-family: @text-bootstrap;
566 font-family: @text-bootstrap;
567 line-height: 1em;
567 line-height: 1em;
568 font-weight: bold;
568 font-weight: bold;
569 color: @grey2;
569 color: @grey2;
570
570
571 &:hover,
571 &:hover,
572 &:focus {
572 &:focus {
573 color: @grey1;
573 color: @grey1;
574 text-decoration: none;
574 text-decoration: none;
575 cursor: pointer;
575 cursor: pointer;
576 }
576 }
577 }
577 }
578
578
579 // GRID
579 // GRID
580 .sorting,
580 .sorting,
581 .sorting_desc,
581 .sorting_desc,
582 .sorting_asc {
582 .sorting_asc {
583 cursor: pointer;
583 cursor: pointer;
584 }
584 }
585 .sorting_desc:after {
585 .sorting_desc:after {
586 content: "\00A0\25B2";
586 content: "\00A0\25B2";
587 font-size: .75em;
587 font-size: .75em;
588 }
588 }
589 .sorting_asc:after {
589 .sorting_asc:after {
590 content: "\00A0\25BC";
590 content: "\00A0\25BC";
591 font-size: .68em;
591 font-size: .68em;
592 }
592 }
593
593
594
594
595 .user_auth_tokens {
595 .user_auth_tokens {
596
596
597 &.truncate {
597 &.truncate {
598 white-space: nowrap;
598 white-space: nowrap;
599 overflow: hidden;
599 overflow: hidden;
600 text-overflow: ellipsis;
600 text-overflow: ellipsis;
601 }
601 }
602
602
603 .fields .field .input {
603 .fields .field .input {
604 margin: 0;
604 margin: 0;
605 }
605 }
606
606
607 input#description {
607 input#description {
608 width: 100px;
608 width: 100px;
609 margin: 0;
609 margin: 0;
610 }
610 }
611
611
612 .drop-menu {
612 .drop-menu {
613 // TODO: johbo: Remove this, should work out of the box when
613 // TODO: johbo: Remove this, should work out of the box when
614 // having multiple inputs inline
614 // having multiple inputs inline
615 margin: 0 0 0 5px;
615 margin: 0 0 0 5px;
616 }
616 }
617 }
617 }
618 #user_list_table {
618 #user_list_table {
619 .closed {
619 .closed {
620 background-color: @grey6;
620 background-color: @grey6;
621 }
621 }
622 }
622 }
623
623
624
624
625 input, textarea {
625 input, textarea {
626 &.disabled {
626 &.disabled {
627 opacity: .5;
627 opacity: .5;
628 }
628 }
629
629
630 &:hover {
630 &:hover {
631 border-color: @grey3;
631 border-color: @grey3;
632 box-shadow: @button-shadow;
632 box-shadow: @button-shadow;
633 }
633 }
634
634
635 &:focus {
635 &:focus {
636 border-color: @rcblue;
636 border-color: @rcblue;
637 box-shadow: @button-shadow;
637 box-shadow: @button-shadow;
638 }
638 }
639 }
639 }
640
640
641 // remove extra padding in firefox
641 // remove extra padding in firefox
642 input::-moz-focus-inner { border:0; padding:0 }
642 input::-moz-focus-inner { border:0; padding:0 }
643
643
644 .adjacent input {
644 .adjacent input {
645 margin-bottom: @padding;
645 margin-bottom: @padding;
646 }
646 }
647
647
648 .permissions_boxes {
648 .permissions_boxes {
649 display: block;
649 display: block;
650 }
650 }
651
651
652 //FORMS
652 //FORMS
653
653
654 .medium-inline,
654 .medium-inline,
655 input#description.medium-inline {
655 input#description.medium-inline {
656 display: inline;
656 display: inline;
657 width: @medium-inline-input-width;
657 width: @medium-inline-input-width;
658 min-width: 100px;
658 min-width: 100px;
659 }
659 }
660
660
661 select {
661 select {
662 //reset
662 //reset
663 -webkit-appearance: none;
663 -webkit-appearance: none;
664 -moz-appearance: none;
664 -moz-appearance: none;
665
665
666 display: inline-block;
666 display: inline-block;
667 height: 28px;
667 height: 28px;
668 width: auto;
668 width: auto;
669 margin: 0 @padding @padding 0;
669 margin: 0 @padding @padding 0;
670 padding: 0 18px 0 8px;
670 padding: 0 18px 0 8px;
671 line-height:1em;
671 line-height:1em;
672 font-size: @basefontsize;
672 font-size: @basefontsize;
673 border: @border-thickness solid @grey5;
673 border: @border-thickness solid @grey5;
674 border-radius: @border-radius;
674 border-radius: @border-radius;
675 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
675 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
676 color: @grey4;
676 color: @grey4;
677 box-shadow: @button-shadow;
677 box-shadow: @button-shadow;
678
678
679 &:after {
679 &:after {
680 content: "\00A0\25BE";
680 content: "\00A0\25BE";
681 }
681 }
682
682
683 &:focus, &:hover {
683 &:focus, &:hover {
684 outline: none;
684 outline: none;
685 border-color: @grey4;
685 border-color: @grey4;
686 color: @rcdarkblue;
686 color: @rcdarkblue;
687 }
687 }
688 }
688 }
689
689
690 option {
690 option {
691 &:focus {
691 &:focus {
692 outline: none;
692 outline: none;
693 }
693 }
694 }
694 }
695
695
696 input,
696 input,
697 textarea {
697 textarea {
698 padding: @input-padding;
698 padding: @input-padding;
699 border: @input-border-thickness solid @border-highlight-color;
699 border: @input-border-thickness solid @border-highlight-color;
700 .border-radius (@border-radius);
700 .border-radius (@border-radius);
701 font-family: @text-light;
701 font-family: @text-light;
702 font-size: @basefontsize;
702 font-size: @basefontsize;
703
703
704 &.input-sm {
704 &.input-sm {
705 padding: 5px;
705 padding: 5px;
706 }
706 }
707
707
708 &#description {
708 &#description {
709 min-width: @input-description-minwidth;
709 min-width: @input-description-minwidth;
710 min-height: 1em;
710 min-height: 1em;
711 padding: 10px;
711 padding: 10px;
712 }
712 }
713 }
713 }
714
714
715 .field-sm {
715 .field-sm {
716 input,
716 input,
717 textarea {
717 textarea {
718 padding: 5px;
718 padding: 5px;
719 }
719 }
720 }
720 }
721
721
722 textarea {
722 textarea {
723 display: block;
723 display: block;
724 clear: both;
724 clear: both;
725 width: 100%;
725 width: 100%;
726 min-height: 100px;
726 min-height: 100px;
727 margin-bottom: @padding;
727 margin-bottom: @padding;
728 .box-sizing(border-box);
728 .box-sizing(border-box);
729 overflow: auto;
729 overflow: auto;
730 }
730 }
731
731
732 label {
732 label {
733 font-family: @text-light;
733 font-family: @text-light;
734 }
734 }
735
735
736 // GRAVATARS
736 // GRAVATARS
737 // centers gravatar on username to the right
737 // centers gravatar on username to the right
738
738
739 .gravatar {
739 .gravatar {
740 display: inline;
740 display: inline;
741 min-width: 16px;
741 min-width: 16px;
742 min-height: 16px;
742 min-height: 16px;
743 margin: -5px 0;
743 margin: -5px 0;
744 padding: 0;
744 padding: 0;
745 line-height: 1em;
745 line-height: 1em;
746 box-sizing: content-box;
746 box-sizing: content-box;
747 border-radius: 50%;
747 border-radius: 50%;
748
748
749 &.gravatar-large {
749 &.gravatar-large {
750 margin: -0.5em .25em -0.5em 0;
750 margin: -0.5em .25em -0.5em 0;
751 }
751 }
752
752
753 & + .user {
753 & + .user {
754 display: inline;
754 display: inline;
755 margin: 0;
755 margin: 0;
756 padding: 0 0 0 .17em;
756 padding: 0 0 0 .17em;
757 line-height: 1em;
757 line-height: 1em;
758 }
758 }
759 }
759 }
760
760
761 .user-inline-data {
761 .user-inline-data {
762 display: inline-block;
762 display: inline-block;
763 float: left;
763 float: left;
764 padding-left: .5em;
764 padding-left: .5em;
765 line-height: 1.3em;
765 line-height: 1.3em;
766 }
766 }
767
767
768 .rc-user { // gravatar + user wrapper
768 .rc-user { // gravatar + user wrapper
769 float: left;
769 float: left;
770 position: relative;
770 position: relative;
771 min-width: 100px;
771 min-width: 100px;
772 max-width: 200px;
772 max-width: 200px;
773 min-height: (@gravatar-size + @border-thickness * 2); // account for border
773 min-height: (@gravatar-size + @border-thickness * 2); // account for border
774 display: block;
774 display: block;
775 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
775 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
776
776
777
777
778 .gravatar {
778 .gravatar {
779 display: block;
779 display: block;
780 position: absolute;
780 position: absolute;
781 top: 0;
781 top: 0;
782 left: 0;
782 left: 0;
783 min-width: @gravatar-size;
783 min-width: @gravatar-size;
784 min-height: @gravatar-size;
784 min-height: @gravatar-size;
785 margin: 0;
785 margin: 0;
786 }
786 }
787
787
788 .user {
788 .user {
789 display: block;
789 display: block;
790 max-width: 175px;
790 max-width: 175px;
791 padding-top: 2px;
791 padding-top: 2px;
792 overflow: hidden;
792 overflow: hidden;
793 text-overflow: ellipsis;
793 text-overflow: ellipsis;
794 }
794 }
795 }
795 }
796
796
797 .gist-gravatar,
797 .gist-gravatar,
798 .journal_container {
798 .journal_container {
799 .gravatar-large {
799 .gravatar-large {
800 margin: 0 .5em -10px 0;
800 margin: 0 .5em -10px 0;
801 }
801 }
802 }
802 }
803
803
804
804
805 // ADMIN SETTINGS
805 // ADMIN SETTINGS
806
806
807 // Tag Patterns
807 // Tag Patterns
808 .tag_patterns {
808 .tag_patterns {
809 .tag_input {
809 .tag_input {
810 margin-bottom: @padding;
810 margin-bottom: @padding;
811 }
811 }
812 }
812 }
813
813
814 .locked_input {
814 .locked_input {
815 position: relative;
815 position: relative;
816
816
817 input {
817 input {
818 display: inline;
818 display: inline;
819 margin: 3px 5px 0px 0px;
819 margin: 3px 5px 0px 0px;
820 }
820 }
821
821
822 br {
822 br {
823 display: none;
823 display: none;
824 }
824 }
825
825
826 .error-message {
826 .error-message {
827 float: left;
827 float: left;
828 width: 100%;
828 width: 100%;
829 }
829 }
830
830
831 .lock_input_button {
831 .lock_input_button {
832 display: inline;
832 display: inline;
833 }
833 }
834
834
835 .help-block {
835 .help-block {
836 clear: both;
836 clear: both;
837 }
837 }
838 }
838 }
839
839
840 // Notifications
840 // Notifications
841
841
842 .notifications_buttons {
842 .notifications_buttons {
843 margin: 0 0 @space 0;
843 margin: 0 0 @space 0;
844 padding: 0;
844 padding: 0;
845
845
846 .btn {
846 .btn {
847 display: inline-block;
847 display: inline-block;
848 }
848 }
849 }
849 }
850
850
851 .notification-list {
851 .notification-list {
852
852
853 div {
853 div {
854 display: inline-block;
854 display: inline-block;
855 vertical-align: middle;
855 vertical-align: middle;
856 }
856 }
857
857
858 .container {
858 .container {
859 display: block;
859 display: block;
860 margin: 0 0 @padding 0;
860 margin: 0 0 @padding 0;
861 }
861 }
862
862
863 .delete-notifications {
863 .delete-notifications {
864 margin-left: @padding;
864 margin-left: @padding;
865 text-align: right;
865 text-align: right;
866 cursor: pointer;
866 cursor: pointer;
867 }
867 }
868
868
869 .read-notifications {
869 .read-notifications {
870 margin-left: @padding/2;
870 margin-left: @padding/2;
871 text-align: right;
871 text-align: right;
872 width: 35px;
872 width: 35px;
873 cursor: pointer;
873 cursor: pointer;
874 }
874 }
875
875
876 .icon-minus-sign {
876 .icon-minus-sign {
877 color: @alert2;
877 color: @alert2;
878 }
878 }
879
879
880 .icon-ok-sign {
880 .icon-ok-sign {
881 color: @alert1;
881 color: @alert1;
882 }
882 }
883 }
883 }
884
884
885 .user_settings {
885 .user_settings {
886 float: left;
886 float: left;
887 clear: both;
887 clear: both;
888 display: block;
888 display: block;
889 width: 100%;
889 width: 100%;
890
890
891 .gravatar_box {
891 .gravatar_box {
892 margin-bottom: @padding;
892 margin-bottom: @padding;
893
893
894 &:after {
894 &:after {
895 content: " ";
895 content: " ";
896 clear: both;
896 clear: both;
897 width: 100%;
897 width: 100%;
898 }
898 }
899 }
899 }
900
900
901 .fields .field {
901 .fields .field {
902 clear: both;
902 clear: both;
903 }
903 }
904 }
904 }
905
905
906 .advanced_settings {
906 .advanced_settings {
907 margin-bottom: @space;
907 margin-bottom: @space;
908
908
909 .help-block {
909 .help-block {
910 margin-left: 0;
910 margin-left: 0;
911 }
911 }
912
912
913 button + .help-block {
913 button + .help-block {
914 margin-top: @padding;
914 margin-top: @padding;
915 }
915 }
916 }
916 }
917
917
918 // admin settings radio buttons and labels
918 // admin settings radio buttons and labels
919 .label-2 {
919 .label-2 {
920 float: left;
920 float: left;
921 width: @label2-width;
921 width: @label2-width;
922
922
923 label {
923 label {
924 color: @grey1;
924 color: @grey1;
925 }
925 }
926 }
926 }
927 .checkboxes {
927 .checkboxes {
928 float: left;
928 float: left;
929 width: @checkboxes-width;
929 width: @checkboxes-width;
930 margin-bottom: @padding;
930 margin-bottom: @padding;
931
931
932 .checkbox {
932 .checkbox {
933 width: 100%;
933 width: 100%;
934
934
935 label {
935 label {
936 margin: 0;
936 margin: 0;
937 padding: 0;
937 padding: 0;
938 }
938 }
939 }
939 }
940
940
941 .checkbox + .checkbox {
941 .checkbox + .checkbox {
942 display: inline-block;
942 display: inline-block;
943 }
943 }
944
944
945 label {
945 label {
946 margin-right: 1em;
946 margin-right: 1em;
947 }
947 }
948 }
948 }
949
949
950 // CHANGELOG
950 // CHANGELOG
951 .container_header {
951 .container_header {
952 float: left;
952 float: left;
953 display: block;
953 display: block;
954 width: 100%;
954 width: 100%;
955 margin: @padding 0 @padding;
955 margin: @padding 0 @padding;
956
956
957 #filter_changelog {
957 #filter_changelog {
958 float: left;
958 float: left;
959 margin-right: @padding;
959 margin-right: @padding;
960 }
960 }
961
961
962 .breadcrumbs_light {
962 .breadcrumbs_light {
963 display: inline-block;
963 display: inline-block;
964 }
964 }
965 }
965 }
966
966
967 .info_box {
967 .info_box {
968 float: right;
968 float: right;
969 }
969 }
970
970
971
971
972
972
973 #graph_content{
973 #graph_content{
974
974
975 // adjust for table headers so that graph renders properly
975 // adjust for table headers so that graph renders properly
976 // #graph_nodes padding - table cell padding
976 // #graph_nodes padding - table cell padding
977 padding-top: (@space - (@basefontsize * 2.4));
977 padding-top: (@space - (@basefontsize * 2.4));
978
978
979 &.graph_full_width {
979 &.graph_full_width {
980 width: 100%;
980 width: 100%;
981 max-width: 100%;
981 max-width: 100%;
982 }
982 }
983 }
983 }
984
984
985 #graph {
985 #graph {
986 .flag_status {
987 margin: 0;
988 }
989
986
990 .pagination-left {
987 .pagination-left {
991 float: left;
988 float: left;
992 clear: both;
989 clear: both;
993 }
990 }
994
991
995 .log-container {
992 .log-container {
996 max-width: 345px;
993 max-width: 345px;
997
994
998 .message{
995 .message{
999 max-width: 340px;
996 max-width: 340px;
1000 }
997 }
1001 }
998 }
1002
999
1003 .graph-col-wrapper {
1000 .graph-col-wrapper {
1004
1001
1005 #graph_nodes {
1002 #graph_nodes {
1006 width: 100px;
1003 width: 100px;
1007 position: absolute;
1004 position: absolute;
1008 left: 70px;
1005 left: 70px;
1009 z-index: -1;
1006 z-index: -1;
1010 }
1007 }
1011 }
1008 }
1012
1009
1013 .load-more-commits {
1010 .load-more-commits {
1014 text-align: center;
1011 text-align: center;
1015 }
1012 }
1016 .load-more-commits:hover {
1013 .load-more-commits:hover {
1017 background-color: @grey7;
1014 background-color: @grey7;
1018 }
1015 }
1019 .load-more-commits {
1016 .load-more-commits {
1020 a {
1017 a {
1021 display: block;
1018 display: block;
1022 }
1019 }
1023 }
1020 }
1024 }
1021 }
1025
1022
1026 .obsolete-toggle {
1023 .obsolete-toggle {
1027 line-height: 30px;
1024 line-height: 30px;
1028 margin-left: -15px;
1025 margin-left: -15px;
1029 }
1026 }
1030
1027
1031 #rev_range_container, #rev_range_clear, #rev_range_more {
1028 #rev_range_container, #rev_range_clear, #rev_range_more {
1032 margin-top: -5px;
1029 margin-top: -5px;
1033 margin-bottom: -5px;
1030 margin-bottom: -5px;
1034 }
1031 }
1035
1032
1036 #filter_changelog {
1033 #filter_changelog {
1037 float: left;
1034 float: left;
1038 }
1035 }
1039
1036
1040
1037
1041 //--- THEME ------------------//
1038 //--- THEME ------------------//
1042
1039
1043 #logo {
1040 #logo {
1044 float: left;
1041 float: left;
1045 margin: 9px 0 0 0;
1042 margin: 9px 0 0 0;
1046
1043
1047 .header {
1044 .header {
1048 background-color: transparent;
1045 background-color: transparent;
1049 }
1046 }
1050
1047
1051 a {
1048 a {
1052 display: inline-block;
1049 display: inline-block;
1053 }
1050 }
1054
1051
1055 img {
1052 img {
1056 height:30px;
1053 height:30px;
1057 }
1054 }
1058 }
1055 }
1059
1056
1060 .logo-wrapper {
1057 .logo-wrapper {
1061 float:left;
1058 float:left;
1062 }
1059 }
1063
1060
1064 .branding {
1061 .branding {
1065 float: left;
1062 float: left;
1066 padding: 9px 2px;
1063 padding: 9px 2px;
1067 line-height: 1em;
1064 line-height: 1em;
1068 font-size: @navigation-fontsize;
1065 font-size: @navigation-fontsize;
1069
1066
1070 a {
1067 a {
1071 color: @grey5
1068 color: @grey5
1072 }
1069 }
1073 @media screen and (max-width: 1200px) {
1070 @media screen and (max-width: 1200px) {
1074 display: none;
1071 display: none;
1075 }
1072 }
1076 }
1073 }
1077
1074
1078 img {
1075 img {
1079 border: none;
1076 border: none;
1080 outline: none;
1077 outline: none;
1081 }
1078 }
1082 user-profile-header
1079 user-profile-header
1083 label {
1080 label {
1084
1081
1085 input[type="checkbox"] {
1082 input[type="checkbox"] {
1086 margin-right: 1em;
1083 margin-right: 1em;
1087 }
1084 }
1088 input[type="radio"] {
1085 input[type="radio"] {
1089 margin-right: 1em;
1086 margin-right: 1em;
1090 }
1087 }
1091 }
1088 }
1092
1089
1093 .flag_status {
1094 margin: 2px;
1095 &.under_review {
1096 .circle(5px, @alert3);
1097 }
1098 &.approved {
1099 .circle(5px, @alert1);
1100 }
1101 &.rejected,
1102 &.forced_closed{
1103 .circle(5px, @alert2);
1104 }
1105 &.not_reviewed {
1106 .circle(5px, @grey5);
1107 }
1108 }
1109
1110 .review-status {
1090 .review-status {
1111 &.under_review {
1091 &.under_review {
1112 color: @alert3;
1092 color: @alert3;
1113 }
1093 }
1114 &.approved {
1094 &.approved {
1115 color: @alert1;
1095 color: @alert1;
1116 }
1096 }
1117 &.rejected,
1097 &.rejected,
1118 &.forced_closed{
1098 &.forced_closed{
1119 color: @alert2;
1099 color: @alert2;
1120 }
1100 }
1121 &.not_reviewed {
1101 &.not_reviewed {
1122 color: @grey5;
1102 color: @grey5;
1123 }
1103 }
1124 }
1104 }
1125
1105
1126 .review-status-under_review {
1106 .review-status-under_review {
1127 color: @alert3;
1107 color: @alert3;
1128 }
1108 }
1129 .status-tag-under_review {
1109 .status-tag-under_review {
1130 border-color: @alert3;
1110 border-color: @alert3;
1131 }
1111 }
1132
1112
1133 .review-status-approved {
1113 .review-status-approved {
1134 color: @alert1;
1114 color: @alert1;
1135 }
1115 }
1136 .status-tag-approved {
1116 .status-tag-approved {
1137 border-color: @alert1;
1117 border-color: @alert1;
1138 }
1118 }
1139
1119
1140 .review-status-rejected,
1120 .review-status-rejected,
1141 .review-status-forced_closed {
1121 .review-status-forced_closed {
1142 color: @alert2;
1122 color: @alert2;
1143 }
1123 }
1144 .status-tag-rejected,
1124 .status-tag-rejected,
1145 .status-tag-forced_closed {
1125 .status-tag-forced_closed {
1146 border-color: @alert2;
1126 border-color: @alert2;
1147 }
1127 }
1148
1128
1149 .review-status-not_reviewed {
1129 .review-status-not_reviewed {
1150 color: @grey5;
1130 color: @grey5;
1151 }
1131 }
1152 .status-tag-not_reviewed {
1132 .status-tag-not_reviewed {
1153 border-color: @grey5;
1133 border-color: @grey5;
1154 }
1134 }
1155
1135
1156 .flag_status_comment_box {
1157 margin: 5px 6px 0px 2px;
1158 }
1159 .test_pattern_preview {
1136 .test_pattern_preview {
1160 margin: @space 0;
1137 margin: @space 0;
1161
1138
1162 p {
1139 p {
1163 margin-bottom: 0;
1140 margin-bottom: 0;
1164 border-bottom: @border-thickness solid @border-default-color;
1141 border-bottom: @border-thickness solid @border-default-color;
1165 color: @grey3;
1142 color: @grey3;
1166 }
1143 }
1167
1144
1168 .btn {
1145 .btn {
1169 margin-bottom: @padding;
1146 margin-bottom: @padding;
1170 }
1147 }
1171 }
1148 }
1172 #test_pattern_result {
1149 #test_pattern_result {
1173 display: none;
1150 display: none;
1174 &:extend(pre);
1151 &:extend(pre);
1175 padding: .9em;
1152 padding: .9em;
1176 color: @grey3;
1153 color: @grey3;
1177 background-color: @grey7;
1154 background-color: @grey7;
1178 border-right: @border-thickness solid @border-default-color;
1155 border-right: @border-thickness solid @border-default-color;
1179 border-bottom: @border-thickness solid @border-default-color;
1156 border-bottom: @border-thickness solid @border-default-color;
1180 border-left: @border-thickness solid @border-default-color;
1157 border-left: @border-thickness solid @border-default-color;
1181 }
1158 }
1182
1159
1183 #repo_vcs_settings {
1160 #repo_vcs_settings {
1184 #inherit_overlay_vcs_default {
1161 #inherit_overlay_vcs_default {
1185 display: none;
1162 display: none;
1186 }
1163 }
1187 #inherit_overlay_vcs_custom {
1164 #inherit_overlay_vcs_custom {
1188 display: custom;
1165 display: custom;
1189 }
1166 }
1190 &.inherited {
1167 &.inherited {
1191 #inherit_overlay_vcs_default {
1168 #inherit_overlay_vcs_default {
1192 display: block;
1169 display: block;
1193 }
1170 }
1194 #inherit_overlay_vcs_custom {
1171 #inherit_overlay_vcs_custom {
1195 display: none;
1172 display: none;
1196 }
1173 }
1197 }
1174 }
1198 }
1175 }
1199
1176
1200 .issue-tracker-link {
1177 .issue-tracker-link {
1201 color: @rcblue;
1178 color: @rcblue;
1202 }
1179 }
1203
1180
1204 // Issue Tracker Table Show/Hide
1181 // Issue Tracker Table Show/Hide
1205 #repo_issue_tracker {
1182 #repo_issue_tracker {
1206 #inherit_overlay {
1183 #inherit_overlay {
1207 display: none;
1184 display: none;
1208 }
1185 }
1209 #custom_overlay {
1186 #custom_overlay {
1210 display: custom;
1187 display: custom;
1211 }
1188 }
1212 &.inherited {
1189 &.inherited {
1213 #inherit_overlay {
1190 #inherit_overlay {
1214 display: block;
1191 display: block;
1215 }
1192 }
1216 #custom_overlay {
1193 #custom_overlay {
1217 display: none;
1194 display: none;
1218 }
1195 }
1219 }
1196 }
1220 }
1197 }
1221 table.issuetracker {
1198 table.issuetracker {
1222 &.readonly {
1199 &.readonly {
1223 tr, td {
1200 tr, td {
1224 color: @grey3;
1201 color: @grey3;
1225 }
1202 }
1226 }
1203 }
1227 .edit {
1204 .edit {
1228 display: none;
1205 display: none;
1229 }
1206 }
1230 .editopen {
1207 .editopen {
1231 .edit {
1208 .edit {
1232 display: inline;
1209 display: inline;
1233 }
1210 }
1234 .entry {
1211 .entry {
1235 display: none;
1212 display: none;
1236 }
1213 }
1237 }
1214 }
1238 tr td.td-action {
1215 tr td.td-action {
1239 min-width: 117px;
1216 min-width: 117px;
1240 }
1217 }
1241 td input {
1218 td input {
1242 max-width: none;
1219 max-width: none;
1243 min-width: 30px;
1220 min-width: 30px;
1244 width: 80%;
1221 width: 80%;
1245 }
1222 }
1246 .issuetracker_pref input {
1223 .issuetracker_pref input {
1247 width: 40%;
1224 width: 40%;
1248 }
1225 }
1249 input.edit_issuetracker_update {
1226 input.edit_issuetracker_update {
1250 margin-right: 0;
1227 margin-right: 0;
1251 width: auto;
1228 width: auto;
1252 }
1229 }
1253 }
1230 }
1254
1231
1255 table.integrations {
1232 table.integrations {
1256 .td-icon {
1233 .td-icon {
1257 width: 20px;
1234 width: 20px;
1258 .integration-icon {
1235 .integration-icon {
1259 height: 20px;
1236 height: 20px;
1260 width: 20px;
1237 width: 20px;
1261 }
1238 }
1262 }
1239 }
1263 }
1240 }
1264
1241
1265 .integrations {
1242 .integrations {
1266 a.integration-box {
1243 a.integration-box {
1267 color: @text-color;
1244 color: @text-color;
1268 &:hover {
1245 &:hover {
1269 .panel {
1246 .panel {
1270 background: #fbfbfb;
1247 background: #fbfbfb;
1271 }
1248 }
1272 }
1249 }
1273 .integration-icon {
1250 .integration-icon {
1274 width: 30px;
1251 width: 30px;
1275 height: 30px;
1252 height: 30px;
1276 margin-right: 20px;
1253 margin-right: 20px;
1277 float: left;
1254 float: left;
1278 }
1255 }
1279
1256
1280 .panel-body {
1257 .panel-body {
1281 padding: 10px;
1258 padding: 10px;
1282 }
1259 }
1283 .panel {
1260 .panel {
1284 margin-bottom: 10px;
1261 margin-bottom: 10px;
1285 }
1262 }
1286 h2 {
1263 h2 {
1287 display: inline-block;
1264 display: inline-block;
1288 margin: 0;
1265 margin: 0;
1289 min-width: 140px;
1266 min-width: 140px;
1290 }
1267 }
1291 }
1268 }
1292 a.integration-box.dummy-integration {
1269 a.integration-box.dummy-integration {
1293 color: @grey4
1270 color: @grey4
1294 }
1271 }
1295 }
1272 }
1296
1273
1297 //Permissions Settings
1274 //Permissions Settings
1298 #add_perm {
1275 #add_perm {
1299 margin: 0 0 @padding;
1276 margin: 0 0 @padding;
1300 cursor: pointer;
1277 cursor: pointer;
1301 }
1278 }
1302
1279
1303 .perm_ac {
1280 .perm_ac {
1304 input {
1281 input {
1305 width: 95%;
1282 width: 95%;
1306 }
1283 }
1307 }
1284 }
1308
1285
1309 .autocomplete-suggestions {
1286 .autocomplete-suggestions {
1310 width: auto !important; // overrides autocomplete.js
1287 width: auto !important; // overrides autocomplete.js
1311 min-width: 278px;
1288 min-width: 278px;
1312 margin: 0;
1289 margin: 0;
1313 border: @border-thickness solid @grey5;
1290 border: @border-thickness solid @grey5;
1314 border-radius: @border-radius;
1291 border-radius: @border-radius;
1315 color: @grey2;
1292 color: @grey2;
1316 background-color: white;
1293 background-color: white;
1317 }
1294 }
1318
1295
1319 .autocomplete-qfilter-suggestions {
1296 .autocomplete-qfilter-suggestions {
1320 width: auto !important; // overrides autocomplete.js
1297 width: auto !important; // overrides autocomplete.js
1321 max-height: 100% !important;
1298 max-height: 100% !important;
1322 min-width: 376px;
1299 min-width: 376px;
1323 margin: 0;
1300 margin: 0;
1324 border: @border-thickness solid @grey5;
1301 border: @border-thickness solid @grey5;
1325 color: @grey2;
1302 color: @grey2;
1326 background-color: white;
1303 background-color: white;
1327 }
1304 }
1328
1305
1329 .autocomplete-selected {
1306 .autocomplete-selected {
1330 background: #F0F0F0;
1307 background: #F0F0F0;
1331 }
1308 }
1332
1309
1333 .ac-container-wrap {
1310 .ac-container-wrap {
1334 margin: 0;
1311 margin: 0;
1335 padding: 8px;
1312 padding: 8px;
1336 border-bottom: @border-thickness solid @grey5;
1313 border-bottom: @border-thickness solid @grey5;
1337 list-style-type: none;
1314 list-style-type: none;
1338 cursor: pointer;
1315 cursor: pointer;
1339
1316
1340 &:hover {
1317 &:hover {
1341 background-color: @grey7;
1318 background-color: @grey7;
1342 }
1319 }
1343
1320
1344 img {
1321 img {
1345 height: @gravatar-size;
1322 height: @gravatar-size;
1346 width: @gravatar-size;
1323 width: @gravatar-size;
1347 margin-right: 1em;
1324 margin-right: 1em;
1348 }
1325 }
1349
1326
1350 strong {
1327 strong {
1351 font-weight: normal;
1328 font-weight: normal;
1352 }
1329 }
1353 }
1330 }
1354
1331
1355 // Settings Dropdown
1332 // Settings Dropdown
1356 .user-menu .container {
1333 .user-menu .container {
1357 padding: 0 4px;
1334 padding: 0 4px;
1358 margin: 0;
1335 margin: 0;
1359 }
1336 }
1360
1337
1361 .user-menu .gravatar {
1338 .user-menu .gravatar {
1362 cursor: pointer;
1339 cursor: pointer;
1363 }
1340 }
1364
1341
1365 .codeblock {
1342 .codeblock {
1366 margin-bottom: @padding;
1343 margin-bottom: @padding;
1367 clear: both;
1344 clear: both;
1368
1345
1369 .stats {
1346 .stats {
1370 overflow: hidden;
1347 overflow: hidden;
1371 }
1348 }
1372
1349
1373 .message{
1350 .message{
1374 textarea{
1351 textarea{
1375 margin: 0;
1352 margin: 0;
1376 }
1353 }
1377 }
1354 }
1378
1355
1379 .code-header {
1356 .code-header {
1380 .stats {
1357 .stats {
1381 line-height: 2em;
1358 line-height: 2em;
1382
1359
1383 .revision_id {
1360 .revision_id {
1384 margin-left: 0;
1361 margin-left: 0;
1385 }
1362 }
1386 .buttons {
1363 .buttons {
1387 padding-right: 0;
1364 padding-right: 0;
1388 }
1365 }
1389 }
1366 }
1390
1367
1391 .item{
1368 .item{
1392 margin-right: 0.5em;
1369 margin-right: 0.5em;
1393 }
1370 }
1394 }
1371 }
1395
1372
1396 #editor_container {
1373 #editor_container {
1397 position: relative;
1374 position: relative;
1398 margin: @padding 10px;
1375 margin: @padding 10px;
1399 }
1376 }
1400 }
1377 }
1401
1378
1402 #file_history_container {
1379 #file_history_container {
1403 display: none;
1380 display: none;
1404 }
1381 }
1405
1382
1406 .file-history-inner {
1383 .file-history-inner {
1407 margin-bottom: 10px;
1384 margin-bottom: 10px;
1408 }
1385 }
1409
1386
1410 // Pull Requests
1387 // Pull Requests
1411 .summary-details {
1388 .summary-details {
1412 width: 72%;
1389 width: 72%;
1413 }
1390 }
1414 .pr-summary {
1391 .pr-summary {
1415 border-bottom: @border-thickness solid @grey5;
1392 border-bottom: @border-thickness solid @grey5;
1416 margin-bottom: @space;
1393 margin-bottom: @space;
1417 }
1394 }
1418 .reviewers-title {
1395 .reviewers-title {
1419 width: 25%;
1396 width: 25%;
1420 min-width: 200px;
1397 min-width: 200px;
1421 }
1398 }
1422 .reviewers {
1399 .reviewers {
1423 width: 25%;
1400 width: 25%;
1424 min-width: 200px;
1401 min-width: 200px;
1425 }
1402 }
1426 .reviewers ul li {
1403 .reviewers ul li {
1427 position: relative;
1404 position: relative;
1428 width: 100%;
1405 width: 100%;
1429 padding-bottom: 8px;
1406 padding-bottom: 8px;
1430 list-style-type: none;
1407 list-style-type: none;
1431 }
1408 }
1432
1409
1433 .reviewer_entry {
1410 .reviewer_entry {
1434 min-height: 55px;
1411 min-height: 55px;
1435 }
1412 }
1436
1413
1437 .reviewers_member {
1414 .reviewers_member {
1438 width: 100%;
1415 width: 100%;
1439 overflow: auto;
1416 overflow: auto;
1440 }
1417 }
1441 .reviewer_reason {
1418 .reviewer_reason {
1442 padding-left: 20px;
1419 padding-left: 20px;
1443 line-height: 1.5em;
1420 line-height: 1.5em;
1444 }
1421 }
1445 .reviewer_status {
1422 .reviewer_status {
1446 display: inline-block;
1423 display: inline-block;
1447 vertical-align: top;
1424 vertical-align: top;
1448 width: 25px;
1425 width: 25px;
1449 min-width: 25px;
1426 min-width: 25px;
1450 height: 1.2em;
1427 height: 1.2em;
1451 margin-top: 3px;
1428 margin-top: 3px;
1452 line-height: 1em;
1429 line-height: 1em;
1453 }
1430 }
1454
1431
1455 .reviewer_name {
1432 .reviewer_name {
1456 display: inline-block;
1433 display: inline-block;
1457 max-width: 83%;
1434 max-width: 83%;
1458 padding-right: 20px;
1435 padding-right: 20px;
1459 vertical-align: middle;
1436 vertical-align: middle;
1460 line-height: 1;
1437 line-height: 1;
1461
1438
1462 .rc-user {
1439 .rc-user {
1463 min-width: 0;
1440 min-width: 0;
1464 margin: -2px 1em 0 0;
1441 margin: -2px 1em 0 0;
1465 }
1442 }
1466
1443
1467 .reviewer {
1444 .reviewer {
1468 float: left;
1445 float: left;
1469 }
1446 }
1470 }
1447 }
1471
1448
1472 .reviewer_member_mandatory {
1449 .reviewer_member_mandatory {
1473 position: absolute;
1450 position: absolute;
1474 left: 15px;
1451 left: 15px;
1475 top: 8px;
1452 top: 8px;
1476 width: 16px;
1453 width: 16px;
1477 font-size: 11px;
1454 font-size: 11px;
1478 margin: 0;
1455 margin: 0;
1479 padding: 0;
1456 padding: 0;
1480 color: black;
1457 color: black;
1481 }
1458 }
1482
1459
1483 .reviewer_member_mandatory_remove,
1460 .reviewer_member_mandatory_remove,
1484 .reviewer_member_remove {
1461 .reviewer_member_remove {
1485 position: absolute;
1462 position: absolute;
1486 right: 0;
1463 right: 0;
1487 top: 0;
1464 top: 0;
1488 width: 16px;
1465 width: 16px;
1489 margin-bottom: 10px;
1466 margin-bottom: 10px;
1490 padding: 0;
1467 padding: 0;
1491 color: black;
1468 color: black;
1492 }
1469 }
1493
1470
1494 .reviewer_member_mandatory_remove {
1471 .reviewer_member_mandatory_remove {
1495 color: @grey4;
1472 color: @grey4;
1496 }
1473 }
1497
1474
1498 .reviewer_member_status {
1475 .reviewer_member_status {
1499 margin-top: 5px;
1476 margin-top: 5px;
1500 }
1477 }
1501 .pr-summary #summary{
1478 .pr-summary #summary{
1502 width: 100%;
1479 width: 100%;
1503 }
1480 }
1504 .pr-summary .action_button:hover {
1481 .pr-summary .action_button:hover {
1505 border: 0;
1482 border: 0;
1506 cursor: pointer;
1483 cursor: pointer;
1507 }
1484 }
1508 .pr-details-title {
1485 .pr-details-title {
1509 padding-bottom: 8px;
1486 padding-bottom: 8px;
1510 border-bottom: @border-thickness solid @grey5;
1487 border-bottom: @border-thickness solid @grey5;
1511
1488
1512 .action_button.disabled {
1489 .action_button.disabled {
1513 color: @grey4;
1490 color: @grey4;
1514 cursor: inherit;
1491 cursor: inherit;
1515 }
1492 }
1516 .action_button {
1493 .action_button {
1517 color: @rcblue;
1494 color: @rcblue;
1518 }
1495 }
1519 }
1496 }
1520 .pr-details-content {
1497 .pr-details-content {
1521 margin-top: @textmargin;
1498 margin-top: @textmargin;
1522 margin-bottom: @textmargin;
1499 margin-bottom: @textmargin;
1523 }
1500 }
1524
1501
1525 .pr-reviewer-rules {
1502 .pr-reviewer-rules {
1526 padding: 10px 0px 20px 0px;
1503 padding: 10px 0px 20px 0px;
1527 }
1504 }
1528
1505
1529 .group_members {
1506 .group_members {
1530 margin-top: 0;
1507 margin-top: 0;
1531 padding: 0;
1508 padding: 0;
1532 list-style: outside none none;
1509 list-style: outside none none;
1533
1510
1534 img {
1511 img {
1535 height: @gravatar-size;
1512 height: @gravatar-size;
1536 width: @gravatar-size;
1513 width: @gravatar-size;
1537 margin-right: .5em;
1514 margin-right: .5em;
1538 margin-left: 3px;
1515 margin-left: 3px;
1539 }
1516 }
1540
1517
1541 .to-delete {
1518 .to-delete {
1542 .user {
1519 .user {
1543 text-decoration: line-through;
1520 text-decoration: line-through;
1544 }
1521 }
1545 }
1522 }
1546 }
1523 }
1547
1524
1548 .compare_view_commits_title {
1525 .compare_view_commits_title {
1549 .disabled {
1526 .disabled {
1550 cursor: inherit;
1527 cursor: inherit;
1551 &:hover{
1528 &:hover{
1552 background-color: inherit;
1529 background-color: inherit;
1553 color: inherit;
1530 color: inherit;
1554 }
1531 }
1555 }
1532 }
1556 }
1533 }
1557
1534
1558 .subtitle-compare {
1535 .subtitle-compare {
1559 margin: -15px 0px 0px 0px;
1536 margin: -15px 0px 0px 0px;
1560 }
1537 }
1561
1538
1562 .comments-summary-td {
1539 .comments-summary-td {
1563 border-top: 1px dashed @grey5;
1540 border-top: 1px dashed @grey5;
1564 }
1541 }
1565
1542
1566 // new entry in group_members
1543 // new entry in group_members
1567 .td-author-new-entry {
1544 .td-author-new-entry {
1568 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1545 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1569 }
1546 }
1570
1547
1571 .usergroup_member_remove {
1548 .usergroup_member_remove {
1572 width: 16px;
1549 width: 16px;
1573 margin-bottom: 10px;
1550 margin-bottom: 10px;
1574 padding: 0;
1551 padding: 0;
1575 color: black !important;
1552 color: black !important;
1576 cursor: pointer;
1553 cursor: pointer;
1577 }
1554 }
1578
1555
1579 .reviewer_ac .ac-input {
1556 .reviewer_ac .ac-input {
1580 width: 92%;
1557 width: 92%;
1581 margin-bottom: 1em;
1558 margin-bottom: 1em;
1582 }
1559 }
1583
1560
1584 .compare_view_commits tr{
1561 .compare_view_commits tr{
1585 height: 20px;
1562 height: 20px;
1586 }
1563 }
1587 .compare_view_commits td {
1564 .compare_view_commits td {
1588 vertical-align: top;
1565 vertical-align: top;
1589 padding-top: 10px;
1566 padding-top: 10px;
1590 }
1567 }
1591 .compare_view_commits .author {
1568 .compare_view_commits .author {
1592 margin-left: 5px;
1569 margin-left: 5px;
1593 }
1570 }
1594
1571
1595 .compare_view_commits {
1572 .compare_view_commits {
1596 .color-a {
1573 .color-a {
1597 color: @alert1;
1574 color: @alert1;
1598 }
1575 }
1599
1576
1600 .color-c {
1577 .color-c {
1601 color: @color3;
1578 color: @color3;
1602 }
1579 }
1603
1580
1604 .color-r {
1581 .color-r {
1605 color: @color5;
1582 color: @color5;
1606 }
1583 }
1607
1584
1608 .color-a-bg {
1585 .color-a-bg {
1609 background-color: @alert1;
1586 background-color: @alert1;
1610 }
1587 }
1611
1588
1612 .color-c-bg {
1589 .color-c-bg {
1613 background-color: @alert3;
1590 background-color: @alert3;
1614 }
1591 }
1615
1592
1616 .color-r-bg {
1593 .color-r-bg {
1617 background-color: @alert2;
1594 background-color: @alert2;
1618 }
1595 }
1619
1596
1620 .color-a-border {
1597 .color-a-border {
1621 border: 1px solid @alert1;
1598 border: 1px solid @alert1;
1622 }
1599 }
1623
1600
1624 .color-c-border {
1601 .color-c-border {
1625 border: 1px solid @alert3;
1602 border: 1px solid @alert3;
1626 }
1603 }
1627
1604
1628 .color-r-border {
1605 .color-r-border {
1629 border: 1px solid @alert2;
1606 border: 1px solid @alert2;
1630 }
1607 }
1631
1608
1632 .commit-change-indicator {
1609 .commit-change-indicator {
1633 width: 15px;
1610 width: 15px;
1634 height: 15px;
1611 height: 15px;
1635 position: relative;
1612 position: relative;
1636 left: 15px;
1613 left: 15px;
1637 }
1614 }
1638
1615
1639 .commit-change-content {
1616 .commit-change-content {
1640 text-align: center;
1617 text-align: center;
1641 vertical-align: middle;
1618 vertical-align: middle;
1642 line-height: 15px;
1619 line-height: 15px;
1643 }
1620 }
1644 }
1621 }
1645
1622
1646 .compare_view_filepath {
1623 .compare_view_filepath {
1647 color: @grey1;
1624 color: @grey1;
1648 }
1625 }
1649
1626
1650 .show_more {
1627 .show_more {
1651 display: inline-block;
1628 display: inline-block;
1652 width: 0;
1629 width: 0;
1653 height: 0;
1630 height: 0;
1654 vertical-align: middle;
1631 vertical-align: middle;
1655 content: "";
1632 content: "";
1656 border: 4px solid;
1633 border: 4px solid;
1657 border-right-color: transparent;
1634 border-right-color: transparent;
1658 border-bottom-color: transparent;
1635 border-bottom-color: transparent;
1659 border-left-color: transparent;
1636 border-left-color: transparent;
1660 font-size: 0;
1637 font-size: 0;
1661 }
1638 }
1662
1639
1663 .journal_more .show_more {
1640 .journal_more .show_more {
1664 display: inline;
1641 display: inline;
1665
1642
1666 &:after {
1643 &:after {
1667 content: none;
1644 content: none;
1668 }
1645 }
1669 }
1646 }
1670
1647
1671 .compare_view_commits .collapse_commit:after {
1648 .compare_view_commits .collapse_commit:after {
1672 cursor: pointer;
1649 cursor: pointer;
1673 content: "\00A0\25B4";
1650 content: "\00A0\25B4";
1674 margin-left: -3px;
1651 margin-left: -3px;
1675 font-size: 17px;
1652 font-size: 17px;
1676 color: @grey4;
1653 color: @grey4;
1677 }
1654 }
1678
1655
1679 .diff_links {
1656 .diff_links {
1680 margin-left: 8px;
1657 margin-left: 8px;
1681 }
1658 }
1682
1659
1683 #pull_request_overview {
1660 #pull_request_overview {
1684 div.ancestor {
1661 div.ancestor {
1685 margin: -33px 0;
1662 margin: -33px 0;
1686 }
1663 }
1687 }
1664 }
1688
1665
1689 div.ancestor {
1666 div.ancestor {
1690 line-height: 33px;
1667 line-height: 33px;
1691 }
1668 }
1692
1669
1693 .cs_icon_td input[type="checkbox"] {
1670 .cs_icon_td input[type="checkbox"] {
1694 display: none;
1671 display: none;
1695 }
1672 }
1696
1673
1697 .cs_icon_td .expand_file_icon:after {
1674 .cs_icon_td .expand_file_icon:after {
1698 cursor: pointer;
1675 cursor: pointer;
1699 content: "\00A0\25B6";
1676 content: "\00A0\25B6";
1700 font-size: 12px;
1677 font-size: 12px;
1701 color: @grey4;
1678 color: @grey4;
1702 }
1679 }
1703
1680
1704 .cs_icon_td .collapse_file_icon:after {
1681 .cs_icon_td .collapse_file_icon:after {
1705 cursor: pointer;
1682 cursor: pointer;
1706 content: "\00A0\25BC";
1683 content: "\00A0\25BC";
1707 font-size: 12px;
1684 font-size: 12px;
1708 color: @grey4;
1685 color: @grey4;
1709 }
1686 }
1710
1687
1711 /*new binary
1688 /*new binary
1712 NEW_FILENODE = 1
1689 NEW_FILENODE = 1
1713 DEL_FILENODE = 2
1690 DEL_FILENODE = 2
1714 MOD_FILENODE = 3
1691 MOD_FILENODE = 3
1715 RENAMED_FILENODE = 4
1692 RENAMED_FILENODE = 4
1716 COPIED_FILENODE = 5
1693 COPIED_FILENODE = 5
1717 CHMOD_FILENODE = 6
1694 CHMOD_FILENODE = 6
1718 BIN_FILENODE = 7
1695 BIN_FILENODE = 7
1719 */
1696 */
1720 .cs_files_expand {
1697 .cs_files_expand {
1721 font-size: @basefontsize + 5px;
1698 font-size: @basefontsize + 5px;
1722 line-height: 1.8em;
1699 line-height: 1.8em;
1723 float: right;
1700 float: right;
1724 }
1701 }
1725
1702
1726 .cs_files_expand span{
1703 .cs_files_expand span{
1727 color: @rcblue;
1704 color: @rcblue;
1728 cursor: pointer;
1705 cursor: pointer;
1729 }
1706 }
1730 .cs_files {
1707 .cs_files {
1731 clear: both;
1708 clear: both;
1732 padding-bottom: @padding;
1709 padding-bottom: @padding;
1733
1710
1734 .cur_cs {
1711 .cur_cs {
1735 margin: 10px 2px;
1712 margin: 10px 2px;
1736 font-weight: bold;
1713 font-weight: bold;
1737 }
1714 }
1738
1715
1739 .node {
1716 .node {
1740 float: left;
1717 float: left;
1741 }
1718 }
1742
1719
1743 .changes {
1720 .changes {
1744 float: right;
1721 float: right;
1745 color: white;
1722 color: white;
1746 font-size: @basefontsize - 4px;
1723 font-size: @basefontsize - 4px;
1747 margin-top: 4px;
1724 margin-top: 4px;
1748 opacity: 0.6;
1725 opacity: 0.6;
1749 filter: Alpha(opacity=60); /* IE8 and earlier */
1726 filter: Alpha(opacity=60); /* IE8 and earlier */
1750
1727
1751 .added {
1728 .added {
1752 background-color: @alert1;
1729 background-color: @alert1;
1753 float: left;
1730 float: left;
1754 text-align: center;
1731 text-align: center;
1755 }
1732 }
1756
1733
1757 .deleted {
1734 .deleted {
1758 background-color: @alert2;
1735 background-color: @alert2;
1759 float: left;
1736 float: left;
1760 text-align: center;
1737 text-align: center;
1761 }
1738 }
1762
1739
1763 .bin {
1740 .bin {
1764 background-color: @alert1;
1741 background-color: @alert1;
1765 text-align: center;
1742 text-align: center;
1766 }
1743 }
1767
1744
1768 /*new binary*/
1745 /*new binary*/
1769 .bin.bin1 {
1746 .bin.bin1 {
1770 background-color: @alert1;
1747 background-color: @alert1;
1771 text-align: center;
1748 text-align: center;
1772 }
1749 }
1773
1750
1774 /*deleted binary*/
1751 /*deleted binary*/
1775 .bin.bin2 {
1752 .bin.bin2 {
1776 background-color: @alert2;
1753 background-color: @alert2;
1777 text-align: center;
1754 text-align: center;
1778 }
1755 }
1779
1756
1780 /*mod binary*/
1757 /*mod binary*/
1781 .bin.bin3 {
1758 .bin.bin3 {
1782 background-color: @grey2;
1759 background-color: @grey2;
1783 text-align: center;
1760 text-align: center;
1784 }
1761 }
1785
1762
1786 /*rename file*/
1763 /*rename file*/
1787 .bin.bin4 {
1764 .bin.bin4 {
1788 background-color: @alert4;
1765 background-color: @alert4;
1789 text-align: center;
1766 text-align: center;
1790 }
1767 }
1791
1768
1792 /*copied file*/
1769 /*copied file*/
1793 .bin.bin5 {
1770 .bin.bin5 {
1794 background-color: @alert4;
1771 background-color: @alert4;
1795 text-align: center;
1772 text-align: center;
1796 }
1773 }
1797
1774
1798 /*chmod file*/
1775 /*chmod file*/
1799 .bin.bin6 {
1776 .bin.bin6 {
1800 background-color: @grey2;
1777 background-color: @grey2;
1801 text-align: center;
1778 text-align: center;
1802 }
1779 }
1803 }
1780 }
1804 }
1781 }
1805
1782
1806 .cs_files .cs_added, .cs_files .cs_A,
1783 .cs_files .cs_added, .cs_files .cs_A,
1807 .cs_files .cs_added, .cs_files .cs_M,
1784 .cs_files .cs_added, .cs_files .cs_M,
1808 .cs_files .cs_added, .cs_files .cs_D {
1785 .cs_files .cs_added, .cs_files .cs_D {
1809 height: 16px;
1786 height: 16px;
1810 padding-right: 10px;
1787 padding-right: 10px;
1811 margin-top: 7px;
1788 margin-top: 7px;
1812 text-align: left;
1789 text-align: left;
1813 }
1790 }
1814
1791
1815 .cs_icon_td {
1792 .cs_icon_td {
1816 min-width: 16px;
1793 min-width: 16px;
1817 width: 16px;
1794 width: 16px;
1818 }
1795 }
1819
1796
1820 .pull-request-merge {
1797 .pull-request-merge {
1821 border: 1px solid @grey5;
1798 border: 1px solid @grey5;
1822 padding: 10px 0px 20px;
1799 padding: 10px 0px 20px;
1823 margin-top: 10px;
1800 margin-top: 10px;
1824 margin-bottom: 20px;
1801 margin-bottom: 20px;
1825 }
1802 }
1826
1803
1827 .pull-request-merge ul {
1804 .pull-request-merge ul {
1828 padding: 0px 0px;
1805 padding: 0px 0px;
1829 }
1806 }
1830
1807
1831 .pull-request-merge li {
1808 .pull-request-merge li {
1832 list-style-type: none;
1809 list-style-type: none;
1833 }
1810 }
1834
1811
1835 .pull-request-merge .pull-request-wrap {
1812 .pull-request-merge .pull-request-wrap {
1836 height: auto;
1813 height: auto;
1837 padding: 0px 0px;
1814 padding: 0px 0px;
1838 text-align: right;
1815 text-align: right;
1839 }
1816 }
1840
1817
1841 .pull-request-merge span {
1818 .pull-request-merge span {
1842 margin-right: 5px;
1819 margin-right: 5px;
1843 }
1820 }
1844
1821
1845 .pull-request-merge-actions {
1822 .pull-request-merge-actions {
1846 min-height: 30px;
1823 min-height: 30px;
1847 padding: 0px 0px;
1824 padding: 0px 0px;
1848 }
1825 }
1849
1826
1850 .pull-request-merge-info {
1827 .pull-request-merge-info {
1851 padding: 0px 5px 5px 0px;
1828 padding: 0px 5px 5px 0px;
1852 }
1829 }
1853
1830
1854 .merge-status {
1831 .merge-status {
1855 margin-right: 5px;
1832 margin-right: 5px;
1856 }
1833 }
1857
1834
1858 .merge-message {
1835 .merge-message {
1859 font-size: 1.2em
1836 font-size: 1.2em
1860 }
1837 }
1861
1838
1862 .merge-message.success i,
1839 .merge-message.success i,
1863 .merge-icon.success i {
1840 .merge-icon.success i {
1864 color:@alert1;
1841 color:@alert1;
1865 }
1842 }
1866
1843
1867 .merge-message.warning i,
1844 .merge-message.warning i,
1868 .merge-icon.warning i {
1845 .merge-icon.warning i {
1869 color: @alert3;
1846 color: @alert3;
1870 }
1847 }
1871
1848
1872 .merge-message.error i,
1849 .merge-message.error i,
1873 .merge-icon.error i {
1850 .merge-icon.error i {
1874 color:@alert2;
1851 color:@alert2;
1875 }
1852 }
1876
1853
1877 .pr-versions {
1854 .pr-versions {
1878 font-size: 1.1em;
1855 font-size: 1.1em;
1879
1856
1880 table {
1857 table {
1881 padding: 0px 5px;
1858 padding: 0px 5px;
1882 }
1859 }
1883
1860
1884 td {
1861 td {
1885 line-height: 15px;
1862 line-height: 15px;
1886 }
1863 }
1887
1864
1888 .flag_status {
1889 margin: 0;
1890 }
1891
1892 .compare-radio-button {
1865 .compare-radio-button {
1893 position: relative;
1866 position: relative;
1894 top: -3px;
1867 top: -3px;
1895 }
1868 }
1896 }
1869 }
1897
1870
1898
1871
1899 #close_pull_request {
1872 #close_pull_request {
1900 margin-right: 0px;
1873 margin-right: 0px;
1901 }
1874 }
1902
1875
1903 .empty_data {
1876 .empty_data {
1904 color: @grey4;
1877 color: @grey4;
1905 }
1878 }
1906
1879
1907 #changeset_compare_view_content {
1880 #changeset_compare_view_content {
1908 clear: both;
1881 clear: both;
1909 width: 100%;
1882 width: 100%;
1910 box-sizing: border-box;
1883 box-sizing: border-box;
1911 .border-radius(@border-radius);
1884 .border-radius(@border-radius);
1912
1885
1913 .help-block {
1886 .help-block {
1914 margin: @padding 0;
1887 margin: @padding 0;
1915 color: @text-color;
1888 color: @text-color;
1916 &.pre-formatting {
1889 &.pre-formatting {
1917 white-space: pre;
1890 white-space: pre;
1918 }
1891 }
1919 }
1892 }
1920
1893
1921 .empty_data {
1894 .empty_data {
1922 margin: @padding 0;
1895 margin: @padding 0;
1923 }
1896 }
1924
1897
1925 .alert {
1898 .alert {
1926 margin-bottom: @space;
1899 margin-bottom: @space;
1927 }
1900 }
1928 }
1901 }
1929
1902
1930 .table_disp {
1903 .table_disp {
1931 .status {
1904 .status {
1932 width: auto;
1905 width: auto;
1933
1934 .flag_status {
1935 float: left;
1936 }
1937 }
1906 }
1938 }
1907 }
1939
1908
1940
1909
1941 .creation_in_progress {
1910 .creation_in_progress {
1942 color: @grey4
1911 color: @grey4
1943 }
1912 }
1944
1913
1945 .status_box_menu {
1914 .status_box_menu {
1946 margin: 0;
1915 margin: 0;
1947 }
1916 }
1948
1917
1949 .notification-table{
1918 .notification-table{
1950 margin-bottom: @space;
1919 margin-bottom: @space;
1951 display: table;
1920 display: table;
1952 width: 100%;
1921 width: 100%;
1953
1922
1954 .container{
1923 .container{
1955 display: table-row;
1924 display: table-row;
1956
1925
1957 .notification-header{
1926 .notification-header{
1958 border-bottom: @border-thickness solid @border-default-color;
1927 border-bottom: @border-thickness solid @border-default-color;
1959 }
1928 }
1960
1929
1961 .notification-subject{
1930 .notification-subject{
1962 display: table-cell;
1931 display: table-cell;
1963 }
1932 }
1964 }
1933 }
1965 }
1934 }
1966
1935
1967 // Notifications
1936 // Notifications
1968 .notification-header{
1937 .notification-header{
1969 display: table;
1938 display: table;
1970 width: 100%;
1939 width: 100%;
1971 padding: floor(@basefontsize/2) 0;
1940 padding: floor(@basefontsize/2) 0;
1972 line-height: 1em;
1941 line-height: 1em;
1973
1942
1974 .desc, .delete-notifications, .read-notifications{
1943 .desc, .delete-notifications, .read-notifications{
1975 display: table-cell;
1944 display: table-cell;
1976 text-align: left;
1945 text-align: left;
1977 }
1946 }
1978
1947
1979 .desc{
1948 .desc{
1980 width: 1163px;
1949 width: 1163px;
1981 }
1950 }
1982
1951
1983 .delete-notifications, .read-notifications{
1952 .delete-notifications, .read-notifications{
1984 width: 35px;
1953 width: 35px;
1985 min-width: 35px; //fixes when only one button is displayed
1954 min-width: 35px; //fixes when only one button is displayed
1986 }
1955 }
1987 }
1956 }
1988
1957
1989 .notification-body {
1958 .notification-body {
1990 .markdown-block,
1959 .markdown-block,
1991 .rst-block {
1960 .rst-block {
1992 padding: @padding 0;
1961 padding: @padding 0;
1993 }
1962 }
1994
1963
1995 .notification-subject {
1964 .notification-subject {
1996 padding: @textmargin 0;
1965 padding: @textmargin 0;
1997 border-bottom: @border-thickness solid @border-default-color;
1966 border-bottom: @border-thickness solid @border-default-color;
1998 }
1967 }
1999 }
1968 }
2000
1969
2001
1970
2002 .notifications_buttons{
1971 .notifications_buttons{
2003 float: right;
1972 float: right;
2004 }
1973 }
2005
1974
2006 #notification-status{
1975 #notification-status{
2007 display: inline;
1976 display: inline;
2008 }
1977 }
2009
1978
2010 // Repositories
1979 // Repositories
2011
1980
2012 #summary.fields{
1981 #summary.fields{
2013 display: table;
1982 display: table;
2014
1983
2015 .field{
1984 .field{
2016 display: table-row;
1985 display: table-row;
2017
1986
2018 .label-summary{
1987 .label-summary{
2019 display: table-cell;
1988 display: table-cell;
2020 min-width: @label-summary-minwidth;
1989 min-width: @label-summary-minwidth;
2021 padding-top: @padding/2;
1990 padding-top: @padding/2;
2022 padding-bottom: @padding/2;
1991 padding-bottom: @padding/2;
2023 padding-right: @padding/2;
1992 padding-right: @padding/2;
2024 }
1993 }
2025
1994
2026 .input{
1995 .input{
2027 display: table-cell;
1996 display: table-cell;
2028 padding: @padding/2;
1997 padding: @padding/2;
2029
1998
2030 input{
1999 input{
2031 min-width: 29em;
2000 min-width: 29em;
2032 padding: @padding/4;
2001 padding: @padding/4;
2033 }
2002 }
2034 }
2003 }
2035 .statistics, .downloads{
2004 .statistics, .downloads{
2036 .disabled{
2005 .disabled{
2037 color: @grey4;
2006 color: @grey4;
2038 }
2007 }
2039 }
2008 }
2040 }
2009 }
2041 }
2010 }
2042
2011
2043 #summary{
2012 #summary{
2044 width: 70%;
2013 width: 70%;
2045 }
2014 }
2046
2015
2047
2016
2048 // Journal
2017 // Journal
2049 .journal.title {
2018 .journal.title {
2050 h5 {
2019 h5 {
2051 float: left;
2020 float: left;
2052 margin: 0;
2021 margin: 0;
2053 width: 70%;
2022 width: 70%;
2054 }
2023 }
2055
2024
2056 ul {
2025 ul {
2057 float: right;
2026 float: right;
2058 display: inline-block;
2027 display: inline-block;
2059 margin: 0;
2028 margin: 0;
2060 width: 30%;
2029 width: 30%;
2061 text-align: right;
2030 text-align: right;
2062
2031
2063 li {
2032 li {
2064 display: inline;
2033 display: inline;
2065 font-size: @journal-fontsize;
2034 font-size: @journal-fontsize;
2066 line-height: 1em;
2035 line-height: 1em;
2067
2036
2068 list-style-type: none;
2037 list-style-type: none;
2069 }
2038 }
2070 }
2039 }
2071 }
2040 }
2072
2041
2073 .filterexample {
2042 .filterexample {
2074 position: absolute;
2043 position: absolute;
2075 top: 95px;
2044 top: 95px;
2076 left: @contentpadding;
2045 left: @contentpadding;
2077 color: @rcblue;
2046 color: @rcblue;
2078 font-size: 11px;
2047 font-size: 11px;
2079 font-family: @text-regular;
2048 font-family: @text-regular;
2080 cursor: help;
2049 cursor: help;
2081
2050
2082 &:hover {
2051 &:hover {
2083 color: @rcdarkblue;
2052 color: @rcdarkblue;
2084 }
2053 }
2085
2054
2086 @media (max-width:768px) {
2055 @media (max-width:768px) {
2087 position: relative;
2056 position: relative;
2088 top: auto;
2057 top: auto;
2089 left: auto;
2058 left: auto;
2090 display: block;
2059 display: block;
2091 }
2060 }
2092 }
2061 }
2093
2062
2094
2063
2095 #journal{
2064 #journal{
2096 margin-bottom: @space;
2065 margin-bottom: @space;
2097
2066
2098 .journal_day{
2067 .journal_day{
2099 margin-bottom: @textmargin/2;
2068 margin-bottom: @textmargin/2;
2100 padding-bottom: @textmargin/2;
2069 padding-bottom: @textmargin/2;
2101 font-size: @journal-fontsize;
2070 font-size: @journal-fontsize;
2102 border-bottom: @border-thickness solid @border-default-color;
2071 border-bottom: @border-thickness solid @border-default-color;
2103 }
2072 }
2104
2073
2105 .journal_container{
2074 .journal_container{
2106 margin-bottom: @space;
2075 margin-bottom: @space;
2107
2076
2108 .journal_user{
2077 .journal_user{
2109 display: inline-block;
2078 display: inline-block;
2110 }
2079 }
2111 .journal_action_container{
2080 .journal_action_container{
2112 display: block;
2081 display: block;
2113 margin-top: @textmargin;
2082 margin-top: @textmargin;
2114
2083
2115 div{
2084 div{
2116 display: inline;
2085 display: inline;
2117 }
2086 }
2118
2087
2119 div.journal_action_params{
2088 div.journal_action_params{
2120 display: block;
2089 display: block;
2121 }
2090 }
2122
2091
2123 div.journal_repo:after{
2092 div.journal_repo:after{
2124 content: "\A";
2093 content: "\A";
2125 white-space: pre;
2094 white-space: pre;
2126 }
2095 }
2127
2096
2128 div.date{
2097 div.date{
2129 display: block;
2098 display: block;
2130 margin-bottom: @textmargin;
2099 margin-bottom: @textmargin;
2131 }
2100 }
2132 }
2101 }
2133 }
2102 }
2134 }
2103 }
2135
2104
2136 // Files
2105 // Files
2137 .edit-file-title {
2106 .edit-file-title {
2138 font-size: 16px;
2107 font-size: 16px;
2139
2108
2140 .title-heading {
2109 .title-heading {
2141 padding: 2px;
2110 padding: 2px;
2142 }
2111 }
2143 }
2112 }
2144
2113
2145 .edit-file-fieldset {
2114 .edit-file-fieldset {
2146 margin: @sidebarpadding 0;
2115 margin: @sidebarpadding 0;
2147
2116
2148 .fieldset {
2117 .fieldset {
2149 .left-label {
2118 .left-label {
2150 width: 13%;
2119 width: 13%;
2151 }
2120 }
2152 .right-content {
2121 .right-content {
2153 width: 87%;
2122 width: 87%;
2154 max-width: 100%;
2123 max-width: 100%;
2155 }
2124 }
2156 .filename-label {
2125 .filename-label {
2157 margin-top: 13px;
2126 margin-top: 13px;
2158 }
2127 }
2159 .commit-message-label {
2128 .commit-message-label {
2160 margin-top: 4px;
2129 margin-top: 4px;
2161 }
2130 }
2162 .file-upload-input {
2131 .file-upload-input {
2163 input {
2132 input {
2164 display: none;
2133 display: none;
2165 }
2134 }
2166 margin-top: 10px;
2135 margin-top: 10px;
2167 }
2136 }
2168 .file-upload-label {
2137 .file-upload-label {
2169 margin-top: 10px;
2138 margin-top: 10px;
2170 }
2139 }
2171 p {
2140 p {
2172 margin-top: 5px;
2141 margin-top: 5px;
2173 }
2142 }
2174
2143
2175 }
2144 }
2176 .custom-path-link {
2145 .custom-path-link {
2177 margin-left: 5px;
2146 margin-left: 5px;
2178 }
2147 }
2179 #commit {
2148 #commit {
2180 resize: vertical;
2149 resize: vertical;
2181 }
2150 }
2182 }
2151 }
2183
2152
2184 .delete-file-preview {
2153 .delete-file-preview {
2185 max-height: 250px;
2154 max-height: 250px;
2186 }
2155 }
2187
2156
2188 .new-file,
2157 .new-file,
2189 #filter_activate,
2158 #filter_activate,
2190 #filter_deactivate {
2159 #filter_deactivate {
2191 float: right;
2160 float: right;
2192 margin: 0 0 0 10px;
2161 margin: 0 0 0 10px;
2193 }
2162 }
2194
2163
2195 .file-upload-transaction-wrapper {
2164 .file-upload-transaction-wrapper {
2196 margin-top: 57px;
2165 margin-top: 57px;
2197 clear: both;
2166 clear: both;
2198 }
2167 }
2199
2168
2200 .file-upload-transaction-wrapper .error {
2169 .file-upload-transaction-wrapper .error {
2201 color: @color5;
2170 color: @color5;
2202 }
2171 }
2203
2172
2204 .file-upload-transaction {
2173 .file-upload-transaction {
2205 min-height: 200px;
2174 min-height: 200px;
2206 padding: 54px;
2175 padding: 54px;
2207 border: 1px solid @grey5;
2176 border: 1px solid @grey5;
2208 text-align: center;
2177 text-align: center;
2209 clear: both;
2178 clear: both;
2210 }
2179 }
2211
2180
2212 .file-upload-transaction i {
2181 .file-upload-transaction i {
2213 font-size: 48px
2182 font-size: 48px
2214 }
2183 }
2215
2184
2216 h3.files_location{
2185 h3.files_location{
2217 line-height: 2.4em;
2186 line-height: 2.4em;
2218 }
2187 }
2219
2188
2220 .browser-nav {
2189 .browser-nav {
2221 width: 100%;
2190 width: 100%;
2222 display: table;
2191 display: table;
2223 margin-bottom: 20px;
2192 margin-bottom: 20px;
2224
2193
2225 .info_box {
2194 .info_box {
2226 float: left;
2195 float: left;
2227 display: inline-table;
2196 display: inline-table;
2228 height: 2.5em;
2197 height: 2.5em;
2229
2198
2230 .browser-cur-rev, .info_box_elem {
2199 .browser-cur-rev, .info_box_elem {
2231 display: table-cell;
2200 display: table-cell;
2232 vertical-align: middle;
2201 vertical-align: middle;
2233 }
2202 }
2234
2203
2235 .drop-menu {
2204 .drop-menu {
2236 margin: 0 10px;
2205 margin: 0 10px;
2237 }
2206 }
2238
2207
2239 .info_box_elem {
2208 .info_box_elem {
2240 border-top: @border-thickness solid @grey5;
2209 border-top: @border-thickness solid @grey5;
2241 border-bottom: @border-thickness solid @grey5;
2210 border-bottom: @border-thickness solid @grey5;
2242 box-shadow: @button-shadow;
2211 box-shadow: @button-shadow;
2243
2212
2244 #at_rev, a {
2213 #at_rev, a {
2245 padding: 0.6em 0.4em;
2214 padding: 0.6em 0.4em;
2246 margin: 0;
2215 margin: 0;
2247 .box-shadow(none);
2216 .box-shadow(none);
2248 border: 0;
2217 border: 0;
2249 height: 12px;
2218 height: 12px;
2250 color: @grey2;
2219 color: @grey2;
2251 }
2220 }
2252
2221
2253 input#at_rev {
2222 input#at_rev {
2254 max-width: 50px;
2223 max-width: 50px;
2255 text-align: center;
2224 text-align: center;
2256 }
2225 }
2257
2226
2258 &.previous {
2227 &.previous {
2259 border: @border-thickness solid @grey5;
2228 border: @border-thickness solid @grey5;
2260 border-top-left-radius: @border-radius;
2229 border-top-left-radius: @border-radius;
2261 border-bottom-left-radius: @border-radius;
2230 border-bottom-left-radius: @border-radius;
2262
2231
2263 &:hover {
2232 &:hover {
2264 border-color: @grey4;
2233 border-color: @grey4;
2265 }
2234 }
2266
2235
2267 .disabled {
2236 .disabled {
2268 color: @grey5;
2237 color: @grey5;
2269 cursor: not-allowed;
2238 cursor: not-allowed;
2270 opacity: 0.5;
2239 opacity: 0.5;
2271 }
2240 }
2272 }
2241 }
2273
2242
2274 &.next {
2243 &.next {
2275 border: @border-thickness solid @grey5;
2244 border: @border-thickness solid @grey5;
2276 border-top-right-radius: @border-radius;
2245 border-top-right-radius: @border-radius;
2277 border-bottom-right-radius: @border-radius;
2246 border-bottom-right-radius: @border-radius;
2278
2247
2279 &:hover {
2248 &:hover {
2280 border-color: @grey4;
2249 border-color: @grey4;
2281 }
2250 }
2282
2251
2283 .disabled {
2252 .disabled {
2284 color: @grey5;
2253 color: @grey5;
2285 cursor: not-allowed;
2254 cursor: not-allowed;
2286 opacity: 0.5;
2255 opacity: 0.5;
2287 }
2256 }
2288 }
2257 }
2289 }
2258 }
2290
2259
2291 .browser-cur-rev {
2260 .browser-cur-rev {
2292
2261
2293 span{
2262 span{
2294 margin: 0;
2263 margin: 0;
2295 color: @rcblue;
2264 color: @rcblue;
2296 height: 12px;
2265 height: 12px;
2297 display: inline-block;
2266 display: inline-block;
2298 padding: 0.7em 1em ;
2267 padding: 0.7em 1em ;
2299 border: @border-thickness solid @rcblue;
2268 border: @border-thickness solid @rcblue;
2300 margin-right: @padding;
2269 margin-right: @padding;
2301 }
2270 }
2302 }
2271 }
2303
2272
2304 }
2273 }
2305
2274
2306 .select-index-number {
2275 .select-index-number {
2307 margin: 0 0 0 20px;
2276 margin: 0 0 0 20px;
2308 color: @grey3;
2277 color: @grey3;
2309 }
2278 }
2310
2279
2311 .search_activate {
2280 .search_activate {
2312 display: table-cell;
2281 display: table-cell;
2313 vertical-align: middle;
2282 vertical-align: middle;
2314
2283
2315 input, label{
2284 input, label{
2316 margin: 0;
2285 margin: 0;
2317 padding: 0;
2286 padding: 0;
2318 }
2287 }
2319
2288
2320 input{
2289 input{
2321 margin-left: @textmargin;
2290 margin-left: @textmargin;
2322 }
2291 }
2323
2292
2324 }
2293 }
2325 }
2294 }
2326
2295
2327 .browser-cur-rev{
2296 .browser-cur-rev{
2328 margin-bottom: @textmargin;
2297 margin-bottom: @textmargin;
2329 }
2298 }
2330
2299
2331 #node_filter_box_loading{
2300 #node_filter_box_loading{
2332 .info_text;
2301 .info_text;
2333 }
2302 }
2334
2303
2335 .browser-search {
2304 .browser-search {
2336 margin: -25px 0px 5px 0px;
2305 margin: -25px 0px 5px 0px;
2337 }
2306 }
2338
2307
2339 .files-quick-filter {
2308 .files-quick-filter {
2340 float: right;
2309 float: right;
2341 width: 180px;
2310 width: 180px;
2342 position: relative;
2311 position: relative;
2343 }
2312 }
2344
2313
2345 .files-filter-box {
2314 .files-filter-box {
2346 display: flex;
2315 display: flex;
2347 padding: 0px;
2316 padding: 0px;
2348 border-radius: 3px;
2317 border-radius: 3px;
2349 margin-bottom: 0;
2318 margin-bottom: 0;
2350
2319
2351 a {
2320 a {
2352 border: none !important;
2321 border: none !important;
2353 }
2322 }
2354
2323
2355 li {
2324 li {
2356 list-style-type: none
2325 list-style-type: none
2357 }
2326 }
2358 }
2327 }
2359
2328
2360 .files-filter-box-path {
2329 .files-filter-box-path {
2361 line-height: 33px;
2330 line-height: 33px;
2362 padding: 0;
2331 padding: 0;
2363 width: 20px;
2332 width: 20px;
2364 position: absolute;
2333 position: absolute;
2365 z-index: 11;
2334 z-index: 11;
2366 left: 5px;
2335 left: 5px;
2367 }
2336 }
2368
2337
2369 .files-filter-box-input {
2338 .files-filter-box-input {
2370 margin-right: 0;
2339 margin-right: 0;
2371
2340
2372 input {
2341 input {
2373 border: 1px solid @white;
2342 border: 1px solid @white;
2374 padding-left: 25px;
2343 padding-left: 25px;
2375 width: 145px;
2344 width: 145px;
2376
2345
2377 &:hover {
2346 &:hover {
2378 border-color: @grey6;
2347 border-color: @grey6;
2379 }
2348 }
2380
2349
2381 &:focus {
2350 &:focus {
2382 border-color: @grey5;
2351 border-color: @grey5;
2383 }
2352 }
2384 }
2353 }
2385 }
2354 }
2386
2355
2387 .browser-result{
2356 .browser-result{
2388 td a{
2357 td a{
2389 margin-left: 0.5em;
2358 margin-left: 0.5em;
2390 display: inline-block;
2359 display: inline-block;
2391
2360
2392 em {
2361 em {
2393 font-weight: @text-bold-weight;
2362 font-weight: @text-bold-weight;
2394 font-family: @text-bold;
2363 font-family: @text-bold;
2395 }
2364 }
2396 }
2365 }
2397 }
2366 }
2398
2367
2399 .browser-highlight{
2368 .browser-highlight{
2400 background-color: @grey5-alpha;
2369 background-color: @grey5-alpha;
2401 }
2370 }
2402
2371
2403
2372
2404 .edit-file-fieldset #location,
2373 .edit-file-fieldset #location,
2405 .edit-file-fieldset #filename {
2374 .edit-file-fieldset #filename {
2406 display: flex;
2375 display: flex;
2407 width: -moz-available; /* WebKit-based browsers will ignore this. */
2376 width: -moz-available; /* WebKit-based browsers will ignore this. */
2408 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2377 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2409 width: fill-available;
2378 width: fill-available;
2410 border: 0;
2379 border: 0;
2411 }
2380 }
2412
2381
2413 .path-items {
2382 .path-items {
2414 display: flex;
2383 display: flex;
2415 padding: 0;
2384 padding: 0;
2416 border: 1px solid #eeeeee;
2385 border: 1px solid #eeeeee;
2417 width: 100%;
2386 width: 100%;
2418 float: left;
2387 float: left;
2419
2388
2420 .breadcrumb-path {
2389 .breadcrumb-path {
2421 line-height: 30px;
2390 line-height: 30px;
2422 padding: 0 4px;
2391 padding: 0 4px;
2423 white-space: nowrap;
2392 white-space: nowrap;
2424 }
2393 }
2425
2394
2426 .location-path {
2395 .location-path {
2427 width: -moz-available; /* WebKit-based browsers will ignore this. */
2396 width: -moz-available; /* WebKit-based browsers will ignore this. */
2428 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2397 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2429 width: fill-available;
2398 width: fill-available;
2430
2399
2431 .file-name-input {
2400 .file-name-input {
2432 padding: 0.5em 0;
2401 padding: 0.5em 0;
2433 }
2402 }
2434
2403
2435 }
2404 }
2436
2405
2437 ul {
2406 ul {
2438 display: flex;
2407 display: flex;
2439 margin: 0;
2408 margin: 0;
2440 padding: 0;
2409 padding: 0;
2441 width: 100%;
2410 width: 100%;
2442 }
2411 }
2443
2412
2444 li {
2413 li {
2445 list-style-type: none;
2414 list-style-type: none;
2446 }
2415 }
2447
2416
2448 }
2417 }
2449
2418
2450 .editor-items {
2419 .editor-items {
2451 height: 40px;
2420 height: 40px;
2452 margin: 10px 0 -17px 10px;
2421 margin: 10px 0 -17px 10px;
2453
2422
2454 .editor-action {
2423 .editor-action {
2455 cursor: pointer;
2424 cursor: pointer;
2456 }
2425 }
2457
2426
2458 .editor-action.active {
2427 .editor-action.active {
2459 border-bottom: 2px solid #5C5C5C;
2428 border-bottom: 2px solid #5C5C5C;
2460 }
2429 }
2461
2430
2462 li {
2431 li {
2463 list-style-type: none;
2432 list-style-type: none;
2464 }
2433 }
2465 }
2434 }
2466
2435
2467 .edit-file-fieldset .message textarea {
2436 .edit-file-fieldset .message textarea {
2468 border: 1px solid #eeeeee;
2437 border: 1px solid #eeeeee;
2469 }
2438 }
2470
2439
2471 #files_data .codeblock {
2440 #files_data .codeblock {
2472 background-color: #F5F5F5;
2441 background-color: #F5F5F5;
2473 }
2442 }
2474
2443
2475 #editor_preview {
2444 #editor_preview {
2476 background: white;
2445 background: white;
2477 }
2446 }
2478
2447
2479 .show-editor {
2448 .show-editor {
2480 padding: 10px;
2449 padding: 10px;
2481 background-color: white;
2450 background-color: white;
2482
2451
2483 }
2452 }
2484
2453
2485 .show-preview {
2454 .show-preview {
2486 padding: 10px;
2455 padding: 10px;
2487 background-color: white;
2456 background-color: white;
2488 border-left: 1px solid #eeeeee;
2457 border-left: 1px solid #eeeeee;
2489 }
2458 }
2490 // quick filter
2459 // quick filter
2491 .grid-quick-filter {
2460 .grid-quick-filter {
2492 float: right;
2461 float: right;
2493 position: relative;
2462 position: relative;
2494 }
2463 }
2495
2464
2496 .grid-filter-box {
2465 .grid-filter-box {
2497 display: flex;
2466 display: flex;
2498 padding: 0px;
2467 padding: 0px;
2499 border-radius: 3px;
2468 border-radius: 3px;
2500 margin-bottom: 0;
2469 margin-bottom: 0;
2501
2470
2502 a {
2471 a {
2503 border: none !important;
2472 border: none !important;
2504 }
2473 }
2505
2474
2506 li {
2475 li {
2507 list-style-type: none
2476 list-style-type: none
2508 }
2477 }
2509 }
2478 }
2510
2479
2511 .grid-filter-box-icon {
2480 .grid-filter-box-icon {
2512 line-height: 33px;
2481 line-height: 33px;
2513 padding: 0;
2482 padding: 0;
2514 width: 20px;
2483 width: 20px;
2515 position: absolute;
2484 position: absolute;
2516 z-index: 11;
2485 z-index: 11;
2517 left: 5px;
2486 left: 5px;
2518 }
2487 }
2519
2488
2520 .grid-filter-box-input {
2489 .grid-filter-box-input {
2521 margin-right: 0;
2490 margin-right: 0;
2522
2491
2523 input {
2492 input {
2524 border: 1px solid @white;
2493 border: 1px solid @white;
2525 padding-left: 25px;
2494 padding-left: 25px;
2526 width: 145px;
2495 width: 145px;
2527
2496
2528 &:hover {
2497 &:hover {
2529 border-color: @grey6;
2498 border-color: @grey6;
2530 }
2499 }
2531
2500
2532 &:focus {
2501 &:focus {
2533 border-color: @grey5;
2502 border-color: @grey5;
2534 }
2503 }
2535 }
2504 }
2536 }
2505 }
2537
2506
2538
2507
2539
2508
2540 // Search
2509 // Search
2541
2510
2542 .search-form{
2511 .search-form{
2543 #q {
2512 #q {
2544 width: @search-form-width;
2513 width: @search-form-width;
2545 }
2514 }
2546 .fields{
2515 .fields{
2547 margin: 0 0 @space;
2516 margin: 0 0 @space;
2548 }
2517 }
2549
2518
2550 label{
2519 label{
2551 display: inline-block;
2520 display: inline-block;
2552 margin-right: @textmargin;
2521 margin-right: @textmargin;
2553 padding-top: 0.25em;
2522 padding-top: 0.25em;
2554 }
2523 }
2555
2524
2556
2525
2557 .results{
2526 .results{
2558 clear: both;
2527 clear: both;
2559 margin: 0 0 @padding;
2528 margin: 0 0 @padding;
2560 }
2529 }
2561
2530
2562 .search-tags {
2531 .search-tags {
2563 padding: 5px 0;
2532 padding: 5px 0;
2564 }
2533 }
2565 }
2534 }
2566
2535
2567 div.search-feedback-items {
2536 div.search-feedback-items {
2568 display: inline-block;
2537 display: inline-block;
2569 }
2538 }
2570
2539
2571 div.search-code-body {
2540 div.search-code-body {
2572 background-color: #ffffff; padding: 5px 0 5px 10px;
2541 background-color: #ffffff; padding: 5px 0 5px 10px;
2573 pre {
2542 pre {
2574 .match { background-color: #faffa6;}
2543 .match { background-color: #faffa6;}
2575 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2544 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2576 }
2545 }
2577 }
2546 }
2578
2547
2579 .expand_commit.search {
2548 .expand_commit.search {
2580 .show_more.open {
2549 .show_more.open {
2581 height: auto;
2550 height: auto;
2582 max-height: none;
2551 max-height: none;
2583 }
2552 }
2584 }
2553 }
2585
2554
2586 .search-results {
2555 .search-results {
2587
2556
2588 h2 {
2557 h2 {
2589 margin-bottom: 0;
2558 margin-bottom: 0;
2590 }
2559 }
2591 .codeblock {
2560 .codeblock {
2592 border: none;
2561 border: none;
2593 background: transparent;
2562 background: transparent;
2594 }
2563 }
2595
2564
2596 .codeblock-header {
2565 .codeblock-header {
2597 border: none;
2566 border: none;
2598 background: transparent;
2567 background: transparent;
2599 }
2568 }
2600
2569
2601 .code-body {
2570 .code-body {
2602 border: @border-thickness solid @grey6;
2571 border: @border-thickness solid @grey6;
2603 .border-radius(@border-radius);
2572 .border-radius(@border-radius);
2604 }
2573 }
2605
2574
2606 .td-commit {
2575 .td-commit {
2607 &:extend(pre);
2576 &:extend(pre);
2608 border-bottom: @border-thickness solid @border-default-color;
2577 border-bottom: @border-thickness solid @border-default-color;
2609 }
2578 }
2610
2579
2611 .message {
2580 .message {
2612 height: auto;
2581 height: auto;
2613 max-width: 350px;
2582 max-width: 350px;
2614 white-space: normal;
2583 white-space: normal;
2615 text-overflow: initial;
2584 text-overflow: initial;
2616 overflow: visible;
2585 overflow: visible;
2617
2586
2618 .match { background-color: #faffa6;}
2587 .match { background-color: #faffa6;}
2619 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2588 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2620 }
2589 }
2621
2590
2622 .path {
2591 .path {
2623 border-bottom: none !important;
2592 border-bottom: none !important;
2624 border-left: 1px solid @grey6 !important;
2593 border-left: 1px solid @grey6 !important;
2625 border-right: 1px solid @grey6 !important;
2594 border-right: 1px solid @grey6 !important;
2626 }
2595 }
2627 }
2596 }
2628
2597
2629 table.rctable td.td-search-results div {
2598 table.rctable td.td-search-results div {
2630 max-width: 100%;
2599 max-width: 100%;
2631 }
2600 }
2632
2601
2633 #tip-box, .tip-box{
2602 #tip-box, .tip-box{
2634 padding: @menupadding/2;
2603 padding: @menupadding/2;
2635 display: block;
2604 display: block;
2636 border: @border-thickness solid @border-highlight-color;
2605 border: @border-thickness solid @border-highlight-color;
2637 .border-radius(@border-radius);
2606 .border-radius(@border-radius);
2638 background-color: white;
2607 background-color: white;
2639 z-index: 99;
2608 z-index: 99;
2640 white-space: pre-wrap;
2609 white-space: pre-wrap;
2641 }
2610 }
2642
2611
2643 #linktt {
2612 #linktt {
2644 width: 79px;
2613 width: 79px;
2645 }
2614 }
2646
2615
2647 #help_kb .modal-content{
2616 #help_kb .modal-content{
2648 max-width: 750px;
2617 max-width: 750px;
2649 margin: 10% auto;
2618 margin: 10% auto;
2650
2619
2651 table{
2620 table{
2652 td,th{
2621 td,th{
2653 border-bottom: none;
2622 border-bottom: none;
2654 line-height: 2.5em;
2623 line-height: 2.5em;
2655 }
2624 }
2656 th{
2625 th{
2657 padding-bottom: @textmargin/2;
2626 padding-bottom: @textmargin/2;
2658 }
2627 }
2659 td.keys{
2628 td.keys{
2660 text-align: center;
2629 text-align: center;
2661 }
2630 }
2662 }
2631 }
2663
2632
2664 .block-left{
2633 .block-left{
2665 width: 45%;
2634 width: 45%;
2666 margin-right: 5%;
2635 margin-right: 5%;
2667 }
2636 }
2668 .modal-footer{
2637 .modal-footer{
2669 clear: both;
2638 clear: both;
2670 }
2639 }
2671 .key.tag{
2640 .key.tag{
2672 padding: 0.5em;
2641 padding: 0.5em;
2673 background-color: @rcblue;
2642 background-color: @rcblue;
2674 color: white;
2643 color: white;
2675 border-color: @rcblue;
2644 border-color: @rcblue;
2676 .box-shadow(none);
2645 .box-shadow(none);
2677 }
2646 }
2678 }
2647 }
2679
2648
2680
2649
2681
2650
2682 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2651 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2683
2652
2684 @import 'statistics-graph';
2653 @import 'statistics-graph';
2685 @import 'tables';
2654 @import 'tables';
2686 @import 'forms';
2655 @import 'forms';
2687 @import 'diff';
2656 @import 'diff';
2688 @import 'summary';
2657 @import 'summary';
2689 @import 'navigation';
2658 @import 'navigation';
2690
2659
2691 //--- SHOW/HIDE SECTIONS --//
2660 //--- SHOW/HIDE SECTIONS --//
2692
2661
2693 .btn-collapse {
2662 .btn-collapse {
2694 float: right;
2663 float: right;
2695 text-align: right;
2664 text-align: right;
2696 font-family: @text-light;
2665 font-family: @text-light;
2697 font-size: @basefontsize;
2666 font-size: @basefontsize;
2698 cursor: pointer;
2667 cursor: pointer;
2699 border: none;
2668 border: none;
2700 color: @rcblue;
2669 color: @rcblue;
2701 }
2670 }
2702
2671
2703 table.rctable,
2672 table.rctable,
2704 table.dataTable {
2673 table.dataTable {
2705 .btn-collapse {
2674 .btn-collapse {
2706 float: right;
2675 float: right;
2707 text-align: right;
2676 text-align: right;
2708 }
2677 }
2709 }
2678 }
2710
2679
2711 table.rctable {
2680 table.rctable {
2712 &.permissions {
2681 &.permissions {
2713
2682
2714 th.td-owner {
2683 th.td-owner {
2715 padding: 0;
2684 padding: 0;
2716 }
2685 }
2717
2686
2718 th {
2687 th {
2719 font-weight: normal;
2688 font-weight: normal;
2720 padding: 0 5px;
2689 padding: 0 5px;
2721 }
2690 }
2722
2691
2723 }
2692 }
2724 }
2693 }
2725
2694
2726
2695
2727 // TODO: johbo: Fix for IE10, this avoids that we see a border
2696 // TODO: johbo: Fix for IE10, this avoids that we see a border
2728 // and padding around checkboxes and radio boxes. Move to the right place,
2697 // and padding around checkboxes and radio boxes. Move to the right place,
2729 // or better: Remove this once we did the form refactoring.
2698 // or better: Remove this once we did the form refactoring.
2730 input[type=checkbox],
2699 input[type=checkbox],
2731 input[type=radio] {
2700 input[type=radio] {
2732 padding: 0;
2701 padding: 0;
2733 border: none;
2702 border: none;
2734 }
2703 }
2735
2704
2736 .toggle-ajax-spinner{
2705 .toggle-ajax-spinner{
2737 height: 16px;
2706 height: 16px;
2738 width: 16px;
2707 width: 16px;
2739 }
2708 }
2740
2709
2741
2710
2742 .markup-form .clearfix {
2711 .markup-form .clearfix {
2743 .border-radius(@border-radius);
2712 .border-radius(@border-radius);
2744 margin: 0px;
2713 margin: 0px;
2745 }
2714 }
2746
2715
2747 .markup-form-area {
2716 .markup-form-area {
2748 padding: 8px 12px;
2717 padding: 8px 12px;
2749 border: 1px solid @grey4;
2718 border: 1px solid @grey4;
2750 .border-radius(@border-radius);
2719 .border-radius(@border-radius);
2751 }
2720 }
2752
2721
2753 .markup-form-area-header .nav-links {
2722 .markup-form-area-header .nav-links {
2754 display: flex;
2723 display: flex;
2755 flex-flow: row wrap;
2724 flex-flow: row wrap;
2756 -webkit-flex-flow: row wrap;
2725 -webkit-flex-flow: row wrap;
2757 width: 100%;
2726 width: 100%;
2758 }
2727 }
2759
2728
2760 .markup-form-area-footer {
2729 .markup-form-area-footer {
2761 display: flex;
2730 display: flex;
2762 }
2731 }
2763
2732
2764 .markup-form-area-footer .toolbar {
2733 .markup-form-area-footer .toolbar {
2765
2734
2766 }
2735 }
2767
2736
2768 // markup Form
2737 // markup Form
2769 div.markup-form {
2738 div.markup-form {
2770 margin-top: 20px;
2739 margin-top: 20px;
2771 }
2740 }
2772
2741
2773 .markup-form strong {
2742 .markup-form strong {
2774 display: block;
2743 display: block;
2775 margin-bottom: 15px;
2744 margin-bottom: 15px;
2776 }
2745 }
2777
2746
2778 .markup-form textarea {
2747 .markup-form textarea {
2779 width: 100%;
2748 width: 100%;
2780 height: 100px;
2749 height: 100px;
2781 font-family: @text-monospace;
2750 font-family: @text-monospace;
2782 }
2751 }
2783
2752
2784 form.markup-form {
2753 form.markup-form {
2785 margin-top: 10px;
2754 margin-top: 10px;
2786 margin-left: 10px;
2755 margin-left: 10px;
2787 }
2756 }
2788
2757
2789 .markup-form .comment-block-ta,
2758 .markup-form .comment-block-ta,
2790 .markup-form .preview-box {
2759 .markup-form .preview-box {
2791 .border-radius(@border-radius);
2760 .border-radius(@border-radius);
2792 .box-sizing(border-box);
2761 .box-sizing(border-box);
2793 background-color: white;
2762 background-color: white;
2794 }
2763 }
2795
2764
2796 .markup-form .preview-box.unloaded {
2765 .markup-form .preview-box.unloaded {
2797 height: 50px;
2766 height: 50px;
2798 text-align: center;
2767 text-align: center;
2799 padding: 20px;
2768 padding: 20px;
2800 background-color: white;
2769 background-color: white;
2801 }
2770 }
2802
2771
2803
2772
2804 .dropzone-wrapper {
2773 .dropzone-wrapper {
2805 border: 1px solid @grey5;
2774 border: 1px solid @grey5;
2806 padding: 20px;
2775 padding: 20px;
2807 }
2776 }
2808
2777
2809 .dropzone,
2778 .dropzone,
2810 .dropzone-pure {
2779 .dropzone-pure {
2811 border: 2px dashed @grey5;
2780 border: 2px dashed @grey5;
2812 border-radius: 5px;
2781 border-radius: 5px;
2813 background: white;
2782 background: white;
2814 min-height: 200px;
2783 min-height: 200px;
2815 padding: 54px;
2784 padding: 54px;
2816
2785
2817 .dz-message {
2786 .dz-message {
2818 font-weight: 700;
2787 font-weight: 700;
2819 text-align: center;
2788 text-align: center;
2820 margin: 2em 0;
2789 margin: 2em 0;
2821 }
2790 }
2822
2791
2823 }
2792 }
2824
2793
2825 .dz-preview {
2794 .dz-preview {
2826 margin: 10px 0 !important;
2795 margin: 10px 0 !important;
2827 position: relative;
2796 position: relative;
2828 vertical-align: top;
2797 vertical-align: top;
2829 padding: 10px;
2798 padding: 10px;
2830 border-bottom: 1px solid @grey5;
2799 border-bottom: 1px solid @grey5;
2831 }
2800 }
2832
2801
2833 .dz-filename {
2802 .dz-filename {
2834 font-weight: 700;
2803 font-weight: 700;
2835 float:left;
2804 float:left;
2836 }
2805 }
2837
2806
2838 .dz-sending {
2807 .dz-sending {
2839 float: right;
2808 float: right;
2840 }
2809 }
2841
2810
2842 .dz-response {
2811 .dz-response {
2843 clear:both
2812 clear:both
2844 }
2813 }
2845
2814
2846 .dz-filename-size {
2815 .dz-filename-size {
2847 float:right
2816 float:right
2848 }
2817 }
2849
2818
2850 .dz-error-message {
2819 .dz-error-message {
2851 color: @alert2;
2820 color: @alert2;
2852 padding-top: 10px;
2821 padding-top: 10px;
2853 clear: both;
2822 clear: both;
2854 }
2823 }
@@ -1,242 +1,234 b''
1 // select2.less
1 // select2.less
2 // For use in RhodeCode application drop down select boxes;
2 // For use in RhodeCode application drop down select boxes;
3 // see style guide documentation for guidelines.
3 // see style guide documentation for guidelines.
4
4
5
5
6 // SELECT2 DROPDOWN MENUS
6 // SELECT2 DROPDOWN MENUS
7
7
8 //Select2 Dropdown
8 //Select2 Dropdown
9 .select2-results{
9 .select2-results{
10 .box-sizing(border-box);
10 .box-sizing(border-box);
11 overflow-y: scroll;
11 overflow-y: scroll;
12 }
12 }
13
13
14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
15 .select2-container,
15 .select2-container,
16 .select2-drop,
16 .select2-drop,
17 .select2-search,
17 .select2-search,
18 .select2-search input {.box-sizing(border-box);}
18 .select2-search input {.box-sizing(border-box);}
19 .select2-container .select2-choice{display:block; line-height:1em; -webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;user-select:none; }
19 .select2-container .select2-choice{display:block; line-height:1em; -webkit-touch-callout:none;-moz-user-select:none;-ms-user-select:none;user-select:none; }
20 .main .select2-container .select2-choice { background-color: white; box-shadow: @button-shadow;}
20 .main .select2-container .select2-choice { background-color: white; box-shadow: @button-shadow;}
21 .select2-container .select2-choice abbr { display: none; width: 12px; height: 12px; position: absolute; right: 24px; top: 8px; font-size: 1px; text-decoration: none; border: 0; background: url('../images/select2.png') right top no-repeat; cursor: pointer; outline: 0; }
21 .select2-container .select2-choice abbr { display: none; width: 12px; height: 12px; position: absolute; right: 24px; top: 8px; font-size: 1px; text-decoration: none; border: 0; background: url('../images/select2.png') right top no-repeat; cursor: pointer; outline: 0; }
22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
24 .select2-drop-mask { border: 0; margin: 0; padding: 0; position: fixed; left: 0; top: 0; min-height: 100%; min-width: 100%; height: auto; width: auto; opacity: 0; z-index: 998; background-color: #fff; filter: alpha(opacity=0); }
24 .select2-drop-mask { border: 0; margin: 0; padding: 0; position: fixed; left: 0; top: 0; min-height: 100%; min-width: 100%; height: auto; width: auto; opacity: 0; z-index: 998; background-color: #fff; filter: alpha(opacity=0); }
25 .select2-drop { width: 100%; margin-top: -1px; position: absolute; z-index: 999; top: 100%; background: #fff; color: #000; border: @border-thickness solid @rcblue; border-top: 0; border-radius: 0 0 @border-radius @border-radius; }
25 .select2-drop { width: 100%; margin-top: -1px; position: absolute; z-index: 999; top: 100%; background: #fff; color: #000; border: @border-thickness solid @rcblue; border-top: 0; border-radius: 0 0 @border-radius @border-radius; }
26 .select2-drop.select2-drop-above { margin-top: 1px; border-top: @border-thickness solid @rclightblue; border-bottom: 0; border-radius: @border-radius @border-radius 0 0; }
26 .select2-drop.select2-drop-above { margin-top: 1px; border-top: @border-thickness solid @rclightblue; border-bottom: 0; border-radius: @border-radius @border-radius 0 0; }
27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
31 html[dir="rtl"] .select2-container .select2-choice .select2-arrow { left: 0; right: auto; border-left: none; border-right: @border-thickness solid @grey5; border-radius: @border-radius 0 0 @border-radius; }
31 html[dir="rtl"] .select2-container .select2-choice .select2-arrow { left: 0; right: auto; border-left: none; border-right: @border-thickness solid @grey5; border-radius: @border-radius 0 0 @border-radius; }
32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
33 .select2-search { display: inline-block; width: 100%; min-height: 26px; margin: 0; padding-left: 4px; padding-right: 4px; position: relative; z-index: 1000; white-space: nowrap; }
33 .select2-search { display: inline-block; width: 100%; min-height: 26px; margin: 0; padding-left: 4px; padding-right: 4px; position: relative; z-index: 1000; white-space: nowrap; }
34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
39 .select2-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
39 .select2-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
40 /* results */
40 /* results */
41 .select2-results { max-height: 200px; padding: 0 0 0 4px; margin: 4px 4px 4px 0; position: relative; overflow-x: hidden; overflow-y: auto; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
41 .select2-results { max-height: 200px; padding: 0 0 0 4px; margin: 4px 4px 4px 0; position: relative; overflow-x: hidden; overflow-y: auto; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
44 .select2-results .select2-selected{display:none}
44 .select2-results .select2-selected{display:none}
45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
49 .select2-container-multi .select2-choices li{float:left;list-style:none}
49 .select2-container-multi .select2-choices li{float:left;list-style:none}
50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
52 .select2-search-choice-close{display:block;width:12px;height:13px;position:absolute;right:3px;top:4px;font-size:1px;outline:none;background:url('../images/select2.png') right top no-repeat}
52 .select2-search-choice-close{display:block;width:12px;height:13px;position:absolute;right:3px;top:4px;font-size:1px;outline:none;background:url('../images/select2.png') right top no-repeat}
53 .select2-container-multi .select2-search-choice-close{left:3px}
53 .select2-container-multi .select2-search-choice-close{left:3px}
54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
60 .select2-display-none,
60 .select2-display-none,
61 .select2-search-hidden {display:none}
61 .select2-search-hidden {display:none}
62 .select2-search input { border-color: @rclightblue; }
62 .select2-search input { border-color: @rclightblue; }
63
63
64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
66 only screen and (min-resolution:144dpi){
66 only screen and (min-resolution:144dpi){
67 .select2-search input,
67 .select2-search input,
68 .select2-search-choice-close,
68 .select2-search-choice-close,
69 .select2-container .select2-choice abbr,
69 .select2-container .select2-choice abbr,
70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
71 .select2-search input{background-position:100% -21px}
71 .select2-search input{background-position:100% -21px}
72 }
72 }
73 [class^="input-"] [class^="select2-choice"]>div{display:none}
73 [class^="input-"] [class^="select2-choice"]>div{display:none}
74 [class^="input-"] .select2-offscreen{position:absolute}
74 [class^="input-"] .select2-offscreen{position:absolute}
75 select.select2{height:28px;visibility:hidden}
75 select.select2{height:28px;visibility:hidden}
76 .autocomplete-suggestions{overflow:auto}
76 .autocomplete-suggestions{overflow:auto}
77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
78
78
79 /* Retina-ize icons */
79 /* Retina-ize icons */
80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
81 only screen and (min-resolution:144dpi){
81 only screen and (min-resolution:144dpi){
82 .select2-search input,
82 .select2-search input,
83 .select2-search-choice-close,
83 .select2-search-choice-close,
84 .select2-container .select2-choice abbr,
84 .select2-container .select2-choice abbr,
85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
86 .select2-search input{background-position:100% -21px}
86 .select2-search input{background-position:100% -21px}
87 }
87 }
88
88
89 //Internal Select2 Dropdown Menus
89 //Internal Select2 Dropdown Menus
90
90
91 .drop-menu-core {
91 .drop-menu-core {
92 min-width: 160px;
92 min-width: 160px;
93 margin: 0 @padding 0 0;
93 margin: 0 @padding 0 0;
94 padding: 0;
94 padding: 0;
95 border: @border-thickness solid @grey5;
95 border: @border-thickness solid @grey5;
96 border-radius: @border-radius;
96 border-radius: @border-radius;
97 color: @grey2;
97 color: @grey2;
98 background-color: white;
98 background-color: white;
99
99
100 a {
100 a {
101 color: @grey2;
101 color: @grey2;
102
102
103 &:hover {
103 &:hover {
104 color: @rcdarkblue;
104 color: @rcdarkblue;
105 }
105 }
106 }
106 }
107 }
107 }
108
108
109 .drop-menu-dropdown {
109 .drop-menu-dropdown {
110 .drop-menu-core;
110 .drop-menu-core;
111
112 .flag_status {
113 margin-top: 0;
114 }
115 }
111 }
116
112
117 .drop-menu-base {
113 .drop-menu-base {
118 .drop-menu-core;
114 .drop-menu-core;
119 position: relative;
115 position: relative;
120 display: inline-block;
116 display: inline-block;
121 line-height: 1em;
117 line-height: 1em;
122 z-index: 2;
118 z-index: 2;
123 cursor: pointer;
119 cursor: pointer;
124
120
125 .flag_status {
126 margin-top: 0;
127 }
128
129 a {
121 a {
130 display:block;
122 display:block;
131 padding: .7em;
123 padding: .7em;
132 padding-right: 2em;
124 padding-right: 2em;
133 position: relative;
125 position: relative;
134
126
135 &:after {
127 &:after {
136 position: absolute;
128 position: absolute;
137 content: "\00A0\25BE";
129 content: "\00A0\25BE";
138 right: .1em;
130 right: .1em;
139 line-height: 1em;
131 line-height: 1em;
140 top: 0.2em;
132 top: 0.2em;
141 width: 1em;
133 width: 1em;
142 font-size: 20px;
134 font-size: 20px;
143 }
135 }
144 }
136 }
145 }
137 }
146
138
147 .drop-menu {
139 .drop-menu {
148 .drop-menu-base;
140 .drop-menu-base;
149 width: auto !important;
141 width: auto !important;
150 }
142 }
151
143
152 .drop-menu-no-width {
144 .drop-menu-no-width {
153 .drop-menu-base;
145 .drop-menu-base;
154 width: auto;
146 width: auto;
155 min-width: 0;
147 min-width: 0;
156 margin: 0;
148 margin: 0;
157 }
149 }
158
150
159 .field-sm .drop-menu {
151 .field-sm .drop-menu {
160 padding: 1px 0 0 0;
152 padding: 1px 0 0 0;
161 a {
153 a {
162 padding: 6px;
154 padding: 6px;
163 };
155 };
164 }
156 }
165
157
166 .select2-search input {
158 .select2-search input {
167 width: 100%;
159 width: 100%;
168 margin: .5em 0;
160 margin: .5em 0;
169 padding: .5em;
161 padding: .5em;
170 border-color: @grey4;
162 border-color: @grey4;
171
163
172 &:focus, &:hover {
164 &:focus, &:hover {
173 border-color: @rcblue;
165 border-color: @rcblue;
174 box-shadow: @button-shadow;
166 box-shadow: @button-shadow;
175 }
167 }
176 }
168 }
177
169
178 .select2-no-results {
170 .select2-no-results {
179 padding: .5em;
171 padding: .5em;
180 }
172 }
181
173
182 .drop-menu-dropdown ul {
174 .drop-menu-dropdown ul {
183 width: auto;
175 width: auto;
184 margin: 0;
176 margin: 0;
185 padding: 0;
177 padding: 0;
186 z-index: 50;
178 z-index: 50;
187
179
188 li {
180 li {
189 margin: 0;
181 margin: 0;
190 line-height: 1em;
182 line-height: 1em;
191 list-style-type: none;
183 list-style-type: none;
192
184
193 &:hover,
185 &:hover,
194 &.select2-highlighted {
186 &.select2-highlighted {
195 background-color: @grey7;
187 background-color: @grey7;
196
188
197 .select2-result-label {
189 .select2-result-label {
198 &:hover {
190 &:hover {
199 color: @grey1!important;
191 color: @grey1!important;
200 }
192 }
201 }
193 }
202 }
194 }
203
195
204 &.select2-result-with-children {
196 &.select2-result-with-children {
205 &:hover {
197 &:hover {
206 background-color: white;
198 background-color: white;
207 }
199 }
208 }
200 }
209
201
210 .select2-result-label {
202 .select2-result-label {
211 display:block;
203 display:block;
212 padding: 8px;
204 padding: 8px;
213 font-family: @text-regular;
205 font-family: @text-regular;
214 color: @grey2;
206 color: @grey2;
215 cursor: pointer;
207 cursor: pointer;
216 }
208 }
217 &.select2-result-with-children {
209 &.select2-result-with-children {
218
210
219 .select2-result-label {
211 .select2-result-label {
220 color: @rcdarkblue;
212 color: @rcdarkblue;
221 cursor: default;
213 cursor: default;
222 font-weight: @text-semibold-weight;
214 font-weight: @text-semibold-weight;
223 font-family: @text-semibold;
215 font-family: @text-semibold;
224 }
216 }
225
217
226 ul.select2-result-sub li .select2-result-label {
218 ul.select2-result-sub li .select2-result-label {
227 padding-left: 16px;
219 padding-left: 16px;
228 font-family: @text-regular;
220 font-family: @text-regular;
229 color: @grey2;
221 color: @grey2;
230 cursor: pointer;
222 cursor: pointer;
231 }
223 }
232 }
224 }
233 }
225 }
234 }
226 }
235
227
236 .side-by-side-selector {
228 .side-by-side-selector {
237 .left-group,
229 .left-group,
238 .middle-group,
230 .middle-group,
239 .right-group {
231 .right-group {
240 margin-bottom: @padding;
232 margin-bottom: @padding;
241 }
233 }
242 }
234 }
@@ -1,843 +1,844 b''
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 /**
19 /**
20 * Code Mirror
20 * Code Mirror
21 */
21 */
22 // global code-mirror logger;, to enable run
22 // global code-mirror logger;, to enable run
23 // Logger.get('CodeMirror').setLevel(Logger.DEBUG)
23 // Logger.get('CodeMirror').setLevel(Logger.DEBUG)
24
24
25 cmLog = Logger.get('CodeMirror');
25 cmLog = Logger.get('CodeMirror');
26 cmLog.setLevel(Logger.OFF);
26 cmLog.setLevel(Logger.OFF);
27
27
28
28
29 //global cache for inline forms
29 //global cache for inline forms
30 var userHintsCache = {};
30 var userHintsCache = {};
31
31
32 // global timer, used to cancel async loading
32 // global timer, used to cancel async loading
33 var CodeMirrorLoadUserHintTimer;
33 var CodeMirrorLoadUserHintTimer;
34
34
35 var escapeRegExChars = function(value) {
35 var escapeRegExChars = function(value) {
36 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
36 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
37 };
37 };
38
38
39 /**
39 /**
40 * Load hints from external source returns an array of objects in a format
40 * Load hints from external source returns an array of objects in a format
41 * that hinting lib requires
41 * that hinting lib requires
42 * @returns {Array}
42 * @returns {Array}
43 */
43 */
44 var CodeMirrorLoadUserHints = function(query, triggerHints) {
44 var CodeMirrorLoadUserHints = function(query, triggerHints) {
45 cmLog.debug('Loading mentions users via AJAX');
45 cmLog.debug('Loading mentions users via AJAX');
46 var _users = [];
46 var _users = [];
47 $.ajax({
47 $.ajax({
48 type: 'GET',
48 type: 'GET',
49 data: {query: query},
49 data: {query: query},
50 url: pyroutes.url('user_autocomplete_data'),
50 url: pyroutes.url('user_autocomplete_data'),
51 headers: {'X-PARTIAL-XHR': true},
51 headers: {'X-PARTIAL-XHR': true},
52 async: true
52 async: true
53 })
53 })
54 .done(function(data) {
54 .done(function(data) {
55 var tmpl = '<img class="gravatar" src="{0}"/>{1}';
55 var tmpl = '<img class="gravatar" src="{0}"/>{1}';
56 $.each(data.suggestions, function(i) {
56 $.each(data.suggestions, function(i) {
57 var userObj = data.suggestions[i];
57 var userObj = data.suggestions[i];
58
58
59 if (userObj.username !== "default") {
59 if (userObj.username !== "default") {
60 _users.push({
60 _users.push({
61 text: userObj.username + " ",
61 text: userObj.username + " ",
62 org_text: userObj.username,
62 org_text: userObj.username,
63 displayText: userObj.value_display, // search that field
63 displayText: userObj.value_display, // search that field
64 // internal caches
64 // internal caches
65 _icon_link: userObj.icon_link,
65 _icon_link: userObj.icon_link,
66 _text: userObj.value_display,
66 _text: userObj.value_display,
67
67
68 render: function(elt, data, completion) {
68 render: function(elt, data, completion) {
69 var el = document.createElement('div');
69 var el = document.createElement('div');
70 el.className = "CodeMirror-hint-entry";
70 el.className = "CodeMirror-hint-entry";
71 el.innerHTML = tmpl.format(
71 el.innerHTML = tmpl.format(
72 completion._icon_link, completion._text);
72 completion._icon_link, completion._text);
73 elt.appendChild(el);
73 elt.appendChild(el);
74 }
74 }
75 });
75 });
76 }
76 }
77 });
77 });
78 cmLog.debug('Mention users loaded');
78 cmLog.debug('Mention users loaded');
79 // set to global cache
79 // set to global cache
80 userHintsCache[query] = _users;
80 userHintsCache[query] = _users;
81 triggerHints(userHintsCache[query]);
81 triggerHints(userHintsCache[query]);
82 })
82 })
83 .fail(function(data, textStatus, xhr) {
83 .fail(function(data, textStatus, xhr) {
84 alert("error processing request. \n" +
84 alert("error processing request. \n" +
85 "Error code {0} ({1}).".format(data.status, data.statusText));
85 "Error code {0} ({1}).".format(data.status, data.statusText));
86 });
86 });
87 };
87 };
88
88
89 /**
89 /**
90 * filters the results based on the current context
90 * filters the results based on the current context
91 * @param users
91 * @param users
92 * @param context
92 * @param context
93 * @returns {Array}
93 * @returns {Array}
94 */
94 */
95 var CodeMirrorFilterUsers = function(users, context) {
95 var CodeMirrorFilterUsers = function(users, context) {
96 var MAX_LIMIT = 10;
96 var MAX_LIMIT = 10;
97 var filtered_users = [];
97 var filtered_users = [];
98 var curWord = context.string;
98 var curWord = context.string;
99
99
100 cmLog.debug('Filtering users based on query:', curWord);
100 cmLog.debug('Filtering users based on query:', curWord);
101 $.each(users, function(i) {
101 $.each(users, function(i) {
102 var match = users[i];
102 var match = users[i];
103 var searchText = match.displayText;
103 var searchText = match.displayText;
104
104
105 if (!curWord ||
105 if (!curWord ||
106 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
106 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
107 // reset state
107 // reset state
108 match._text = match.displayText;
108 match._text = match.displayText;
109 if (curWord) {
109 if (curWord) {
110 // do highlighting
110 // do highlighting
111 var pattern = '(' + escapeRegExChars(curWord) + ')';
111 var pattern = '(' + escapeRegExChars(curWord) + ')';
112 match._text = searchText.replace(
112 match._text = searchText.replace(
113 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
113 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
114 }
114 }
115
115
116 filtered_users.push(match);
116 filtered_users.push(match);
117 }
117 }
118 // to not return to many results, use limit of filtered results
118 // to not return to many results, use limit of filtered results
119 if (filtered_users.length > MAX_LIMIT) {
119 if (filtered_users.length > MAX_LIMIT) {
120 return false;
120 return false;
121 }
121 }
122 });
122 });
123
123
124 return filtered_users;
124 return filtered_users;
125 };
125 };
126
126
127 var CodeMirrorMentionHint = function(editor, callback, options) {
127 var CodeMirrorMentionHint = function(editor, callback, options) {
128 var cur = editor.getCursor();
128 var cur = editor.getCursor();
129 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
129 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
130
130
131 // match on @ +1char
131 // match on @ +1char
132 var tokenMatch = new RegExp(
132 var tokenMatch = new RegExp(
133 '(^@| @)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*)$').exec(curLine);
133 '(^@| @)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*)$').exec(curLine);
134
134
135 var tokenStr = '';
135 var tokenStr = '';
136 if (tokenMatch !== null && tokenMatch.length > 0){
136 if (tokenMatch !== null && tokenMatch.length > 0){
137 tokenStr = tokenMatch[0].strip();
137 tokenStr = tokenMatch[0].strip();
138 } else {
138 } else {
139 // skip if we didn't match our token
139 // skip if we didn't match our token
140 return;
140 return;
141 }
141 }
142
142
143 var context = {
143 var context = {
144 start: (cur.ch - tokenStr.length) + 1,
144 start: (cur.ch - tokenStr.length) + 1,
145 end: cur.ch,
145 end: cur.ch,
146 string: tokenStr.slice(1),
146 string: tokenStr.slice(1),
147 type: null
147 type: null
148 };
148 };
149
149
150 // case when we put the @sign in fron of a string,
150 // case when we put the @sign in fron of a string,
151 // eg <@ we put it here>sometext then we need to prepend to text
151 // eg <@ we put it here>sometext then we need to prepend to text
152 if (context.end > cur.ch) {
152 if (context.end > cur.ch) {
153 context.start = context.start + 1; // we add to the @ sign
153 context.start = context.start + 1; // we add to the @ sign
154 context.end = cur.ch; // don't eat front part just append
154 context.end = cur.ch; // don't eat front part just append
155 context.string = context.string.slice(1, cur.ch - context.start);
155 context.string = context.string.slice(1, cur.ch - context.start);
156 }
156 }
157
157
158 cmLog.debug('Mention context', context);
158 cmLog.debug('Mention context', context);
159
159
160 var triggerHints = function(userHints){
160 var triggerHints = function(userHints){
161 return callback({
161 return callback({
162 list: CodeMirrorFilterUsers(userHints, context),
162 list: CodeMirrorFilterUsers(userHints, context),
163 from: CodeMirror.Pos(cur.line, context.start),
163 from: CodeMirror.Pos(cur.line, context.start),
164 to: CodeMirror.Pos(cur.line, context.end)
164 to: CodeMirror.Pos(cur.line, context.end)
165 });
165 });
166 };
166 };
167
167
168 var queryBasedHintsCache = undefined;
168 var queryBasedHintsCache = undefined;
169 // if we have something in the cache, try to fetch the query based cache
169 // if we have something in the cache, try to fetch the query based cache
170 if (userHintsCache !== {}){
170 if (userHintsCache !== {}){
171 queryBasedHintsCache = userHintsCache[context.string];
171 queryBasedHintsCache = userHintsCache[context.string];
172 }
172 }
173
173
174 if (queryBasedHintsCache !== undefined) {
174 if (queryBasedHintsCache !== undefined) {
175 cmLog.debug('Users loaded from cache');
175 cmLog.debug('Users loaded from cache');
176 triggerHints(queryBasedHintsCache);
176 triggerHints(queryBasedHintsCache);
177 } else {
177 } else {
178 // this takes care for async loading, and then displaying results
178 // this takes care for async loading, and then displaying results
179 // and also propagates the userHintsCache
179 // and also propagates the userHintsCache
180 window.clearTimeout(CodeMirrorLoadUserHintTimer);
180 window.clearTimeout(CodeMirrorLoadUserHintTimer);
181 CodeMirrorLoadUserHintTimer = setTimeout(function() {
181 CodeMirrorLoadUserHintTimer = setTimeout(function() {
182 CodeMirrorLoadUserHints(context.string, triggerHints);
182 CodeMirrorLoadUserHints(context.string, triggerHints);
183 }, 300);
183 }, 300);
184 }
184 }
185 };
185 };
186
186
187 var CodeMirrorCompleteAfter = function(cm, pred) {
187 var CodeMirrorCompleteAfter = function(cm, pred) {
188 var options = {
188 var options = {
189 completeSingle: false,
189 completeSingle: false,
190 async: true,
190 async: true,
191 closeOnUnfocus: true
191 closeOnUnfocus: true
192 };
192 };
193 var cur = cm.getCursor();
193 var cur = cm.getCursor();
194 setTimeout(function() {
194 setTimeout(function() {
195 if (!cm.state.completionActive) {
195 if (!cm.state.completionActive) {
196 cmLog.debug('Trigger mentions hinting');
196 cmLog.debug('Trigger mentions hinting');
197 CodeMirror.showHint(cm, CodeMirror.hint.mentions, options);
197 CodeMirror.showHint(cm, CodeMirror.hint.mentions, options);
198 }
198 }
199 }, 100);
199 }, 100);
200
200
201 // tell CodeMirror we didn't handle the key
201 // tell CodeMirror we didn't handle the key
202 // trick to trigger on a char but still complete it
202 // trick to trigger on a char but still complete it
203 return CodeMirror.Pass;
203 return CodeMirror.Pass;
204 };
204 };
205
205
206 var initCodeMirror = function(textAreadId, resetUrl, focus, options) {
206 var initCodeMirror = function(textAreadId, resetUrl, focus, options) {
207 if (textAreadId.substr(0,1) === "#"){
207 if (textAreadId.substr(0,1) === "#"){
208 var ta = $(textAreadId).get(0);
208 var ta = $(textAreadId).get(0);
209 }else {
209 }else {
210 var ta = $('#' + textAreadId).get(0);
210 var ta = $('#' + textAreadId).get(0);
211 }
211 }
212
212
213 if (focus === undefined) {
213 if (focus === undefined) {
214 focus = true;
214 focus = true;
215 }
215 }
216
216
217 // default options
217 // default options
218 var codeMirrorOptions = {
218 var codeMirrorOptions = {
219 mode: "null",
219 mode: "null",
220 lineNumbers: true,
220 lineNumbers: true,
221 indentUnit: 4,
221 indentUnit: 4,
222 autofocus: focus
222 autofocus: focus
223 };
223 };
224
224
225 if (options !== undefined) {
225 if (options !== undefined) {
226 // extend with custom options
226 // extend with custom options
227 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
227 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
228 }
228 }
229
229
230 var myCodeMirror = CodeMirror.fromTextArea(ta, codeMirrorOptions);
230 var myCodeMirror = CodeMirror.fromTextArea(ta, codeMirrorOptions);
231
231
232 $('#reset').on('click', function(e) {
232 $('#reset').on('click', function(e) {
233 window.location = resetUrl;
233 window.location = resetUrl;
234 });
234 });
235
235
236 return myCodeMirror;
236 return myCodeMirror;
237 };
237 };
238
238
239
239
240 var initMarkupCodeMirror = function(textAreadId, focus, options) {
240 var initMarkupCodeMirror = function(textAreadId, focus, options) {
241 var initialHeight = 100;
241 var initialHeight = 100;
242
242
243 var ta = $(textAreadId).get(0);
243 var ta = $(textAreadId).get(0);
244 if (focus === undefined) {
244 if (focus === undefined) {
245 focus = true;
245 focus = true;
246 }
246 }
247
247
248 // default options
248 // default options
249 var codeMirrorOptions = {
249 var codeMirrorOptions = {
250 lineNumbers: false,
250 lineNumbers: false,
251 indentUnit: 4,
251 indentUnit: 4,
252 viewportMargin: 30,
252 viewportMargin: 30,
253 // this is a trick to trigger some logic behind codemirror placeholder
253 // this is a trick to trigger some logic behind codemirror placeholder
254 // it influences styling and behaviour.
254 // it influences styling and behaviour.
255 placeholder: " ",
255 placeholder: " ",
256 lineWrapping: true,
256 lineWrapping: true,
257 autofocus: focus
257 autofocus: focus
258 };
258 };
259
259
260 if (options !== undefined) {
260 if (options !== undefined) {
261 // extend with custom options
261 // extend with custom options
262 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
262 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
263 }
263 }
264
264
265 var cm = CodeMirror.fromTextArea(ta, codeMirrorOptions);
265 var cm = CodeMirror.fromTextArea(ta, codeMirrorOptions);
266 cm.setSize(null, initialHeight);
266 cm.setSize(null, initialHeight);
267 cm.setOption("mode", DEFAULT_RENDERER);
267 cm.setOption("mode", DEFAULT_RENDERER);
268 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
268 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
269 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
269 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
270
270
271 // start listening on changes to make auto-expanded editor
271 // start listening on changes to make auto-expanded editor
272 cm.on("change", function(instance, changeObj) {
272 cm.on("change", function(instance, changeObj) {
273 var height = initialHeight;
273 var height = initialHeight;
274 var lines = instance.lineCount();
274 var lines = instance.lineCount();
275 if ( lines > 6 && lines < 20) {
275 if ( lines > 6 && lines < 20) {
276 height = "auto";
276 height = "auto";
277 }
277 }
278 else if (lines >= 20){
278 else if (lines >= 20){
279 zheight = 20*15;
279 zheight = 20*15;
280 }
280 }
281 instance.setSize(null, height);
281 instance.setSize(null, height);
282
282
283 // detect if the change was trigger by auto desc, or user input
283 // detect if the change was trigger by auto desc, or user input
284 var changeOrigin = changeObj.origin;
284 var changeOrigin = changeObj.origin;
285
285
286 if (changeOrigin === "setValue") {
286 if (changeOrigin === "setValue") {
287 cmLog.debug('Change triggered by setValue');
287 cmLog.debug('Change triggered by setValue');
288 }
288 }
289 else {
289 else {
290 cmLog.debug('user triggered change !');
290 cmLog.debug('user triggered change !');
291 // set special marker to indicate user has created an input.
291 // set special marker to indicate user has created an input.
292 instance._userDefinedValue = true;
292 instance._userDefinedValue = true;
293 }
293 }
294
294
295 });
295 });
296
296
297 return cm;
297 return cm;
298 };
298 };
299
299
300
300
301 var initCommentBoxCodeMirror = function(CommentForm, textAreaId, triggerActions){
301 var initCommentBoxCodeMirror = function(CommentForm, textAreaId, triggerActions){
302 var initialHeight = 100;
302 var initialHeight = 100;
303
303
304 if (typeof userHintsCache === "undefined") {
304 if (typeof userHintsCache === "undefined") {
305 userHintsCache = {};
305 userHintsCache = {};
306 cmLog.debug('Init empty cache for mentions');
306 cmLog.debug('Init empty cache for mentions');
307 }
307 }
308 if (!$(textAreaId).get(0)) {
308 if (!$(textAreaId).get(0)) {
309 cmLog.debug('Element for textarea not found', textAreaId);
309 cmLog.debug('Element for textarea not found', textAreaId);
310 return;
310 return;
311 }
311 }
312 /**
312 /**
313 * Filter action based on typed in text
313 * Filter action based on typed in text
314 * @param actions
314 * @param actions
315 * @param context
315 * @param context
316 * @returns {Array}
316 * @returns {Array}
317 */
317 */
318
318
319 var filterActions = function(actions, context){
319 var filterActions = function(actions, context){
320
320
321 var MAX_LIMIT = 10;
321 var MAX_LIMIT = 10;
322 var filtered_actions = [];
322 var filtered_actions = [];
323 var curWord = context.string;
323 var curWord = context.string;
324
324
325 cmLog.debug('Filtering actions based on query:', curWord);
325 cmLog.debug('Filtering actions based on query:', curWord);
326 $.each(actions, function(i) {
326 $.each(actions, function(i) {
327 var match = actions[i];
327 var match = actions[i];
328 var searchText = match.searchText;
328 var searchText = match.searchText;
329
329
330 if (!curWord ||
330 if (!curWord ||
331 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
331 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
332 // reset state
332 // reset state
333 match._text = match.displayText;
333 match._text = match.displayText;
334 if (curWord) {
334 if (curWord) {
335 // do highlighting
335 // do highlighting
336 var pattern = '(' + escapeRegExChars(curWord) + ')';
336 var pattern = '(' + escapeRegExChars(curWord) + ')';
337 match._text = searchText.replace(
337 match._text = searchText.replace(
338 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
338 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
339 }
339 }
340
340
341 filtered_actions.push(match);
341 filtered_actions.push(match);
342 }
342 }
343 // to not return to many results, use limit of filtered results
343 // to not return to many results, use limit of filtered results
344 if (filtered_actions.length > MAX_LIMIT) {
344 if (filtered_actions.length > MAX_LIMIT) {
345 return false;
345 return false;
346 }
346 }
347 });
347 });
348
348
349 return filtered_actions;
349 return filtered_actions;
350 };
350 };
351
351
352 var submitForm = function(cm, pred) {
352 var submitForm = function(cm, pred) {
353 $(cm.display.input.textarea.form).submit();
353 $(cm.display.input.textarea.form).submit();
354 return CodeMirror.Pass;
354 return CodeMirror.Pass;
355 };
355 };
356
356
357 var completeActions = function(actions){
357 var completeActions = function(actions){
358
358
359 var registeredActions = [];
359 var registeredActions = [];
360 var allActions = [
360 var allActions = [
361 {
361 {
362 text: "approve",
362 text: "approve",
363 searchText: "status approved",
363 searchText: "status approved",
364 displayText: _gettext('Set status to Approved'),
364 displayText: _gettext('Set status to Approved'),
365 hint: function(CodeMirror, data, completion) {
365 hint: function(CodeMirror, data, completion) {
366 CodeMirror.replaceRange("", completion.from || data.from,
366 CodeMirror.replaceRange("", completion.from || data.from,
367 completion.to || data.to, "complete");
367 completion.to || data.to, "complete");
368 $(CommentForm.statusChange).select2("val", 'approved').trigger('change');
368 $(CommentForm.statusChange).select2("val", 'approved').trigger('change');
369 },
369 },
370 render: function(elt, data, completion) {
370 render: function(elt, data, completion) {
371 var el = document.createElement('div');
371 var el = document.createElement('i');
372 el.className = "flag_status flag_status_comment_box approved pull-left";
372
373 el.className = "icon-circle review-status-approved";
373 elt.appendChild(el);
374 elt.appendChild(el);
374
375
375 el = document.createElement('span');
376 el = document.createElement('span');
376 el.innerHTML = completion.displayText;
377 el.innerHTML = completion.displayText;
377 elt.appendChild(el);
378 elt.appendChild(el);
378 }
379 }
379 },
380 },
380 {
381 {
381 text: "reject",
382 text: "reject",
382 searchText: "status rejected",
383 searchText: "status rejected",
383 displayText: _gettext('Set status to Rejected'),
384 displayText: _gettext('Set status to Rejected'),
384 hint: function(CodeMirror, data, completion) {
385 hint: function(CodeMirror, data, completion) {
385 CodeMirror.replaceRange("", completion.from || data.from,
386 CodeMirror.replaceRange("", completion.from || data.from,
386 completion.to || data.to, "complete");
387 completion.to || data.to, "complete");
387 $(CommentForm.statusChange).select2("val", 'rejected').trigger('change');
388 $(CommentForm.statusChange).select2("val", 'rejected').trigger('change');
388 },
389 },
389 render: function(elt, data, completion) {
390 render: function(elt, data, completion) {
390 var el = document.createElement('div');
391 var el = document.createElement('i');
391 el.className = "flag_status flag_status_comment_box rejected pull-left";
392 el.className = "icon-circle review-status-rejected";
392 elt.appendChild(el);
393 elt.appendChild(el);
393
394
394 el = document.createElement('span');
395 el = document.createElement('span');
395 el.innerHTML = completion.displayText;
396 el.innerHTML = completion.displayText;
396 elt.appendChild(el);
397 elt.appendChild(el);
397 }
398 }
398 },
399 },
399 {
400 {
400 text: "as_todo",
401 text: "as_todo",
401 searchText: "todo comment",
402 searchText: "todo comment",
402 displayText: _gettext('TODO comment'),
403 displayText: _gettext('TODO comment'),
403 hint: function(CodeMirror, data, completion) {
404 hint: function(CodeMirror, data, completion) {
404 CodeMirror.replaceRange("", completion.from || data.from,
405 CodeMirror.replaceRange("", completion.from || data.from,
405 completion.to || data.to, "complete");
406 completion.to || data.to, "complete");
406
407
407 $(CommentForm.commentType).val('todo');
408 $(CommentForm.commentType).val('todo');
408 },
409 },
409 render: function(elt, data, completion) {
410 render: function(elt, data, completion) {
410 var el = document.createElement('div');
411 var el = document.createElement('div');
411 el.className = "pull-left";
412 el.className = "pull-left";
412 elt.appendChild(el);
413 elt.appendChild(el);
413
414
414 el = document.createElement('span');
415 el = document.createElement('span');
415 el.innerHTML = completion.displayText;
416 el.innerHTML = completion.displayText;
416 elt.appendChild(el);
417 elt.appendChild(el);
417 }
418 }
418 },
419 },
419 {
420 {
420 text: "as_note",
421 text: "as_note",
421 searchText: "note comment",
422 searchText: "note comment",
422 displayText: _gettext('Note Comment'),
423 displayText: _gettext('Note Comment'),
423 hint: function(CodeMirror, data, completion) {
424 hint: function(CodeMirror, data, completion) {
424 CodeMirror.replaceRange("", completion.from || data.from,
425 CodeMirror.replaceRange("", completion.from || data.from,
425 completion.to || data.to, "complete");
426 completion.to || data.to, "complete");
426
427
427 $(CommentForm.commentType).val('note');
428 $(CommentForm.commentType).val('note');
428 },
429 },
429 render: function(elt, data, completion) {
430 render: function(elt, data, completion) {
430 var el = document.createElement('div');
431 var el = document.createElement('div');
431 el.className = "pull-left";
432 el.className = "pull-left";
432 elt.appendChild(el);
433 elt.appendChild(el);
433
434
434 el = document.createElement('span');
435 el = document.createElement('span');
435 el.innerHTML = completion.displayText;
436 el.innerHTML = completion.displayText;
436 elt.appendChild(el);
437 elt.appendChild(el);
437 }
438 }
438 }
439 }
439 ];
440 ];
440
441
441 $.each(allActions, function(index, value){
442 $.each(allActions, function(index, value){
442 var actionData = allActions[index];
443 var actionData = allActions[index];
443 if (actions.indexOf(actionData['text']) != -1) {
444 if (actions.indexOf(actionData['text']) != -1) {
444 registeredActions.push(actionData);
445 registeredActions.push(actionData);
445 }
446 }
446 });
447 });
447
448
448 return function(cm, pred) {
449 return function(cm, pred) {
449 var cur = cm.getCursor();
450 var cur = cm.getCursor();
450 var options = {
451 var options = {
451 closeOnUnfocus: true,
452 closeOnUnfocus: true,
452 registeredActions: registeredActions
453 registeredActions: registeredActions
453 };
454 };
454 setTimeout(function() {
455 setTimeout(function() {
455 if (!cm.state.completionActive) {
456 if (!cm.state.completionActive) {
456 cmLog.debug('Trigger actions hinting');
457 cmLog.debug('Trigger actions hinting');
457 CodeMirror.showHint(cm, CodeMirror.hint.actions, options);
458 CodeMirror.showHint(cm, CodeMirror.hint.actions, options);
458 }
459 }
459 }, 100);
460 }, 100);
460
461
461 // tell CodeMirror we didn't handle the key
462 // tell CodeMirror we didn't handle the key
462 // trick to trigger on a char but still complete it
463 // trick to trigger on a char but still complete it
463 return CodeMirror.Pass;
464 return CodeMirror.Pass;
464 }
465 }
465 };
466 };
466
467
467 var extraKeys = {
468 var extraKeys = {
468 "'@'": CodeMirrorCompleteAfter,
469 "'@'": CodeMirrorCompleteAfter,
469 Tab: function(cm) {
470 Tab: function(cm) {
470 // space indent instead of TABS
471 // space indent instead of TABS
471 var spaces = new Array(cm.getOption("indentUnit") + 1).join(" ");
472 var spaces = new Array(cm.getOption("indentUnit") + 1).join(" ");
472 cm.replaceSelection(spaces);
473 cm.replaceSelection(spaces);
473 }
474 }
474 };
475 };
475 // submit form on Meta-Enter
476 // submit form on Meta-Enter
476 if (OSType === "mac") {
477 if (OSType === "mac") {
477 extraKeys["Cmd-Enter"] = submitForm;
478 extraKeys["Cmd-Enter"] = submitForm;
478 }
479 }
479 else {
480 else {
480 extraKeys["Ctrl-Enter"] = submitForm;
481 extraKeys["Ctrl-Enter"] = submitForm;
481 }
482 }
482
483
483 if (triggerActions) {
484 if (triggerActions) {
484 // register triggerActions for this instance
485 // register triggerActions for this instance
485 extraKeys["'/'"] = completeActions(triggerActions);
486 extraKeys["'/'"] = completeActions(triggerActions);
486 }
487 }
487
488
488 var cm = CodeMirror.fromTextArea($(textAreaId).get(0), {
489 var cm = CodeMirror.fromTextArea($(textAreaId).get(0), {
489 lineNumbers: false,
490 lineNumbers: false,
490 indentUnit: 4,
491 indentUnit: 4,
491 viewportMargin: 30,
492 viewportMargin: 30,
492 // this is a trick to trigger some logic behind codemirror placeholder
493 // this is a trick to trigger some logic behind codemirror placeholder
493 // it influences styling and behaviour.
494 // it influences styling and behaviour.
494 placeholder: " ",
495 placeholder: " ",
495 extraKeys: extraKeys,
496 extraKeys: extraKeys,
496 lineWrapping: true
497 lineWrapping: true
497 });
498 });
498
499
499 cm.setSize(null, initialHeight);
500 cm.setSize(null, initialHeight);
500 cm.setOption("mode", DEFAULT_RENDERER);
501 cm.setOption("mode", DEFAULT_RENDERER);
501 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
502 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
502 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
503 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
503 // start listening on changes to make auto-expanded editor
504 // start listening on changes to make auto-expanded editor
504 cm.on("change", function(self) {
505 cm.on("change", function(self) {
505 var height = initialHeight;
506 var height = initialHeight;
506 var lines = self.lineCount();
507 var lines = self.lineCount();
507 if ( lines > 6 && lines < 20) {
508 if ( lines > 6 && lines < 20) {
508 height = "auto";
509 height = "auto";
509 }
510 }
510 else if (lines >= 20){
511 else if (lines >= 20){
511 zheight = 20*15;
512 zheight = 20*15;
512 }
513 }
513 self.setSize(null, height);
514 self.setSize(null, height);
514 });
515 });
515
516
516 var actionHint = function(editor, options) {
517 var actionHint = function(editor, options) {
517
518
518 var cur = editor.getCursor();
519 var cur = editor.getCursor();
519 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
520 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
520
521
521 // match only on /+1 character minimum
522 // match only on /+1 character minimum
522 var tokenMatch = new RegExp('(^/\|/\)([a-zA-Z]*)$').exec(curLine);
523 var tokenMatch = new RegExp('(^/\|/\)([a-zA-Z]*)$').exec(curLine);
523
524
524 var tokenStr = '';
525 var tokenStr = '';
525 if (tokenMatch !== null && tokenMatch.length > 0){
526 if (tokenMatch !== null && tokenMatch.length > 0){
526 tokenStr = tokenMatch[2].strip();
527 tokenStr = tokenMatch[2].strip();
527 }
528 }
528
529
529 var context = {
530 var context = {
530 start: (cur.ch - tokenStr.length) - 1,
531 start: (cur.ch - tokenStr.length) - 1,
531 end: cur.ch,
532 end: cur.ch,
532 string: tokenStr,
533 string: tokenStr,
533 type: null
534 type: null
534 };
535 };
535
536
536 return {
537 return {
537 list: filterActions(options.registeredActions, context),
538 list: filterActions(options.registeredActions, context),
538 from: CodeMirror.Pos(cur.line, context.start),
539 from: CodeMirror.Pos(cur.line, context.start),
539 to: CodeMirror.Pos(cur.line, context.end)
540 to: CodeMirror.Pos(cur.line, context.end)
540 };
541 };
541
542
542 };
543 };
543 CodeMirror.registerHelper("hint", "mentions", CodeMirrorMentionHint);
544 CodeMirror.registerHelper("hint", "mentions", CodeMirrorMentionHint);
544 CodeMirror.registerHelper("hint", "actions", actionHint);
545 CodeMirror.registerHelper("hint", "actions", actionHint);
545 return cm;
546 return cm;
546 };
547 };
547
548
548 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
549 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
549 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
550 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
550 codeMirrorInstance.setOption("mode", mode);
551 codeMirrorInstance.setOption("mode", mode);
551 };
552 };
552
553
553 var setCodeMirrorLineWrap = function(codeMirrorInstance, line_wrap) {
554 var setCodeMirrorLineWrap = function(codeMirrorInstance, line_wrap) {
554 codeMirrorInstance.setOption("lineWrapping", line_wrap);
555 codeMirrorInstance.setOption("lineWrapping", line_wrap);
555 };
556 };
556
557
557 var setCodeMirrorModeFromSelect = function(
558 var setCodeMirrorModeFromSelect = function(
558 targetSelect, targetFileInput, codeMirrorInstance, callback){
559 targetSelect, targetFileInput, codeMirrorInstance, callback){
559
560
560 $(targetSelect).on('change', function(e) {
561 $(targetSelect).on('change', function(e) {
561 cmLog.debug('codemirror select2 mode change event !');
562 cmLog.debug('codemirror select2 mode change event !');
562 var selected = e.currentTarget;
563 var selected = e.currentTarget;
563 var node = selected.options[selected.selectedIndex];
564 var node = selected.options[selected.selectedIndex];
564 var mimetype = node.value;
565 var mimetype = node.value;
565 cmLog.debug('picked mimetype', mimetype);
566 cmLog.debug('picked mimetype', mimetype);
566 var new_mode = $(node).attr('mode');
567 var new_mode = $(node).attr('mode');
567 setCodeMirrorMode(codeMirrorInstance, new_mode);
568 setCodeMirrorMode(codeMirrorInstance, new_mode);
568 cmLog.debug('set new mode', new_mode);
569 cmLog.debug('set new mode', new_mode);
569
570
570 //propose filename from picked mode
571 //propose filename from picked mode
571 cmLog.debug('setting mimetype', mimetype);
572 cmLog.debug('setting mimetype', mimetype);
572 var proposed_ext = getExtFromMimeType(mimetype);
573 var proposed_ext = getExtFromMimeType(mimetype);
573 cmLog.debug('file input', $(targetFileInput).val());
574 cmLog.debug('file input', $(targetFileInput).val());
574 var file_data = getFilenameAndExt($(targetFileInput).val());
575 var file_data = getFilenameAndExt($(targetFileInput).val());
575 var filename = file_data.filename || 'filename1';
576 var filename = file_data.filename || 'filename1';
576 $(targetFileInput).val(filename + proposed_ext);
577 $(targetFileInput).val(filename + proposed_ext);
577 cmLog.debug('proposed file', filename + proposed_ext);
578 cmLog.debug('proposed file', filename + proposed_ext);
578
579
579
580
580 if (typeof(callback) === 'function') {
581 if (typeof(callback) === 'function') {
581 try {
582 try {
582 cmLog.debug('running callback', callback);
583 cmLog.debug('running callback', callback);
583 callback(filename, mimetype, new_mode);
584 callback(filename, mimetype, new_mode);
584 } catch (err) {
585 } catch (err) {
585 console.log('failed to run callback', callback, err);
586 console.log('failed to run callback', callback, err);
586 }
587 }
587 }
588 }
588 cmLog.debug('finish iteration...');
589 cmLog.debug('finish iteration...');
589 });
590 });
590 };
591 };
591
592
592 var setCodeMirrorModeFromInput = function(
593 var setCodeMirrorModeFromInput = function(
593 targetSelect, targetFileInput, codeMirrorInstance, callback) {
594 targetSelect, targetFileInput, codeMirrorInstance, callback) {
594
595
595 // on type the new filename set mode
596 // on type the new filename set mode
596 $(targetFileInput).on('keyup', function(e) {
597 $(targetFileInput).on('keyup', function(e) {
597 var file_data = getFilenameAndExt(this.value);
598 var file_data = getFilenameAndExt(this.value);
598 if (file_data.ext === null) {
599 if (file_data.ext === null) {
599 return;
600 return;
600 }
601 }
601
602
602 var mimetypes = getMimeTypeFromExt(file_data.ext, true);
603 var mimetypes = getMimeTypeFromExt(file_data.ext, true);
603 cmLog.debug('mimetype from file', file_data, mimetypes);
604 cmLog.debug('mimetype from file', file_data, mimetypes);
604 var detected_mode;
605 var detected_mode;
605 var detected_option;
606 var detected_option;
606 for (var i in mimetypes) {
607 for (var i in mimetypes) {
607 var mt = mimetypes[i];
608 var mt = mimetypes[i];
608 if (!detected_mode) {
609 if (!detected_mode) {
609 detected_mode = detectCodeMirrorMode(this.value, mt);
610 detected_mode = detectCodeMirrorMode(this.value, mt);
610 }
611 }
611
612
612 if (!detected_option) {
613 if (!detected_option) {
613 cmLog.debug('#mimetype option[value="{0}"]'.format(mt));
614 cmLog.debug('#mimetype option[value="{0}"]'.format(mt));
614 if ($(targetSelect).find('option[value="{0}"]'.format(mt)).length) {
615 if ($(targetSelect).find('option[value="{0}"]'.format(mt)).length) {
615 detected_option = mt;
616 detected_option = mt;
616 }
617 }
617 }
618 }
618 }
619 }
619
620
620 cmLog.debug('detected mode', detected_mode);
621 cmLog.debug('detected mode', detected_mode);
621 cmLog.debug('detected option', detected_option);
622 cmLog.debug('detected option', detected_option);
622 if (detected_mode && detected_option){
623 if (detected_mode && detected_option){
623
624
624 $(targetSelect).select2("val", detected_option);
625 $(targetSelect).select2("val", detected_option);
625 setCodeMirrorMode(codeMirrorInstance, detected_mode);
626 setCodeMirrorMode(codeMirrorInstance, detected_mode);
626
627
627 if(typeof(callback) === 'function'){
628 if(typeof(callback) === 'function'){
628 try{
629 try{
629 cmLog.debug('running callback', callback);
630 cmLog.debug('running callback', callback);
630 var filename = file_data.filename + "." + file_data.ext;
631 var filename = file_data.filename + "." + file_data.ext;
631 callback(filename, detected_option, detected_mode);
632 callback(filename, detected_option, detected_mode);
632 }catch (err){
633 }catch (err){
633 console.log('failed to run callback', callback, err);
634 console.log('failed to run callback', callback, err);
634 }
635 }
635 }
636 }
636 }
637 }
637
638
638 });
639 });
639 };
640 };
640
641
641 var fillCodeMirrorOptions = function(targetSelect) {
642 var fillCodeMirrorOptions = function(targetSelect) {
642 //inject new modes, based on codeMirrors modeInfo object
643 //inject new modes, based on codeMirrors modeInfo object
643 var modes_select = $(targetSelect);
644 var modes_select = $(targetSelect);
644 for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
645 for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
645 var m = CodeMirror.modeInfo[i];
646 var m = CodeMirror.modeInfo[i];
646 var opt = new Option(m.name, m.mime);
647 var opt = new Option(m.name, m.mime);
647 $(opt).attr('mode', m.mode);
648 $(opt).attr('mode', m.mode);
648 modes_select.append(opt);
649 modes_select.append(opt);
649 }
650 }
650 };
651 };
651
652
652
653
653 /* markup form */
654 /* markup form */
654 (function(mod) {
655 (function(mod) {
655
656
656 if (typeof exports == "object" && typeof module == "object") {
657 if (typeof exports == "object" && typeof module == "object") {
657 // CommonJS
658 // CommonJS
658 module.exports = mod();
659 module.exports = mod();
659 }
660 }
660 else {
661 else {
661 // Plain browser env
662 // Plain browser env
662 (this || window).MarkupForm = mod();
663 (this || window).MarkupForm = mod();
663 }
664 }
664
665
665 })(function() {
666 })(function() {
666 "use strict";
667 "use strict";
667
668
668 function MarkupForm(textareaId) {
669 function MarkupForm(textareaId) {
669 if (!(this instanceof MarkupForm)) {
670 if (!(this instanceof MarkupForm)) {
670 return new MarkupForm(textareaId);
671 return new MarkupForm(textareaId);
671 }
672 }
672
673
673 // bind the element instance to our Form
674 // bind the element instance to our Form
674 $('#' + textareaId).get(0).MarkupForm = this;
675 $('#' + textareaId).get(0).MarkupForm = this;
675
676
676 this.withSelectorId = function(selector) {
677 this.withSelectorId = function(selector) {
677 var selectorId = textareaId;
678 var selectorId = textareaId;
678 return selector + '_' + selectorId;
679 return selector + '_' + selectorId;
679 };
680 };
680
681
681 this.previewButton = this.withSelectorId('#preview-btn');
682 this.previewButton = this.withSelectorId('#preview-btn');
682 this.previewContainer = this.withSelectorId('#preview-container');
683 this.previewContainer = this.withSelectorId('#preview-container');
683
684
684 this.previewBoxSelector = this.withSelectorId('#preview-box');
685 this.previewBoxSelector = this.withSelectorId('#preview-box');
685
686
686 this.editButton = this.withSelectorId('#edit-btn');
687 this.editButton = this.withSelectorId('#edit-btn');
687 this.editContainer = this.withSelectorId('#edit-container');
688 this.editContainer = this.withSelectorId('#edit-container');
688
689
689 this.cmBox = textareaId;
690 this.cmBox = textareaId;
690 this.cm = initMarkupCodeMirror('#' + textareaId);
691 this.cm = initMarkupCodeMirror('#' + textareaId);
691
692
692 this.previewUrl = pyroutes.url('markup_preview');
693 this.previewUrl = pyroutes.url('markup_preview');
693
694
694 // FUNCTIONS and helpers
695 // FUNCTIONS and helpers
695 var self = this;
696 var self = this;
696
697
697 this.getCmInstance = function(){
698 this.getCmInstance = function(){
698 return this.cm
699 return this.cm
699 };
700 };
700
701
701 this.setPlaceholder = function(placeholder) {
702 this.setPlaceholder = function(placeholder) {
702 var cm = this.getCmInstance();
703 var cm = this.getCmInstance();
703 if (cm){
704 if (cm){
704 cm.setOption('placeholder', placeholder);
705 cm.setOption('placeholder', placeholder);
705 }
706 }
706 };
707 };
707
708
708 this.initStatusChangeSelector = function(){
709 this.initStatusChangeSelector = function(){
709 var formatChangeStatus = function(state, escapeMarkup) {
710 var formatChangeStatus = function(state, escapeMarkup) {
710 var originalOption = state.element;
711 var originalOption = state.element;
711 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
712 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
712 '<span>' + escapeMarkup(state.text) + '</span>';
713 return tmpl
713 };
714 };
714 var formatResult = function(result, container, query, escapeMarkup) {
715 var formatResult = function(result, container, query, escapeMarkup) {
715 return formatChangeStatus(result, escapeMarkup);
716 return formatChangeStatus(result, escapeMarkup);
716 };
717 };
717
718
718 var formatSelection = function(data, container, escapeMarkup) {
719 var formatSelection = function(data, container, escapeMarkup) {
719 return formatChangeStatus(data, escapeMarkup);
720 return formatChangeStatus(data, escapeMarkup);
720 };
721 };
721
722
722 $(this.submitForm).find(this.statusChange).select2({
723 $(this.submitForm).find(this.statusChange).select2({
723 placeholder: _gettext('Status Review'),
724 placeholder: _gettext('Status Review'),
724 formatResult: formatResult,
725 formatResult: formatResult,
725 formatSelection: formatSelection,
726 formatSelection: formatSelection,
726 containerCssClass: "drop-menu status_box_menu",
727 containerCssClass: "drop-menu status_box_menu",
727 dropdownCssClass: "drop-menu-dropdown",
728 dropdownCssClass: "drop-menu-dropdown",
728 dropdownAutoWidth: true,
729 dropdownAutoWidth: true,
729 minimumResultsForSearch: -1
730 minimumResultsForSearch: -1
730 });
731 });
731 $(this.submitForm).find(this.statusChange).on('change', function() {
732 $(this.submitForm).find(this.statusChange).on('change', function() {
732 var status = self.getCommentStatus();
733 var status = self.getCommentStatus();
733
734
734 if (status && !self.isInline()) {
735 if (status && !self.isInline()) {
735 $(self.submitButton).prop('disabled', false);
736 $(self.submitButton).prop('disabled', false);
736 }
737 }
737
738
738 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
739 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
739 self.setPlaceholder(placeholderText)
740 self.setPlaceholder(placeholderText)
740 })
741 })
741 };
742 };
742
743
743 // reset the text area into it's original state
744 // reset the text area into it's original state
744 this.resetMarkupFormState = function(content) {
745 this.resetMarkupFormState = function(content) {
745 content = content || '';
746 content = content || '';
746
747
747 $(this.editContainer).show();
748 $(this.editContainer).show();
748 $(this.editButton).parent().addClass('active');
749 $(this.editButton).parent().addClass('active');
749
750
750 $(this.previewContainer).hide();
751 $(this.previewContainer).hide();
751 $(this.previewButton).parent().removeClass('active');
752 $(this.previewButton).parent().removeClass('active');
752
753
753 this.setActionButtonsDisabled(true);
754 this.setActionButtonsDisabled(true);
754 self.cm.setValue(content);
755 self.cm.setValue(content);
755 self.cm.setOption("readOnly", false);
756 self.cm.setOption("readOnly", false);
756 };
757 };
757
758
758 this.previewSuccessCallback = function(o) {
759 this.previewSuccessCallback = function(o) {
759 $(self.previewBoxSelector).html(o);
760 $(self.previewBoxSelector).html(o);
760 $(self.previewBoxSelector).removeClass('unloaded');
761 $(self.previewBoxSelector).removeClass('unloaded');
761
762
762 // swap buttons, making preview active
763 // swap buttons, making preview active
763 $(self.previewButton).parent().addClass('active');
764 $(self.previewButton).parent().addClass('active');
764 $(self.editButton).parent().removeClass('active');
765 $(self.editButton).parent().removeClass('active');
765
766
766 // unlock buttons
767 // unlock buttons
767 self.setActionButtonsDisabled(false);
768 self.setActionButtonsDisabled(false);
768 };
769 };
769
770
770 this.setActionButtonsDisabled = function(state) {
771 this.setActionButtonsDisabled = function(state) {
771 $(this.editButton).prop('disabled', state);
772 $(this.editButton).prop('disabled', state);
772 $(this.previewButton).prop('disabled', state);
773 $(this.previewButton).prop('disabled', state);
773 };
774 };
774
775
775 // lock preview/edit/submit buttons on load, but exclude cancel button
776 // lock preview/edit/submit buttons on load, but exclude cancel button
776 var excludeCancelBtn = true;
777 var excludeCancelBtn = true;
777 this.setActionButtonsDisabled(true);
778 this.setActionButtonsDisabled(true);
778
779
779 // anonymous users don't have access to initialized CM instance
780 // anonymous users don't have access to initialized CM instance
780 if (this.cm !== undefined){
781 if (this.cm !== undefined){
781 this.cm.on('change', function(cMirror) {
782 this.cm.on('change', function(cMirror) {
782 if (cMirror.getValue() === "") {
783 if (cMirror.getValue() === "") {
783 self.setActionButtonsDisabled(true)
784 self.setActionButtonsDisabled(true)
784 } else {
785 } else {
785 self.setActionButtonsDisabled(false)
786 self.setActionButtonsDisabled(false)
786 }
787 }
787 });
788 });
788 }
789 }
789
790
790 $(this.editButton).on('click', function(e) {
791 $(this.editButton).on('click', function(e) {
791 e.preventDefault();
792 e.preventDefault();
792
793
793 $(self.previewButton).parent().removeClass('active');
794 $(self.previewButton).parent().removeClass('active');
794 $(self.previewContainer).hide();
795 $(self.previewContainer).hide();
795
796
796 $(self.editButton).parent().addClass('active');
797 $(self.editButton).parent().addClass('active');
797 $(self.editContainer).show();
798 $(self.editContainer).show();
798
799
799 });
800 });
800
801
801 $(this.previewButton).on('click', function(e) {
802 $(this.previewButton).on('click', function(e) {
802 e.preventDefault();
803 e.preventDefault();
803 var text = self.cm.getValue();
804 var text = self.cm.getValue();
804
805
805 if (text === "") {
806 if (text === "") {
806 return;
807 return;
807 }
808 }
808
809
809 var postData = {
810 var postData = {
810 'text': text,
811 'text': text,
811 'renderer': templateContext.visual.default_renderer,
812 'renderer': templateContext.visual.default_renderer,
812 'csrf_token': CSRF_TOKEN
813 'csrf_token': CSRF_TOKEN
813 };
814 };
814
815
815 // lock ALL buttons on preview
816 // lock ALL buttons on preview
816 self.setActionButtonsDisabled(true);
817 self.setActionButtonsDisabled(true);
817
818
818 $(self.previewBoxSelector).addClass('unloaded');
819 $(self.previewBoxSelector).addClass('unloaded');
819 $(self.previewBoxSelector).html(_gettext('Loading ...'));
820 $(self.previewBoxSelector).html(_gettext('Loading ...'));
820
821
821 $(self.editContainer).hide();
822 $(self.editContainer).hide();
822 $(self.previewContainer).show();
823 $(self.previewContainer).show();
823
824
824 // by default we reset state of comment preserving the text
825 // by default we reset state of comment preserving the text
825 var previewFailCallback = function(data){
826 var previewFailCallback = function(data){
826 alert(
827 alert(
827 "Error while submitting preview.\n" +
828 "Error while submitting preview.\n" +
828 "Error code {0} ({1}).".format(data.status, data.statusText)
829 "Error code {0} ({1}).".format(data.status, data.statusText)
829 );
830 );
830 self.resetMarkupFormState(text)
831 self.resetMarkupFormState(text)
831 };
832 };
832 _submitAjaxPOST(
833 _submitAjaxPOST(
833 self.previewUrl, postData, self.previewSuccessCallback,
834 self.previewUrl, postData, self.previewSuccessCallback,
834 previewFailCallback);
835 previewFailCallback);
835
836
836 $(self.previewButton).parent().addClass('active');
837 $(self.previewButton).parent().addClass('active');
837 $(self.editButton).parent().removeClass('active');
838 $(self.editButton).parent().removeClass('active');
838 });
839 });
839
840
840 }
841 }
841
842
842 return MarkupForm;
843 return MarkupForm;
843 });
844 });
@@ -1,838 +1,838 b''
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 var firefoxAnchorFix = function() {
19 var firefoxAnchorFix = function() {
20 // hack to make anchor links behave properly on firefox, in our inline
20 // hack to make anchor links behave properly on firefox, in our inline
21 // comments generation when comments are injected firefox is misbehaving
21 // comments generation when comments are injected firefox is misbehaving
22 // when jumping to anchor links
22 // when jumping to anchor links
23 if (location.href.indexOf('#') > -1) {
23 if (location.href.indexOf('#') > -1) {
24 location.href += '';
24 location.href += '';
25 }
25 }
26 };
26 };
27
27
28 var linkifyComments = function(comments) {
28 var linkifyComments = function(comments) {
29 var firstCommentId = null;
29 var firstCommentId = null;
30 if (comments) {
30 if (comments) {
31 firstCommentId = $(comments[0]).data('comment-id');
31 firstCommentId = $(comments[0]).data('comment-id');
32 }
32 }
33
33
34 if (firstCommentId){
34 if (firstCommentId){
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
36 }
36 }
37 };
37 };
38
38
39 var bindToggleButtons = function() {
39 var bindToggleButtons = function() {
40 $('.comment-toggle').on('click', function() {
40 $('.comment-toggle').on('click', function() {
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
42 });
42 });
43 };
43 };
44
44
45
45
46
46
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
48 failHandler = failHandler || function() {};
48 failHandler = failHandler || function() {};
49 postData = toQueryString(postData);
49 postData = toQueryString(postData);
50 var request = $.ajax({
50 var request = $.ajax({
51 url: url,
51 url: url,
52 type: 'POST',
52 type: 'POST',
53 data: postData,
53 data: postData,
54 headers: {'X-PARTIAL-XHR': true}
54 headers: {'X-PARTIAL-XHR': true}
55 })
55 })
56 .done(function (data) {
56 .done(function (data) {
57 successHandler(data);
57 successHandler(data);
58 })
58 })
59 .fail(function (data, textStatus, errorThrown) {
59 .fail(function (data, textStatus, errorThrown) {
60 failHandler(data, textStatus, errorThrown)
60 failHandler(data, textStatus, errorThrown)
61 });
61 });
62 return request;
62 return request;
63 };
63 };
64
64
65
65
66
66
67
67
68 /* Comment form for main and inline comments */
68 /* Comment form for main and inline comments */
69 (function(mod) {
69 (function(mod) {
70
70
71 if (typeof exports == "object" && typeof module == "object") {
71 if (typeof exports == "object" && typeof module == "object") {
72 // CommonJS
72 // CommonJS
73 module.exports = mod();
73 module.exports = mod();
74 }
74 }
75 else {
75 else {
76 // Plain browser env
76 // Plain browser env
77 (this || window).CommentForm = mod();
77 (this || window).CommentForm = mod();
78 }
78 }
79
79
80 })(function() {
80 })(function() {
81 "use strict";
81 "use strict";
82
82
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
84 if (!(this instanceof CommentForm)) {
84 if (!(this instanceof CommentForm)) {
85 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
85 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
86 }
86 }
87
87
88 // bind the element instance to our Form
88 // bind the element instance to our Form
89 $(formElement).get(0).CommentForm = this;
89 $(formElement).get(0).CommentForm = this;
90
90
91 this.withLineNo = function(selector) {
91 this.withLineNo = function(selector) {
92 var lineNo = this.lineNo;
92 var lineNo = this.lineNo;
93 if (lineNo === undefined) {
93 if (lineNo === undefined) {
94 return selector
94 return selector
95 } else {
95 } else {
96 return selector + '_' + lineNo;
96 return selector + '_' + lineNo;
97 }
97 }
98 };
98 };
99
99
100 this.commitId = commitId;
100 this.commitId = commitId;
101 this.pullRequestId = pullRequestId;
101 this.pullRequestId = pullRequestId;
102 this.lineNo = lineNo;
102 this.lineNo = lineNo;
103 this.initAutocompleteActions = initAutocompleteActions;
103 this.initAutocompleteActions = initAutocompleteActions;
104
104
105 this.previewButton = this.withLineNo('#preview-btn');
105 this.previewButton = this.withLineNo('#preview-btn');
106 this.previewContainer = this.withLineNo('#preview-container');
106 this.previewContainer = this.withLineNo('#preview-container');
107
107
108 this.previewBoxSelector = this.withLineNo('#preview-box');
108 this.previewBoxSelector = this.withLineNo('#preview-box');
109
109
110 this.editButton = this.withLineNo('#edit-btn');
110 this.editButton = this.withLineNo('#edit-btn');
111 this.editContainer = this.withLineNo('#edit-container');
111 this.editContainer = this.withLineNo('#edit-container');
112 this.cancelButton = this.withLineNo('#cancel-btn');
112 this.cancelButton = this.withLineNo('#cancel-btn');
113 this.commentType = this.withLineNo('#comment_type');
113 this.commentType = this.withLineNo('#comment_type');
114
114
115 this.resolvesId = null;
115 this.resolvesId = null;
116 this.resolvesActionId = null;
116 this.resolvesActionId = null;
117
117
118 this.closesPr = '#close_pull_request';
118 this.closesPr = '#close_pull_request';
119
119
120 this.cmBox = this.withLineNo('#text');
120 this.cmBox = this.withLineNo('#text');
121 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
121 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
122
122
123 this.statusChange = this.withLineNo('#change_status');
123 this.statusChange = this.withLineNo('#change_status');
124
124
125 this.submitForm = formElement;
125 this.submitForm = formElement;
126 this.submitButton = $(this.submitForm).find('input[type="submit"]');
126 this.submitButton = $(this.submitForm).find('input[type="submit"]');
127 this.submitButtonText = this.submitButton.val();
127 this.submitButtonText = this.submitButton.val();
128
128
129 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
129 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
130 {'repo_name': templateContext.repo_name,
130 {'repo_name': templateContext.repo_name,
131 'commit_id': templateContext.commit_data.commit_id});
131 'commit_id': templateContext.commit_data.commit_id});
132
132
133 if (resolvesCommentId){
133 if (resolvesCommentId){
134 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
134 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
135 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
135 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
136 $(this.commentType).prop('disabled', true);
136 $(this.commentType).prop('disabled', true);
137 $(this.commentType).addClass('disabled');
137 $(this.commentType).addClass('disabled');
138
138
139 // disable select
139 // disable select
140 setTimeout(function() {
140 setTimeout(function() {
141 $(self.statusChange).select2('readonly', true);
141 $(self.statusChange).select2('readonly', true);
142 }, 10);
142 }, 10);
143
143
144 var resolvedInfo = (
144 var resolvedInfo = (
145 '<li class="resolve-action">' +
145 '<li class="resolve-action">' +
146 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
146 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
147 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
147 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
148 '</li>'
148 '</li>'
149 ).format(resolvesCommentId, _gettext('resolve comment'));
149 ).format(resolvesCommentId, _gettext('resolve comment'));
150 $(resolvedInfo).insertAfter($(this.commentType).parent());
150 $(resolvedInfo).insertAfter($(this.commentType).parent());
151 }
151 }
152
152
153 // based on commitId, or pullRequestId decide where do we submit
153 // based on commitId, or pullRequestId decide where do we submit
154 // out data
154 // out data
155 if (this.commitId){
155 if (this.commitId){
156 this.submitUrl = pyroutes.url('repo_commit_comment_create',
156 this.submitUrl = pyroutes.url('repo_commit_comment_create',
157 {'repo_name': templateContext.repo_name,
157 {'repo_name': templateContext.repo_name,
158 'commit_id': this.commitId});
158 'commit_id': this.commitId});
159 this.selfUrl = pyroutes.url('repo_commit',
159 this.selfUrl = pyroutes.url('repo_commit',
160 {'repo_name': templateContext.repo_name,
160 {'repo_name': templateContext.repo_name,
161 'commit_id': this.commitId});
161 'commit_id': this.commitId});
162
162
163 } else if (this.pullRequestId) {
163 } else if (this.pullRequestId) {
164 this.submitUrl = pyroutes.url('pullrequest_comment_create',
164 this.submitUrl = pyroutes.url('pullrequest_comment_create',
165 {'repo_name': templateContext.repo_name,
165 {'repo_name': templateContext.repo_name,
166 'pull_request_id': this.pullRequestId});
166 'pull_request_id': this.pullRequestId});
167 this.selfUrl = pyroutes.url('pullrequest_show',
167 this.selfUrl = pyroutes.url('pullrequest_show',
168 {'repo_name': templateContext.repo_name,
168 {'repo_name': templateContext.repo_name,
169 'pull_request_id': this.pullRequestId});
169 'pull_request_id': this.pullRequestId});
170
170
171 } else {
171 } else {
172 throw new Error(
172 throw new Error(
173 'CommentForm requires pullRequestId, or commitId to be specified.')
173 'CommentForm requires pullRequestId, or commitId to be specified.')
174 }
174 }
175
175
176 // FUNCTIONS and helpers
176 // FUNCTIONS and helpers
177 var self = this;
177 var self = this;
178
178
179 this.isInline = function(){
179 this.isInline = function(){
180 return this.lineNo && this.lineNo != 'general';
180 return this.lineNo && this.lineNo != 'general';
181 };
181 };
182
182
183 this.getCmInstance = function(){
183 this.getCmInstance = function(){
184 return this.cm
184 return this.cm
185 };
185 };
186
186
187 this.setPlaceholder = function(placeholder) {
187 this.setPlaceholder = function(placeholder) {
188 var cm = this.getCmInstance();
188 var cm = this.getCmInstance();
189 if (cm){
189 if (cm){
190 cm.setOption('placeholder', placeholder);
190 cm.setOption('placeholder', placeholder);
191 }
191 }
192 };
192 };
193
193
194 this.getCommentStatus = function() {
194 this.getCommentStatus = function() {
195 return $(this.submitForm).find(this.statusChange).val();
195 return $(this.submitForm).find(this.statusChange).val();
196 };
196 };
197 this.getCommentType = function() {
197 this.getCommentType = function() {
198 return $(this.submitForm).find(this.commentType).val();
198 return $(this.submitForm).find(this.commentType).val();
199 };
199 };
200
200
201 this.getResolvesId = function() {
201 this.getResolvesId = function() {
202 return $(this.submitForm).find(this.resolvesId).val() || null;
202 return $(this.submitForm).find(this.resolvesId).val() || null;
203 };
203 };
204
204
205 this.getClosePr = function() {
205 this.getClosePr = function() {
206 return $(this.submitForm).find(this.closesPr).val() || null;
206 return $(this.submitForm).find(this.closesPr).val() || null;
207 };
207 };
208
208
209 this.markCommentResolved = function(resolvedCommentId){
209 this.markCommentResolved = function(resolvedCommentId){
210 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
210 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
211 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
211 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
212 };
212 };
213
213
214 this.isAllowedToSubmit = function() {
214 this.isAllowedToSubmit = function() {
215 return !$(this.submitButton).prop('disabled');
215 return !$(this.submitButton).prop('disabled');
216 };
216 };
217
217
218 this.initStatusChangeSelector = function(){
218 this.initStatusChangeSelector = function(){
219 var formatChangeStatus = function(state, escapeMarkup) {
219 var formatChangeStatus = function(state, escapeMarkup) {
220 var originalOption = state.element;
220 var originalOption = state.element;
221 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
221 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
222 '<span>' + escapeMarkup(state.text) + '</span>';
222 return tmpl
223 };
223 };
224 var formatResult = function(result, container, query, escapeMarkup) {
224 var formatResult = function(result, container, query, escapeMarkup) {
225 return formatChangeStatus(result, escapeMarkup);
225 return formatChangeStatus(result, escapeMarkup);
226 };
226 };
227
227
228 var formatSelection = function(data, container, escapeMarkup) {
228 var formatSelection = function(data, container, escapeMarkup) {
229 return formatChangeStatus(data, escapeMarkup);
229 return formatChangeStatus(data, escapeMarkup);
230 };
230 };
231
231
232 $(this.submitForm).find(this.statusChange).select2({
232 $(this.submitForm).find(this.statusChange).select2({
233 placeholder: _gettext('Status Review'),
233 placeholder: _gettext('Status Review'),
234 formatResult: formatResult,
234 formatResult: formatResult,
235 formatSelection: formatSelection,
235 formatSelection: formatSelection,
236 containerCssClass: "drop-menu status_box_menu",
236 containerCssClass: "drop-menu status_box_menu",
237 dropdownCssClass: "drop-menu-dropdown",
237 dropdownCssClass: "drop-menu-dropdown",
238 dropdownAutoWidth: true,
238 dropdownAutoWidth: true,
239 minimumResultsForSearch: -1
239 minimumResultsForSearch: -1
240 });
240 });
241 $(this.submitForm).find(this.statusChange).on('change', function() {
241 $(this.submitForm).find(this.statusChange).on('change', function() {
242 var status = self.getCommentStatus();
242 var status = self.getCommentStatus();
243
243
244 if (status && !self.isInline()) {
244 if (status && !self.isInline()) {
245 $(self.submitButton).prop('disabled', false);
245 $(self.submitButton).prop('disabled', false);
246 }
246 }
247
247
248 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
248 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
249 self.setPlaceholder(placeholderText)
249 self.setPlaceholder(placeholderText)
250 })
250 })
251 };
251 };
252
252
253 // reset the comment form into it's original state
253 // reset the comment form into it's original state
254 this.resetCommentFormState = function(content) {
254 this.resetCommentFormState = function(content) {
255 content = content || '';
255 content = content || '';
256
256
257 $(this.editContainer).show();
257 $(this.editContainer).show();
258 $(this.editButton).parent().addClass('active');
258 $(this.editButton).parent().addClass('active');
259
259
260 $(this.previewContainer).hide();
260 $(this.previewContainer).hide();
261 $(this.previewButton).parent().removeClass('active');
261 $(this.previewButton).parent().removeClass('active');
262
262
263 this.setActionButtonsDisabled(true);
263 this.setActionButtonsDisabled(true);
264 self.cm.setValue(content);
264 self.cm.setValue(content);
265 self.cm.setOption("readOnly", false);
265 self.cm.setOption("readOnly", false);
266
266
267 if (this.resolvesId) {
267 if (this.resolvesId) {
268 // destroy the resolve action
268 // destroy the resolve action
269 $(this.resolvesId).parent().remove();
269 $(this.resolvesId).parent().remove();
270 }
270 }
271 // reset closingPR flag
271 // reset closingPR flag
272 $('.close-pr-input').remove();
272 $('.close-pr-input').remove();
273
273
274 $(this.statusChange).select2('readonly', false);
274 $(this.statusChange).select2('readonly', false);
275 };
275 };
276
276
277 this.globalSubmitSuccessCallback = function(){
277 this.globalSubmitSuccessCallback = function(){
278 // default behaviour is to call GLOBAL hook, if it's registered.
278 // default behaviour is to call GLOBAL hook, if it's registered.
279 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
279 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
280 commentFormGlobalSubmitSuccessCallback()
280 commentFormGlobalSubmitSuccessCallback()
281 }
281 }
282 };
282 };
283
283
284 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
284 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
285 return _submitAjaxPOST(url, postData, successHandler, failHandler);
285 return _submitAjaxPOST(url, postData, successHandler, failHandler);
286 };
286 };
287
287
288 // overwrite a submitHandler, we need to do it for inline comments
288 // overwrite a submitHandler, we need to do it for inline comments
289 this.setHandleFormSubmit = function(callback) {
289 this.setHandleFormSubmit = function(callback) {
290 this.handleFormSubmit = callback;
290 this.handleFormSubmit = callback;
291 };
291 };
292
292
293 // overwrite a submitSuccessHandler
293 // overwrite a submitSuccessHandler
294 this.setGlobalSubmitSuccessCallback = function(callback) {
294 this.setGlobalSubmitSuccessCallback = function(callback) {
295 this.globalSubmitSuccessCallback = callback;
295 this.globalSubmitSuccessCallback = callback;
296 };
296 };
297
297
298 // default handler for for submit for main comments
298 // default handler for for submit for main comments
299 this.handleFormSubmit = function() {
299 this.handleFormSubmit = function() {
300 var text = self.cm.getValue();
300 var text = self.cm.getValue();
301 var status = self.getCommentStatus();
301 var status = self.getCommentStatus();
302 var commentType = self.getCommentType();
302 var commentType = self.getCommentType();
303 var resolvesCommentId = self.getResolvesId();
303 var resolvesCommentId = self.getResolvesId();
304 var closePullRequest = self.getClosePr();
304 var closePullRequest = self.getClosePr();
305
305
306 if (text === "" && !status) {
306 if (text === "" && !status) {
307 return;
307 return;
308 }
308 }
309
309
310 var excludeCancelBtn = false;
310 var excludeCancelBtn = false;
311 var submitEvent = true;
311 var submitEvent = true;
312 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
312 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
313 self.cm.setOption("readOnly", true);
313 self.cm.setOption("readOnly", true);
314
314
315 var postData = {
315 var postData = {
316 'text': text,
316 'text': text,
317 'changeset_status': status,
317 'changeset_status': status,
318 'comment_type': commentType,
318 'comment_type': commentType,
319 'csrf_token': CSRF_TOKEN
319 'csrf_token': CSRF_TOKEN
320 };
320 };
321
321
322 if (resolvesCommentId) {
322 if (resolvesCommentId) {
323 postData['resolves_comment_id'] = resolvesCommentId;
323 postData['resolves_comment_id'] = resolvesCommentId;
324 }
324 }
325
325
326 if (closePullRequest) {
326 if (closePullRequest) {
327 postData['close_pull_request'] = true;
327 postData['close_pull_request'] = true;
328 }
328 }
329
329
330 var submitSuccessCallback = function(o) {
330 var submitSuccessCallback = function(o) {
331 // reload page if we change status for single commit.
331 // reload page if we change status for single commit.
332 if (status && self.commitId) {
332 if (status && self.commitId) {
333 location.reload(true);
333 location.reload(true);
334 } else {
334 } else {
335 $('#injected_page_comments').append(o.rendered_text);
335 $('#injected_page_comments').append(o.rendered_text);
336 self.resetCommentFormState();
336 self.resetCommentFormState();
337 timeagoActivate();
337 timeagoActivate();
338
338
339 // mark visually which comment was resolved
339 // mark visually which comment was resolved
340 if (resolvesCommentId) {
340 if (resolvesCommentId) {
341 self.markCommentResolved(resolvesCommentId);
341 self.markCommentResolved(resolvesCommentId);
342 }
342 }
343 }
343 }
344
344
345 // run global callback on submit
345 // run global callback on submit
346 self.globalSubmitSuccessCallback();
346 self.globalSubmitSuccessCallback();
347
347
348 };
348 };
349 var submitFailCallback = function(data) {
349 var submitFailCallback = function(data) {
350 alert(
350 alert(
351 "Error while submitting comment.\n" +
351 "Error while submitting comment.\n" +
352 "Error code {0} ({1}).".format(data.status, data.statusText)
352 "Error code {0} ({1}).".format(data.status, data.statusText)
353 );
353 );
354 self.resetCommentFormState(text);
354 self.resetCommentFormState(text);
355 };
355 };
356 self.submitAjaxPOST(
356 self.submitAjaxPOST(
357 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
357 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
358 };
358 };
359
359
360 this.previewSuccessCallback = function(o) {
360 this.previewSuccessCallback = function(o) {
361 $(self.previewBoxSelector).html(o);
361 $(self.previewBoxSelector).html(o);
362 $(self.previewBoxSelector).removeClass('unloaded');
362 $(self.previewBoxSelector).removeClass('unloaded');
363
363
364 // swap buttons, making preview active
364 // swap buttons, making preview active
365 $(self.previewButton).parent().addClass('active');
365 $(self.previewButton).parent().addClass('active');
366 $(self.editButton).parent().removeClass('active');
366 $(self.editButton).parent().removeClass('active');
367
367
368 // unlock buttons
368 // unlock buttons
369 self.setActionButtonsDisabled(false);
369 self.setActionButtonsDisabled(false);
370 };
370 };
371
371
372 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
372 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
373 excludeCancelBtn = excludeCancelBtn || false;
373 excludeCancelBtn = excludeCancelBtn || false;
374 submitEvent = submitEvent || false;
374 submitEvent = submitEvent || false;
375
375
376 $(this.editButton).prop('disabled', state);
376 $(this.editButton).prop('disabled', state);
377 $(this.previewButton).prop('disabled', state);
377 $(this.previewButton).prop('disabled', state);
378
378
379 if (!excludeCancelBtn) {
379 if (!excludeCancelBtn) {
380 $(this.cancelButton).prop('disabled', state);
380 $(this.cancelButton).prop('disabled', state);
381 }
381 }
382
382
383 var submitState = state;
383 var submitState = state;
384 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
384 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
385 // if the value of commit review status is set, we allow
385 // if the value of commit review status is set, we allow
386 // submit button, but only on Main form, isInline means inline
386 // submit button, but only on Main form, isInline means inline
387 submitState = false
387 submitState = false
388 }
388 }
389
389
390 $(this.submitButton).prop('disabled', submitState);
390 $(this.submitButton).prop('disabled', submitState);
391 if (submitEvent) {
391 if (submitEvent) {
392 $(this.submitButton).val(_gettext('Submitting...'));
392 $(this.submitButton).val(_gettext('Submitting...'));
393 } else {
393 } else {
394 $(this.submitButton).val(this.submitButtonText);
394 $(this.submitButton).val(this.submitButtonText);
395 }
395 }
396
396
397 };
397 };
398
398
399 // lock preview/edit/submit buttons on load, but exclude cancel button
399 // lock preview/edit/submit buttons on load, but exclude cancel button
400 var excludeCancelBtn = true;
400 var excludeCancelBtn = true;
401 this.setActionButtonsDisabled(true, excludeCancelBtn);
401 this.setActionButtonsDisabled(true, excludeCancelBtn);
402
402
403 // anonymous users don't have access to initialized CM instance
403 // anonymous users don't have access to initialized CM instance
404 if (this.cm !== undefined){
404 if (this.cm !== undefined){
405 this.cm.on('change', function(cMirror) {
405 this.cm.on('change', function(cMirror) {
406 if (cMirror.getValue() === "") {
406 if (cMirror.getValue() === "") {
407 self.setActionButtonsDisabled(true, excludeCancelBtn)
407 self.setActionButtonsDisabled(true, excludeCancelBtn)
408 } else {
408 } else {
409 self.setActionButtonsDisabled(false, excludeCancelBtn)
409 self.setActionButtonsDisabled(false, excludeCancelBtn)
410 }
410 }
411 });
411 });
412 }
412 }
413
413
414 $(this.editButton).on('click', function(e) {
414 $(this.editButton).on('click', function(e) {
415 e.preventDefault();
415 e.preventDefault();
416
416
417 $(self.previewButton).parent().removeClass('active');
417 $(self.previewButton).parent().removeClass('active');
418 $(self.previewContainer).hide();
418 $(self.previewContainer).hide();
419
419
420 $(self.editButton).parent().addClass('active');
420 $(self.editButton).parent().addClass('active');
421 $(self.editContainer).show();
421 $(self.editContainer).show();
422
422
423 });
423 });
424
424
425 $(this.previewButton).on('click', function(e) {
425 $(this.previewButton).on('click', function(e) {
426 e.preventDefault();
426 e.preventDefault();
427 var text = self.cm.getValue();
427 var text = self.cm.getValue();
428
428
429 if (text === "") {
429 if (text === "") {
430 return;
430 return;
431 }
431 }
432
432
433 var postData = {
433 var postData = {
434 'text': text,
434 'text': text,
435 'renderer': templateContext.visual.default_renderer,
435 'renderer': templateContext.visual.default_renderer,
436 'csrf_token': CSRF_TOKEN
436 'csrf_token': CSRF_TOKEN
437 };
437 };
438
438
439 // lock ALL buttons on preview
439 // lock ALL buttons on preview
440 self.setActionButtonsDisabled(true);
440 self.setActionButtonsDisabled(true);
441
441
442 $(self.previewBoxSelector).addClass('unloaded');
442 $(self.previewBoxSelector).addClass('unloaded');
443 $(self.previewBoxSelector).html(_gettext('Loading ...'));
443 $(self.previewBoxSelector).html(_gettext('Loading ...'));
444
444
445 $(self.editContainer).hide();
445 $(self.editContainer).hide();
446 $(self.previewContainer).show();
446 $(self.previewContainer).show();
447
447
448 // by default we reset state of comment preserving the text
448 // by default we reset state of comment preserving the text
449 var previewFailCallback = function(data){
449 var previewFailCallback = function(data){
450 alert(
450 alert(
451 "Error while preview of comment.\n" +
451 "Error while preview of comment.\n" +
452 "Error code {0} ({1}).".format(data.status, data.statusText)
452 "Error code {0} ({1}).".format(data.status, data.statusText)
453 );
453 );
454 self.resetCommentFormState(text)
454 self.resetCommentFormState(text)
455 };
455 };
456 self.submitAjaxPOST(
456 self.submitAjaxPOST(
457 self.previewUrl, postData, self.previewSuccessCallback,
457 self.previewUrl, postData, self.previewSuccessCallback,
458 previewFailCallback);
458 previewFailCallback);
459
459
460 $(self.previewButton).parent().addClass('active');
460 $(self.previewButton).parent().addClass('active');
461 $(self.editButton).parent().removeClass('active');
461 $(self.editButton).parent().removeClass('active');
462 });
462 });
463
463
464 $(this.submitForm).submit(function(e) {
464 $(this.submitForm).submit(function(e) {
465 e.preventDefault();
465 e.preventDefault();
466 var allowedToSubmit = self.isAllowedToSubmit();
466 var allowedToSubmit = self.isAllowedToSubmit();
467 if (!allowedToSubmit){
467 if (!allowedToSubmit){
468 return false;
468 return false;
469 }
469 }
470 self.handleFormSubmit();
470 self.handleFormSubmit();
471 });
471 });
472
472
473 }
473 }
474
474
475 return CommentForm;
475 return CommentForm;
476 });
476 });
477
477
478 /* comments controller */
478 /* comments controller */
479 var CommentsController = function() {
479 var CommentsController = function() {
480 var mainComment = '#text';
480 var mainComment = '#text';
481 var self = this;
481 var self = this;
482
482
483 this.cancelComment = function(node) {
483 this.cancelComment = function(node) {
484 var $node = $(node);
484 var $node = $(node);
485 var $td = $node.closest('td');
485 var $td = $node.closest('td');
486 $node.closest('.comment-inline-form').remove();
486 $node.closest('.comment-inline-form').remove();
487 return false;
487 return false;
488 };
488 };
489
489
490 this.getLineNumber = function(node) {
490 this.getLineNumber = function(node) {
491 var $node = $(node);
491 var $node = $(node);
492 var lineNo = $node.closest('td').attr('data-line-no');
492 var lineNo = $node.closest('td').attr('data-line-no');
493 if (lineNo === undefined && $node.data('commentInline')){
493 if (lineNo === undefined && $node.data('commentInline')){
494 lineNo = $node.data('commentLineNo')
494 lineNo = $node.data('commentLineNo')
495 }
495 }
496
496
497 return lineNo
497 return lineNo
498 };
498 };
499
499
500 this.scrollToComment = function(node, offset, outdated) {
500 this.scrollToComment = function(node, offset, outdated) {
501 if (offset === undefined) {
501 if (offset === undefined) {
502 offset = 0;
502 offset = 0;
503 }
503 }
504 var outdated = outdated || false;
504 var outdated = outdated || false;
505 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
505 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
506
506
507 if (!node) {
507 if (!node) {
508 node = $('.comment-selected');
508 node = $('.comment-selected');
509 if (!node.length) {
509 if (!node.length) {
510 node = $('comment-current')
510 node = $('comment-current')
511 }
511 }
512 }
512 }
513 $wrapper = $(node).closest('div.comment');
513 $wrapper = $(node).closest('div.comment');
514 $comment = $(node).closest(klass);
514 $comment = $(node).closest(klass);
515 $comments = $(klass);
515 $comments = $(klass);
516
516
517 // show hidden comment when referenced.
517 // show hidden comment when referenced.
518 if (!$wrapper.is(':visible')){
518 if (!$wrapper.is(':visible')){
519 $wrapper.show();
519 $wrapper.show();
520 }
520 }
521
521
522 $('.comment-selected').removeClass('comment-selected');
522 $('.comment-selected').removeClass('comment-selected');
523
523
524 var nextIdx = $(klass).index($comment) + offset;
524 var nextIdx = $(klass).index($comment) + offset;
525 if (nextIdx >= $comments.length) {
525 if (nextIdx >= $comments.length) {
526 nextIdx = 0;
526 nextIdx = 0;
527 }
527 }
528 var $next = $(klass).eq(nextIdx);
528 var $next = $(klass).eq(nextIdx);
529
529
530 var $cb = $next.closest('.cb');
530 var $cb = $next.closest('.cb');
531 $cb.removeClass('cb-collapsed');
531 $cb.removeClass('cb-collapsed');
532
532
533 var $filediffCollapseState = $cb.closest('.filediff').prev();
533 var $filediffCollapseState = $cb.closest('.filediff').prev();
534 $filediffCollapseState.prop('checked', false);
534 $filediffCollapseState.prop('checked', false);
535 $next.addClass('comment-selected');
535 $next.addClass('comment-selected');
536 scrollToElement($next);
536 scrollToElement($next);
537 return false;
537 return false;
538 };
538 };
539
539
540 this.nextComment = function(node) {
540 this.nextComment = function(node) {
541 return self.scrollToComment(node, 1);
541 return self.scrollToComment(node, 1);
542 };
542 };
543
543
544 this.prevComment = function(node) {
544 this.prevComment = function(node) {
545 return self.scrollToComment(node, -1);
545 return self.scrollToComment(node, -1);
546 };
546 };
547
547
548 this.nextOutdatedComment = function(node) {
548 this.nextOutdatedComment = function(node) {
549 return self.scrollToComment(node, 1, true);
549 return self.scrollToComment(node, 1, true);
550 };
550 };
551
551
552 this.prevOutdatedComment = function(node) {
552 this.prevOutdatedComment = function(node) {
553 return self.scrollToComment(node, -1, true);
553 return self.scrollToComment(node, -1, true);
554 };
554 };
555
555
556 this.deleteComment = function(node) {
556 this.deleteComment = function(node) {
557 if (!confirm(_gettext('Delete this comment?'))) {
557 if (!confirm(_gettext('Delete this comment?'))) {
558 return false;
558 return false;
559 }
559 }
560 var $node = $(node);
560 var $node = $(node);
561 var $td = $node.closest('td');
561 var $td = $node.closest('td');
562 var $comment = $node.closest('.comment');
562 var $comment = $node.closest('.comment');
563 var comment_id = $comment.attr('data-comment-id');
563 var comment_id = $comment.attr('data-comment-id');
564 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
564 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
565 var postData = {
565 var postData = {
566 'csrf_token': CSRF_TOKEN
566 'csrf_token': CSRF_TOKEN
567 };
567 };
568
568
569 $comment.addClass('comment-deleting');
569 $comment.addClass('comment-deleting');
570 $comment.hide('fast');
570 $comment.hide('fast');
571
571
572 var success = function(response) {
572 var success = function(response) {
573 $comment.remove();
573 $comment.remove();
574 return false;
574 return false;
575 };
575 };
576 var failure = function(data, textStatus, xhr) {
576 var failure = function(data, textStatus, xhr) {
577 alert("error processing request: " + textStatus);
577 alert("error processing request: " + textStatus);
578 $comment.show('fast');
578 $comment.show('fast');
579 $comment.removeClass('comment-deleting');
579 $comment.removeClass('comment-deleting');
580 return false;
580 return false;
581 };
581 };
582 ajaxPOST(url, postData, success, failure);
582 ajaxPOST(url, postData, success, failure);
583 };
583 };
584
584
585 this.toggleWideMode = function (node) {
585 this.toggleWideMode = function (node) {
586 if ($('#content').hasClass('wrapper')) {
586 if ($('#content').hasClass('wrapper')) {
587 $('#content').removeClass("wrapper");
587 $('#content').removeClass("wrapper");
588 $('#content').addClass("wide-mode-wrapper");
588 $('#content').addClass("wide-mode-wrapper");
589 $(node).addClass('btn-success');
589 $(node).addClass('btn-success');
590 return true
590 return true
591 } else {
591 } else {
592 $('#content').removeClass("wide-mode-wrapper");
592 $('#content').removeClass("wide-mode-wrapper");
593 $('#content').addClass("wrapper");
593 $('#content').addClass("wrapper");
594 $(node).removeClass('btn-success');
594 $(node).removeClass('btn-success');
595 return false
595 return false
596 }
596 }
597
597
598 };
598 };
599
599
600 this.toggleComments = function(node, show) {
600 this.toggleComments = function(node, show) {
601 var $filediff = $(node).closest('.filediff');
601 var $filediff = $(node).closest('.filediff');
602 if (show === true) {
602 if (show === true) {
603 $filediff.removeClass('hide-comments');
603 $filediff.removeClass('hide-comments');
604 } else if (show === false) {
604 } else if (show === false) {
605 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
605 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
606 $filediff.addClass('hide-comments');
606 $filediff.addClass('hide-comments');
607 } else {
607 } else {
608 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
608 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
609 $filediff.toggleClass('hide-comments');
609 $filediff.toggleClass('hide-comments');
610 }
610 }
611 return false;
611 return false;
612 };
612 };
613
613
614 this.toggleLineComments = function(node) {
614 this.toggleLineComments = function(node) {
615 self.toggleComments(node, true);
615 self.toggleComments(node, true);
616 var $node = $(node);
616 var $node = $(node);
617 // mark outdated comments as visible before the toggle;
617 // mark outdated comments as visible before the toggle;
618 $(node.closest('tr')).find('.comment-outdated').show();
618 $(node.closest('tr')).find('.comment-outdated').show();
619 $node.closest('tr').toggleClass('hide-line-comments');
619 $node.closest('tr').toggleClass('hide-line-comments');
620 };
620 };
621
621
622 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
622 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
623 var pullRequestId = templateContext.pull_request_data.pull_request_id;
623 var pullRequestId = templateContext.pull_request_data.pull_request_id;
624 var commitId = templateContext.commit_data.commit_id;
624 var commitId = templateContext.commit_data.commit_id;
625
625
626 var commentForm = new CommentForm(
626 var commentForm = new CommentForm(
627 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
627 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
628 var cm = commentForm.getCmInstance();
628 var cm = commentForm.getCmInstance();
629
629
630 if (resolvesCommentId){
630 if (resolvesCommentId){
631 var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
631 var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
632 }
632 }
633
633
634 setTimeout(function() {
634 setTimeout(function() {
635 // callbacks
635 // callbacks
636 if (cm !== undefined) {
636 if (cm !== undefined) {
637 commentForm.setPlaceholder(placeholderText);
637 commentForm.setPlaceholder(placeholderText);
638 if (commentForm.isInline()) {
638 if (commentForm.isInline()) {
639 cm.focus();
639 cm.focus();
640 cm.refresh();
640 cm.refresh();
641 }
641 }
642 }
642 }
643 }, 10);
643 }, 10);
644
644
645 // trigger scrolldown to the resolve comment, since it might be away
645 // trigger scrolldown to the resolve comment, since it might be away
646 // from the clicked
646 // from the clicked
647 if (resolvesCommentId){
647 if (resolvesCommentId){
648 var actionNode = $(commentForm.resolvesActionId).offset();
648 var actionNode = $(commentForm.resolvesActionId).offset();
649
649
650 setTimeout(function() {
650 setTimeout(function() {
651 if (actionNode) {
651 if (actionNode) {
652 $('body, html').animate({scrollTop: actionNode.top}, 10);
652 $('body, html').animate({scrollTop: actionNode.top}, 10);
653 }
653 }
654 }, 100);
654 }, 100);
655 }
655 }
656
656
657 return commentForm;
657 return commentForm;
658 };
658 };
659
659
660 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
660 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
661
661
662 var tmpl = $('#cb-comment-general-form-template').html();
662 var tmpl = $('#cb-comment-general-form-template').html();
663 tmpl = tmpl.format(null, 'general');
663 tmpl = tmpl.format(null, 'general');
664 var $form = $(tmpl);
664 var $form = $(tmpl);
665
665
666 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
666 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
667 var curForm = $formPlaceholder.find('form');
667 var curForm = $formPlaceholder.find('form');
668 if (curForm){
668 if (curForm){
669 curForm.remove();
669 curForm.remove();
670 }
670 }
671 $formPlaceholder.append($form);
671 $formPlaceholder.append($form);
672
672
673 var _form = $($form[0]);
673 var _form = $($form[0]);
674 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
674 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
675 var commentForm = this.createCommentForm(
675 var commentForm = this.createCommentForm(
676 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId);
676 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId);
677 commentForm.initStatusChangeSelector();
677 commentForm.initStatusChangeSelector();
678
678
679 return commentForm;
679 return commentForm;
680 };
680 };
681
681
682 this.createComment = function(node, resolutionComment) {
682 this.createComment = function(node, resolutionComment) {
683 var resolvesCommentId = resolutionComment || null;
683 var resolvesCommentId = resolutionComment || null;
684 var $node = $(node);
684 var $node = $(node);
685 var $td = $node.closest('td');
685 var $td = $node.closest('td');
686 var $form = $td.find('.comment-inline-form');
686 var $form = $td.find('.comment-inline-form');
687
687
688 if (!$form.length) {
688 if (!$form.length) {
689
689
690 var $filediff = $node.closest('.filediff');
690 var $filediff = $node.closest('.filediff');
691 $filediff.removeClass('hide-comments');
691 $filediff.removeClass('hide-comments');
692 var f_path = $filediff.attr('data-f-path');
692 var f_path = $filediff.attr('data-f-path');
693 var lineno = self.getLineNumber(node);
693 var lineno = self.getLineNumber(node);
694 // create a new HTML from template
694 // create a new HTML from template
695 var tmpl = $('#cb-comment-inline-form-template').html();
695 var tmpl = $('#cb-comment-inline-form-template').html();
696 tmpl = tmpl.format(escapeHtml(f_path), lineno);
696 tmpl = tmpl.format(escapeHtml(f_path), lineno);
697 $form = $(tmpl);
697 $form = $(tmpl);
698
698
699 var $comments = $td.find('.inline-comments');
699 var $comments = $td.find('.inline-comments');
700 if (!$comments.length) {
700 if (!$comments.length) {
701 $comments = $(
701 $comments = $(
702 $('#cb-comments-inline-container-template').html());
702 $('#cb-comments-inline-container-template').html());
703 $td.append($comments);
703 $td.append($comments);
704 }
704 }
705
705
706 $td.find('.cb-comment-add-button').before($form);
706 $td.find('.cb-comment-add-button').before($form);
707
707
708 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
708 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
709 var _form = $($form[0]).find('form');
709 var _form = $($form[0]).find('form');
710 var autocompleteActions = ['as_note', 'as_todo'];
710 var autocompleteActions = ['as_note', 'as_todo'];
711 var commentForm = this.createCommentForm(
711 var commentForm = this.createCommentForm(
712 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId);
712 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId);
713
713
714 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
714 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
715 form: _form,
715 form: _form,
716 parent: $td[0],
716 parent: $td[0],
717 lineno: lineno,
717 lineno: lineno,
718 f_path: f_path}
718 f_path: f_path}
719 );
719 );
720
720
721 // set a CUSTOM submit handler for inline comments.
721 // set a CUSTOM submit handler for inline comments.
722 commentForm.setHandleFormSubmit(function(o) {
722 commentForm.setHandleFormSubmit(function(o) {
723 var text = commentForm.cm.getValue();
723 var text = commentForm.cm.getValue();
724 var commentType = commentForm.getCommentType();
724 var commentType = commentForm.getCommentType();
725 var resolvesCommentId = commentForm.getResolvesId();
725 var resolvesCommentId = commentForm.getResolvesId();
726
726
727 if (text === "") {
727 if (text === "") {
728 return;
728 return;
729 }
729 }
730
730
731 if (lineno === undefined) {
731 if (lineno === undefined) {
732 alert('missing line !');
732 alert('missing line !');
733 return;
733 return;
734 }
734 }
735 if (f_path === undefined) {
735 if (f_path === undefined) {
736 alert('missing file path !');
736 alert('missing file path !');
737 return;
737 return;
738 }
738 }
739
739
740 var excludeCancelBtn = false;
740 var excludeCancelBtn = false;
741 var submitEvent = true;
741 var submitEvent = true;
742 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
742 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
743 commentForm.cm.setOption("readOnly", true);
743 commentForm.cm.setOption("readOnly", true);
744 var postData = {
744 var postData = {
745 'text': text,
745 'text': text,
746 'f_path': f_path,
746 'f_path': f_path,
747 'line': lineno,
747 'line': lineno,
748 'comment_type': commentType,
748 'comment_type': commentType,
749 'csrf_token': CSRF_TOKEN
749 'csrf_token': CSRF_TOKEN
750 };
750 };
751 if (resolvesCommentId){
751 if (resolvesCommentId){
752 postData['resolves_comment_id'] = resolvesCommentId;
752 postData['resolves_comment_id'] = resolvesCommentId;
753 }
753 }
754
754
755 var submitSuccessCallback = function(json_data) {
755 var submitSuccessCallback = function(json_data) {
756 $form.remove();
756 $form.remove();
757 try {
757 try {
758 var html = json_data.rendered_text;
758 var html = json_data.rendered_text;
759 var lineno = json_data.line_no;
759 var lineno = json_data.line_no;
760 var target_id = json_data.target_id;
760 var target_id = json_data.target_id;
761
761
762 $comments.find('.cb-comment-add-button').before(html);
762 $comments.find('.cb-comment-add-button').before(html);
763
763
764 //mark visually which comment was resolved
764 //mark visually which comment was resolved
765 if (resolvesCommentId) {
765 if (resolvesCommentId) {
766 commentForm.markCommentResolved(resolvesCommentId);
766 commentForm.markCommentResolved(resolvesCommentId);
767 }
767 }
768
768
769 // run global callback on submit
769 // run global callback on submit
770 commentForm.globalSubmitSuccessCallback();
770 commentForm.globalSubmitSuccessCallback();
771
771
772 } catch (e) {
772 } catch (e) {
773 console.error(e);
773 console.error(e);
774 }
774 }
775
775
776 // re trigger the linkification of next/prev navigation
776 // re trigger the linkification of next/prev navigation
777 linkifyComments($('.inline-comment-injected'));
777 linkifyComments($('.inline-comment-injected'));
778 timeagoActivate();
778 timeagoActivate();
779
779
780 if (window.updateSticky !== undefined) {
780 if (window.updateSticky !== undefined) {
781 // potentially our comments change the active window size, so we
781 // potentially our comments change the active window size, so we
782 // notify sticky elements
782 // notify sticky elements
783 updateSticky()
783 updateSticky()
784 }
784 }
785
785
786 commentForm.setActionButtonsDisabled(false);
786 commentForm.setActionButtonsDisabled(false);
787
787
788 };
788 };
789 var submitFailCallback = function(data){
789 var submitFailCallback = function(data){
790 alert(
790 alert(
791 "Error while submitting comment.\n" +
791 "Error while submitting comment.\n" +
792 "Error code {0} ({1}).".format(data.status, data.statusText)
792 "Error code {0} ({1}).".format(data.status, data.statusText)
793 );
793 );
794 commentForm.resetCommentFormState(text)
794 commentForm.resetCommentFormState(text)
795 };
795 };
796 commentForm.submitAjaxPOST(
796 commentForm.submitAjaxPOST(
797 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
797 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
798 });
798 });
799 }
799 }
800
800
801 $form.addClass('comment-inline-form-open');
801 $form.addClass('comment-inline-form-open');
802 };
802 };
803
803
804 this.createResolutionComment = function(commentId){
804 this.createResolutionComment = function(commentId){
805 // hide the trigger text
805 // hide the trigger text
806 $('#resolve-comment-{0}'.format(commentId)).hide();
806 $('#resolve-comment-{0}'.format(commentId)).hide();
807
807
808 var comment = $('#comment-'+commentId);
808 var comment = $('#comment-'+commentId);
809 var commentData = comment.data();
809 var commentData = comment.data();
810 if (commentData.commentInline) {
810 if (commentData.commentInline) {
811 this.createComment(comment, commentId)
811 this.createComment(comment, commentId)
812 } else {
812 } else {
813 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
813 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
814 }
814 }
815
815
816 return false;
816 return false;
817 };
817 };
818
818
819 this.submitResolution = function(commentId){
819 this.submitResolution = function(commentId){
820 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
820 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
821 var commentForm = form.get(0).CommentForm;
821 var commentForm = form.get(0).CommentForm;
822
822
823 var cm = commentForm.getCmInstance();
823 var cm = commentForm.getCmInstance();
824 var renderer = templateContext.visual.default_renderer;
824 var renderer = templateContext.visual.default_renderer;
825 if (renderer == 'rst'){
825 if (renderer == 'rst'){
826 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
826 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
827 } else if (renderer == 'markdown') {
827 } else if (renderer == 'markdown') {
828 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
828 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
829 } else {
829 } else {
830 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
830 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
831 }
831 }
832
832
833 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
833 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
834 form.submit();
834 form.submit();
835 return false;
835 return false;
836 };
836 };
837
837
838 };
838 };
@@ -1,407 +1,407 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 ## usage:
2 ## usage:
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
4 ## ${comment.comment_block(comment)}
4 ## ${comment.comment_block(comment)}
5 ##
5 ##
6 <%namespace name="base" file="/base/base.mako"/>
6 <%namespace name="base" file="/base/base.mako"/>
7
7
8 <%def name="comment_block(comment, inline=False)">
8 <%def name="comment_block(comment, inline=False)">
9 <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %>
9 <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %>
10 <% latest_ver = len(getattr(c, 'versions', [])) %>
10 <% latest_ver = len(getattr(c, 'versions', [])) %>
11 % if inline:
11 % if inline:
12 <% outdated_at_ver = comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
12 <% outdated_at_ver = comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
13 % else:
13 % else:
14 <% outdated_at_ver = comment.older_than_version(getattr(c, 'at_version_num', None)) %>
14 <% outdated_at_ver = comment.older_than_version(getattr(c, 'at_version_num', None)) %>
15 % endif
15 % endif
16
16
17
17
18 <div class="comment
18 <div class="comment
19 ${'comment-inline' if inline else 'comment-general'}
19 ${'comment-inline' if inline else 'comment-general'}
20 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
20 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
21 id="comment-${comment.comment_id}"
21 id="comment-${comment.comment_id}"
22 line="${comment.line_no}"
22 line="${comment.line_no}"
23 data-comment-id="${comment.comment_id}"
23 data-comment-id="${comment.comment_id}"
24 data-comment-type="${comment.comment_type}"
24 data-comment-type="${comment.comment_type}"
25 data-comment-line-no="${comment.line_no}"
25 data-comment-line-no="${comment.line_no}"
26 data-comment-inline=${h.json.dumps(inline)}
26 data-comment-inline=${h.json.dumps(inline)}
27 style="${'display: none;' if outdated_at_ver else ''}">
27 style="${'display: none;' if outdated_at_ver else ''}">
28
28
29 <div class="meta">
29 <div class="meta">
30 <div class="comment-type-label">
30 <div class="comment-type-label">
31 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}" title="line: ${comment.line_no}">
31 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}" title="line: ${comment.line_no}">
32 % if comment.comment_type == 'todo':
32 % if comment.comment_type == 'todo':
33 % if comment.resolved:
33 % if comment.resolved:
34 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
34 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
35 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
35 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
36 </div>
36 </div>
37 % else:
37 % else:
38 <div class="resolved tooltip" style="display: none">
38 <div class="resolved tooltip" style="display: none">
39 <span>${comment.comment_type}</span>
39 <span>${comment.comment_type}</span>
40 </div>
40 </div>
41 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to resolve this comment')}">
41 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to resolve this comment')}">
42 ${comment.comment_type}
42 ${comment.comment_type}
43 </div>
43 </div>
44 % endif
44 % endif
45 % else:
45 % else:
46 % if comment.resolved_comment:
46 % if comment.resolved_comment:
47 fix
47 fix
48 % else:
48 % else:
49 ${comment.comment_type or 'note'}
49 ${comment.comment_type or 'note'}
50 % endif
50 % endif
51 % endif
51 % endif
52 </div>
52 </div>
53 </div>
53 </div>
54
54
55 <div class="author ${'author-inline' if inline else 'author-general'}">
55 <div class="author ${'author-inline' if inline else 'author-general'}">
56 ${base.gravatar_with_user(comment.author.email, 16)}
56 ${base.gravatar_with_user(comment.author.email, 16)}
57 </div>
57 </div>
58 <div class="date">
58 <div class="date">
59 ${h.age_component(comment.modified_at, time_is_local=True)}
59 ${h.age_component(comment.modified_at, time_is_local=True)}
60 </div>
60 </div>
61 % if inline:
61 % if inline:
62 <span></span>
62 <span></span>
63 % else:
63 % else:
64 <div class="status-change">
64 <div class="status-change">
65 % if comment.pull_request:
65 % if comment.pull_request:
66 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
66 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
67 % if comment.status_change:
67 % if comment.status_change:
68 ${_('pull request #%s') % comment.pull_request.pull_request_id}:
68 ${_('pull request #%s') % comment.pull_request.pull_request_id}:
69 % else:
69 % else:
70 ${_('pull request #%s') % comment.pull_request.pull_request_id}
70 ${_('pull request #%s') % comment.pull_request.pull_request_id}
71 % endif
71 % endif
72 </a>
72 </a>
73 % else:
73 % else:
74 % if comment.status_change:
74 % if comment.status_change:
75 ${_('Status change on commit')}:
75 ${_('Status change on commit')}:
76 % endif
76 % endif
77 % endif
77 % endif
78 </div>
78 </div>
79 % endif
79 % endif
80
80
81 % if comment.status_change:
81 % if comment.status_change:
82 <div class="${'flag_status %s' % comment.status_change[0].status}"></div>
82 <i class="icon-circle review-status-${comment.status_change[0].status}"></i>
83 <div title="${_('Commit status')}" class="changeset-status-lbl">
83 <div title="${_('Commit status')}" class="changeset-status-lbl">
84 ${comment.status_change[0].status_lbl}
84 ${comment.status_change[0].status_lbl}
85 </div>
85 </div>
86 % endif
86 % endif
87
87
88 % if comment.resolved_comment:
88 % if comment.resolved_comment:
89 <a class="has-spacer-before" href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
89 <a class="has-spacer-before" href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
90 ${_('resolves comment #{}').format(comment.resolved_comment.comment_id)}
90 ${_('resolves comment #{}').format(comment.resolved_comment.comment_id)}
91 </a>
91 </a>
92 % endif
92 % endif
93
93
94 <a class="permalink" href="#comment-${comment.comment_id}"> &para;</a>
94 <a class="permalink" href="#comment-${comment.comment_id}"> &para;</a>
95
95
96 <div class="comment-links-block">
96 <div class="comment-links-block">
97 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
97 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
98 <span class="tag authortag tooltip" title="${_('Pull request author')}">
98 <span class="tag authortag tooltip" title="${_('Pull request author')}">
99 ${_('author')}
99 ${_('author')}
100 </span>
100 </span>
101 |
101 |
102 % endif
102 % endif
103 % if inline:
103 % if inline:
104 <div class="pr-version-inline">
104 <div class="pr-version-inline">
105 <a href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
105 <a href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
106 % if outdated_at_ver:
106 % if outdated_at_ver:
107 <code class="pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
107 <code class="pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
108 outdated ${'v{}'.format(pr_index_ver)} |
108 outdated ${'v{}'.format(pr_index_ver)} |
109 </code>
109 </code>
110 % elif pr_index_ver:
110 % elif pr_index_ver:
111 <code class="pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
111 <code class="pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
112 ${'v{}'.format(pr_index_ver)} |
112 ${'v{}'.format(pr_index_ver)} |
113 </code>
113 </code>
114 % endif
114 % endif
115 </a>
115 </a>
116 </div>
116 </div>
117 % else:
117 % else:
118 % if comment.pull_request_version_id and pr_index_ver:
118 % if comment.pull_request_version_id and pr_index_ver:
119 |
119 |
120 <div class="pr-version">
120 <div class="pr-version">
121 % if comment.outdated:
121 % if comment.outdated:
122 <a href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}">
122 <a href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}">
123 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}
123 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}
124 </a>
124 </a>
125 % else:
125 % else:
126 <div title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
126 <div title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
127 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}">
127 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}">
128 <code class="pr-version-num">
128 <code class="pr-version-num">
129 ${'v{}'.format(pr_index_ver)}
129 ${'v{}'.format(pr_index_ver)}
130 </code>
130 </code>
131 </a>
131 </a>
132 </div>
132 </div>
133 % endif
133 % endif
134 </div>
134 </div>
135 % endif
135 % endif
136 % endif
136 % endif
137
137
138 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
138 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
139 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
139 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
140 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
140 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
141 ## permissions to delete
141 ## permissions to delete
142 %if c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id:
142 %if c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id:
143 ## TODO: dan: add edit comment here
143 ## TODO: dan: add edit comment here
144 <a onclick="return Rhodecode.comments.deleteComment(this);" class="delete-comment"> ${_('Delete')}</a>
144 <a onclick="return Rhodecode.comments.deleteComment(this);" class="delete-comment"> ${_('Delete')}</a>
145 %else:
145 %else:
146 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
146 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
147 %endif
147 %endif
148 %else:
148 %else:
149 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
149 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
150 %endif
150 %endif
151
151
152 % if outdated_at_ver:
152 % if outdated_at_ver:
153 | <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="prev-comment"> ${_('Prev')}</a>
153 | <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="prev-comment"> ${_('Prev')}</a>
154 | <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="next-comment"> ${_('Next')}</a>
154 | <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="next-comment"> ${_('Next')}</a>
155 % else:
155 % else:
156 | <a onclick="return Rhodecode.comments.prevComment(this);" class="prev-comment"> ${_('Prev')}</a>
156 | <a onclick="return Rhodecode.comments.prevComment(this);" class="prev-comment"> ${_('Prev')}</a>
157 | <a onclick="return Rhodecode.comments.nextComment(this);" class="next-comment"> ${_('Next')}</a>
157 | <a onclick="return Rhodecode.comments.nextComment(this);" class="next-comment"> ${_('Next')}</a>
158 % endif
158 % endif
159
159
160 </div>
160 </div>
161 </div>
161 </div>
162 <div class="text">
162 <div class="text">
163 ${h.render(comment.text, renderer=comment.renderer, mentions=True)}
163 ${h.render(comment.text, renderer=comment.renderer, mentions=True)}
164 </div>
164 </div>
165
165
166 </div>
166 </div>
167 </%def>
167 </%def>
168
168
169 ## generate main comments
169 ## generate main comments
170 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
170 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
171 <div class="general-comments" id="comments">
171 <div class="general-comments" id="comments">
172 %for comment in comments:
172 %for comment in comments:
173 <div id="comment-tr-${comment.comment_id}">
173 <div id="comment-tr-${comment.comment_id}">
174 ## only render comments that are not from pull request, or from
174 ## only render comments that are not from pull request, or from
175 ## pull request and a status change
175 ## pull request and a status change
176 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
176 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
177 ${comment_block(comment)}
177 ${comment_block(comment)}
178 %endif
178 %endif
179 </div>
179 </div>
180 %endfor
180 %endfor
181 ## to anchor ajax comments
181 ## to anchor ajax comments
182 <div id="injected_page_comments"></div>
182 <div id="injected_page_comments"></div>
183 </div>
183 </div>
184 </%def>
184 </%def>
185
185
186
186
187 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
187 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
188
188
189 <div class="comments">
189 <div class="comments">
190 <%
190 <%
191 if is_pull_request:
191 if is_pull_request:
192 placeholder = _('Leave a comment on this Pull Request.')
192 placeholder = _('Leave a comment on this Pull Request.')
193 elif is_compare:
193 elif is_compare:
194 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
194 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
195 else:
195 else:
196 placeholder = _('Leave a comment on this Commit.')
196 placeholder = _('Leave a comment on this Commit.')
197 %>
197 %>
198
198
199 % if c.rhodecode_user.username != h.DEFAULT_USER:
199 % if c.rhodecode_user.username != h.DEFAULT_USER:
200 <div class="js-template" id="cb-comment-general-form-template">
200 <div class="js-template" id="cb-comment-general-form-template">
201 ## template generated for injection
201 ## template generated for injection
202 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
202 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
203 </div>
203 </div>
204
204
205 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
205 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
206 ## inject form here
206 ## inject form here
207 </div>
207 </div>
208 <script type="text/javascript">
208 <script type="text/javascript">
209 var lineNo = 'general';
209 var lineNo = 'general';
210 var resolvesCommentId = null;
210 var resolvesCommentId = null;
211 var generalCommentForm = Rhodecode.comments.createGeneralComment(
211 var generalCommentForm = Rhodecode.comments.createGeneralComment(
212 lineNo, "${placeholder}", resolvesCommentId);
212 lineNo, "${placeholder}", resolvesCommentId);
213
213
214 // set custom success callback on rangeCommit
214 // set custom success callback on rangeCommit
215 % if is_compare:
215 % if is_compare:
216 generalCommentForm.setHandleFormSubmit(function(o) {
216 generalCommentForm.setHandleFormSubmit(function(o) {
217 var self = generalCommentForm;
217 var self = generalCommentForm;
218
218
219 var text = self.cm.getValue();
219 var text = self.cm.getValue();
220 var status = self.getCommentStatus();
220 var status = self.getCommentStatus();
221 var commentType = self.getCommentType();
221 var commentType = self.getCommentType();
222
222
223 if (text === "" && !status) {
223 if (text === "" && !status) {
224 return;
224 return;
225 }
225 }
226
226
227 // we can pick which commits we want to make the comment by
227 // we can pick which commits we want to make the comment by
228 // selecting them via click on preview pane, this will alter the hidden inputs
228 // selecting them via click on preview pane, this will alter the hidden inputs
229 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
229 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
230
230
231 var commitIds = [];
231 var commitIds = [];
232 $('#changeset_compare_view_content .compare_select').each(function(el) {
232 $('#changeset_compare_view_content .compare_select').each(function(el) {
233 var commitId = this.id.replace('row-', '');
233 var commitId = this.id.replace('row-', '');
234 if ($(this).hasClass('hl') || !cherryPicked) {
234 if ($(this).hasClass('hl') || !cherryPicked) {
235 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
235 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
236 commitIds.push(commitId);
236 commitIds.push(commitId);
237 } else {
237 } else {
238 $("input[data-commit-id='{0}']".format(commitId)).val('')
238 $("input[data-commit-id='{0}']".format(commitId)).val('')
239 }
239 }
240 });
240 });
241
241
242 self.setActionButtonsDisabled(true);
242 self.setActionButtonsDisabled(true);
243 self.cm.setOption("readOnly", true);
243 self.cm.setOption("readOnly", true);
244 var postData = {
244 var postData = {
245 'text': text,
245 'text': text,
246 'changeset_status': status,
246 'changeset_status': status,
247 'comment_type': commentType,
247 'comment_type': commentType,
248 'commit_ids': commitIds,
248 'commit_ids': commitIds,
249 'csrf_token': CSRF_TOKEN
249 'csrf_token': CSRF_TOKEN
250 };
250 };
251
251
252 var submitSuccessCallback = function(o) {
252 var submitSuccessCallback = function(o) {
253 location.reload(true);
253 location.reload(true);
254 };
254 };
255 var submitFailCallback = function(){
255 var submitFailCallback = function(){
256 self.resetCommentFormState(text)
256 self.resetCommentFormState(text)
257 };
257 };
258 self.submitAjaxPOST(
258 self.submitAjaxPOST(
259 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
259 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
260 });
260 });
261 % endif
261 % endif
262
262
263
263
264 </script>
264 </script>
265 % else:
265 % else:
266 ## form state when not logged in
266 ## form state when not logged in
267 <div class="comment-form ac">
267 <div class="comment-form ac">
268
268
269 <div class="comment-area">
269 <div class="comment-area">
270 <div class="comment-area-header">
270 <div class="comment-area-header">
271 <ul class="nav-links clearfix">
271 <ul class="nav-links clearfix">
272 <li class="active">
272 <li class="active">
273 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
273 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
274 </li>
274 </li>
275 <li class="">
275 <li class="">
276 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
276 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
277 </li>
277 </li>
278 </ul>
278 </ul>
279 </div>
279 </div>
280
280
281 <div class="comment-area-write" style="display: block;">
281 <div class="comment-area-write" style="display: block;">
282 <div id="edit-container">
282 <div id="edit-container">
283 <div style="padding: 40px 0">
283 <div style="padding: 40px 0">
284 ${_('You need to be logged in to leave comments.')}
284 ${_('You need to be logged in to leave comments.')}
285 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
285 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
286 </div>
286 </div>
287 </div>
287 </div>
288 <div id="preview-container" class="clearfix" style="display: none;">
288 <div id="preview-container" class="clearfix" style="display: none;">
289 <div id="preview-box" class="preview-box"></div>
289 <div id="preview-box" class="preview-box"></div>
290 </div>
290 </div>
291 </div>
291 </div>
292
292
293 <div class="comment-area-footer">
293 <div class="comment-area-footer">
294 <div class="toolbar">
294 <div class="toolbar">
295 <div class="toolbar-text">
295 <div class="toolbar-text">
296 </div>
296 </div>
297 </div>
297 </div>
298 </div>
298 </div>
299 </div>
299 </div>
300
300
301 <div class="comment-footer">
301 <div class="comment-footer">
302 </div>
302 </div>
303
303
304 </div>
304 </div>
305 % endif
305 % endif
306
306
307 <script type="text/javascript">
307 <script type="text/javascript">
308 bindToggleButtons();
308 bindToggleButtons();
309 </script>
309 </script>
310 </div>
310 </div>
311 </%def>
311 </%def>
312
312
313
313
314 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
314 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
315 ## comment injected based on assumption that user is logged in
315 ## comment injected based on assumption that user is logged in
316
316
317 <form ${'id="{}"'.format(form_id) if form_id else '' |n} action="#" method="GET">
317 <form ${'id="{}"'.format(form_id) if form_id else '' |n} action="#" method="GET">
318
318
319 <div class="comment-area">
319 <div class="comment-area">
320 <div class="comment-area-header">
320 <div class="comment-area-header">
321 <ul class="nav-links clearfix">
321 <ul class="nav-links clearfix">
322 <li class="active">
322 <li class="active">
323 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
323 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
324 </li>
324 </li>
325 <li class="">
325 <li class="">
326 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
326 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
327 </li>
327 </li>
328 <li class="pull-right">
328 <li class="pull-right">
329 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
329 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
330 % for val in c.visual.comment_types:
330 % for val in c.visual.comment_types:
331 <option value="${val}">${val.upper()}</option>
331 <option value="${val}">${val.upper()}</option>
332 % endfor
332 % endfor
333 </select>
333 </select>
334 </li>
334 </li>
335 </ul>
335 </ul>
336 </div>
336 </div>
337
337
338 <div class="comment-area-write" style="display: block;">
338 <div class="comment-area-write" style="display: block;">
339 <div id="edit-container_${lineno_id}">
339 <div id="edit-container_${lineno_id}">
340 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
340 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
341 </div>
341 </div>
342 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
342 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
343 <div id="preview-box_${lineno_id}" class="preview-box"></div>
343 <div id="preview-box_${lineno_id}" class="preview-box"></div>
344 </div>
344 </div>
345 </div>
345 </div>
346
346
347 <div class="comment-area-footer">
347 <div class="comment-area-footer">
348 <div class="toolbar">
348 <div class="toolbar">
349 <div class="toolbar-text">
349 <div class="toolbar-text">
350 ${(_('Comments parsed using %s syntax with %s, and %s actions support.') % (
350 ${(_('Comments parsed using %s syntax with %s, and %s actions support.') % (
351 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
351 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
352 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')),
352 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')),
353 ('<span class="tooltip" title="%s">`/`</span>' % _('Start typing with / for certain actions to be triggered via text box.'))
353 ('<span class="tooltip" title="%s">`/`</span>' % _('Start typing with / for certain actions to be triggered via text box.'))
354 )
354 )
355 )|n}
355 )|n}
356 </div>
356 </div>
357 </div>
357 </div>
358 </div>
358 </div>
359 </div>
359 </div>
360
360
361 <div class="comment-footer">
361 <div class="comment-footer">
362
362
363 % if review_statuses:
363 % if review_statuses:
364 <div class="status_box">
364 <div class="status_box">
365 <select id="change_status_${lineno_id}" name="changeset_status">
365 <select id="change_status_${lineno_id}" name="changeset_status">
366 <option></option> ## Placeholder
366 <option></option> ## Placeholder
367 % for status, lbl in review_statuses:
367 % for status, lbl in review_statuses:
368 <option value="${status}" data-status="${status}">${lbl}</option>
368 <option value="${status}" data-status="${status}">${lbl}</option>
369 %if is_pull_request and change_status and status in ('approved', 'rejected'):
369 %if is_pull_request and change_status and status in ('approved', 'rejected'):
370 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
370 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
371 %endif
371 %endif
372 % endfor
372 % endfor
373 </select>
373 </select>
374 </div>
374 </div>
375 % endif
375 % endif
376
376
377 ## inject extra inputs into the form
377 ## inject extra inputs into the form
378 % if form_extras and isinstance(form_extras, (list, tuple)):
378 % if form_extras and isinstance(form_extras, (list, tuple)):
379 <div id="comment_form_extras">
379 <div id="comment_form_extras">
380 % for form_ex_el in form_extras:
380 % for form_ex_el in form_extras:
381 ${form_ex_el|n}
381 ${form_ex_el|n}
382 % endfor
382 % endfor
383 </div>
383 </div>
384 % endif
384 % endif
385
385
386 <div class="action-buttons">
386 <div class="action-buttons">
387 ## inline for has a file, and line-number together with cancel hide button.
387 ## inline for has a file, and line-number together with cancel hide button.
388 % if form_type == 'inline':
388 % if form_type == 'inline':
389 <input type="hidden" name="f_path" value="{0}">
389 <input type="hidden" name="f_path" value="{0}">
390 <input type="hidden" name="line" value="${lineno_id}">
390 <input type="hidden" name="line" value="${lineno_id}">
391 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
391 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
392 ${_('Cancel')}
392 ${_('Cancel')}
393 </button>
393 </button>
394 % endif
394 % endif
395
395
396 % if form_type != 'inline':
396 % if form_type != 'inline':
397 <div class="action-buttons-extra"></div>
397 <div class="action-buttons-extra"></div>
398 % endif
398 % endif
399
399
400 ${h.submit('save', _('Comment'), class_='btn btn-success comment-button-input')}
400 ${h.submit('save', _('Comment'), class_='btn btn-success comment-button-input')}
401
401
402 </div>
402 </div>
403 </div>
403 </div>
404
404
405 </form>
405 </form>
406
406
407 </%def> No newline at end of file
407 </%def>
@@ -1,159 +1,159 b''
1 ## small box that displays changed/added/removed details fetched by AJAX
1 ## small box that displays changed/added/removed details fetched by AJAX
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3
3
4 % if c.prev_page:
4 % if c.prev_page:
5 <tr>
5 <tr>
6 <td colspan="10" class="load-more-commits">
6 <td colspan="10" class="load-more-commits">
7 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
7 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
8 ${_('load previous')}
8 ${_('load previous')}
9 </a>
9 </a>
10 </td>
10 </td>
11 </tr>
11 </tr>
12 % endif
12 % endif
13
13
14 ## to speed up lookups cache some functions before the loop
14 ## to speed up lookups cache some functions before the loop
15 <%
15 <%
16 active_patterns = h.get_active_pattern_entries(c.repo_name)
16 active_patterns = h.get_active_pattern_entries(c.repo_name)
17 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
17 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
18 %>
18 %>
19
19
20 % for cnt,commit in enumerate(c.pagination):
20 % for cnt,commit in enumerate(c.pagination):
21 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
21 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
22
22
23 <td class="td-checkbox">
23 <td class="td-checkbox">
24 ${h.checkbox(commit.raw_id,class_="commit-range", **{'data-commit-idx':commit.idx, 'data-commit-id': commit.raw_id, 'data-short-id': commit.short_id})}
24 ${h.checkbox(commit.raw_id,class_="commit-range", **{'data-commit-idx':commit.idx, 'data-commit-id': commit.raw_id, 'data-short-id': commit.short_id})}
25 </td>
25 </td>
26 ##
26 ##
27 <td class="td-graphbox">
27 <td class="td-graphbox">
28
28
29 </td>
29 </td>
30
30
31 <td class="td-status">
31 <td class="td-status">
32 %if c.statuses.get(commit.raw_id):
32 %if c.statuses.get(commit.raw_id):
33 <div class="changeset-status-ico">
33 <div class="changeset-status-ico">
34 %if c.statuses.get(commit.raw_id)[2]:
34 %if c.statuses.get(commit.raw_id)[2]:
35 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
35 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
36 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
36 <i class="icon-circle review-status-${c.statuses.get(commit.raw_id)[0]}"></i>
37 </a>
37 </a>
38 %else:
38 %else:
39 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
39 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
40 <div class="${'flag_status {}'.format(c.statuses.get(commit.raw_id)[0])}"></div>
40 <i class="icon-circle review-status-${c.statuses.get(commit.raw_id)[0]}"></i>
41 </a>
41 </a>
42 %endif
42 %endif
43 </div>
43 </div>
44 %else:
44 %else:
45 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
45 <i class="icon-circle review-status-not_reviewed" title="${_('Commit status: Not Reviewed')}"></i>
46 %endif
46 %endif
47 </td>
47 </td>
48
48
49 <td class="td-hash">
49 <td class="td-hash">
50 <code>
50 <code>
51
51
52 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
52 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
53 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
53 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
54 </a>
54 </a>
55
55
56 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
56 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
57
57
58 ## COMMIT PHASES
58 ## COMMIT PHASES
59
59
60 ## Draft
60 ## Draft
61 % if hasattr(commit, 'phase'):
61 % if hasattr(commit, 'phase'):
62 % if commit.phase != 'public':
62 % if commit.phase != 'public':
63 <span class="tag phase-${commit.phase} tooltip" title="${_('{} commit phase').format(commit.phase)}">${commit.phase[0].upper()}</span>
63 <span class="tag phase-${commit.phase} tooltip" title="${_('{} commit phase').format(commit.phase)}">${commit.phase[0].upper()}</span>
64 % endif
64 % endif
65 % endif
65 % endif
66
66
67 ## obsolete commits
67 ## obsolete commits
68 % if hasattr(commit, 'obsolete') and commit.obsolete:
68 % if hasattr(commit, 'obsolete') and commit.obsolete:
69 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Obsolete Evolve State')}">O</span>
69 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Obsolete Evolve State')}">O</span>
70 % endif
70 % endif
71
71
72 ## hidden commits
72 ## hidden commits
73 % if hasattr(commit, 'hidden') and commit.hidden:
73 % if hasattr(commit, 'hidden') and commit.hidden:
74 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Hidden Evolve State')}">H</span>
74 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Hidden Evolve State')}">H</span>
75 % endif
75 % endif
76
76
77 </code>
77 </code>
78 </td>
78 </td>
79
79
80 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this, true); return false">
80 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this, true); return false">
81 <i class="icon-expand-linked"></i>&nbsp;
81 <i class="icon-expand-linked"></i>&nbsp;
82 </td>
82 </td>
83 <td class="td-description mid">
83 <td class="td-description mid">
84 <div class="log-container truncate-wrap">
84 <div class="log-container truncate-wrap">
85 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${urlify_commit_message(commit.message, c.repo_name)}</div>
85 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${urlify_commit_message(commit.message, c.repo_name)}</div>
86 </div>
86 </div>
87 </td>
87 </td>
88
88
89 <td class="td-time">
89 <td class="td-time">
90 ${h.age_component(commit.date)}
90 ${h.age_component(commit.date)}
91 </td>
91 </td>
92 <td class="td-user">
92 <td class="td-user">
93 ${base.gravatar_with_user(commit.author)}
93 ${base.gravatar_with_user(commit.author)}
94 </td>
94 </td>
95
95
96 <td class="td-tags tags-col">
96 <td class="td-tags tags-col">
97 <div id="t-${commit.raw_id}">
97 <div id="t-${commit.raw_id}">
98
98
99 ## merge
99 ## merge
100 %if commit.merge:
100 %if commit.merge:
101 <span class="tag mergetag">
101 <span class="tag mergetag">
102 <i class="icon-merge"></i>${_('merge')}
102 <i class="icon-merge"></i>${_('merge')}
103 </span>
103 </span>
104 %endif
104 %endif
105
105
106 ## branch
106 ## branch
107 %if commit.branch:
107 %if commit.branch:
108 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
108 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
109 <a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
109 <a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=commit.branch))}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
110 </span>
110 </span>
111 %endif
111 %endif
112
112
113 ## bookmarks
113 ## bookmarks
114 %if h.is_hg(c.rhodecode_repo):
114 %if h.is_hg(c.rhodecode_repo):
115 %for book in commit.bookmarks:
115 %for book in commit.bookmarks:
116 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
116 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
117 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
117 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
118 </span>
118 </span>
119 %endfor
119 %endfor
120 %endif
120 %endif
121
121
122 ## tags
122 ## tags
123 %for tag in commit.tags:
123 %for tag in commit.tags:
124 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
124 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
125 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
125 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=commit.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
126 </span>
126 </span>
127 %endfor
127 %endfor
128
128
129 </div>
129 </div>
130 </td>
130 </td>
131
131
132 <td class="td-comments comments-col">
132 <td class="td-comments comments-col">
133 <% cs_comments = c.comments.get(commit.raw_id,[]) %>
133 <% cs_comments = c.comments.get(commit.raw_id,[]) %>
134 % if cs_comments:
134 % if cs_comments:
135 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % cs_comments[0].comment_id)}">
135 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id,_anchor='comment-%s' % cs_comments[0].comment_id)}">
136 <i class="icon-comment"></i> ${len(cs_comments)}
136 <i class="icon-comment"></i> ${len(cs_comments)}
137 </a>
137 </a>
138 % else:
138 % else:
139 <i class="icon-comment"></i> ${len(cs_comments)}
139 <i class="icon-comment"></i> ${len(cs_comments)}
140 % endif
140 % endif
141 </td>
141 </td>
142
142
143 </tr>
143 </tr>
144 % endfor
144 % endfor
145
145
146 % if c.next_page:
146 % if c.next_page:
147 <tr>
147 <tr>
148 <td colspan="10" class="load-more-commits">
148 <td colspan="10" class="load-more-commits">
149 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
149 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}', '${c.commit_id}', '${c.f_path}');return false">
150 ${_('load next')}
150 ${_('load next')}
151 </a>
151 </a>
152 </td>
152 </td>
153 </tr>
153 </tr>
154 % endif
154 % endif
155 <tr class="chunk-graph-data" style="display:none"
155 <tr class="chunk-graph-data" style="display:none"
156 data-graph='${c.graph_data|n}'
156 data-graph='${c.graph_data|n}'
157 data-node='${c.prev_page}:${c.next_page}'
157 data-node='${c.prev_page}:${c.next_page}'
158 data-commits='${c.graph_commits|n}'>
158 data-commits='${c.graph_commits|n}'>
159 </tr> No newline at end of file
159 </tr>
@@ -1,452 +1,453 b''
1 ## DATA TABLE RE USABLE ELEMENTS
1 ## DATA TABLE RE USABLE ELEMENTS
2 ## usage:
2 ## usage:
3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
5
5
6 <%def name="metatags_help()">
6 <%def name="metatags_help()">
7 <table>
7 <table>
8 <%
8 <%
9 example_tags = [
9 example_tags = [
10 ('state','[stable]'),
10 ('state','[stable]'),
11 ('state','[stale]'),
11 ('state','[stale]'),
12 ('state','[featured]'),
12 ('state','[featured]'),
13 ('state','[dev]'),
13 ('state','[dev]'),
14 ('state','[dead]'),
14 ('state','[dead]'),
15 ('state','[deprecated]'),
15 ('state','[deprecated]'),
16
16
17 ('label','[personal]'),
17 ('label','[personal]'),
18 ('generic','[v2.0.0]'),
18 ('generic','[v2.0.0]'),
19
19
20 ('lang','[lang =&gt; JavaScript]'),
20 ('lang','[lang =&gt; JavaScript]'),
21 ('license','[license =&gt; LicenseName]'),
21 ('license','[license =&gt; LicenseName]'),
22
22
23 ('ref','[requires =&gt; RepoName]'),
23 ('ref','[requires =&gt; RepoName]'),
24 ('ref','[recommends =&gt; GroupName]'),
24 ('ref','[recommends =&gt; GroupName]'),
25 ('ref','[conflicts =&gt; SomeName]'),
25 ('ref','[conflicts =&gt; SomeName]'),
26 ('ref','[base =&gt; SomeName]'),
26 ('ref','[base =&gt; SomeName]'),
27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
28 ('see','[see =&gt; http://rhodecode.com]'),
28 ('see','[see =&gt; http://rhodecode.com]'),
29 ]
29 ]
30 %>
30 %>
31 % for tag_type, tag in example_tags:
31 % for tag_type, tag in example_tags:
32 <tr>
32 <tr>
33 <td>${tag|n}</td>
33 <td>${tag|n}</td>
34 <td>${h.style_metatag(tag_type, tag)|n}</td>
34 <td>${h.style_metatag(tag_type, tag)|n}</td>
35 </tr>
35 </tr>
36 % endfor
36 % endfor
37 </table>
37 </table>
38 </%def>
38 </%def>
39
39
40 ## REPOSITORY RENDERERS
40 ## REPOSITORY RENDERERS
41 <%def name="quick_menu(repo_name)">
41 <%def name="quick_menu(repo_name)">
42 <i class="icon-more"></i>
42 <i class="icon-more"></i>
43 <div class="menu_items_container hidden">
43 <div class="menu_items_container hidden">
44 <ul class="menu_items">
44 <ul class="menu_items">
45 <li>
45 <li>
46 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
46 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
47 <span>${_('Summary')}</span>
47 <span>${_('Summary')}</span>
48 </a>
48 </a>
49 </li>
49 </li>
50 <li>
50 <li>
51 <a title="${_('Commits')}" href="${h.route_path('repo_commits',repo_name=repo_name)}">
51 <a title="${_('Commits')}" href="${h.route_path('repo_commits',repo_name=repo_name)}">
52 <span>${_('Commits')}</span>
52 <span>${_('Commits')}</span>
53 </a>
53 </a>
54 </li>
54 </li>
55 <li>
55 <li>
56 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
56 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
57 <span>${_('Files')}</span>
57 <span>${_('Files')}</span>
58 </a>
58 </a>
59 </li>
59 </li>
60 <li>
60 <li>
61 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
61 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
62 <span>${_('Fork')}</span>
62 <span>${_('Fork')}</span>
63 </a>
63 </a>
64 </li>
64 </li>
65 </ul>
65 </ul>
66 </div>
66 </div>
67 </%def>
67 </%def>
68
68
69 <%def name="repo_name(name,rtype,rstate,private,archived,fork_of,short_name=False,admin=False)">
69 <%def name="repo_name(name,rtype,rstate,private,archived,fork_of,short_name=False,admin=False)">
70 <%
70 <%
71 def get_name(name,short_name=short_name):
71 def get_name(name,short_name=short_name):
72 if short_name:
72 if short_name:
73 return name.split('/')[-1]
73 return name.split('/')[-1]
74 else:
74 else:
75 return name
75 return name
76 %>
76 %>
77 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
77 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
78 ##NAME
78 ##NAME
79 <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.route_path('repo_summary',repo_name=name)}">
79 <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.route_path('repo_summary',repo_name=name)}">
80
80
81 ##TYPE OF REPO
81 ##TYPE OF REPO
82 %if h.is_hg(rtype):
82 %if h.is_hg(rtype):
83 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
83 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
84 %elif h.is_git(rtype):
84 %elif h.is_git(rtype):
85 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
85 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
86 %elif h.is_svn(rtype):
86 %elif h.is_svn(rtype):
87 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
87 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
88 %endif
88 %endif
89
89
90 ##PRIVATE/PUBLIC
90 ##PRIVATE/PUBLIC
91 %if private is True and c.visual.show_private_icon:
91 %if private is True and c.visual.show_private_icon:
92 <i class="icon-lock" title="${_('Private repository')}"></i>
92 <i class="icon-lock" title="${_('Private repository')}"></i>
93 %elif private is False and c.visual.show_public_icon:
93 %elif private is False and c.visual.show_public_icon:
94 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
94 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
95 %else:
95 %else:
96 <span></span>
96 <span></span>
97 %endif
97 %endif
98 ${get_name(name)}
98 ${get_name(name)}
99 </a>
99 </a>
100 %if fork_of:
100 %if fork_of:
101 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
101 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
102 %endif
102 %endif
103 %if rstate == 'repo_state_pending':
103 %if rstate == 'repo_state_pending':
104 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
104 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
105 (${_('creating...')})
105 (${_('creating...')})
106 </span>
106 </span>
107 %endif
107 %endif
108
108
109 </div>
109 </div>
110 </%def>
110 </%def>
111
111
112 <%def name="repo_desc(description, stylify_metatags)">
112 <%def name="repo_desc(description, stylify_metatags)">
113 <%
113 <%
114 tags, description = h.extract_metatags(description)
114 tags, description = h.extract_metatags(description)
115 %>
115 %>
116
116
117 <div class="truncate-wrap">
117 <div class="truncate-wrap">
118 % if stylify_metatags:
118 % if stylify_metatags:
119 % for tag_type, tag in tags:
119 % for tag_type, tag in tags:
120 ${h.style_metatag(tag_type, tag)|n}
120 ${h.style_metatag(tag_type, tag)|n}
121 % endfor
121 % endfor
122 % endif
122 % endif
123 ${description}
123 ${description}
124 </div>
124 </div>
125
125
126 </%def>
126 </%def>
127
127
128 <%def name="last_change(last_change)">
128 <%def name="last_change(last_change)">
129 ${h.age_component(last_change, time_is_local=True)}
129 ${h.age_component(last_change, time_is_local=True)}
130 </%def>
130 </%def>
131
131
132 <%def name="revision(name,rev,tip,author,last_msg, commit_date)">
132 <%def name="revision(name,rev,tip,author,last_msg, commit_date)">
133 <div>
133 <div>
134 %if rev >= 0:
134 %if rev >= 0:
135 <code><a title="${h.tooltip('%s\n%s\n\n%s' % (author, commit_date, last_msg))}" class="tooltip" href="${h.route_path('repo_commit',repo_name=name,commit_id=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code>
135 <code><a title="${h.tooltip('%s\n%s\n\n%s' % (author, commit_date, last_msg))}" class="tooltip" href="${h.route_path('repo_commit',repo_name=name,commit_id=tip)}">${'r%s:%s' % (rev,h.short_id(tip))}</a></code>
136 %else:
136 %else:
137 ${_('No commits yet')}
137 ${_('No commits yet')}
138 %endif
138 %endif
139 </div>
139 </div>
140 </%def>
140 </%def>
141
141
142 <%def name="rss(name)">
142 <%def name="rss(name)">
143 %if c.rhodecode_user.username != h.DEFAULT_USER:
143 %if c.rhodecode_user.username != h.DEFAULT_USER:
144 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
144 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
145 %else:
145 %else:
146 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
146 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
147 %endif
147 %endif
148 </%def>
148 </%def>
149
149
150 <%def name="atom(name)">
150 <%def name="atom(name)">
151 %if c.rhodecode_user.username != h.DEFAULT_USER:
151 %if c.rhodecode_user.username != h.DEFAULT_USER:
152 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
152 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
153 %else:
153 %else:
154 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
154 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
155 %endif
155 %endif
156 </%def>
156 </%def>
157
157
158 <%def name="user_gravatar(email, size=16)">
158 <%def name="user_gravatar(email, size=16)">
159 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
159 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
160 ${base.gravatar(email, 16)}
160 ${base.gravatar(email, 16)}
161 </div>
161 </div>
162 </%def>
162 </%def>
163
163
164 <%def name="repo_actions(repo_name, super_user=True)">
164 <%def name="repo_actions(repo_name, super_user=True)">
165 <div>
165 <div>
166 <div class="grid_edit">
166 <div class="grid_edit">
167 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
167 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
168 Edit
168 Edit
169 </a>
169 </a>
170 </div>
170 </div>
171 <div class="grid_delete">
171 <div class="grid_delete">
172 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
172 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
173 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger",
173 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger",
174 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
174 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
175 ${h.end_form()}
175 ${h.end_form()}
176 </div>
176 </div>
177 </div>
177 </div>
178 </%def>
178 </%def>
179
179
180 <%def name="repo_state(repo_state)">
180 <%def name="repo_state(repo_state)">
181 <div>
181 <div>
182 %if repo_state == 'repo_state_pending':
182 %if repo_state == 'repo_state_pending':
183 <div class="tag tag4">${_('Creating')}</div>
183 <div class="tag tag4">${_('Creating')}</div>
184 %elif repo_state == 'repo_state_created':
184 %elif repo_state == 'repo_state_created':
185 <div class="tag tag1">${_('Created')}</div>
185 <div class="tag tag1">${_('Created')}</div>
186 %else:
186 %else:
187 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
187 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
188 %endif
188 %endif
189 </div>
189 </div>
190 </%def>
190 </%def>
191
191
192
192
193 ## REPO GROUP RENDERERS
193 ## REPO GROUP RENDERERS
194 <%def name="quick_repo_group_menu(repo_group_name)">
194 <%def name="quick_repo_group_menu(repo_group_name)">
195 <i class="icon-more"></i>
195 <i class="icon-more"></i>
196 <div class="menu_items_container hidden">
196 <div class="menu_items_container hidden">
197 <ul class="menu_items">
197 <ul class="menu_items">
198 <li>
198 <li>
199 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
199 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
200 </li>
200 </li>
201
201
202 </ul>
202 </ul>
203 </div>
203 </div>
204 </%def>
204 </%def>
205
205
206 <%def name="repo_group_name(repo_group_name, children_groups=None)">
206 <%def name="repo_group_name(repo_group_name, children_groups=None)">
207 <div>
207 <div>
208 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
208 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
209 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
209 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
210 %if children_groups:
210 %if children_groups:
211 ${h.literal(' &raquo; '.join(children_groups))}
211 ${h.literal(' &raquo; '.join(children_groups))}
212 %else:
212 %else:
213 ${repo_group_name}
213 ${repo_group_name}
214 %endif
214 %endif
215 </a>
215 </a>
216 </div>
216 </div>
217 </%def>
217 </%def>
218
218
219 <%def name="repo_group_desc(description, personal, stylify_metatags)">
219 <%def name="repo_group_desc(description, personal, stylify_metatags)">
220
220
221 <%
221 <%
222 tags, description = h.extract_metatags(description)
222 tags, description = h.extract_metatags(description)
223 %>
223 %>
224
224
225 <div class="truncate-wrap">
225 <div class="truncate-wrap">
226 % if personal:
226 % if personal:
227 <div class="metatag" tag="personal">${_('personal')}</div>
227 <div class="metatag" tag="personal">${_('personal')}</div>
228 % endif
228 % endif
229
229
230 % if stylify_metatags:
230 % if stylify_metatags:
231 % for tag_type, tag in tags:
231 % for tag_type, tag in tags:
232 ${h.style_metatag(tag_type, tag)|n}
232 ${h.style_metatag(tag_type, tag)|n}
233 % endfor
233 % endfor
234 % endif
234 % endif
235 ${description}
235 ${description}
236 </div>
236 </div>
237
237
238 </%def>
238 </%def>
239
239
240 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
240 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
241 <div class="grid_edit">
241 <div class="grid_edit">
242 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
242 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
243 </div>
243 </div>
244 <div class="grid_delete">
244 <div class="grid_delete">
245 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
245 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
246 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger",
246 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger",
247 onclick="return confirm('"+_ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
247 onclick="return confirm('"+_ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
248 ${h.end_form()}
248 ${h.end_form()}
249 </div>
249 </div>
250 </%def>
250 </%def>
251
251
252
252
253 <%def name="user_actions(user_id, username)">
253 <%def name="user_actions(user_id, username)">
254 <div class="grid_edit">
254 <div class="grid_edit">
255 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
255 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
256 ${_('Edit')}
256 ${_('Edit')}
257 </a>
257 </a>
258 </div>
258 </div>
259 <div class="grid_delete">
259 <div class="grid_delete">
260 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
260 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
261 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger",
261 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger",
262 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
262 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
263 ${h.end_form()}
263 ${h.end_form()}
264 </div>
264 </div>
265 </%def>
265 </%def>
266
266
267 <%def name="user_group_actions(user_group_id, user_group_name)">
267 <%def name="user_group_actions(user_group_id, user_group_name)">
268 <div class="grid_edit">
268 <div class="grid_edit">
269 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
269 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
270 </div>
270 </div>
271 <div class="grid_delete">
271 <div class="grid_delete">
272 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
272 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
273 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
273 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
274 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
274 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
275 ${h.end_form()}
275 ${h.end_form()}
276 </div>
276 </div>
277 </%def>
277 </%def>
278
278
279
279
280 <%def name="user_name(user_id, username)">
280 <%def name="user_name(user_id, username)">
281 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
281 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
282 </%def>
282 </%def>
283
283
284 <%def name="user_profile(username)">
284 <%def name="user_profile(username)">
285 ${base.gravatar_with_user(username, 16)}
285 ${base.gravatar_with_user(username, 16)}
286 </%def>
286 </%def>
287
287
288 <%def name="user_group_name(user_group_name)">
288 <%def name="user_group_name(user_group_name)">
289 <div>
289 <div>
290 <i class="icon-user-group" title="${_('User group')}"></i>
290 <i class="icon-user-group" title="${_('User group')}"></i>
291 ${h.link_to_group(user_group_name)}
291 ${h.link_to_group(user_group_name)}
292 </div>
292 </div>
293 </%def>
293 </%def>
294
294
295
295
296 ## GISTS
296 ## GISTS
297
297
298 <%def name="gist_gravatar(full_contact)">
298 <%def name="gist_gravatar(full_contact)">
299 <div class="gist_gravatar">
299 <div class="gist_gravatar">
300 ${base.gravatar(full_contact, 30)}
300 ${base.gravatar(full_contact, 30)}
301 </div>
301 </div>
302 </%def>
302 </%def>
303
303
304 <%def name="gist_access_id(gist_access_id, full_contact)">
304 <%def name="gist_access_id(gist_access_id, full_contact)">
305 <div>
305 <div>
306 <b>
306 <b>
307 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">gist: ${gist_access_id}</a>
307 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">gist: ${gist_access_id}</a>
308 </b>
308 </b>
309 </div>
309 </div>
310 </%def>
310 </%def>
311
311
312 <%def name="gist_author(full_contact, created_on, expires)">
312 <%def name="gist_author(full_contact, created_on, expires)">
313 ${base.gravatar_with_user(full_contact, 16)}
313 ${base.gravatar_with_user(full_contact, 16)}
314 </%def>
314 </%def>
315
315
316
316
317 <%def name="gist_created(created_on)">
317 <%def name="gist_created(created_on)">
318 <div class="created">
318 <div class="created">
319 ${h.age_component(created_on, time_is_local=True)}
319 ${h.age_component(created_on, time_is_local=True)}
320 </div>
320 </div>
321 </%def>
321 </%def>
322
322
323 <%def name="gist_expires(expires)">
323 <%def name="gist_expires(expires)">
324 <div class="created">
324 <div class="created">
325 %if expires == -1:
325 %if expires == -1:
326 ${_('never')}
326 ${_('never')}
327 %else:
327 %else:
328 ${h.age_component(h.time_to_utcdatetime(expires))}
328 ${h.age_component(h.time_to_utcdatetime(expires))}
329 %endif
329 %endif
330 </div>
330 </div>
331 </%def>
331 </%def>
332
332
333 <%def name="gist_type(gist_type)">
333 <%def name="gist_type(gist_type)">
334 %if gist_type != 'public':
334 %if gist_type != 'public':
335 <div class="tag">${_('Private')}</div>
335 <div class="tag">${_('Private')}</div>
336 %endif
336 %endif
337 </%def>
337 </%def>
338
338
339 <%def name="gist_description(gist_description)">
339 <%def name="gist_description(gist_description)">
340 ${gist_description}
340 ${gist_description}
341 </%def>
341 </%def>
342
342
343
343
344 ## PULL REQUESTS GRID RENDERERS
344 ## PULL REQUESTS GRID RENDERERS
345
345
346 <%def name="pullrequest_target_repo(repo_name)">
346 <%def name="pullrequest_target_repo(repo_name)">
347 <div class="truncate">
347 <div class="truncate">
348 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
348 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
349 </div>
349 </div>
350 </%def>
350 </%def>
351
351 <%def name="pullrequest_status(status)">
352 <%def name="pullrequest_status(status)">
352 <div class="${'flag_status %s' % status} pull-left"></div>
353 <i class="icon-circle review-status-${status}"></i>
353 </%def>
354 </%def>
354
355
355 <%def name="pullrequest_title(title, description)">
356 <%def name="pullrequest_title(title, description)">
356 ${title}
357 ${title}
357 </%def>
358 </%def>
358
359
359 <%def name="pullrequest_comments(comments_nr)">
360 <%def name="pullrequest_comments(comments_nr)">
360 <i class="icon-comment"></i> ${comments_nr}
361 <i class="icon-comment"></i> ${comments_nr}
361 </%def>
362 </%def>
362
363
363 <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)">
364 <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)">
364 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
365 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
365 % if short:
366 % if short:
366 #${pull_request_id}
367 #${pull_request_id}
367 % else:
368 % else:
368 ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}}
369 ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}}
369 % endif
370 % endif
370 </a>
371 </a>
371 </%def>
372 </%def>
372
373
373 <%def name="pullrequest_updated_on(updated_on)">
374 <%def name="pullrequest_updated_on(updated_on)">
374 ${h.age_component(h.time_to_utcdatetime(updated_on))}
375 ${h.age_component(h.time_to_utcdatetime(updated_on))}
375 </%def>
376 </%def>
376
377
377 <%def name="pullrequest_author(full_contact)">
378 <%def name="pullrequest_author(full_contact)">
378 ${base.gravatar_with_user(full_contact, 16)}
379 ${base.gravatar_with_user(full_contact, 16)}
379 </%def>
380 </%def>
380
381
381
382
382 ## ARTIFACT RENDERERS
383 ## ARTIFACT RENDERERS
383
384
384 <%def name="repo_artifact_uid(repo_name, file_uid)">
385 <%def name="repo_artifact_uid(repo_name, file_uid)">
385 <code><a href="${h.route_path('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}">${file_uid}</a></code>
386 <code><a href="${h.route_path('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}">${file_uid}</a></code>
386 </%def>
387 </%def>
387
388
388 <%def name="repo_artifact_uid_action(repo_name, file_uid)">
389 <%def name="repo_artifact_uid_action(repo_name, file_uid)">
389 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${h.route_url('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}" title="${_('Copy the full url')}"></i>
390 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${h.route_url('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}" title="${_('Copy the full url')}"></i>
390 </%def>
391 </%def>
391
392
392 <%def name="repo_artifact_actions(repo_name, file_store_id, file_uid)">
393 <%def name="repo_artifact_actions(repo_name, file_store_id, file_uid)">
393 ## <div class="grid_edit">
394 ## <div class="grid_edit">
394 ## <a href="#Edit" title="${_('Edit')}">${_('Edit')}</a>
395 ## <a href="#Edit" title="${_('Edit')}">${_('Edit')}</a>
395 ## </div>
396 ## </div>
396 % if h.HasRepoPermissionAny('repository.admin')(c.repo_name):
397 % if h.HasRepoPermissionAny('repository.admin')(c.repo_name):
397 <div class="grid_delete">
398 <div class="grid_delete">
398 ${h.secure_form(h.route_path('repo_artifacts_delete', repo_name=repo_name, uid=file_store_id), request=request)}
399 ${h.secure_form(h.route_path('repo_artifacts_delete', repo_name=repo_name, uid=file_store_id), request=request)}
399 ${h.submit('remove_',_('Delete'),id="remove_artifact_%s" % file_store_id, class_="btn btn-link btn-danger",
400 ${h.submit('remove_',_('Delete'),id="remove_artifact_%s" % file_store_id, class_="btn btn-link btn-danger",
400 onclick="return confirm('"+_('Confirm to delete this artifact: %s') % file_uid+"');")}
401 onclick="return confirm('"+_('Confirm to delete this artifact: %s') % file_uid+"');")}
401 ${h.end_form()}
402 ${h.end_form()}
402 </div>
403 </div>
403 % endif
404 % endif
404 </%def>
405 </%def>
405
406
406 <%def name="markup_form(form_id, form_text='', help_text=None)">
407 <%def name="markup_form(form_id, form_text='', help_text=None)">
407
408
408 <div class="markup-form">
409 <div class="markup-form">
409 <div class="markup-form-area">
410 <div class="markup-form-area">
410 <div class="markup-form-area-header">
411 <div class="markup-form-area-header">
411 <ul class="nav-links clearfix">
412 <ul class="nav-links clearfix">
412 <li class="active">
413 <li class="active">
413 <a href="#edit-text" tabindex="-1" id="edit-btn_${form_id}">${_('Write')}</a>
414 <a href="#edit-text" tabindex="-1" id="edit-btn_${form_id}">${_('Write')}</a>
414 </li>
415 </li>
415 <li class="">
416 <li class="">
416 <a href="#preview-text" tabindex="-1" id="preview-btn_${form_id}">${_('Preview')}</a>
417 <a href="#preview-text" tabindex="-1" id="preview-btn_${form_id}">${_('Preview')}</a>
417 </li>
418 </li>
418 </ul>
419 </ul>
419 </div>
420 </div>
420
421
421 <div class="markup-form-area-write" style="display: block;">
422 <div class="markup-form-area-write" style="display: block;">
422 <div id="edit-container_${form_id}">
423 <div id="edit-container_${form_id}">
423 <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea>
424 <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea>
424 </div>
425 </div>
425 <div id="preview-container_${form_id}" class="clearfix" style="display: none;">
426 <div id="preview-container_${form_id}" class="clearfix" style="display: none;">
426 <div id="preview-box_${form_id}" class="preview-box"></div>
427 <div id="preview-box_${form_id}" class="preview-box"></div>
427 </div>
428 </div>
428 </div>
429 </div>
429
430
430 <div class="markup-form-area-footer">
431 <div class="markup-form-area-footer">
431 <div class="toolbar">
432 <div class="toolbar">
432 <div class="toolbar-text">
433 <div class="toolbar-text">
433 ${(_('Parsed using %s syntax') % (
434 ${(_('Parsed using %s syntax') % (
434 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
435 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
435 )
436 )
436 )|n}
437 )|n}
437 </div>
438 </div>
438 </div>
439 </div>
439 </div>
440 </div>
440 </div>
441 </div>
441
442
442 <div class="markup-form-footer">
443 <div class="markup-form-footer">
443 % if help_text:
444 % if help_text:
444 <span class="help-block">${help_text}</span>
445 <span class="help-block">${help_text}</span>
445 % endif
446 % endif
446 </div>
447 </div>
447 </div>
448 </div>
448 <script type="text/javascript">
449 <script type="text/javascript">
449 new MarkupForm('${form_id}');
450 new MarkupForm('${form_id}');
450 </script>
451 </script>
451
452
452 </%def>
453 </%def>
@@ -1,841 +1,841 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
7 %if c.rhodecode_name:
7 %if c.rhodecode_name:
8 &middot; ${h.branding(c.rhodecode_name)}
8 &middot; ${h.branding(c.rhodecode_name)}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13 <span id="pr-title">
13 <span id="pr-title">
14 ${c.pull_request.title}
14 ${c.pull_request.title}
15 %if c.pull_request.is_closed():
15 %if c.pull_request.is_closed():
16 (${_('Closed')})
16 (${_('Closed')})
17 %endif
17 %endif
18 </span>
18 </span>
19 <div id="pr-title-edit" class="input" style="display: none;">
19 <div id="pr-title-edit" class="input" style="display: none;">
20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
21 </div>
21 </div>
22 </%def>
22 </%def>
23
23
24 <%def name="menu_bar_nav()">
24 <%def name="menu_bar_nav()">
25 ${self.menu_items(active='repositories')}
25 ${self.menu_items(active='repositories')}
26 </%def>
26 </%def>
27
27
28 <%def name="menu_bar_subnav()">
28 <%def name="menu_bar_subnav()">
29 ${self.repo_menu(active='showpullrequest')}
29 ${self.repo_menu(active='showpullrequest')}
30 </%def>
30 </%def>
31
31
32 <%def name="main()">
32 <%def name="main()">
33
33
34 <script type="text/javascript">
34 <script type="text/javascript">
35 // TODO: marcink switch this to pyroutes
35 // TODO: marcink switch this to pyroutes
36 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
36 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 </script>
38 </script>
39 <div class="box">
39 <div class="box">
40
40
41 ${self.breadcrumbs()}
41 ${self.breadcrumbs()}
42
42
43 <div class="box pr-summary">
43 <div class="box pr-summary">
44
44
45 <div class="summary-details block-left">
45 <div class="summary-details block-left">
46 <% summary = lambda n:{False:'summary-short'}.get(n) %>
46 <% summary = lambda n:{False:'summary-short'}.get(n) %>
47 <div class="pr-details-title">
47 <div class="pr-details-title">
48 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request #%s') % c.pull_request.pull_request_id}</a> ${_('From')} ${h.format_date(c.pull_request.created_on)}
48 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request #%s') % c.pull_request.pull_request_id}</a> ${_('From')} ${h.format_date(c.pull_request.created_on)}
49 %if c.allowed_to_update:
49 %if c.allowed_to_update:
50 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
50 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
51 % if c.allowed_to_delete:
51 % if c.allowed_to_delete:
52 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
52 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
53 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
53 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
54 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
54 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
55 ${h.end_form()}
55 ${h.end_form()}
56 % else:
56 % else:
57 ${_('Delete')}
57 ${_('Delete')}
58 % endif
58 % endif
59 </div>
59 </div>
60 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
60 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
61 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
61 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
62 %endif
62 %endif
63 </div>
63 </div>
64
64
65 <div id="summary" class="fields pr-details-content">
65 <div id="summary" class="fields pr-details-content">
66 <div class="field">
66 <div class="field">
67 <div class="label-summary">
67 <div class="label-summary">
68 <label>${_('Source')}:</label>
68 <label>${_('Source')}:</label>
69 </div>
69 </div>
70 <div class="input">
70 <div class="input">
71 <div class="pr-origininfo">
71 <div class="pr-origininfo">
72 ## branch link is only valid if it is a branch
72 ## branch link is only valid if it is a branch
73 <span class="tag">
73 <span class="tag">
74 %if c.pull_request.source_ref_parts.type == 'branch':
74 %if c.pull_request.source_ref_parts.type == 'branch':
75 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
75 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}">${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}</a>
76 %else:
76 %else:
77 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
77 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
78 %endif
78 %endif
79 </span>
79 </span>
80 <span class="clone-url">
80 <span class="clone-url">
81 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.clone_url()}</a>
81 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.clone_url()}</a>
82 </span>
82 </span>
83 <br/>
83 <br/>
84 % if c.ancestor_commit:
84 % if c.ancestor_commit:
85 ${_('Common ancestor')}:
85 ${_('Common ancestor')}:
86 <code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
86 <code><a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a></code>
87 % endif
87 % endif
88 </div>
88 </div>
89 %if h.is_hg(c.pull_request.source_repo):
89 %if h.is_hg(c.pull_request.source_repo):
90 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
90 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
91 %elif h.is_git(c.pull_request.source_repo):
91 %elif h.is_git(c.pull_request.source_repo):
92 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
92 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
93 %endif
93 %endif
94
94
95 <div class="">
95 <div class="">
96 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
96 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
97 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
97 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
98 </div>
98 </div>
99
99
100 </div>
100 </div>
101 </div>
101 </div>
102 <div class="field">
102 <div class="field">
103 <div class="label-summary">
103 <div class="label-summary">
104 <label>${_('Target')}:</label>
104 <label>${_('Target')}:</label>
105 </div>
105 </div>
106 <div class="input">
106 <div class="input">
107 <div class="pr-targetinfo">
107 <div class="pr-targetinfo">
108 ## branch link is only valid if it is a branch
108 ## branch link is only valid if it is a branch
109 <span class="tag">
109 <span class="tag">
110 %if c.pull_request.target_ref_parts.type == 'branch':
110 %if c.pull_request.target_ref_parts.type == 'branch':
111 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
111 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}">${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}</a>
112 %else:
112 %else:
113 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
113 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
114 %endif
114 %endif
115 </span>
115 </span>
116 <span class="clone-url">
116 <span class="clone-url">
117 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
117 <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.clone_url()}</a>
118 </span>
118 </span>
119 </div>
119 </div>
120 </div>
120 </div>
121 </div>
121 </div>
122
122
123 ## Link to the shadow repository.
123 ## Link to the shadow repository.
124 <div class="field">
124 <div class="field">
125 <div class="label-summary">
125 <div class="label-summary">
126 <label>${_('Merge')}:</label>
126 <label>${_('Merge')}:</label>
127 </div>
127 </div>
128 <div class="input">
128 <div class="input">
129 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
129 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
130 %if h.is_hg(c.pull_request.target_repo):
130 %if h.is_hg(c.pull_request.target_repo):
131 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
131 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
132 %elif h.is_git(c.pull_request.target_repo):
132 %elif h.is_git(c.pull_request.target_repo):
133 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
133 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
134 %endif
134 %endif
135 <div class="">
135 <div class="">
136 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
136 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
137 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
137 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
138 </div>
138 </div>
139 % else:
139 % else:
140 <div class="">
140 <div class="">
141 ${_('Shadow repository data not available')}.
141 ${_('Shadow repository data not available')}.
142 </div>
142 </div>
143 % endif
143 % endif
144 </div>
144 </div>
145 </div>
145 </div>
146
146
147 <div class="field">
147 <div class="field">
148 <div class="label-summary">
148 <div class="label-summary">
149 <label>${_('Review')}:</label>
149 <label>${_('Review')}:</label>
150 </div>
150 </div>
151 <div class="input">
151 <div class="input">
152 %if c.pull_request_review_status:
152 %if c.pull_request_review_status:
153 <div class="${'flag_status %s' % c.pull_request_review_status} tooltip pull-left"></div>
153 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
154 <span class="changeset-status-lbl tooltip">
154 <span class="changeset-status-lbl tooltip">
155 %if c.pull_request.is_closed():
155 %if c.pull_request.is_closed():
156 ${_('Closed')},
156 ${_('Closed')},
157 %endif
157 %endif
158 ${h.commit_status_lbl(c.pull_request_review_status)}
158 ${h.commit_status_lbl(c.pull_request_review_status)}
159 </span>
159 </span>
160 - ${_ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
160 - ${_ungettext('calculated based on %s reviewer vote', 'calculated based on %s reviewers votes', len(c.pull_request_reviewers)) % len(c.pull_request_reviewers)}
161 %endif
161 %endif
162 </div>
162 </div>
163 </div>
163 </div>
164 <div class="field">
164 <div class="field">
165 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
165 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
166 <label>${_('Description')}:</label>
166 <label>${_('Description')}:</label>
167 </div>
167 </div>
168 <div id="pr-desc" class="input">
168 <div id="pr-desc" class="input">
169 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
169 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
170 </div>
170 </div>
171 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
171 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
172 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
172 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
173 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
173 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
174 </div>
174 </div>
175 </div>
175 </div>
176
176
177 <div class="field">
177 <div class="field">
178 <div class="label-summary">
178 <div class="label-summary">
179 <label>${_('Versions')}:</label>
179 <label>${_('Versions')}:</label>
180 </div>
180 </div>
181
181
182 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
182 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
183 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
183 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
184
184
185 <div class="pr-versions">
185 <div class="pr-versions">
186 % if c.show_version_changes:
186 % if c.show_version_changes:
187 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
187 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
188 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
188 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
189 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
189 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
190 data-toggle-on="${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}"
190 data-toggle-on="${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}"
191 data-toggle-off="${_('Hide all versions of this pull request')}">
191 data-toggle-off="${_('Hide all versions of this pull request')}">
192 ${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
192 ${_ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}
193 </a>
193 </a>
194 <table>
194 <table>
195 ## SHOW ALL VERSIONS OF PR
195 ## SHOW ALL VERSIONS OF PR
196 <% ver_pr = None %>
196 <% ver_pr = None %>
197
197
198 % for data in reversed(list(enumerate(c.versions, 1))):
198 % for data in reversed(list(enumerate(c.versions, 1))):
199 <% ver_pos = data[0] %>
199 <% ver_pos = data[0] %>
200 <% ver = data[1] %>
200 <% ver = data[1] %>
201 <% ver_pr = ver.pull_request_version_id %>
201 <% ver_pr = ver.pull_request_version_id %>
202 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
202 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
203
203
204 <tr class="version-pr" style="display: ${display_row}">
204 <tr class="version-pr" style="display: ${display_row}">
205 <td>
205 <td>
206 <code>
206 <code>
207 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
207 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
208 </code>
208 </code>
209 </td>
209 </td>
210 <td>
210 <td>
211 <input ${'checked="checked"' if c.from_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
211 <input ${'checked="checked"' if c.from_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
212 <input ${'checked="checked"' if c.at_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
212 <input ${'checked="checked"' if c.at_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
213 </td>
213 </td>
214 <td>
214 <td>
215 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
215 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
216 <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}">
216 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
217 </div>
217 </div>
218 </td>
218 </td>
219 <td>
219 <td>
220 % if c.at_version_num != ver_pr:
220 % if c.at_version_num != ver_pr:
221 <i class="icon-comment"></i>
221 <i class="icon-comment"></i>
222 <code class="tooltip" title="${_('Comment from pull request version v{0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
222 <code class="tooltip" title="${_('Comment from pull request version v{0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}">
223 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
223 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
224 </code>
224 </code>
225 % endif
225 % endif
226 </td>
226 </td>
227 <td>
227 <td>
228 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
228 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
229 </td>
229 </td>
230 <td>
230 <td>
231 ${h.age_component(ver.updated_on, time_is_local=True)}
231 ${h.age_component(ver.updated_on, time_is_local=True)}
232 </td>
232 </td>
233 </tr>
233 </tr>
234 % endfor
234 % endfor
235
235
236 <tr>
236 <tr>
237 <td colspan="6">
237 <td colspan="6">
238 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
238 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
239 data-label-text-locked="${_('select versions to show changes')}"
239 data-label-text-locked="${_('select versions to show changes')}"
240 data-label-text-diff="${_('show changes between versions')}"
240 data-label-text-diff="${_('show changes between versions')}"
241 data-label-text-show="${_('show pull request for this version')}"
241 data-label-text-show="${_('show pull request for this version')}"
242 >
242 >
243 ${_('select versions to show changes')}
243 ${_('select versions to show changes')}
244 </button>
244 </button>
245 </td>
245 </td>
246 </tr>
246 </tr>
247
247
248 ## show comment/inline comments summary
248 ## show comment/inline comments summary
249 <%def name="comments_summary()">
249 <%def name="comments_summary()">
250 <tr>
250 <tr>
251 <td colspan="6" class="comments-summary-td">
251 <td colspan="6" class="comments-summary-td">
252
252
253 % if c.at_version:
253 % if c.at_version:
254 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
254 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
255 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
255 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
256 ${_('Comments at this version')}:
256 ${_('Comments at this version')}:
257 % else:
257 % else:
258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
260 ${_('Comments for this pull request')}:
260 ${_('Comments for this pull request')}:
261 % endif
261 % endif
262
262
263
263
264 %if general_comm_count_ver:
264 %if general_comm_count_ver:
265 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
265 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
266 %else:
266 %else:
267 ${_("%d General ") % general_comm_count_ver}
267 ${_("%d General ") % general_comm_count_ver}
268 %endif
268 %endif
269
269
270 %if inline_comm_count_ver:
270 %if inline_comm_count_ver:
271 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
271 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
272 %else:
272 %else:
273 , ${_("%d Inline") % inline_comm_count_ver}
273 , ${_("%d Inline") % inline_comm_count_ver}
274 %endif
274 %endif
275
275
276 %if outdated_comm_count_ver:
276 %if outdated_comm_count_ver:
277 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
277 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
278 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
278 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
279 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
279 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
280 %else:
280 %else:
281 , ${_("%d Outdated") % outdated_comm_count_ver}
281 , ${_("%d Outdated") % outdated_comm_count_ver}
282 %endif
282 %endif
283 </td>
283 </td>
284 </tr>
284 </tr>
285 </%def>
285 </%def>
286 ${comments_summary()}
286 ${comments_summary()}
287 </table>
287 </table>
288 % else:
288 % else:
289 <div class="input">
289 <div class="input">
290 ${_('Pull request versions not available')}.
290 ${_('Pull request versions not available')}.
291 </div>
291 </div>
292 <div>
292 <div>
293 <table>
293 <table>
294 ${comments_summary()}
294 ${comments_summary()}
295 </table>
295 </table>
296 </div>
296 </div>
297 % endif
297 % endif
298 </div>
298 </div>
299 </div>
299 </div>
300
300
301 <div id="pr-save" class="field" style="display: none;">
301 <div id="pr-save" class="field" style="display: none;">
302 <div class="label-summary"></div>
302 <div class="label-summary"></div>
303 <div class="input">
303 <div class="input">
304 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
304 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
305 </div>
305 </div>
306 </div>
306 </div>
307 </div>
307 </div>
308 </div>
308 </div>
309 <div>
309 <div>
310 ## AUTHOR
310 ## AUTHOR
311 <div class="reviewers-title block-right">
311 <div class="reviewers-title block-right">
312 <div class="pr-details-title">
312 <div class="pr-details-title">
313 ${_('Author of this pull request')}
313 ${_('Author of this pull request')}
314 </div>
314 </div>
315 </div>
315 </div>
316 <div class="block-right pr-details-content reviewers">
316 <div class="block-right pr-details-content reviewers">
317 <ul class="group_members">
317 <ul class="group_members">
318 <li>
318 <li>
319 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
319 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
320 </li>
320 </li>
321 </ul>
321 </ul>
322 </div>
322 </div>
323
323
324 ## REVIEW RULES
324 ## REVIEW RULES
325 <div id="review_rules" style="display: none" class="reviewers-title block-right">
325 <div id="review_rules" style="display: none" class="reviewers-title block-right">
326 <div class="pr-details-title">
326 <div class="pr-details-title">
327 ${_('Reviewer rules')}
327 ${_('Reviewer rules')}
328 %if c.allowed_to_update:
328 %if c.allowed_to_update:
329 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
329 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
330 %endif
330 %endif
331 </div>
331 </div>
332 <div class="pr-reviewer-rules">
332 <div class="pr-reviewer-rules">
333 ## review rules will be appended here, by default reviewers logic
333 ## review rules will be appended here, by default reviewers logic
334 </div>
334 </div>
335 <input id="review_data" type="hidden" name="review_data" value="">
335 <input id="review_data" type="hidden" name="review_data" value="">
336 </div>
336 </div>
337
337
338 ## REVIEWERS
338 ## REVIEWERS
339 <div class="reviewers-title block-right">
339 <div class="reviewers-title block-right">
340 <div class="pr-details-title">
340 <div class="pr-details-title">
341 ${_('Pull request reviewers')}
341 ${_('Pull request reviewers')}
342 %if c.allowed_to_update:
342 %if c.allowed_to_update:
343 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
343 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
344 %endif
344 %endif
345 </div>
345 </div>
346 </div>
346 </div>
347 <div id="reviewers" class="block-right pr-details-content reviewers">
347 <div id="reviewers" class="block-right pr-details-content reviewers">
348
348
349 ## members redering block
349 ## members redering block
350 <input type="hidden" name="__start__" value="review_members:sequence">
350 <input type="hidden" name="__start__" value="review_members:sequence">
351 <ul id="review_members" class="group_members">
351 <ul id="review_members" class="group_members">
352
352
353 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
353 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
354 <script>
354 <script>
355 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
355 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
356 var status = "${(status[0][1].status if status else 'not_reviewed')}";
356 var status = "${(status[0][1].status if status else 'not_reviewed')}";
357 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
357 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
358 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
358 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
359
359
360 var entry = renderTemplate('reviewMemberEntry', {
360 var entry = renderTemplate('reviewMemberEntry', {
361 'member': member,
361 'member': member,
362 'mandatory': member.mandatory,
362 'mandatory': member.mandatory,
363 'reasons': member.reasons,
363 'reasons': member.reasons,
364 'allowed_to_update': allowed_to_update,
364 'allowed_to_update': allowed_to_update,
365 'review_status': status,
365 'review_status': status,
366 'review_status_label': status_lbl,
366 'review_status_label': status_lbl,
367 'user_group': member.user_group,
367 'user_group': member.user_group,
368 'create': false
368 'create': false
369 });
369 });
370 $('#review_members').append(entry)
370 $('#review_members').append(entry)
371 </script>
371 </script>
372
372
373 % endfor
373 % endfor
374
374
375 </ul>
375 </ul>
376 <input type="hidden" name="__end__" value="review_members:sequence">
376 <input type="hidden" name="__end__" value="review_members:sequence">
377 ## end members redering block
377 ## end members redering block
378
378
379 %if not c.pull_request.is_closed():
379 %if not c.pull_request.is_closed():
380 <div id="add_reviewer" class="ac" style="display: none;">
380 <div id="add_reviewer" class="ac" style="display: none;">
381 %if c.allowed_to_update:
381 %if c.allowed_to_update:
382 % if not c.forbid_adding_reviewers:
382 % if not c.forbid_adding_reviewers:
383 <div id="add_reviewer_input" class="reviewer_ac">
383 <div id="add_reviewer_input" class="reviewer_ac">
384 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
384 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
385 <div id="reviewers_container"></div>
385 <div id="reviewers_container"></div>
386 </div>
386 </div>
387 % endif
387 % endif
388 <div class="pull-right">
388 <div class="pull-right">
389 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
389 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
390 </div>
390 </div>
391 %endif
391 %endif
392 </div>
392 </div>
393 %endif
393 %endif
394 </div>
394 </div>
395 </div>
395 </div>
396 </div>
396 </div>
397 <div class="box">
397 <div class="box">
398 ##DIFF
398 ##DIFF
399 <div class="table" >
399 <div class="table" >
400 <div id="changeset_compare_view_content">
400 <div id="changeset_compare_view_content">
401 ##CS
401 ##CS
402 % if c.missing_requirements:
402 % if c.missing_requirements:
403 <div class="box">
403 <div class="box">
404 <div class="alert alert-warning">
404 <div class="alert alert-warning">
405 <div>
405 <div>
406 <strong>${_('Missing requirements:')}</strong>
406 <strong>${_('Missing requirements:')}</strong>
407 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
407 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
408 </div>
408 </div>
409 </div>
409 </div>
410 </div>
410 </div>
411 % elif c.missing_commits:
411 % elif c.missing_commits:
412 <div class="box">
412 <div class="box">
413 <div class="alert alert-warning">
413 <div class="alert alert-warning">
414 <div>
414 <div>
415 <strong>${_('Missing commits')}:</strong>
415 <strong>${_('Missing commits')}:</strong>
416 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
416 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
417 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
417 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
418 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
418 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
419 </div>
419 </div>
420 </div>
420 </div>
421 </div>
421 </div>
422 % endif
422 % endif
423
423
424 <div class="compare_view_commits_title">
424 <div class="compare_view_commits_title">
425 % if not c.compare_mode:
425 % if not c.compare_mode:
426
426
427 % if c.at_version_pos:
427 % if c.at_version_pos:
428 <h4>
428 <h4>
429 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
429 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
430 </h4>
430 </h4>
431 % endif
431 % endif
432
432
433 <div class="pull-left">
433 <div class="pull-left">
434 <div class="btn-group">
434 <div class="btn-group">
435 <a
435 <a
436 class="btn"
436 class="btn"
437 href="#"
437 href="#"
438 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
438 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
439 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
439 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
440 </a>
440 </a>
441 <a
441 <a
442 class="btn"
442 class="btn"
443 href="#"
443 href="#"
444 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
444 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
445 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
445 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
446 </a>
446 </a>
447 </div>
447 </div>
448 </div>
448 </div>
449
449
450 <div class="pull-right">
450 <div class="pull-right">
451 % if c.allowed_to_update and not c.pull_request.is_closed():
451 % if c.allowed_to_update and not c.pull_request.is_closed():
452 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
452 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
453 % else:
453 % else:
454 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
454 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
455 % endif
455 % endif
456
456
457 </div>
457 </div>
458 % endif
458 % endif
459 </div>
459 </div>
460
460
461 % if not c.missing_commits:
461 % if not c.missing_commits:
462 % if c.compare_mode:
462 % if c.compare_mode:
463 % if c.at_version:
463 % if c.at_version:
464 <h4>
464 <h4>
465 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
465 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
466 </h4>
466 </h4>
467
467
468 <div class="subtitle-compare">
468 <div class="subtitle-compare">
469 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
469 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
470 </div>
470 </div>
471
471
472 <div class="container">
472 <div class="container">
473 <table class="rctable compare_view_commits">
473 <table class="rctable compare_view_commits">
474 <tr>
474 <tr>
475 <th></th>
475 <th></th>
476 <th>${_('Time')}</th>
476 <th>${_('Time')}</th>
477 <th>${_('Author')}</th>
477 <th>${_('Author')}</th>
478 <th>${_('Commit')}</th>
478 <th>${_('Commit')}</th>
479 <th></th>
479 <th></th>
480 <th>${_('Description')}</th>
480 <th>${_('Description')}</th>
481 </tr>
481 </tr>
482
482
483 % for c_type, commit in c.commit_changes:
483 % for c_type, commit in c.commit_changes:
484 % if c_type in ['a', 'r']:
484 % if c_type in ['a', 'r']:
485 <%
485 <%
486 if c_type == 'a':
486 if c_type == 'a':
487 cc_title = _('Commit added in displayed changes')
487 cc_title = _('Commit added in displayed changes')
488 elif c_type == 'r':
488 elif c_type == 'r':
489 cc_title = _('Commit removed in displayed changes')
489 cc_title = _('Commit removed in displayed changes')
490 else:
490 else:
491 cc_title = ''
491 cc_title = ''
492 %>
492 %>
493 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
493 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
494 <td>
494 <td>
495 <div class="commit-change-indicator color-${c_type}-border">
495 <div class="commit-change-indicator color-${c_type}-border">
496 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
496 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
497 ${c_type.upper()}
497 ${c_type.upper()}
498 </div>
498 </div>
499 </div>
499 </div>
500 </td>
500 </td>
501 <td class="td-time">
501 <td class="td-time">
502 ${h.age_component(commit.date)}
502 ${h.age_component(commit.date)}
503 </td>
503 </td>
504 <td class="td-user">
504 <td class="td-user">
505 ${base.gravatar_with_user(commit.author, 16)}
505 ${base.gravatar_with_user(commit.author, 16)}
506 </td>
506 </td>
507 <td class="td-hash">
507 <td class="td-hash">
508 <code>
508 <code>
509 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
509 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
510 r${commit.idx}:${h.short_id(commit.raw_id)}
510 r${commit.idx}:${h.short_id(commit.raw_id)}
511 </a>
511 </a>
512 ${h.hidden('revisions', commit.raw_id)}
512 ${h.hidden('revisions', commit.raw_id)}
513 </code>
513 </code>
514 </td>
514 </td>
515 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
515 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
516 <i class="icon-expand-linked"></i>
516 <i class="icon-expand-linked"></i>
517 </td>
517 </td>
518 <td class="mid td-description">
518 <td class="mid td-description">
519 <div class="log-container truncate-wrap">
519 <div class="log-container truncate-wrap">
520 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
520 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
521 </div>
521 </div>
522 </td>
522 </td>
523 </tr>
523 </tr>
524 % endif
524 % endif
525 % endfor
525 % endfor
526 </table>
526 </table>
527 </div>
527 </div>
528
528
529 % endif
529 % endif
530
530
531 % else:
531 % else:
532 <%include file="/compare/compare_commits.mako" />
532 <%include file="/compare/compare_commits.mako" />
533 % endif
533 % endif
534
534
535 <div class="cs_files">
535 <div class="cs_files">
536 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
536 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
537
537
538 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
538 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
539
539
540 % if c.range_diff_on:
540 % if c.range_diff_on:
541 % for commit in c.commit_ranges:
541 % for commit in c.commit_ranges:
542 ${cbdiffs.render_diffset(
542 ${cbdiffs.render_diffset(
543 c.changes[commit.raw_id],
543 c.changes[commit.raw_id],
544 commit=commit, use_comments=True,
544 commit=commit, use_comments=True,
545 collapse_when_files_over=5,
545 collapse_when_files_over=5,
546 disable_new_comments=True,
546 disable_new_comments=True,
547 deleted_files_comments=c.deleted_files_comments,
547 deleted_files_comments=c.deleted_files_comments,
548 inline_comments=c.inline_comments)}
548 inline_comments=c.inline_comments)}
549 % endfor
549 % endfor
550 % else:
550 % else:
551 ${cbdiffs.render_diffset(
551 ${cbdiffs.render_diffset(
552 c.diffset, use_comments=True,
552 c.diffset, use_comments=True,
553 collapse_when_files_over=30,
553 collapse_when_files_over=30,
554 disable_new_comments=not c.allowed_to_comment,
554 disable_new_comments=not c.allowed_to_comment,
555 deleted_files_comments=c.deleted_files_comments,
555 deleted_files_comments=c.deleted_files_comments,
556 inline_comments=c.inline_comments)}
556 inline_comments=c.inline_comments)}
557 % endif
557 % endif
558
558
559 </div>
559 </div>
560 % else:
560 % else:
561 ## skipping commits we need to clear the view for missing commits
561 ## skipping commits we need to clear the view for missing commits
562 <div style="clear:both;"></div>
562 <div style="clear:both;"></div>
563 % endif
563 % endif
564
564
565 </div>
565 </div>
566 </div>
566 </div>
567
567
568 ## template for inline comment form
568 ## template for inline comment form
569 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
569 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
570
570
571 ## render general comments
571 ## render general comments
572
572
573 <div id="comment-tr-show">
573 <div id="comment-tr-show">
574 <div class="comment">
574 <div class="comment">
575 % if general_outdated_comm_count_ver:
575 % if general_outdated_comm_count_ver:
576 <div class="meta">
576 <div class="meta">
577 % if general_outdated_comm_count_ver == 1:
577 % if general_outdated_comm_count_ver == 1:
578 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
578 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
579 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
579 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
580 % else:
580 % else:
581 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
581 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
582 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
582 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
583 % endif
583 % endif
584 </div>
584 </div>
585 % endif
585 % endif
586 </div>
586 </div>
587 </div>
587 </div>
588
588
589 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
589 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
590
590
591 % if not c.pull_request.is_closed():
591 % if not c.pull_request.is_closed():
592 ## merge status, and merge action
592 ## merge status, and merge action
593 <div class="pull-request-merge">
593 <div class="pull-request-merge">
594 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
594 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
595 </div>
595 </div>
596
596
597 ## main comment form and it status
597 ## main comment form and it status
598 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
598 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
599 pull_request_id=c.pull_request.pull_request_id),
599 pull_request_id=c.pull_request.pull_request_id),
600 c.pull_request_review_status,
600 c.pull_request_review_status,
601 is_pull_request=True, change_status=c.allowed_to_change_status)}
601 is_pull_request=True, change_status=c.allowed_to_change_status)}
602 %endif
602 %endif
603
603
604 <script type="text/javascript">
604 <script type="text/javascript">
605 if (location.hash) {
605 if (location.hash) {
606 var result = splitDelimitedHash(location.hash);
606 var result = splitDelimitedHash(location.hash);
607 var line = $('html').find(result.loc);
607 var line = $('html').find(result.loc);
608 // show hidden comments if we use location.hash
608 // show hidden comments if we use location.hash
609 if (line.hasClass('comment-general')) {
609 if (line.hasClass('comment-general')) {
610 $(line).show();
610 $(line).show();
611 } else if (line.hasClass('comment-inline')) {
611 } else if (line.hasClass('comment-inline')) {
612 $(line).show();
612 $(line).show();
613 var $cb = $(line).closest('.cb');
613 var $cb = $(line).closest('.cb');
614 $cb.removeClass('cb-collapsed')
614 $cb.removeClass('cb-collapsed')
615 }
615 }
616 if (line.length > 0){
616 if (line.length > 0){
617 offsetScroll(line, 70);
617 offsetScroll(line, 70);
618 }
618 }
619 }
619 }
620
620
621 versionController = new VersionController();
621 versionController = new VersionController();
622 versionController.init();
622 versionController.init();
623
623
624 reviewersController = new ReviewersController();
624 reviewersController = new ReviewersController();
625 commitsController = new CommitsController();
625 commitsController = new CommitsController();
626
626
627 $(function(){
627 $(function(){
628
628
629 // custom code mirror
629 // custom code mirror
630 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
630 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
631
631
632 var PRDetails = {
632 var PRDetails = {
633 editButton: $('#open_edit_pullrequest'),
633 editButton: $('#open_edit_pullrequest'),
634 closeButton: $('#close_edit_pullrequest'),
634 closeButton: $('#close_edit_pullrequest'),
635 deleteButton: $('#delete_pullrequest'),
635 deleteButton: $('#delete_pullrequest'),
636 viewFields: $('#pr-desc, #pr-title'),
636 viewFields: $('#pr-desc, #pr-title'),
637 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
637 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
638
638
639 init: function() {
639 init: function() {
640 var that = this;
640 var that = this;
641 this.editButton.on('click', function(e) { that.edit(); });
641 this.editButton.on('click', function(e) { that.edit(); });
642 this.closeButton.on('click', function(e) { that.view(); });
642 this.closeButton.on('click', function(e) { that.view(); });
643 },
643 },
644
644
645 edit: function(event) {
645 edit: function(event) {
646 this.viewFields.hide();
646 this.viewFields.hide();
647 this.editButton.hide();
647 this.editButton.hide();
648 this.deleteButton.hide();
648 this.deleteButton.hide();
649 this.closeButton.show();
649 this.closeButton.show();
650 this.editFields.show();
650 this.editFields.show();
651 codeMirrorInstance.refresh();
651 codeMirrorInstance.refresh();
652 },
652 },
653
653
654 view: function(event) {
654 view: function(event) {
655 this.editButton.show();
655 this.editButton.show();
656 this.deleteButton.show();
656 this.deleteButton.show();
657 this.editFields.hide();
657 this.editFields.hide();
658 this.closeButton.hide();
658 this.closeButton.hide();
659 this.viewFields.show();
659 this.viewFields.show();
660 }
660 }
661 };
661 };
662
662
663 var ReviewersPanel = {
663 var ReviewersPanel = {
664 editButton: $('#open_edit_reviewers'),
664 editButton: $('#open_edit_reviewers'),
665 closeButton: $('#close_edit_reviewers'),
665 closeButton: $('#close_edit_reviewers'),
666 addButton: $('#add_reviewer'),
666 addButton: $('#add_reviewer'),
667 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
667 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
668
668
669 init: function() {
669 init: function() {
670 var self = this;
670 var self = this;
671 this.editButton.on('click', function(e) { self.edit(); });
671 this.editButton.on('click', function(e) { self.edit(); });
672 this.closeButton.on('click', function(e) { self.close(); });
672 this.closeButton.on('click', function(e) { self.close(); });
673 },
673 },
674
674
675 edit: function(event) {
675 edit: function(event) {
676 this.editButton.hide();
676 this.editButton.hide();
677 this.closeButton.show();
677 this.closeButton.show();
678 this.addButton.show();
678 this.addButton.show();
679 this.removeButtons.css('visibility', 'visible');
679 this.removeButtons.css('visibility', 'visible');
680 // review rules
680 // review rules
681 reviewersController.loadReviewRules(
681 reviewersController.loadReviewRules(
682 ${c.pull_request.reviewer_data_json | n});
682 ${c.pull_request.reviewer_data_json | n});
683 },
683 },
684
684
685 close: function(event) {
685 close: function(event) {
686 this.editButton.show();
686 this.editButton.show();
687 this.closeButton.hide();
687 this.closeButton.hide();
688 this.addButton.hide();
688 this.addButton.hide();
689 this.removeButtons.css('visibility', 'hidden');
689 this.removeButtons.css('visibility', 'hidden');
690 // hide review rules
690 // hide review rules
691 reviewersController.hideReviewRules()
691 reviewersController.hideReviewRules()
692 }
692 }
693 };
693 };
694
694
695 PRDetails.init();
695 PRDetails.init();
696 ReviewersPanel.init();
696 ReviewersPanel.init();
697
697
698 showOutdated = function(self){
698 showOutdated = function(self){
699 $('.comment-inline.comment-outdated').show();
699 $('.comment-inline.comment-outdated').show();
700 $('.filediff-outdated').show();
700 $('.filediff-outdated').show();
701 $('.showOutdatedComments').hide();
701 $('.showOutdatedComments').hide();
702 $('.hideOutdatedComments').show();
702 $('.hideOutdatedComments').show();
703 };
703 };
704
704
705 hideOutdated = function(self){
705 hideOutdated = function(self){
706 $('.comment-inline.comment-outdated').hide();
706 $('.comment-inline.comment-outdated').hide();
707 $('.filediff-outdated').hide();
707 $('.filediff-outdated').hide();
708 $('.hideOutdatedComments').hide();
708 $('.hideOutdatedComments').hide();
709 $('.showOutdatedComments').show();
709 $('.showOutdatedComments').show();
710 };
710 };
711
711
712 refreshMergeChecks = function(){
712 refreshMergeChecks = function(){
713 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
713 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
714 $('.pull-request-merge').css('opacity', 0.3);
714 $('.pull-request-merge').css('opacity', 0.3);
715 $('.action-buttons-extra').css('opacity', 0.3);
715 $('.action-buttons-extra').css('opacity', 0.3);
716
716
717 $('.pull-request-merge').load(
717 $('.pull-request-merge').load(
718 loadUrl, function() {
718 loadUrl, function() {
719 $('.pull-request-merge').css('opacity', 1);
719 $('.pull-request-merge').css('opacity', 1);
720
720
721 $('.action-buttons-extra').css('opacity', 1);
721 $('.action-buttons-extra').css('opacity', 1);
722 injectCloseAction();
722 injectCloseAction();
723 }
723 }
724 );
724 );
725 };
725 };
726
726
727 injectCloseAction = function() {
727 injectCloseAction = function() {
728 var closeAction = $('#close-pull-request-action').html();
728 var closeAction = $('#close-pull-request-action').html();
729 var $actionButtons = $('.action-buttons-extra');
729 var $actionButtons = $('.action-buttons-extra');
730 // clear the action before
730 // clear the action before
731 $actionButtons.html("");
731 $actionButtons.html("");
732 $actionButtons.html(closeAction);
732 $actionButtons.html(closeAction);
733 };
733 };
734
734
735 closePullRequest = function (status) {
735 closePullRequest = function (status) {
736 // inject closing flag
736 // inject closing flag
737 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
737 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
738 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
738 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
739 $(generalCommentForm.submitForm).submit();
739 $(generalCommentForm.submitForm).submit();
740 };
740 };
741
741
742 $('#show-outdated-comments').on('click', function(e){
742 $('#show-outdated-comments').on('click', function(e){
743 var button = $(this);
743 var button = $(this);
744 var outdated = $('.comment-outdated');
744 var outdated = $('.comment-outdated');
745
745
746 if (button.html() === "(Show)") {
746 if (button.html() === "(Show)") {
747 button.html("(Hide)");
747 button.html("(Hide)");
748 outdated.show();
748 outdated.show();
749 } else {
749 } else {
750 button.html("(Show)");
750 button.html("(Show)");
751 outdated.hide();
751 outdated.hide();
752 }
752 }
753 });
753 });
754
754
755 $('.show-inline-comments').on('change', function(e){
755 $('.show-inline-comments').on('change', function(e){
756 var show = 'none';
756 var show = 'none';
757 var target = e.currentTarget;
757 var target = e.currentTarget;
758 if(target.checked){
758 if(target.checked){
759 show = ''
759 show = ''
760 }
760 }
761 var boxid = $(target).attr('id_for');
761 var boxid = $(target).attr('id_for');
762 var comments = $('#{0} .inline-comments'.format(boxid));
762 var comments = $('#{0} .inline-comments'.format(boxid));
763 var fn_display = function(idx){
763 var fn_display = function(idx){
764 $(this).css('display', show);
764 $(this).css('display', show);
765 };
765 };
766 $(comments).each(fn_display);
766 $(comments).each(fn_display);
767 var btns = $('#{0} .inline-comments-button'.format(boxid));
767 var btns = $('#{0} .inline-comments-button'.format(boxid));
768 $(btns).each(fn_display);
768 $(btns).each(fn_display);
769 });
769 });
770
770
771 $('#merge_pull_request_form').submit(function() {
771 $('#merge_pull_request_form').submit(function() {
772 if (!$('#merge_pull_request').attr('disabled')) {
772 if (!$('#merge_pull_request').attr('disabled')) {
773 $('#merge_pull_request').attr('disabled', 'disabled');
773 $('#merge_pull_request').attr('disabled', 'disabled');
774 }
774 }
775 return true;
775 return true;
776 });
776 });
777
777
778 $('#edit_pull_request').on('click', function(e){
778 $('#edit_pull_request').on('click', function(e){
779 var title = $('#pr-title-input').val();
779 var title = $('#pr-title-input').val();
780 var description = codeMirrorInstance.getValue();
780 var description = codeMirrorInstance.getValue();
781 var renderer = $('#pr-renderer-input').val();
781 var renderer = $('#pr-renderer-input').val();
782 editPullRequest(
782 editPullRequest(
783 "${c.repo_name}", "${c.pull_request.pull_request_id}",
783 "${c.repo_name}", "${c.pull_request.pull_request_id}",
784 title, description, renderer);
784 title, description, renderer);
785 });
785 });
786
786
787 $('#update_pull_request').on('click', function(e){
787 $('#update_pull_request').on('click', function(e){
788 $(this).attr('disabled', 'disabled');
788 $(this).attr('disabled', 'disabled');
789 $(this).addClass('disabled');
789 $(this).addClass('disabled');
790 $(this).html(_gettext('Saving...'));
790 $(this).html(_gettext('Saving...'));
791 reviewersController.updateReviewers(
791 reviewersController.updateReviewers(
792 "${c.repo_name}", "${c.pull_request.pull_request_id}");
792 "${c.repo_name}", "${c.pull_request.pull_request_id}");
793 });
793 });
794
794
795 $('#update_commits').on('click', function(e){
795 $('#update_commits').on('click', function(e){
796 var isDisabled = !$(e.currentTarget).attr('disabled');
796 var isDisabled = !$(e.currentTarget).attr('disabled');
797 $(e.currentTarget).attr('disabled', 'disabled');
797 $(e.currentTarget).attr('disabled', 'disabled');
798 $(e.currentTarget).addClass('disabled');
798 $(e.currentTarget).addClass('disabled');
799 $(e.currentTarget).removeClass('btn-primary');
799 $(e.currentTarget).removeClass('btn-primary');
800 $(e.currentTarget).text(_gettext('Updating...'));
800 $(e.currentTarget).text(_gettext('Updating...'));
801 if(isDisabled){
801 if(isDisabled){
802 updateCommits(
802 updateCommits(
803 "${c.repo_name}", "${c.pull_request.pull_request_id}");
803 "${c.repo_name}", "${c.pull_request.pull_request_id}");
804 }
804 }
805 });
805 });
806 // fixing issue with caches on firefox
806 // fixing issue with caches on firefox
807 $('#update_commits').removeAttr("disabled");
807 $('#update_commits').removeAttr("disabled");
808
808
809 $('.show-inline-comments').on('click', function(e){
809 $('.show-inline-comments').on('click', function(e){
810 var boxid = $(this).attr('data-comment-id');
810 var boxid = $(this).attr('data-comment-id');
811 var button = $(this);
811 var button = $(this);
812
812
813 if(button.hasClass("comments-visible")) {
813 if(button.hasClass("comments-visible")) {
814 $('#{0} .inline-comments'.format(boxid)).each(function(index){
814 $('#{0} .inline-comments'.format(boxid)).each(function(index){
815 $(this).hide();
815 $(this).hide();
816 });
816 });
817 button.removeClass("comments-visible");
817 button.removeClass("comments-visible");
818 } else {
818 } else {
819 $('#{0} .inline-comments'.format(boxid)).each(function(index){
819 $('#{0} .inline-comments'.format(boxid)).each(function(index){
820 $(this).show();
820 $(this).show();
821 });
821 });
822 button.addClass("comments-visible");
822 button.addClass("comments-visible");
823 }
823 }
824 });
824 });
825
825
826 // register submit callback on commentForm form to track TODOs
826 // register submit callback on commentForm form to track TODOs
827 window.commentFormGlobalSubmitSuccessCallback = function(){
827 window.commentFormGlobalSubmitSuccessCallback = function(){
828 refreshMergeChecks();
828 refreshMergeChecks();
829 };
829 };
830 // initial injection
830 // initial injection
831 injectCloseAction();
831 injectCloseAction();
832
832
833 ReviewerAutoComplete('#user');
833 ReviewerAutoComplete('#user');
834
834
835 })
835 })
836 </script>
836 </script>
837
837
838 </div>
838 </div>
839 </div>
839 </div>
840
840
841 </%def>
841 </%def>
@@ -1,167 +1,167 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3 %if c.repo_commits:
3 %if c.repo_commits:
4 <table class="rctable repo_summary table_disp">
4 <table class="rctable repo_summary table_disp">
5 <tr>
5 <tr>
6
6
7 <th class="status"></th>
7 <th class="status"></th>
8 <th>${_('Commit')}</th>
8 <th>${_('Commit')}</th>
9 <th>${_('Commit message')}</th>
9 <th>${_('Commit message')}</th>
10 <th>${_('Age')}</th>
10 <th>${_('Age')}</th>
11 <th>${_('Author')}</th>
11 <th>${_('Author')}</th>
12 <th colspan="2">${_('Refs')}</th>
12 <th colspan="2">${_('Refs')}</th>
13 </tr>
13 </tr>
14
14
15 ## to speed up lookups cache some functions before the loop
15 ## to speed up lookups cache some functions before the loop
16 <%
16 <%
17 active_patterns = h.get_active_pattern_entries(c.repo_name)
17 active_patterns = h.get_active_pattern_entries(c.repo_name)
18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
19 %>
19 %>
20 %for cnt,cs in enumerate(c.repo_commits):
20 %for cnt,cs in enumerate(c.repo_commits):
21 <tr class="parity${cnt%2}">
21 <tr class="parity${cnt%2}">
22
22
23 <td class="td-status">
23 <td class="td-status">
24 %if c.statuses.get(cs.raw_id):
24 %if c.statuses.get(cs.raw_id):
25 <div class="changeset-status-ico shortlog">
25 <div class="changeset-status-ico shortlog">
26 %if c.statuses.get(cs.raw_id)[2]:
26 %if c.statuses.get(cs.raw_id)[2]:
27 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (c.statuses.get(cs.raw_id)[0], c.statuses.get(cs.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
27 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (c.statuses.get(cs.raw_id)[0], c.statuses.get(cs.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
28 <div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
28 <i class="icon-circle review-status-${c.statuses.get(cs.raw_id)[0]}"></i>
29 </a>
29 </a>
30 %else:
30 %else:
31 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(cs.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
31 <a class="tooltip" title="${_('Commit status: {}').format(h.commit_status_lbl(c.statuses.get(cs.raw_id)[0]))}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
32 <div class="${'flag_status {}'.format(c.statuses.get(cs.raw_id)[0])}"></div>
32 <i class="icon-circle review-status-${c.statuses.get(cs.raw_id)[0]}"></i>
33 </a>
33 </a>
34 %endif
34 %endif
35 </div>
35 </div>
36 %else:
36 %else:
37 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
37 <i class="icon-circle review-status-not_reviewed" title="${_('Commit status: Not Reviewed')}"></i>
38 %endif
38 %endif
39 </td>
39 </td>
40 <td class="td-commit">
40 <td class="td-commit">
41 <code>
41 <code>
42 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=cs.raw_id)}">${h.show_id(cs)}</a>
42 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=cs.raw_id)}">${h.show_id(cs)}</a>
43 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${cs.raw_id}" title="${_('Copy the full commit id')}"></i>
43 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${cs.raw_id}" title="${_('Copy the full commit id')}"></i>
44 </code>
44 </code>
45 </td>
45 </td>
46
46
47 <td class="td-description mid">
47 <td class="td-description mid">
48 <div class="log-container truncate-wrap">
48 <div class="log-container truncate-wrap">
49 <div class="message truncate" id="c-${cs.raw_id}">${urlify_commit_message(cs.message, c.repo_name)}</div>
49 <div class="message truncate" id="c-${cs.raw_id}">${urlify_commit_message(cs.message, c.repo_name)}</div>
50 </div>
50 </div>
51 </td>
51 </td>
52
52
53 <td class="td-time">
53 <td class="td-time">
54 ${h.age_component(cs.date)}
54 ${h.age_component(cs.date)}
55 </td>
55 </td>
56 <td class="td-user author">
56 <td class="td-user author">
57 ${base.gravatar_with_user(cs.author)}
57 ${base.gravatar_with_user(cs.author)}
58 </td>
58 </td>
59
59
60 <td class="td-tags">
60 <td class="td-tags">
61 <div class="autoexpand">
61 <div class="autoexpand">
62 %if h.is_hg(c.rhodecode_repo):
62 %if h.is_hg(c.rhodecode_repo):
63 %for book in cs.bookmarks:
63 %for book in cs.bookmarks:
64 <span class="booktag tag" title="${h.tooltip(_('Bookmark %s') % book)}">
64 <span class="booktag tag" title="${h.tooltip(_('Bookmark %s') % book)}">
65 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=cs.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
65 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=cs.raw_id, _query=dict(at=book))}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
66 </span>
66 </span>
67 %endfor
67 %endfor
68 %endif
68 %endif
69 ## tags
69 ## tags
70 %for tag in cs.tags:
70 %for tag in cs.tags:
71 <span class="tagtag tag" title="${h.tooltip(_('Tag %s') % tag)}">
71 <span class="tagtag tag" title="${h.tooltip(_('Tag %s') % tag)}">
72 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=cs.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
72 <a href="${h.route_path('repo_files:default_path',repo_name=c.repo_name,commit_id=cs.raw_id, _query=dict(at=tag))}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
73 </span>
73 </span>
74 %endfor
74 %endfor
75
75
76 ## branch
76 ## branch
77 %if cs.branch:
77 %if cs.branch:
78 <span class="branchtag tag" title="${h.tooltip(_('Branch %s') % cs.branch)}">
78 <span class="branchtag tag" title="${h.tooltip(_('Branch %s') % cs.branch)}">
79 <a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=cs.branch))}"><i class="icon-code-fork"></i>${h.shorter(cs.branch)}</a>
79 <a href="${h.route_path('repo_commits',repo_name=c.repo_name,_query=dict(branch=cs.branch))}"><i class="icon-code-fork"></i>${h.shorter(cs.branch)}</a>
80 </span>
80 </span>
81 %endif
81 %endif
82 </div>
82 </div>
83 </td>
83 </td>
84 <td class="td-comments">
84 <td class="td-comments">
85 <% cs_comments = c.comments.get(cs.raw_id,[]) %>
85 <% cs_comments = c.comments.get(cs.raw_id,[]) %>
86 % if cs_comments:
86 % if cs_comments:
87 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % cs_comments[0].comment_id)}">
87 <a title="${_('Commit has comments')}" href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=cs.raw_id,_anchor='comment-%s' % cs_comments[0].comment_id)}">
88 <i class="icon-comment"></i> ${len(cs_comments)}
88 <i class="icon-comment"></i> ${len(cs_comments)}
89 </a>
89 </a>
90 % else:
90 % else:
91 <i class="icon-comment"></i> ${len(cs_comments)}
91 <i class="icon-comment"></i> ${len(cs_comments)}
92 % endif
92 % endif
93 </td>
93 </td>
94 </tr>
94 </tr>
95 %endfor
95 %endfor
96
96
97 </table>
97 </table>
98
98
99 <script type="text/javascript">
99 <script type="text/javascript">
100 $(document).pjax('#shortlog_data .pager_link','#shortlog_data', {timeout: 5000, scrollTo: false, push: false});
100 $(document).pjax('#shortlog_data .pager_link','#shortlog_data', {timeout: 5000, scrollTo: false, push: false});
101 $(document).on('pjax:success', function(){ timeagoActivate(); });
101 $(document).on('pjax:success', function(){ timeagoActivate(); });
102 $(document).on('pjax:timeout', function(event) {
102 $(document).on('pjax:timeout', function(event) {
103 // Prevent default timeout redirection behavior
103 // Prevent default timeout redirection behavior
104 event.preventDefault()
104 event.preventDefault()
105 })
105 })
106
106
107 </script>
107 </script>
108
108
109 <div class="pagination-wh pagination-left">
109 <div class="pagination-wh pagination-left">
110 ${c.repo_commits.pager('$link_previous ~2~ $link_next')}
110 ${c.repo_commits.pager('$link_previous ~2~ $link_next')}
111 </div>
111 </div>
112 %else:
112 %else:
113
113
114 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
114 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
115 <div class="quick_start">
115 <div class="quick_start">
116 <div class="fieldset">
116 <div class="fieldset">
117 <p><b>${_('Add or upload files directly via RhodeCode:')}</b></p>
117 <p><b>${_('Add or upload files directly via RhodeCode:')}</b></p>
118 <div class="pull-left">
118 <div class="pull-left">
119 <a href="${h.route_path('repo_files_add_file',repo_name=c.repo_name,commit_id=0, f_path='')}" class="btn btn-default">${_('Add New File')}</a>
119 <a href="${h.route_path('repo_files_add_file',repo_name=c.repo_name,commit_id=0, f_path='')}" class="btn btn-default">${_('Add New File')}</a>
120 </div>
120 </div>
121 <div class="pull-left">
121 <div class="pull-left">
122 <a href="${h.route_path('repo_files_upload_file',repo_name=c.repo_name,commit_id=0, f_path='')}" class="btn btn-default">${_('Upload New File')}</a>
122 <a href="${h.route_path('repo_files_upload_file',repo_name=c.repo_name,commit_id=0, f_path='')}" class="btn btn-default">${_('Upload New File')}</a>
123 </div>
123 </div>
124 %endif
124 %endif
125 </div>
125 </div>
126
126
127 <div class="fieldset">
127 <div class="fieldset">
128 <p><b>${_('Push new repo:')}</b></p>
128 <p><b>${_('Push new repo:')}</b></p>
129 <pre>
129 <pre>
130 %if h.is_git(c.rhodecode_repo):
130 %if h.is_git(c.rhodecode_repo):
131 git clone ${c.clone_repo_url}
131 git clone ${c.clone_repo_url}
132 git add README # add first file
132 git add README # add first file
133 git commit -m "Initial commit" # commit with message
133 git commit -m "Initial commit" # commit with message
134 git remote add origin ${c.clone_repo_url}
134 git remote add origin ${c.clone_repo_url}
135 git push -u origin master # push changes back to default master branch
135 git push -u origin master # push changes back to default master branch
136 %elif h.is_hg(c.rhodecode_repo):
136 %elif h.is_hg(c.rhodecode_repo):
137 hg clone ${c.clone_repo_url}
137 hg clone ${c.clone_repo_url}
138 hg add README # add first file
138 hg add README # add first file
139 hg commit -m "Initial commit" # commit with message
139 hg commit -m "Initial commit" # commit with message
140 hg push ${c.clone_repo_url}
140 hg push ${c.clone_repo_url}
141 %elif h.is_svn(c.rhodecode_repo):
141 %elif h.is_svn(c.rhodecode_repo):
142 svn co ${c.clone_repo_url}
142 svn co ${c.clone_repo_url}
143 svn add README # add first file
143 svn add README # add first file
144 svn commit -m "Initial commit"
144 svn commit -m "Initial commit"
145 svn commit # send changes back to the server
145 svn commit # send changes back to the server
146 %endif
146 %endif
147 </pre>
147 </pre>
148 </div>
148 </div>
149
149
150 <div class="fieldset">
150 <div class="fieldset">
151 <p><b>${_('Existing repository?')}</b></p>
151 <p><b>${_('Existing repository?')}</b></p>
152 <pre>
152 <pre>
153 %if h.is_git(c.rhodecode_repo):
153 %if h.is_git(c.rhodecode_repo):
154 git remote add origin ${c.clone_repo_url}
154 git remote add origin ${c.clone_repo_url}
155 git push -u origin master
155 git push -u origin master
156 %elif h.is_hg(c.rhodecode_repo):
156 %elif h.is_hg(c.rhodecode_repo):
157 hg push ${c.clone_repo_url}
157 hg push ${c.clone_repo_url}
158 %elif h.is_svn(c.rhodecode_repo):
158 %elif h.is_svn(c.rhodecode_repo):
159 svn co ${c.clone_repo_url}
159 svn co ${c.clone_repo_url}
160 %endif
160 %endif
161 </pre>
161 </pre>
162
162
163 </div>
163 </div>
164
164
165
165
166 </div>
166 </div>
167 %endif
167 %endif
General Comments 0
You need to be logged in to leave comments. Login now