##// 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 1 // comments.less
2 2 // For use in RhodeCode applications;
3 3 // see style guide documentation for guidelines.
4 4
5 5
6 6 // Comments
7 7 @comment-outdated-opacity: 0.6;
8 8
9 9 .comments {
10 10 width: 100%;
11 11 }
12 12
13 13 .comments-heading {
14 14 margin-bottom: -1px;
15 15 background: @grey6;
16 16 display: block;
17 17 padding: 10px 0px;
18 18 font-size: 18px
19 19 }
20 20
21 21 tr.inline-comments div {
22 22 max-width: 100%;
23 23
24 24 p {
25 25 white-space: normal;
26 26 }
27 27
28 28 code, pre, .code, dd {
29 29 overflow-x: auto;
30 30 width: 1062px;
31 31 }
32 32
33 33 dd {
34 34 width: auto;
35 35 }
36 36 }
37 37
38 38 #injected_page_comments {
39 39 .comment-previous-link,
40 40 .comment-next-link,
41 41 .comment-links-divider {
42 42 display: none;
43 43 }
44 44 }
45 45
46 46 .add-comment {
47 47 margin-bottom: 10px;
48 48 }
49 49 .hide-comment-button .add-comment {
50 50 display: none;
51 51 }
52 52
53 53 .comment-bubble {
54 54 color: @grey4;
55 55 margin-top: 4px;
56 56 margin-right: 30px;
57 57 visibility: hidden;
58 58 }
59 59
60 60 .comment-label {
61 61 float: left;
62 62
63 63 padding: 0.4em 0.4em;
64 64 margin: 3px 5px 0px -10px;
65 65 display: inline-block;
66 66 min-height: 0;
67 67
68 68 text-align: center;
69 69 font-size: 10px;
70 70 line-height: .8em;
71 71
72 72 font-family: @text-italic;
73 73 font-style: italic;
74 74 background: #fff none;
75 75 color: @grey4;
76 76 border: 1px solid @grey4;
77 77 white-space: nowrap;
78 78
79 79 text-transform: uppercase;
80 80 min-width: 40px;
81 81
82 82 &.todo {
83 83 color: @color5;
84 84 font-style: italic;
85 85 font-weight: @text-bold-italic-weight;
86 86 font-family: @text-bold-italic;
87 87 }
88 88
89 89 .resolve {
90 90 cursor: pointer;
91 91 text-decoration: underline;
92 92 }
93 93
94 94 .resolved {
95 95 text-decoration: line-through;
96 96 color: @color1;
97 97 }
98 98 .resolved a {
99 99 text-decoration: line-through;
100 100 color: @color1;
101 101 }
102 102 .resolve-text {
103 103 color: @color1;
104 104 margin: 2px 8px;
105 105 font-family: @text-italic;
106 106 font-style: italic;
107 107 }
108 108 }
109 109
110 110 .has-spacer-after {
111 111 &:after {
112 112 content: ' | ';
113 113 color: @grey5;
114 114 }
115 115 }
116 116
117 117 .has-spacer-before {
118 118 &:before {
119 119 content: ' | ';
120 120 color: @grey5;
121 121 }
122 122 }
123 123
124 124 .comment {
125 125
126 126 &.comment-general {
127 127 border: 1px solid @grey5;
128 128 padding: 5px 5px 5px 5px;
129 129 }
130 130
131 131 margin: @padding 0;
132 132 padding: 4px 0 0 0;
133 133 line-height: 1em;
134 134
135 135 .rc-user {
136 136 min-width: 0;
137 137 margin: 0px .5em 0 0;
138 138
139 139 .user {
140 140 display: inline;
141 141 }
142 142 }
143 143
144 144 .meta {
145 145 position: relative;
146 146 width: 100%;
147 147 border-bottom: 1px solid @grey5;
148 148 margin: -5px 0px;
149 149 line-height: 24px;
150 150
151 151 &:hover .permalink {
152 152 visibility: visible;
153 153 color: @rcblue;
154 154 }
155 155 }
156 156
157 157 .author,
158 158 .date {
159 159 display: inline;
160 160
161 161 &:after {
162 162 content: ' | ';
163 163 color: @grey5;
164 164 }
165 165 }
166 166
167 167 .author-general img {
168 168 top: 3px;
169 169 }
170 170 .author-inline img {
171 171 top: 3px;
172 172 }
173 173
174 174 .status-change,
175 175 .permalink,
176 176 .changeset-status-lbl {
177 177 display: inline;
178 178 }
179 179
180 180 .permalink {
181 181 visibility: hidden;
182 182 }
183 183
184 184 .comment-links-divider {
185 185 display: inline;
186 186 }
187 187
188 188 .comment-links-block {
189 189 float:right;
190 190 text-align: right;
191 191 min-width: 85px;
192 192
193 193 [class^="icon-"]:before,
194 194 [class*=" icon-"]:before {
195 195 margin-left: 0;
196 196 margin-right: 0;
197 197 }
198 198 }
199 199
200 200 .comment-previous-link {
201 201 display: inline-block;
202 202
203 203 .arrow_comment_link{
204 204 cursor: pointer;
205 205 i {
206 206 font-size:10px;
207 207 }
208 208 }
209 209 .arrow_comment_link.disabled {
210 210 cursor: default;
211 211 color: @grey5;
212 212 }
213 213 }
214 214
215 215 .comment-next-link {
216 216 display: inline-block;
217 217
218 218 .arrow_comment_link{
219 219 cursor: pointer;
220 220 i {
221 221 font-size:10px;
222 222 }
223 223 }
224 224 .arrow_comment_link.disabled {
225 225 cursor: default;
226 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 230 .delete-comment {
236 231 display: inline-block;
237 232 color: @rcblue;
238 233
239 234 &:hover {
240 235 cursor: pointer;
241 236 }
242 237 }
243 238
244 239 .text {
245 240 clear: both;
246 241 .border-radius(@border-radius);
247 242 .box-sizing(border-box);
248 243
249 244 .markdown-block p,
250 245 .rst-block p {
251 246 margin: .5em 0 !important;
252 247 // TODO: lisa: This is needed because of other rst !important rules :[
253 248 }
254 249 }
255 250
256 251 .pr-version {
257 252 float: left;
258 253 margin: 0px 4px;
259 254 }
260 255 .pr-version-inline {
261 256 float: left;
262 257 margin: 0px 4px;
263 258 }
264 259 .pr-version-num {
265 260 font-size: 10px;
266 261 }
267 262 }
268 263
269 264 @comment-padding: 5px;
270 265
271 266 .general-comments {
272 267 .comment-outdated {
273 268 opacity: @comment-outdated-opacity;
274 269 }
275 270 }
276 271
277 272 .inline-comments {
278 273 border-radius: @border-radius;
279 274 .comment {
280 275 margin: 0;
281 276 border-radius: @border-radius;
282 277 }
283 278 .comment-outdated {
284 279 opacity: @comment-outdated-opacity;
285 280 }
286 281
287 282 .comment-inline {
288 283 background: white;
289 284 padding: @comment-padding @comment-padding;
290 285 border: @comment-padding solid @grey6;
291 286
292 287 .text {
293 288 border: none;
294 289 }
295 290 .meta {
296 291 border-bottom: 1px solid @grey6;
297 292 margin: -5px 0px;
298 293 line-height: 24px;
299 294 }
300 295 }
301 296 .comment-selected {
302 297 border-left: 6px solid @comment-highlight-color;
303 298 }
304 299 .comment-inline-form {
305 300 padding: @comment-padding;
306 301 display: none;
307 302 }
308 303 .cb-comment-add-button {
309 304 margin: @comment-padding;
310 305 }
311 306 /* hide add comment button when form is open */
312 307 .comment-inline-form-open ~ .cb-comment-add-button {
313 308 display: none;
314 309 }
315 310 .comment-inline-form-open {
316 311 display: block;
317 312 }
318 313 /* hide add comment button when form but no comments */
319 314 .comment-inline-form:first-child + .cb-comment-add-button {
320 315 display: none;
321 316 }
322 317 /* hide add comment button when no comments or form */
323 318 .cb-comment-add-button:first-child {
324 319 display: none;
325 320 }
326 321 /* hide add comment button when only comment is being deleted */
327 322 .comment-deleting:first-child + .cb-comment-add-button {
328 323 display: none;
329 324 }
330 325 }
331 326
332 327
333 328 .show-outdated-comments {
334 329 display: inline;
335 330 color: @rcblue;
336 331 }
337 332
338 333 // Comment Form
339 334 div.comment-form {
340 335 margin-top: 20px;
341 336 }
342 337
343 338 .comment-form strong {
344 339 display: block;
345 340 margin-bottom: 15px;
346 341 }
347 342
348 343 .comment-form textarea {
349 344 width: 100%;
350 345 height: 100px;
351 346 font-family: @text-monospace;
352 347 }
353 348
354 349 form.comment-form {
355 350 margin-top: 10px;
356 351 margin-left: 10px;
357 352 }
358 353
359 354 .comment-inline-form .comment-block-ta,
360 355 .comment-form .comment-block-ta,
361 356 .comment-form .preview-box {
362 357 .border-radius(@border-radius);
363 358 .box-sizing(border-box);
364 359 background-color: white;
365 360 }
366 361
367 362 .comment-form-submit {
368 363 margin-top: 5px;
369 364 margin-left: 525px;
370 365 }
371 366
372 367 .file-comments {
373 368 display: none;
374 369 }
375 370
376 371 .comment-form .preview-box.unloaded,
377 372 .comment-inline-form .preview-box.unloaded {
378 373 height: 50px;
379 374 text-align: center;
380 375 padding: 20px;
381 376 background-color: white;
382 377 }
383 378
384 379 .comment-footer {
385 380 position: relative;
386 381 width: 100%;
387 382 min-height: 42px;
388 383
389 384 .status_box,
390 385 .cancel-button {
391 386 float: left;
392 387 display: inline-block;
393 388 }
394 389
395 390 .action-buttons {
396 391 float: right;
397 392 display: inline-block;
398 393 }
399 394
400 395 .action-buttons-extra {
401 396 display: inline-block;
402 397 }
403 398 }
404 399
405 400 .comment-form {
406 401
407 402 .comment {
408 403 margin-left: 10px;
409 404 }
410 405
411 406 .comment-help {
412 407 color: @grey4;
413 408 padding: 5px 0 5px 0;
414 409 }
415 410
416 411 .comment-title {
417 412 padding: 5px 0 5px 0;
418 413 }
419 414
420 415 .comment-button {
421 416 display: inline-block;
422 417 }
423 418
424 419 .comment-button-input {
425 420 margin-right: 0;
426 421 }
427 422
428 423 .comment-footer {
429 424 margin-bottom: 110px;
430 425 margin-top: 10px;
431 426 }
432 427 }
433 428
434 429
435 430 .comment-form-login {
436 431 .comment-help {
437 432 padding: 0.7em; //same as the button
438 433 }
439 434
440 435 div.clearfix {
441 436 clear: both;
442 437 width: 100%;
443 438 display: block;
444 439 }
445 440 }
446 441
447 442 .comment-type {
448 443 margin: 0px;
449 444 border-radius: inherit;
450 445 border-color: @grey6;
451 446 }
452 447
453 448 .preview-box {
454 449 min-height: 105px;
455 450 margin-bottom: 15px;
456 451 background-color: white;
457 452 .border-radius(@border-radius);
458 453 .box-sizing(border-box);
459 454 }
460 455
461 456 .add-another-button {
462 457 margin-left: 10px;
463 458 margin-top: 10px;
464 459 margin-bottom: 10px;
465 460 }
466 461
467 462 .comment .buttons {
468 463 float: right;
469 464 margin: -1px 0px 0px 0px;
470 465 }
471 466
472 467 // Inline Comment Form
473 468 .injected_diff .comment-inline-form,
474 469 .comment-inline-form {
475 470 background-color: white;
476 471 margin-top: 10px;
477 472 margin-bottom: 20px;
478 473 }
479 474
480 475 .inline-form {
481 476 padding: 10px 7px;
482 477 }
483 478
484 479 .inline-form div {
485 480 max-width: 100%;
486 481 }
487 482
488 483 .overlay {
489 484 display: none;
490 485 position: absolute;
491 486 width: 100%;
492 487 text-align: center;
493 488 vertical-align: middle;
494 489 font-size: 16px;
495 490 background: none repeat scroll 0 0 white;
496 491
497 492 &.submitting {
498 493 display: block;
499 494 opacity: 0.5;
500 495 z-index: 100;
501 496 }
502 497 }
503 498 .comment-inline-form .overlay.submitting .overlay-text {
504 499 margin-top: 5%;
505 500 }
506 501
507 502 .comment-inline-form .clearfix,
508 503 .comment-form .clearfix {
509 504 .border-radius(@border-radius);
510 505 margin: 0px;
511 506 }
512 507
513 508 .comment-inline-form .comment-footer {
514 509 margin: 10px 0px 0px 0px;
515 510 }
516 511
517 512 .hide-inline-form-button {
518 513 margin-left: 5px;
519 514 }
520 515 .comment-button .hide-inline-form {
521 516 background: white;
522 517 }
523 518
524 519 .comment-area {
525 520 padding: 8px 12px;
526 521 border: 1px solid @grey5;
527 522 .border-radius(@border-radius);
528 523
529 524 .resolve-action {
530 525 padding: 1px 0px 0px 6px;
531 526 }
532 527
533 528 }
534 529
535 530 .comment-area-header .nav-links {
536 531 display: flex;
537 532 flex-flow: row wrap;
538 533 -webkit-flex-flow: row wrap;
539 534 width: 100%;
540 535 }
541 536
542 537 .comment-area-footer {
543 538 display: flex;
544 539 }
545 540
546 541 .comment-footer .toolbar {
547 542
548 543 }
549 544
550 545 .nav-links {
551 546 padding: 0;
552 547 margin: 0;
553 548 list-style: none;
554 549 height: auto;
555 550 border-bottom: 1px solid @grey5;
556 551 }
557 552 .nav-links li {
558 553 display: inline-block;
559 554 list-style-type: none;
560 555 }
561 556
562 557 .nav-links li a.disabled {
563 558 cursor: not-allowed;
564 559 }
565 560
566 561 .nav-links li.active a {
567 562 border-bottom: 2px solid @rcblue;
568 563 color: #000;
569 564 font-weight: 600;
570 565 }
571 566 .nav-links li a {
572 567 display: inline-block;
573 568 padding: 0px 10px 5px 10px;
574 569 margin-bottom: -1px;
575 570 font-size: 14px;
576 571 line-height: 28px;
577 572 color: #8f8f8f;
578 573 border-bottom: 2px solid transparent;
579 574 }
580 575
581 576 .toolbar-text {
582 577 float: left;
583 578 margin: -5px 0px 0px 0px;
584 579 font-size: 12px;
585 580 }
586 581
@@ -1,2854 +1,2823 b''
1 1 //Primary CSS
2 2
3 3 //--- IMPORTS ------------------//
4 4
5 5 @import 'helpers';
6 6 @import 'mixins';
7 7 @import 'rcicons';
8 8 @import 'variables';
9 9 @import 'bootstrap-variables';
10 10 @import 'form-bootstrap';
11 11 @import 'codemirror';
12 12 @import 'legacy_code_styles';
13 13 @import 'readme-box';
14 14 @import 'progress-bar';
15 15
16 16 @import 'type';
17 17 @import 'alerts';
18 18 @import 'buttons';
19 19 @import 'tags';
20 20 @import 'code-block';
21 21 @import 'examples';
22 22 @import 'login';
23 23 @import 'main-content';
24 24 @import 'select2';
25 25 @import 'comments';
26 26 @import 'panels-bootstrap';
27 27 @import 'panels';
28 28 @import 'deform';
29 29
30 30 //--- BASE ------------------//
31 31 .noscript-error {
32 32 top: 0;
33 33 left: 0;
34 34 width: 100%;
35 35 z-index: 101;
36 36 text-align: center;
37 37 font-size: 120%;
38 38 color: white;
39 39 background-color: @alert2;
40 40 padding: 5px 0 5px 0;
41 41 font-weight: @text-semibold-weight;
42 42 font-family: @text-semibold;
43 43 }
44 44
45 45 html {
46 46 display: table;
47 47 height: 100%;
48 48 width: 100%;
49 49 }
50 50
51 51 body {
52 52 display: table-cell;
53 53 width: 100%;
54 54 }
55 55
56 56 //--- LAYOUT ------------------//
57 57
58 58 .hidden{
59 59 display: none !important;
60 60 }
61 61
62 62 .box{
63 63 float: left;
64 64 width: 100%;
65 65 }
66 66
67 67 .browser-header {
68 68 clear: both;
69 69 }
70 70 .main {
71 71 clear: both;
72 72 padding:0 0 @pagepadding;
73 73 height: auto;
74 74
75 75 &:after { //clearfix
76 76 content:"";
77 77 clear:both;
78 78 width:100%;
79 79 display:block;
80 80 }
81 81 }
82 82
83 83 .action-link{
84 84 margin-left: @padding;
85 85 padding-left: @padding;
86 86 border-left: @border-thickness solid @border-default-color;
87 87 }
88 88
89 89 input + .action-link, .action-link.first{
90 90 border-left: none;
91 91 }
92 92
93 93 .action-link.last{
94 94 margin-right: @padding;
95 95 padding-right: @padding;
96 96 }
97 97
98 98 .action-link.active,
99 99 .action-link.active a{
100 100 color: @grey4;
101 101 }
102 102
103 103 .action-link.disabled {
104 104 color: @grey4;
105 105 cursor: inherit;
106 106 }
107 107
108 108 .clipboard-action {
109 109 cursor: pointer;
110 110 color: @grey4;
111 111 margin-left: 5px;
112 112
113 113 &:hover {
114 114 color: @grey2;
115 115 }
116 116 }
117 117
118 118 ul.simple-list{
119 119 list-style: none;
120 120 margin: 0;
121 121 padding: 0;
122 122 }
123 123
124 124 .main-content {
125 125 padding-bottom: @pagepadding;
126 126 }
127 127
128 128 .wide-mode-wrapper {
129 129 max-width:4000px !important;
130 130 }
131 131
132 132 .wrapper {
133 133 position: relative;
134 134 max-width: @wrapper-maxwidth;
135 135 margin: 0 auto;
136 136 }
137 137
138 138 #content {
139 139 clear: both;
140 140 padding: 0 @contentpadding;
141 141 }
142 142
143 143 .advanced-settings-fields{
144 144 input{
145 145 margin-left: @textmargin;
146 146 margin-right: @padding/2;
147 147 }
148 148 }
149 149
150 150 .cs_files_title {
151 151 margin: @pagepadding 0 0;
152 152 }
153 153
154 154 input.inline[type="file"] {
155 155 display: inline;
156 156 }
157 157
158 158 .error_page {
159 159 margin: 10% auto;
160 160
161 161 h1 {
162 162 color: @grey2;
163 163 }
164 164
165 165 .alert {
166 166 margin: @padding 0;
167 167 }
168 168
169 169 .error-branding {
170 170 color: @grey4;
171 171 font-weight: @text-semibold-weight;
172 172 font-family: @text-semibold;
173 173 }
174 174
175 175 .error_message {
176 176 font-family: @text-regular;
177 177 }
178 178
179 179 .sidebar {
180 180 min-height: 275px;
181 181 margin: 0;
182 182 padding: 0 0 @sidebarpadding @sidebarpadding;
183 183 border: none;
184 184 }
185 185
186 186 .main-content {
187 187 position: relative;
188 188 margin: 0 @sidebarpadding @sidebarpadding;
189 189 padding: 0 0 0 @sidebarpadding;
190 190 border-left: @border-thickness solid @grey5;
191 191
192 192 @media (max-width:767px) {
193 193 clear: both;
194 194 width: 100%;
195 195 margin: 0;
196 196 border: none;
197 197 }
198 198 }
199 199
200 200 .inner-column {
201 201 float: left;
202 202 width: 29.75%;
203 203 min-height: 150px;
204 204 margin: @sidebarpadding 2% 0 0;
205 205 padding: 0 2% 0 0;
206 206 border-right: @border-thickness solid @grey5;
207 207
208 208 @media (max-width:767px) {
209 209 clear: both;
210 210 width: 100%;
211 211 border: none;
212 212 }
213 213
214 214 ul {
215 215 padding-left: 1.25em;
216 216 }
217 217
218 218 &:last-child {
219 219 margin: @sidebarpadding 0 0;
220 220 border: none;
221 221 }
222 222
223 223 h4 {
224 224 margin: 0 0 @padding;
225 225 font-weight: @text-semibold-weight;
226 226 font-family: @text-semibold;
227 227 }
228 228 }
229 229 }
230 230 .error-page-logo {
231 231 width: 130px;
232 232 height: 160px;
233 233 }
234 234
235 235 // HEADER
236 236 .header {
237 237
238 238 // TODO: johbo: Fix login pages, so that they work without a min-height
239 239 // for the header and then remove the min-height. I chose a smaller value
240 240 // intentionally here to avoid rendering issues in the main navigation.
241 241 min-height: 49px;
242 242 min-width: 1024px;
243 243
244 244 position: relative;
245 245 vertical-align: bottom;
246 246 padding: 0 @header-padding;
247 247 background-color: @grey1;
248 248 color: @grey5;
249 249
250 250 .title {
251 251 overflow: visible;
252 252 }
253 253
254 254 &:before,
255 255 &:after {
256 256 content: "";
257 257 clear: both;
258 258 width: 100%;
259 259 }
260 260
261 261 // TODO: johbo: Avoids breaking "Repositories" chooser
262 262 .select2-container .select2-choice .select2-arrow {
263 263 display: none;
264 264 }
265 265 }
266 266
267 267 #header-inner {
268 268 &.title {
269 269 margin: 0;
270 270 }
271 271 &:before,
272 272 &:after {
273 273 content: "";
274 274 clear: both;
275 275 }
276 276 }
277 277
278 278 // Gists
279 279 #files_data {
280 280 clear: both; //for firefox
281 281 padding-top: 10px;
282 282 }
283 283
284 284 #gistid {
285 285 margin-right: @padding;
286 286 }
287 287
288 288 // Global Settings Editor
289 289 .textarea.editor {
290 290 float: left;
291 291 position: relative;
292 292 max-width: @texteditor-width;
293 293
294 294 select {
295 295 position: absolute;
296 296 top:10px;
297 297 right:0;
298 298 }
299 299
300 300 .CodeMirror {
301 301 margin: 0;
302 302 }
303 303
304 304 .help-block {
305 305 margin: 0 0 @padding;
306 306 padding:.5em;
307 307 background-color: @grey6;
308 308 &.pre-formatting {
309 309 white-space: pre;
310 310 }
311 311 }
312 312 }
313 313
314 314 ul.auth_plugins {
315 315 margin: @padding 0 @padding @legend-width;
316 316 padding: 0;
317 317
318 318 li {
319 319 margin-bottom: @padding;
320 320 line-height: 1em;
321 321 list-style-type: none;
322 322
323 323 .auth_buttons .btn {
324 324 margin-right: @padding;
325 325 }
326 326
327 327 }
328 328 }
329 329
330 330
331 331 // My Account PR list
332 332
333 333 #show_closed {
334 334 margin: 0 1em 0 0;
335 335 }
336 336
337 337 #pull_request_list_table {
338 338 .closed {
339 339 background-color: @grey6;
340 340 }
341 341
342 342 .state-creating,
343 343 .state-updating,
344 344 .state-merging
345 345 {
346 346 background-color: @grey6;
347 347 }
348 348
349 349 .td-status {
350 350 padding-left: .5em;
351 351 }
352 352 .log-container .truncate {
353 353 height: 2.75em;
354 354 white-space: pre-line;
355 355 }
356 356 table.rctable .user {
357 357 padding-left: 0;
358 358 }
359 359 table.rctable {
360 360 td.td-description,
361 361 .rc-user {
362 362 min-width: auto;
363 363 }
364 364 }
365 365 }
366 366
367 367 // Pull Requests
368 368
369 369 .pullrequests_section_head {
370 370 display: block;
371 371 clear: both;
372 372 margin: @padding 0;
373 373 font-weight: @text-bold-weight;
374 374 font-family: @text-bold;
375 375 }
376 376
377 377 .pr-origininfo, .pr-targetinfo {
378 378 position: relative;
379 379
380 380 .tag {
381 381 display: inline-block;
382 382 margin: 0 1em .5em 0;
383 383 }
384 384
385 385 .clone-url {
386 386 display: inline-block;
387 387 margin: 0 0 .5em 0;
388 388 padding: 0;
389 389 line-height: 1.2em;
390 390 }
391 391 }
392 392
393 393 .pr-mergeinfo {
394 394 min-width: 95% !important;
395 395 padding: 0 !important;
396 396 border: 0;
397 397 }
398 398 .pr-mergeinfo-copy {
399 399 padding: 0 0;
400 400 }
401 401
402 402 .pr-pullinfo {
403 403 min-width: 95% !important;
404 404 padding: 0 !important;
405 405 border: 0;
406 406 }
407 407 .pr-pullinfo-copy {
408 408 padding: 0 0;
409 409 }
410 410
411 411
412 412 #pr-title-input {
413 413 width: 72%;
414 414 font-size: 1em;
415 415 margin: 0;
416 416 padding: 0 0 0 @padding/4;
417 417 line-height: 1.7em;
418 418 color: @text-color;
419 419 letter-spacing: .02em;
420 420 font-weight: @text-bold-weight;
421 421 font-family: @text-bold;
422 422 }
423 423
424 424 #pullrequest_title {
425 425 width: 100%;
426 426 box-sizing: border-box;
427 427 }
428 428
429 429 #pr_open_message {
430 430 border: @border-thickness solid #fff;
431 431 border-radius: @border-radius;
432 432 padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0;
433 433 text-align: left;
434 434 overflow: hidden;
435 435 }
436 436
437 437 .pr-submit-button {
438 438 float: right;
439 439 margin: 0 0 0 5px;
440 440 }
441 441
442 442 .pr-spacing-container {
443 443 padding: 20px;
444 444 clear: both
445 445 }
446 446
447 447 #pr-description-input {
448 448 margin-bottom: 0;
449 449 }
450 450
451 451 .pr-description-label {
452 452 vertical-align: top;
453 453 }
454 454
455 455 .perms_section_head {
456 456 min-width: 625px;
457 457
458 458 h2 {
459 459 margin-bottom: 0;
460 460 }
461 461
462 462 .label-checkbox {
463 463 float: left;
464 464 }
465 465
466 466 &.field {
467 467 margin: @space 0 @padding;
468 468 }
469 469
470 470 &:first-child.field {
471 471 margin-top: 0;
472 472
473 473 .label {
474 474 margin-top: 0;
475 475 padding-top: 0;
476 476 }
477 477
478 478 .radios {
479 479 padding-top: 0;
480 480 }
481 481 }
482 482
483 483 .radios {
484 484 position: relative;
485 485 width: 505px;
486 486 }
487 487 }
488 488
489 489 //--- MODULES ------------------//
490 490
491 491
492 492 // Server Announcement
493 493 #server-announcement {
494 494 width: 95%;
495 495 margin: @padding auto;
496 496 padding: @padding;
497 497 border-width: 2px;
498 498 border-style: solid;
499 499 .border-radius(2px);
500 500 font-weight: @text-bold-weight;
501 501 font-family: @text-bold;
502 502
503 503 &.info { border-color: @alert4; background-color: @alert4-inner; }
504 504 &.warning { border-color: @alert3; background-color: @alert3-inner; }
505 505 &.error { border-color: @alert2; background-color: @alert2-inner; }
506 506 &.success { border-color: @alert1; background-color: @alert1-inner; }
507 507 &.neutral { border-color: @grey3; background-color: @grey6; }
508 508 }
509 509
510 510 // Fixed Sidebar Column
511 511 .sidebar-col-wrapper {
512 512 padding-left: @sidebar-all-width;
513 513
514 514 .sidebar {
515 515 width: @sidebar-width;
516 516 margin-left: -@sidebar-all-width;
517 517 }
518 518 }
519 519
520 520 .sidebar-col-wrapper.scw-small {
521 521 padding-left: @sidebar-small-all-width;
522 522
523 523 .sidebar {
524 524 width: @sidebar-small-width;
525 525 margin-left: -@sidebar-small-all-width;
526 526 }
527 527 }
528 528
529 529
530 530 // FOOTER
531 531 #footer {
532 532 padding: 0;
533 533 text-align: center;
534 534 vertical-align: middle;
535 535 color: @grey2;
536 536 font-size: 11px;
537 537
538 538 p {
539 539 margin: 0;
540 540 padding: 1em;
541 541 line-height: 1em;
542 542 }
543 543
544 544 .server-instance { //server instance
545 545 display: none;
546 546 }
547 547
548 548 .title {
549 549 float: none;
550 550 margin: 0 auto;
551 551 }
552 552 }
553 553
554 554 button.close {
555 555 padding: 0;
556 556 cursor: pointer;
557 557 background: transparent;
558 558 border: 0;
559 559 .box-shadow(none);
560 560 -webkit-appearance: none;
561 561 }
562 562
563 563 .close {
564 564 float: right;
565 565 font-size: 21px;
566 566 font-family: @text-bootstrap;
567 567 line-height: 1em;
568 568 font-weight: bold;
569 569 color: @grey2;
570 570
571 571 &:hover,
572 572 &:focus {
573 573 color: @grey1;
574 574 text-decoration: none;
575 575 cursor: pointer;
576 576 }
577 577 }
578 578
579 579 // GRID
580 580 .sorting,
581 581 .sorting_desc,
582 582 .sorting_asc {
583 583 cursor: pointer;
584 584 }
585 585 .sorting_desc:after {
586 586 content: "\00A0\25B2";
587 587 font-size: .75em;
588 588 }
589 589 .sorting_asc:after {
590 590 content: "\00A0\25BC";
591 591 font-size: .68em;
592 592 }
593 593
594 594
595 595 .user_auth_tokens {
596 596
597 597 &.truncate {
598 598 white-space: nowrap;
599 599 overflow: hidden;
600 600 text-overflow: ellipsis;
601 601 }
602 602
603 603 .fields .field .input {
604 604 margin: 0;
605 605 }
606 606
607 607 input#description {
608 608 width: 100px;
609 609 margin: 0;
610 610 }
611 611
612 612 .drop-menu {
613 613 // TODO: johbo: Remove this, should work out of the box when
614 614 // having multiple inputs inline
615 615 margin: 0 0 0 5px;
616 616 }
617 617 }
618 618 #user_list_table {
619 619 .closed {
620 620 background-color: @grey6;
621 621 }
622 622 }
623 623
624 624
625 625 input, textarea {
626 626 &.disabled {
627 627 opacity: .5;
628 628 }
629 629
630 630 &:hover {
631 631 border-color: @grey3;
632 632 box-shadow: @button-shadow;
633 633 }
634 634
635 635 &:focus {
636 636 border-color: @rcblue;
637 637 box-shadow: @button-shadow;
638 638 }
639 639 }
640 640
641 641 // remove extra padding in firefox
642 642 input::-moz-focus-inner { border:0; padding:0 }
643 643
644 644 .adjacent input {
645 645 margin-bottom: @padding;
646 646 }
647 647
648 648 .permissions_boxes {
649 649 display: block;
650 650 }
651 651
652 652 //FORMS
653 653
654 654 .medium-inline,
655 655 input#description.medium-inline {
656 656 display: inline;
657 657 width: @medium-inline-input-width;
658 658 min-width: 100px;
659 659 }
660 660
661 661 select {
662 662 //reset
663 663 -webkit-appearance: none;
664 664 -moz-appearance: none;
665 665
666 666 display: inline-block;
667 667 height: 28px;
668 668 width: auto;
669 669 margin: 0 @padding @padding 0;
670 670 padding: 0 18px 0 8px;
671 671 line-height:1em;
672 672 font-size: @basefontsize;
673 673 border: @border-thickness solid @grey5;
674 674 border-radius: @border-radius;
675 675 background:white url("../images/dt-arrow-dn.png") no-repeat 100% 50%;
676 676 color: @grey4;
677 677 box-shadow: @button-shadow;
678 678
679 679 &:after {
680 680 content: "\00A0\25BE";
681 681 }
682 682
683 683 &:focus, &:hover {
684 684 outline: none;
685 685 border-color: @grey4;
686 686 color: @rcdarkblue;
687 687 }
688 688 }
689 689
690 690 option {
691 691 &:focus {
692 692 outline: none;
693 693 }
694 694 }
695 695
696 696 input,
697 697 textarea {
698 698 padding: @input-padding;
699 699 border: @input-border-thickness solid @border-highlight-color;
700 700 .border-radius (@border-radius);
701 701 font-family: @text-light;
702 702 font-size: @basefontsize;
703 703
704 704 &.input-sm {
705 705 padding: 5px;
706 706 }
707 707
708 708 &#description {
709 709 min-width: @input-description-minwidth;
710 710 min-height: 1em;
711 711 padding: 10px;
712 712 }
713 713 }
714 714
715 715 .field-sm {
716 716 input,
717 717 textarea {
718 718 padding: 5px;
719 719 }
720 720 }
721 721
722 722 textarea {
723 723 display: block;
724 724 clear: both;
725 725 width: 100%;
726 726 min-height: 100px;
727 727 margin-bottom: @padding;
728 728 .box-sizing(border-box);
729 729 overflow: auto;
730 730 }
731 731
732 732 label {
733 733 font-family: @text-light;
734 734 }
735 735
736 736 // GRAVATARS
737 737 // centers gravatar on username to the right
738 738
739 739 .gravatar {
740 740 display: inline;
741 741 min-width: 16px;
742 742 min-height: 16px;
743 743 margin: -5px 0;
744 744 padding: 0;
745 745 line-height: 1em;
746 746 box-sizing: content-box;
747 747 border-radius: 50%;
748 748
749 749 &.gravatar-large {
750 750 margin: -0.5em .25em -0.5em 0;
751 751 }
752 752
753 753 & + .user {
754 754 display: inline;
755 755 margin: 0;
756 756 padding: 0 0 0 .17em;
757 757 line-height: 1em;
758 758 }
759 759 }
760 760
761 761 .user-inline-data {
762 762 display: inline-block;
763 763 float: left;
764 764 padding-left: .5em;
765 765 line-height: 1.3em;
766 766 }
767 767
768 768 .rc-user { // gravatar + user wrapper
769 769 float: left;
770 770 position: relative;
771 771 min-width: 100px;
772 772 max-width: 200px;
773 773 min-height: (@gravatar-size + @border-thickness * 2); // account for border
774 774 display: block;
775 775 padding: 0 0 0 (@gravatar-size + @basefontsize/2 + @border-thickness * 2);
776 776
777 777
778 778 .gravatar {
779 779 display: block;
780 780 position: absolute;
781 781 top: 0;
782 782 left: 0;
783 783 min-width: @gravatar-size;
784 784 min-height: @gravatar-size;
785 785 margin: 0;
786 786 }
787 787
788 788 .user {
789 789 display: block;
790 790 max-width: 175px;
791 791 padding-top: 2px;
792 792 overflow: hidden;
793 793 text-overflow: ellipsis;
794 794 }
795 795 }
796 796
797 797 .gist-gravatar,
798 798 .journal_container {
799 799 .gravatar-large {
800 800 margin: 0 .5em -10px 0;
801 801 }
802 802 }
803 803
804 804
805 805 // ADMIN SETTINGS
806 806
807 807 // Tag Patterns
808 808 .tag_patterns {
809 809 .tag_input {
810 810 margin-bottom: @padding;
811 811 }
812 812 }
813 813
814 814 .locked_input {
815 815 position: relative;
816 816
817 817 input {
818 818 display: inline;
819 819 margin: 3px 5px 0px 0px;
820 820 }
821 821
822 822 br {
823 823 display: none;
824 824 }
825 825
826 826 .error-message {
827 827 float: left;
828 828 width: 100%;
829 829 }
830 830
831 831 .lock_input_button {
832 832 display: inline;
833 833 }
834 834
835 835 .help-block {
836 836 clear: both;
837 837 }
838 838 }
839 839
840 840 // Notifications
841 841
842 842 .notifications_buttons {
843 843 margin: 0 0 @space 0;
844 844 padding: 0;
845 845
846 846 .btn {
847 847 display: inline-block;
848 848 }
849 849 }
850 850
851 851 .notification-list {
852 852
853 853 div {
854 854 display: inline-block;
855 855 vertical-align: middle;
856 856 }
857 857
858 858 .container {
859 859 display: block;
860 860 margin: 0 0 @padding 0;
861 861 }
862 862
863 863 .delete-notifications {
864 864 margin-left: @padding;
865 865 text-align: right;
866 866 cursor: pointer;
867 867 }
868 868
869 869 .read-notifications {
870 870 margin-left: @padding/2;
871 871 text-align: right;
872 872 width: 35px;
873 873 cursor: pointer;
874 874 }
875 875
876 876 .icon-minus-sign {
877 877 color: @alert2;
878 878 }
879 879
880 880 .icon-ok-sign {
881 881 color: @alert1;
882 882 }
883 883 }
884 884
885 885 .user_settings {
886 886 float: left;
887 887 clear: both;
888 888 display: block;
889 889 width: 100%;
890 890
891 891 .gravatar_box {
892 892 margin-bottom: @padding;
893 893
894 894 &:after {
895 895 content: " ";
896 896 clear: both;
897 897 width: 100%;
898 898 }
899 899 }
900 900
901 901 .fields .field {
902 902 clear: both;
903 903 }
904 904 }
905 905
906 906 .advanced_settings {
907 907 margin-bottom: @space;
908 908
909 909 .help-block {
910 910 margin-left: 0;
911 911 }
912 912
913 913 button + .help-block {
914 914 margin-top: @padding;
915 915 }
916 916 }
917 917
918 918 // admin settings radio buttons and labels
919 919 .label-2 {
920 920 float: left;
921 921 width: @label2-width;
922 922
923 923 label {
924 924 color: @grey1;
925 925 }
926 926 }
927 927 .checkboxes {
928 928 float: left;
929 929 width: @checkboxes-width;
930 930 margin-bottom: @padding;
931 931
932 932 .checkbox {
933 933 width: 100%;
934 934
935 935 label {
936 936 margin: 0;
937 937 padding: 0;
938 938 }
939 939 }
940 940
941 941 .checkbox + .checkbox {
942 942 display: inline-block;
943 943 }
944 944
945 945 label {
946 946 margin-right: 1em;
947 947 }
948 948 }
949 949
950 950 // CHANGELOG
951 951 .container_header {
952 952 float: left;
953 953 display: block;
954 954 width: 100%;
955 955 margin: @padding 0 @padding;
956 956
957 957 #filter_changelog {
958 958 float: left;
959 959 margin-right: @padding;
960 960 }
961 961
962 962 .breadcrumbs_light {
963 963 display: inline-block;
964 964 }
965 965 }
966 966
967 967 .info_box {
968 968 float: right;
969 969 }
970 970
971 971
972 972
973 973 #graph_content{
974 974
975 975 // adjust for table headers so that graph renders properly
976 976 // #graph_nodes padding - table cell padding
977 977 padding-top: (@space - (@basefontsize * 2.4));
978 978
979 979 &.graph_full_width {
980 980 width: 100%;
981 981 max-width: 100%;
982 982 }
983 983 }
984 984
985 985 #graph {
986 .flag_status {
987 margin: 0;
988 }
989 986
990 987 .pagination-left {
991 988 float: left;
992 989 clear: both;
993 990 }
994 991
995 992 .log-container {
996 993 max-width: 345px;
997 994
998 995 .message{
999 996 max-width: 340px;
1000 997 }
1001 998 }
1002 999
1003 1000 .graph-col-wrapper {
1004 1001
1005 1002 #graph_nodes {
1006 1003 width: 100px;
1007 1004 position: absolute;
1008 1005 left: 70px;
1009 1006 z-index: -1;
1010 1007 }
1011 1008 }
1012 1009
1013 1010 .load-more-commits {
1014 1011 text-align: center;
1015 1012 }
1016 1013 .load-more-commits:hover {
1017 1014 background-color: @grey7;
1018 1015 }
1019 1016 .load-more-commits {
1020 1017 a {
1021 1018 display: block;
1022 1019 }
1023 1020 }
1024 1021 }
1025 1022
1026 1023 .obsolete-toggle {
1027 1024 line-height: 30px;
1028 1025 margin-left: -15px;
1029 1026 }
1030 1027
1031 1028 #rev_range_container, #rev_range_clear, #rev_range_more {
1032 1029 margin-top: -5px;
1033 1030 margin-bottom: -5px;
1034 1031 }
1035 1032
1036 1033 #filter_changelog {
1037 1034 float: left;
1038 1035 }
1039 1036
1040 1037
1041 1038 //--- THEME ------------------//
1042 1039
1043 1040 #logo {
1044 1041 float: left;
1045 1042 margin: 9px 0 0 0;
1046 1043
1047 1044 .header {
1048 1045 background-color: transparent;
1049 1046 }
1050 1047
1051 1048 a {
1052 1049 display: inline-block;
1053 1050 }
1054 1051
1055 1052 img {
1056 1053 height:30px;
1057 1054 }
1058 1055 }
1059 1056
1060 1057 .logo-wrapper {
1061 1058 float:left;
1062 1059 }
1063 1060
1064 1061 .branding {
1065 1062 float: left;
1066 1063 padding: 9px 2px;
1067 1064 line-height: 1em;
1068 1065 font-size: @navigation-fontsize;
1069 1066
1070 1067 a {
1071 1068 color: @grey5
1072 1069 }
1073 1070 @media screen and (max-width: 1200px) {
1074 1071 display: none;
1075 1072 }
1076 1073 }
1077 1074
1078 1075 img {
1079 1076 border: none;
1080 1077 outline: none;
1081 1078 }
1082 1079 user-profile-header
1083 1080 label {
1084 1081
1085 1082 input[type="checkbox"] {
1086 1083 margin-right: 1em;
1087 1084 }
1088 1085 input[type="radio"] {
1089 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 1090 .review-status {
1111 1091 &.under_review {
1112 1092 color: @alert3;
1113 1093 }
1114 1094 &.approved {
1115 1095 color: @alert1;
1116 1096 }
1117 1097 &.rejected,
1118 1098 &.forced_closed{
1119 1099 color: @alert2;
1120 1100 }
1121 1101 &.not_reviewed {
1122 1102 color: @grey5;
1123 1103 }
1124 1104 }
1125 1105
1126 1106 .review-status-under_review {
1127 1107 color: @alert3;
1128 1108 }
1129 1109 .status-tag-under_review {
1130 1110 border-color: @alert3;
1131 1111 }
1132 1112
1133 1113 .review-status-approved {
1134 1114 color: @alert1;
1135 1115 }
1136 1116 .status-tag-approved {
1137 1117 border-color: @alert1;
1138 1118 }
1139 1119
1140 1120 .review-status-rejected,
1141 1121 .review-status-forced_closed {
1142 1122 color: @alert2;
1143 1123 }
1144 1124 .status-tag-rejected,
1145 1125 .status-tag-forced_closed {
1146 1126 border-color: @alert2;
1147 1127 }
1148 1128
1149 1129 .review-status-not_reviewed {
1150 1130 color: @grey5;
1151 1131 }
1152 1132 .status-tag-not_reviewed {
1153 1133 border-color: @grey5;
1154 1134 }
1155 1135
1156 .flag_status_comment_box {
1157 margin: 5px 6px 0px 2px;
1158 }
1159 1136 .test_pattern_preview {
1160 1137 margin: @space 0;
1161 1138
1162 1139 p {
1163 1140 margin-bottom: 0;
1164 1141 border-bottom: @border-thickness solid @border-default-color;
1165 1142 color: @grey3;
1166 1143 }
1167 1144
1168 1145 .btn {
1169 1146 margin-bottom: @padding;
1170 1147 }
1171 1148 }
1172 1149 #test_pattern_result {
1173 1150 display: none;
1174 1151 &:extend(pre);
1175 1152 padding: .9em;
1176 1153 color: @grey3;
1177 1154 background-color: @grey7;
1178 1155 border-right: @border-thickness solid @border-default-color;
1179 1156 border-bottom: @border-thickness solid @border-default-color;
1180 1157 border-left: @border-thickness solid @border-default-color;
1181 1158 }
1182 1159
1183 1160 #repo_vcs_settings {
1184 1161 #inherit_overlay_vcs_default {
1185 1162 display: none;
1186 1163 }
1187 1164 #inherit_overlay_vcs_custom {
1188 1165 display: custom;
1189 1166 }
1190 1167 &.inherited {
1191 1168 #inherit_overlay_vcs_default {
1192 1169 display: block;
1193 1170 }
1194 1171 #inherit_overlay_vcs_custom {
1195 1172 display: none;
1196 1173 }
1197 1174 }
1198 1175 }
1199 1176
1200 1177 .issue-tracker-link {
1201 1178 color: @rcblue;
1202 1179 }
1203 1180
1204 1181 // Issue Tracker Table Show/Hide
1205 1182 #repo_issue_tracker {
1206 1183 #inherit_overlay {
1207 1184 display: none;
1208 1185 }
1209 1186 #custom_overlay {
1210 1187 display: custom;
1211 1188 }
1212 1189 &.inherited {
1213 1190 #inherit_overlay {
1214 1191 display: block;
1215 1192 }
1216 1193 #custom_overlay {
1217 1194 display: none;
1218 1195 }
1219 1196 }
1220 1197 }
1221 1198 table.issuetracker {
1222 1199 &.readonly {
1223 1200 tr, td {
1224 1201 color: @grey3;
1225 1202 }
1226 1203 }
1227 1204 .edit {
1228 1205 display: none;
1229 1206 }
1230 1207 .editopen {
1231 1208 .edit {
1232 1209 display: inline;
1233 1210 }
1234 1211 .entry {
1235 1212 display: none;
1236 1213 }
1237 1214 }
1238 1215 tr td.td-action {
1239 1216 min-width: 117px;
1240 1217 }
1241 1218 td input {
1242 1219 max-width: none;
1243 1220 min-width: 30px;
1244 1221 width: 80%;
1245 1222 }
1246 1223 .issuetracker_pref input {
1247 1224 width: 40%;
1248 1225 }
1249 1226 input.edit_issuetracker_update {
1250 1227 margin-right: 0;
1251 1228 width: auto;
1252 1229 }
1253 1230 }
1254 1231
1255 1232 table.integrations {
1256 1233 .td-icon {
1257 1234 width: 20px;
1258 1235 .integration-icon {
1259 1236 height: 20px;
1260 1237 width: 20px;
1261 1238 }
1262 1239 }
1263 1240 }
1264 1241
1265 1242 .integrations {
1266 1243 a.integration-box {
1267 1244 color: @text-color;
1268 1245 &:hover {
1269 1246 .panel {
1270 1247 background: #fbfbfb;
1271 1248 }
1272 1249 }
1273 1250 .integration-icon {
1274 1251 width: 30px;
1275 1252 height: 30px;
1276 1253 margin-right: 20px;
1277 1254 float: left;
1278 1255 }
1279 1256
1280 1257 .panel-body {
1281 1258 padding: 10px;
1282 1259 }
1283 1260 .panel {
1284 1261 margin-bottom: 10px;
1285 1262 }
1286 1263 h2 {
1287 1264 display: inline-block;
1288 1265 margin: 0;
1289 1266 min-width: 140px;
1290 1267 }
1291 1268 }
1292 1269 a.integration-box.dummy-integration {
1293 1270 color: @grey4
1294 1271 }
1295 1272 }
1296 1273
1297 1274 //Permissions Settings
1298 1275 #add_perm {
1299 1276 margin: 0 0 @padding;
1300 1277 cursor: pointer;
1301 1278 }
1302 1279
1303 1280 .perm_ac {
1304 1281 input {
1305 1282 width: 95%;
1306 1283 }
1307 1284 }
1308 1285
1309 1286 .autocomplete-suggestions {
1310 1287 width: auto !important; // overrides autocomplete.js
1311 1288 min-width: 278px;
1312 1289 margin: 0;
1313 1290 border: @border-thickness solid @grey5;
1314 1291 border-radius: @border-radius;
1315 1292 color: @grey2;
1316 1293 background-color: white;
1317 1294 }
1318 1295
1319 1296 .autocomplete-qfilter-suggestions {
1320 1297 width: auto !important; // overrides autocomplete.js
1321 1298 max-height: 100% !important;
1322 1299 min-width: 376px;
1323 1300 margin: 0;
1324 1301 border: @border-thickness solid @grey5;
1325 1302 color: @grey2;
1326 1303 background-color: white;
1327 1304 }
1328 1305
1329 1306 .autocomplete-selected {
1330 1307 background: #F0F0F0;
1331 1308 }
1332 1309
1333 1310 .ac-container-wrap {
1334 1311 margin: 0;
1335 1312 padding: 8px;
1336 1313 border-bottom: @border-thickness solid @grey5;
1337 1314 list-style-type: none;
1338 1315 cursor: pointer;
1339 1316
1340 1317 &:hover {
1341 1318 background-color: @grey7;
1342 1319 }
1343 1320
1344 1321 img {
1345 1322 height: @gravatar-size;
1346 1323 width: @gravatar-size;
1347 1324 margin-right: 1em;
1348 1325 }
1349 1326
1350 1327 strong {
1351 1328 font-weight: normal;
1352 1329 }
1353 1330 }
1354 1331
1355 1332 // Settings Dropdown
1356 1333 .user-menu .container {
1357 1334 padding: 0 4px;
1358 1335 margin: 0;
1359 1336 }
1360 1337
1361 1338 .user-menu .gravatar {
1362 1339 cursor: pointer;
1363 1340 }
1364 1341
1365 1342 .codeblock {
1366 1343 margin-bottom: @padding;
1367 1344 clear: both;
1368 1345
1369 1346 .stats {
1370 1347 overflow: hidden;
1371 1348 }
1372 1349
1373 1350 .message{
1374 1351 textarea{
1375 1352 margin: 0;
1376 1353 }
1377 1354 }
1378 1355
1379 1356 .code-header {
1380 1357 .stats {
1381 1358 line-height: 2em;
1382 1359
1383 1360 .revision_id {
1384 1361 margin-left: 0;
1385 1362 }
1386 1363 .buttons {
1387 1364 padding-right: 0;
1388 1365 }
1389 1366 }
1390 1367
1391 1368 .item{
1392 1369 margin-right: 0.5em;
1393 1370 }
1394 1371 }
1395 1372
1396 1373 #editor_container {
1397 1374 position: relative;
1398 1375 margin: @padding 10px;
1399 1376 }
1400 1377 }
1401 1378
1402 1379 #file_history_container {
1403 1380 display: none;
1404 1381 }
1405 1382
1406 1383 .file-history-inner {
1407 1384 margin-bottom: 10px;
1408 1385 }
1409 1386
1410 1387 // Pull Requests
1411 1388 .summary-details {
1412 1389 width: 72%;
1413 1390 }
1414 1391 .pr-summary {
1415 1392 border-bottom: @border-thickness solid @grey5;
1416 1393 margin-bottom: @space;
1417 1394 }
1418 1395 .reviewers-title {
1419 1396 width: 25%;
1420 1397 min-width: 200px;
1421 1398 }
1422 1399 .reviewers {
1423 1400 width: 25%;
1424 1401 min-width: 200px;
1425 1402 }
1426 1403 .reviewers ul li {
1427 1404 position: relative;
1428 1405 width: 100%;
1429 1406 padding-bottom: 8px;
1430 1407 list-style-type: none;
1431 1408 }
1432 1409
1433 1410 .reviewer_entry {
1434 1411 min-height: 55px;
1435 1412 }
1436 1413
1437 1414 .reviewers_member {
1438 1415 width: 100%;
1439 1416 overflow: auto;
1440 1417 }
1441 1418 .reviewer_reason {
1442 1419 padding-left: 20px;
1443 1420 line-height: 1.5em;
1444 1421 }
1445 1422 .reviewer_status {
1446 1423 display: inline-block;
1447 1424 vertical-align: top;
1448 1425 width: 25px;
1449 1426 min-width: 25px;
1450 1427 height: 1.2em;
1451 1428 margin-top: 3px;
1452 1429 line-height: 1em;
1453 1430 }
1454 1431
1455 1432 .reviewer_name {
1456 1433 display: inline-block;
1457 1434 max-width: 83%;
1458 1435 padding-right: 20px;
1459 1436 vertical-align: middle;
1460 1437 line-height: 1;
1461 1438
1462 1439 .rc-user {
1463 1440 min-width: 0;
1464 1441 margin: -2px 1em 0 0;
1465 1442 }
1466 1443
1467 1444 .reviewer {
1468 1445 float: left;
1469 1446 }
1470 1447 }
1471 1448
1472 1449 .reviewer_member_mandatory {
1473 1450 position: absolute;
1474 1451 left: 15px;
1475 1452 top: 8px;
1476 1453 width: 16px;
1477 1454 font-size: 11px;
1478 1455 margin: 0;
1479 1456 padding: 0;
1480 1457 color: black;
1481 1458 }
1482 1459
1483 1460 .reviewer_member_mandatory_remove,
1484 1461 .reviewer_member_remove {
1485 1462 position: absolute;
1486 1463 right: 0;
1487 1464 top: 0;
1488 1465 width: 16px;
1489 1466 margin-bottom: 10px;
1490 1467 padding: 0;
1491 1468 color: black;
1492 1469 }
1493 1470
1494 1471 .reviewer_member_mandatory_remove {
1495 1472 color: @grey4;
1496 1473 }
1497 1474
1498 1475 .reviewer_member_status {
1499 1476 margin-top: 5px;
1500 1477 }
1501 1478 .pr-summary #summary{
1502 1479 width: 100%;
1503 1480 }
1504 1481 .pr-summary .action_button:hover {
1505 1482 border: 0;
1506 1483 cursor: pointer;
1507 1484 }
1508 1485 .pr-details-title {
1509 1486 padding-bottom: 8px;
1510 1487 border-bottom: @border-thickness solid @grey5;
1511 1488
1512 1489 .action_button.disabled {
1513 1490 color: @grey4;
1514 1491 cursor: inherit;
1515 1492 }
1516 1493 .action_button {
1517 1494 color: @rcblue;
1518 1495 }
1519 1496 }
1520 1497 .pr-details-content {
1521 1498 margin-top: @textmargin;
1522 1499 margin-bottom: @textmargin;
1523 1500 }
1524 1501
1525 1502 .pr-reviewer-rules {
1526 1503 padding: 10px 0px 20px 0px;
1527 1504 }
1528 1505
1529 1506 .group_members {
1530 1507 margin-top: 0;
1531 1508 padding: 0;
1532 1509 list-style: outside none none;
1533 1510
1534 1511 img {
1535 1512 height: @gravatar-size;
1536 1513 width: @gravatar-size;
1537 1514 margin-right: .5em;
1538 1515 margin-left: 3px;
1539 1516 }
1540 1517
1541 1518 .to-delete {
1542 1519 .user {
1543 1520 text-decoration: line-through;
1544 1521 }
1545 1522 }
1546 1523 }
1547 1524
1548 1525 .compare_view_commits_title {
1549 1526 .disabled {
1550 1527 cursor: inherit;
1551 1528 &:hover{
1552 1529 background-color: inherit;
1553 1530 color: inherit;
1554 1531 }
1555 1532 }
1556 1533 }
1557 1534
1558 1535 .subtitle-compare {
1559 1536 margin: -15px 0px 0px 0px;
1560 1537 }
1561 1538
1562 1539 .comments-summary-td {
1563 1540 border-top: 1px dashed @grey5;
1564 1541 }
1565 1542
1566 1543 // new entry in group_members
1567 1544 .td-author-new-entry {
1568 1545 background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3);
1569 1546 }
1570 1547
1571 1548 .usergroup_member_remove {
1572 1549 width: 16px;
1573 1550 margin-bottom: 10px;
1574 1551 padding: 0;
1575 1552 color: black !important;
1576 1553 cursor: pointer;
1577 1554 }
1578 1555
1579 1556 .reviewer_ac .ac-input {
1580 1557 width: 92%;
1581 1558 margin-bottom: 1em;
1582 1559 }
1583 1560
1584 1561 .compare_view_commits tr{
1585 1562 height: 20px;
1586 1563 }
1587 1564 .compare_view_commits td {
1588 1565 vertical-align: top;
1589 1566 padding-top: 10px;
1590 1567 }
1591 1568 .compare_view_commits .author {
1592 1569 margin-left: 5px;
1593 1570 }
1594 1571
1595 1572 .compare_view_commits {
1596 1573 .color-a {
1597 1574 color: @alert1;
1598 1575 }
1599 1576
1600 1577 .color-c {
1601 1578 color: @color3;
1602 1579 }
1603 1580
1604 1581 .color-r {
1605 1582 color: @color5;
1606 1583 }
1607 1584
1608 1585 .color-a-bg {
1609 1586 background-color: @alert1;
1610 1587 }
1611 1588
1612 1589 .color-c-bg {
1613 1590 background-color: @alert3;
1614 1591 }
1615 1592
1616 1593 .color-r-bg {
1617 1594 background-color: @alert2;
1618 1595 }
1619 1596
1620 1597 .color-a-border {
1621 1598 border: 1px solid @alert1;
1622 1599 }
1623 1600
1624 1601 .color-c-border {
1625 1602 border: 1px solid @alert3;
1626 1603 }
1627 1604
1628 1605 .color-r-border {
1629 1606 border: 1px solid @alert2;
1630 1607 }
1631 1608
1632 1609 .commit-change-indicator {
1633 1610 width: 15px;
1634 1611 height: 15px;
1635 1612 position: relative;
1636 1613 left: 15px;
1637 1614 }
1638 1615
1639 1616 .commit-change-content {
1640 1617 text-align: center;
1641 1618 vertical-align: middle;
1642 1619 line-height: 15px;
1643 1620 }
1644 1621 }
1645 1622
1646 1623 .compare_view_filepath {
1647 1624 color: @grey1;
1648 1625 }
1649 1626
1650 1627 .show_more {
1651 1628 display: inline-block;
1652 1629 width: 0;
1653 1630 height: 0;
1654 1631 vertical-align: middle;
1655 1632 content: "";
1656 1633 border: 4px solid;
1657 1634 border-right-color: transparent;
1658 1635 border-bottom-color: transparent;
1659 1636 border-left-color: transparent;
1660 1637 font-size: 0;
1661 1638 }
1662 1639
1663 1640 .journal_more .show_more {
1664 1641 display: inline;
1665 1642
1666 1643 &:after {
1667 1644 content: none;
1668 1645 }
1669 1646 }
1670 1647
1671 1648 .compare_view_commits .collapse_commit:after {
1672 1649 cursor: pointer;
1673 1650 content: "\00A0\25B4";
1674 1651 margin-left: -3px;
1675 1652 font-size: 17px;
1676 1653 color: @grey4;
1677 1654 }
1678 1655
1679 1656 .diff_links {
1680 1657 margin-left: 8px;
1681 1658 }
1682 1659
1683 1660 #pull_request_overview {
1684 1661 div.ancestor {
1685 1662 margin: -33px 0;
1686 1663 }
1687 1664 }
1688 1665
1689 1666 div.ancestor {
1690 1667 line-height: 33px;
1691 1668 }
1692 1669
1693 1670 .cs_icon_td input[type="checkbox"] {
1694 1671 display: none;
1695 1672 }
1696 1673
1697 1674 .cs_icon_td .expand_file_icon:after {
1698 1675 cursor: pointer;
1699 1676 content: "\00A0\25B6";
1700 1677 font-size: 12px;
1701 1678 color: @grey4;
1702 1679 }
1703 1680
1704 1681 .cs_icon_td .collapse_file_icon:after {
1705 1682 cursor: pointer;
1706 1683 content: "\00A0\25BC";
1707 1684 font-size: 12px;
1708 1685 color: @grey4;
1709 1686 }
1710 1687
1711 1688 /*new binary
1712 1689 NEW_FILENODE = 1
1713 1690 DEL_FILENODE = 2
1714 1691 MOD_FILENODE = 3
1715 1692 RENAMED_FILENODE = 4
1716 1693 COPIED_FILENODE = 5
1717 1694 CHMOD_FILENODE = 6
1718 1695 BIN_FILENODE = 7
1719 1696 */
1720 1697 .cs_files_expand {
1721 1698 font-size: @basefontsize + 5px;
1722 1699 line-height: 1.8em;
1723 1700 float: right;
1724 1701 }
1725 1702
1726 1703 .cs_files_expand span{
1727 1704 color: @rcblue;
1728 1705 cursor: pointer;
1729 1706 }
1730 1707 .cs_files {
1731 1708 clear: both;
1732 1709 padding-bottom: @padding;
1733 1710
1734 1711 .cur_cs {
1735 1712 margin: 10px 2px;
1736 1713 font-weight: bold;
1737 1714 }
1738 1715
1739 1716 .node {
1740 1717 float: left;
1741 1718 }
1742 1719
1743 1720 .changes {
1744 1721 float: right;
1745 1722 color: white;
1746 1723 font-size: @basefontsize - 4px;
1747 1724 margin-top: 4px;
1748 1725 opacity: 0.6;
1749 1726 filter: Alpha(opacity=60); /* IE8 and earlier */
1750 1727
1751 1728 .added {
1752 1729 background-color: @alert1;
1753 1730 float: left;
1754 1731 text-align: center;
1755 1732 }
1756 1733
1757 1734 .deleted {
1758 1735 background-color: @alert2;
1759 1736 float: left;
1760 1737 text-align: center;
1761 1738 }
1762 1739
1763 1740 .bin {
1764 1741 background-color: @alert1;
1765 1742 text-align: center;
1766 1743 }
1767 1744
1768 1745 /*new binary*/
1769 1746 .bin.bin1 {
1770 1747 background-color: @alert1;
1771 1748 text-align: center;
1772 1749 }
1773 1750
1774 1751 /*deleted binary*/
1775 1752 .bin.bin2 {
1776 1753 background-color: @alert2;
1777 1754 text-align: center;
1778 1755 }
1779 1756
1780 1757 /*mod binary*/
1781 1758 .bin.bin3 {
1782 1759 background-color: @grey2;
1783 1760 text-align: center;
1784 1761 }
1785 1762
1786 1763 /*rename file*/
1787 1764 .bin.bin4 {
1788 1765 background-color: @alert4;
1789 1766 text-align: center;
1790 1767 }
1791 1768
1792 1769 /*copied file*/
1793 1770 .bin.bin5 {
1794 1771 background-color: @alert4;
1795 1772 text-align: center;
1796 1773 }
1797 1774
1798 1775 /*chmod file*/
1799 1776 .bin.bin6 {
1800 1777 background-color: @grey2;
1801 1778 text-align: center;
1802 1779 }
1803 1780 }
1804 1781 }
1805 1782
1806 1783 .cs_files .cs_added, .cs_files .cs_A,
1807 1784 .cs_files .cs_added, .cs_files .cs_M,
1808 1785 .cs_files .cs_added, .cs_files .cs_D {
1809 1786 height: 16px;
1810 1787 padding-right: 10px;
1811 1788 margin-top: 7px;
1812 1789 text-align: left;
1813 1790 }
1814 1791
1815 1792 .cs_icon_td {
1816 1793 min-width: 16px;
1817 1794 width: 16px;
1818 1795 }
1819 1796
1820 1797 .pull-request-merge {
1821 1798 border: 1px solid @grey5;
1822 1799 padding: 10px 0px 20px;
1823 1800 margin-top: 10px;
1824 1801 margin-bottom: 20px;
1825 1802 }
1826 1803
1827 1804 .pull-request-merge ul {
1828 1805 padding: 0px 0px;
1829 1806 }
1830 1807
1831 1808 .pull-request-merge li {
1832 1809 list-style-type: none;
1833 1810 }
1834 1811
1835 1812 .pull-request-merge .pull-request-wrap {
1836 1813 height: auto;
1837 1814 padding: 0px 0px;
1838 1815 text-align: right;
1839 1816 }
1840 1817
1841 1818 .pull-request-merge span {
1842 1819 margin-right: 5px;
1843 1820 }
1844 1821
1845 1822 .pull-request-merge-actions {
1846 1823 min-height: 30px;
1847 1824 padding: 0px 0px;
1848 1825 }
1849 1826
1850 1827 .pull-request-merge-info {
1851 1828 padding: 0px 5px 5px 0px;
1852 1829 }
1853 1830
1854 1831 .merge-status {
1855 1832 margin-right: 5px;
1856 1833 }
1857 1834
1858 1835 .merge-message {
1859 1836 font-size: 1.2em
1860 1837 }
1861 1838
1862 1839 .merge-message.success i,
1863 1840 .merge-icon.success i {
1864 1841 color:@alert1;
1865 1842 }
1866 1843
1867 1844 .merge-message.warning i,
1868 1845 .merge-icon.warning i {
1869 1846 color: @alert3;
1870 1847 }
1871 1848
1872 1849 .merge-message.error i,
1873 1850 .merge-icon.error i {
1874 1851 color:@alert2;
1875 1852 }
1876 1853
1877 1854 .pr-versions {
1878 1855 font-size: 1.1em;
1879 1856
1880 1857 table {
1881 1858 padding: 0px 5px;
1882 1859 }
1883 1860
1884 1861 td {
1885 1862 line-height: 15px;
1886 1863 }
1887 1864
1888 .flag_status {
1889 margin: 0;
1890 }
1891
1892 1865 .compare-radio-button {
1893 1866 position: relative;
1894 1867 top: -3px;
1895 1868 }
1896 1869 }
1897 1870
1898 1871
1899 1872 #close_pull_request {
1900 1873 margin-right: 0px;
1901 1874 }
1902 1875
1903 1876 .empty_data {
1904 1877 color: @grey4;
1905 1878 }
1906 1879
1907 1880 #changeset_compare_view_content {
1908 1881 clear: both;
1909 1882 width: 100%;
1910 1883 box-sizing: border-box;
1911 1884 .border-radius(@border-radius);
1912 1885
1913 1886 .help-block {
1914 1887 margin: @padding 0;
1915 1888 color: @text-color;
1916 1889 &.pre-formatting {
1917 1890 white-space: pre;
1918 1891 }
1919 1892 }
1920 1893
1921 1894 .empty_data {
1922 1895 margin: @padding 0;
1923 1896 }
1924 1897
1925 1898 .alert {
1926 1899 margin-bottom: @space;
1927 1900 }
1928 1901 }
1929 1902
1930 1903 .table_disp {
1931 1904 .status {
1932 1905 width: auto;
1933
1934 .flag_status {
1935 float: left;
1936 }
1937 1906 }
1938 1907 }
1939 1908
1940 1909
1941 1910 .creation_in_progress {
1942 1911 color: @grey4
1943 1912 }
1944 1913
1945 1914 .status_box_menu {
1946 1915 margin: 0;
1947 1916 }
1948 1917
1949 1918 .notification-table{
1950 1919 margin-bottom: @space;
1951 1920 display: table;
1952 1921 width: 100%;
1953 1922
1954 1923 .container{
1955 1924 display: table-row;
1956 1925
1957 1926 .notification-header{
1958 1927 border-bottom: @border-thickness solid @border-default-color;
1959 1928 }
1960 1929
1961 1930 .notification-subject{
1962 1931 display: table-cell;
1963 1932 }
1964 1933 }
1965 1934 }
1966 1935
1967 1936 // Notifications
1968 1937 .notification-header{
1969 1938 display: table;
1970 1939 width: 100%;
1971 1940 padding: floor(@basefontsize/2) 0;
1972 1941 line-height: 1em;
1973 1942
1974 1943 .desc, .delete-notifications, .read-notifications{
1975 1944 display: table-cell;
1976 1945 text-align: left;
1977 1946 }
1978 1947
1979 1948 .desc{
1980 1949 width: 1163px;
1981 1950 }
1982 1951
1983 1952 .delete-notifications, .read-notifications{
1984 1953 width: 35px;
1985 1954 min-width: 35px; //fixes when only one button is displayed
1986 1955 }
1987 1956 }
1988 1957
1989 1958 .notification-body {
1990 1959 .markdown-block,
1991 1960 .rst-block {
1992 1961 padding: @padding 0;
1993 1962 }
1994 1963
1995 1964 .notification-subject {
1996 1965 padding: @textmargin 0;
1997 1966 border-bottom: @border-thickness solid @border-default-color;
1998 1967 }
1999 1968 }
2000 1969
2001 1970
2002 1971 .notifications_buttons{
2003 1972 float: right;
2004 1973 }
2005 1974
2006 1975 #notification-status{
2007 1976 display: inline;
2008 1977 }
2009 1978
2010 1979 // Repositories
2011 1980
2012 1981 #summary.fields{
2013 1982 display: table;
2014 1983
2015 1984 .field{
2016 1985 display: table-row;
2017 1986
2018 1987 .label-summary{
2019 1988 display: table-cell;
2020 1989 min-width: @label-summary-minwidth;
2021 1990 padding-top: @padding/2;
2022 1991 padding-bottom: @padding/2;
2023 1992 padding-right: @padding/2;
2024 1993 }
2025 1994
2026 1995 .input{
2027 1996 display: table-cell;
2028 1997 padding: @padding/2;
2029 1998
2030 1999 input{
2031 2000 min-width: 29em;
2032 2001 padding: @padding/4;
2033 2002 }
2034 2003 }
2035 2004 .statistics, .downloads{
2036 2005 .disabled{
2037 2006 color: @grey4;
2038 2007 }
2039 2008 }
2040 2009 }
2041 2010 }
2042 2011
2043 2012 #summary{
2044 2013 width: 70%;
2045 2014 }
2046 2015
2047 2016
2048 2017 // Journal
2049 2018 .journal.title {
2050 2019 h5 {
2051 2020 float: left;
2052 2021 margin: 0;
2053 2022 width: 70%;
2054 2023 }
2055 2024
2056 2025 ul {
2057 2026 float: right;
2058 2027 display: inline-block;
2059 2028 margin: 0;
2060 2029 width: 30%;
2061 2030 text-align: right;
2062 2031
2063 2032 li {
2064 2033 display: inline;
2065 2034 font-size: @journal-fontsize;
2066 2035 line-height: 1em;
2067 2036
2068 2037 list-style-type: none;
2069 2038 }
2070 2039 }
2071 2040 }
2072 2041
2073 2042 .filterexample {
2074 2043 position: absolute;
2075 2044 top: 95px;
2076 2045 left: @contentpadding;
2077 2046 color: @rcblue;
2078 2047 font-size: 11px;
2079 2048 font-family: @text-regular;
2080 2049 cursor: help;
2081 2050
2082 2051 &:hover {
2083 2052 color: @rcdarkblue;
2084 2053 }
2085 2054
2086 2055 @media (max-width:768px) {
2087 2056 position: relative;
2088 2057 top: auto;
2089 2058 left: auto;
2090 2059 display: block;
2091 2060 }
2092 2061 }
2093 2062
2094 2063
2095 2064 #journal{
2096 2065 margin-bottom: @space;
2097 2066
2098 2067 .journal_day{
2099 2068 margin-bottom: @textmargin/2;
2100 2069 padding-bottom: @textmargin/2;
2101 2070 font-size: @journal-fontsize;
2102 2071 border-bottom: @border-thickness solid @border-default-color;
2103 2072 }
2104 2073
2105 2074 .journal_container{
2106 2075 margin-bottom: @space;
2107 2076
2108 2077 .journal_user{
2109 2078 display: inline-block;
2110 2079 }
2111 2080 .journal_action_container{
2112 2081 display: block;
2113 2082 margin-top: @textmargin;
2114 2083
2115 2084 div{
2116 2085 display: inline;
2117 2086 }
2118 2087
2119 2088 div.journal_action_params{
2120 2089 display: block;
2121 2090 }
2122 2091
2123 2092 div.journal_repo:after{
2124 2093 content: "\A";
2125 2094 white-space: pre;
2126 2095 }
2127 2096
2128 2097 div.date{
2129 2098 display: block;
2130 2099 margin-bottom: @textmargin;
2131 2100 }
2132 2101 }
2133 2102 }
2134 2103 }
2135 2104
2136 2105 // Files
2137 2106 .edit-file-title {
2138 2107 font-size: 16px;
2139 2108
2140 2109 .title-heading {
2141 2110 padding: 2px;
2142 2111 }
2143 2112 }
2144 2113
2145 2114 .edit-file-fieldset {
2146 2115 margin: @sidebarpadding 0;
2147 2116
2148 2117 .fieldset {
2149 2118 .left-label {
2150 2119 width: 13%;
2151 2120 }
2152 2121 .right-content {
2153 2122 width: 87%;
2154 2123 max-width: 100%;
2155 2124 }
2156 2125 .filename-label {
2157 2126 margin-top: 13px;
2158 2127 }
2159 2128 .commit-message-label {
2160 2129 margin-top: 4px;
2161 2130 }
2162 2131 .file-upload-input {
2163 2132 input {
2164 2133 display: none;
2165 2134 }
2166 2135 margin-top: 10px;
2167 2136 }
2168 2137 .file-upload-label {
2169 2138 margin-top: 10px;
2170 2139 }
2171 2140 p {
2172 2141 margin-top: 5px;
2173 2142 }
2174 2143
2175 2144 }
2176 2145 .custom-path-link {
2177 2146 margin-left: 5px;
2178 2147 }
2179 2148 #commit {
2180 2149 resize: vertical;
2181 2150 }
2182 2151 }
2183 2152
2184 2153 .delete-file-preview {
2185 2154 max-height: 250px;
2186 2155 }
2187 2156
2188 2157 .new-file,
2189 2158 #filter_activate,
2190 2159 #filter_deactivate {
2191 2160 float: right;
2192 2161 margin: 0 0 0 10px;
2193 2162 }
2194 2163
2195 2164 .file-upload-transaction-wrapper {
2196 2165 margin-top: 57px;
2197 2166 clear: both;
2198 2167 }
2199 2168
2200 2169 .file-upload-transaction-wrapper .error {
2201 2170 color: @color5;
2202 2171 }
2203 2172
2204 2173 .file-upload-transaction {
2205 2174 min-height: 200px;
2206 2175 padding: 54px;
2207 2176 border: 1px solid @grey5;
2208 2177 text-align: center;
2209 2178 clear: both;
2210 2179 }
2211 2180
2212 2181 .file-upload-transaction i {
2213 2182 font-size: 48px
2214 2183 }
2215 2184
2216 2185 h3.files_location{
2217 2186 line-height: 2.4em;
2218 2187 }
2219 2188
2220 2189 .browser-nav {
2221 2190 width: 100%;
2222 2191 display: table;
2223 2192 margin-bottom: 20px;
2224 2193
2225 2194 .info_box {
2226 2195 float: left;
2227 2196 display: inline-table;
2228 2197 height: 2.5em;
2229 2198
2230 2199 .browser-cur-rev, .info_box_elem {
2231 2200 display: table-cell;
2232 2201 vertical-align: middle;
2233 2202 }
2234 2203
2235 2204 .drop-menu {
2236 2205 margin: 0 10px;
2237 2206 }
2238 2207
2239 2208 .info_box_elem {
2240 2209 border-top: @border-thickness solid @grey5;
2241 2210 border-bottom: @border-thickness solid @grey5;
2242 2211 box-shadow: @button-shadow;
2243 2212
2244 2213 #at_rev, a {
2245 2214 padding: 0.6em 0.4em;
2246 2215 margin: 0;
2247 2216 .box-shadow(none);
2248 2217 border: 0;
2249 2218 height: 12px;
2250 2219 color: @grey2;
2251 2220 }
2252 2221
2253 2222 input#at_rev {
2254 2223 max-width: 50px;
2255 2224 text-align: center;
2256 2225 }
2257 2226
2258 2227 &.previous {
2259 2228 border: @border-thickness solid @grey5;
2260 2229 border-top-left-radius: @border-radius;
2261 2230 border-bottom-left-radius: @border-radius;
2262 2231
2263 2232 &:hover {
2264 2233 border-color: @grey4;
2265 2234 }
2266 2235
2267 2236 .disabled {
2268 2237 color: @grey5;
2269 2238 cursor: not-allowed;
2270 2239 opacity: 0.5;
2271 2240 }
2272 2241 }
2273 2242
2274 2243 &.next {
2275 2244 border: @border-thickness solid @grey5;
2276 2245 border-top-right-radius: @border-radius;
2277 2246 border-bottom-right-radius: @border-radius;
2278 2247
2279 2248 &:hover {
2280 2249 border-color: @grey4;
2281 2250 }
2282 2251
2283 2252 .disabled {
2284 2253 color: @grey5;
2285 2254 cursor: not-allowed;
2286 2255 opacity: 0.5;
2287 2256 }
2288 2257 }
2289 2258 }
2290 2259
2291 2260 .browser-cur-rev {
2292 2261
2293 2262 span{
2294 2263 margin: 0;
2295 2264 color: @rcblue;
2296 2265 height: 12px;
2297 2266 display: inline-block;
2298 2267 padding: 0.7em 1em ;
2299 2268 border: @border-thickness solid @rcblue;
2300 2269 margin-right: @padding;
2301 2270 }
2302 2271 }
2303 2272
2304 2273 }
2305 2274
2306 2275 .select-index-number {
2307 2276 margin: 0 0 0 20px;
2308 2277 color: @grey3;
2309 2278 }
2310 2279
2311 2280 .search_activate {
2312 2281 display: table-cell;
2313 2282 vertical-align: middle;
2314 2283
2315 2284 input, label{
2316 2285 margin: 0;
2317 2286 padding: 0;
2318 2287 }
2319 2288
2320 2289 input{
2321 2290 margin-left: @textmargin;
2322 2291 }
2323 2292
2324 2293 }
2325 2294 }
2326 2295
2327 2296 .browser-cur-rev{
2328 2297 margin-bottom: @textmargin;
2329 2298 }
2330 2299
2331 2300 #node_filter_box_loading{
2332 2301 .info_text;
2333 2302 }
2334 2303
2335 2304 .browser-search {
2336 2305 margin: -25px 0px 5px 0px;
2337 2306 }
2338 2307
2339 2308 .files-quick-filter {
2340 2309 float: right;
2341 2310 width: 180px;
2342 2311 position: relative;
2343 2312 }
2344 2313
2345 2314 .files-filter-box {
2346 2315 display: flex;
2347 2316 padding: 0px;
2348 2317 border-radius: 3px;
2349 2318 margin-bottom: 0;
2350 2319
2351 2320 a {
2352 2321 border: none !important;
2353 2322 }
2354 2323
2355 2324 li {
2356 2325 list-style-type: none
2357 2326 }
2358 2327 }
2359 2328
2360 2329 .files-filter-box-path {
2361 2330 line-height: 33px;
2362 2331 padding: 0;
2363 2332 width: 20px;
2364 2333 position: absolute;
2365 2334 z-index: 11;
2366 2335 left: 5px;
2367 2336 }
2368 2337
2369 2338 .files-filter-box-input {
2370 2339 margin-right: 0;
2371 2340
2372 2341 input {
2373 2342 border: 1px solid @white;
2374 2343 padding-left: 25px;
2375 2344 width: 145px;
2376 2345
2377 2346 &:hover {
2378 2347 border-color: @grey6;
2379 2348 }
2380 2349
2381 2350 &:focus {
2382 2351 border-color: @grey5;
2383 2352 }
2384 2353 }
2385 2354 }
2386 2355
2387 2356 .browser-result{
2388 2357 td a{
2389 2358 margin-left: 0.5em;
2390 2359 display: inline-block;
2391 2360
2392 2361 em {
2393 2362 font-weight: @text-bold-weight;
2394 2363 font-family: @text-bold;
2395 2364 }
2396 2365 }
2397 2366 }
2398 2367
2399 2368 .browser-highlight{
2400 2369 background-color: @grey5-alpha;
2401 2370 }
2402 2371
2403 2372
2404 2373 .edit-file-fieldset #location,
2405 2374 .edit-file-fieldset #filename {
2406 2375 display: flex;
2407 2376 width: -moz-available; /* WebKit-based browsers will ignore this. */
2408 2377 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2409 2378 width: fill-available;
2410 2379 border: 0;
2411 2380 }
2412 2381
2413 2382 .path-items {
2414 2383 display: flex;
2415 2384 padding: 0;
2416 2385 border: 1px solid #eeeeee;
2417 2386 width: 100%;
2418 2387 float: left;
2419 2388
2420 2389 .breadcrumb-path {
2421 2390 line-height: 30px;
2422 2391 padding: 0 4px;
2423 2392 white-space: nowrap;
2424 2393 }
2425 2394
2426 2395 .location-path {
2427 2396 width: -moz-available; /* WebKit-based browsers will ignore this. */
2428 2397 width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
2429 2398 width: fill-available;
2430 2399
2431 2400 .file-name-input {
2432 2401 padding: 0.5em 0;
2433 2402 }
2434 2403
2435 2404 }
2436 2405
2437 2406 ul {
2438 2407 display: flex;
2439 2408 margin: 0;
2440 2409 padding: 0;
2441 2410 width: 100%;
2442 2411 }
2443 2412
2444 2413 li {
2445 2414 list-style-type: none;
2446 2415 }
2447 2416
2448 2417 }
2449 2418
2450 2419 .editor-items {
2451 2420 height: 40px;
2452 2421 margin: 10px 0 -17px 10px;
2453 2422
2454 2423 .editor-action {
2455 2424 cursor: pointer;
2456 2425 }
2457 2426
2458 2427 .editor-action.active {
2459 2428 border-bottom: 2px solid #5C5C5C;
2460 2429 }
2461 2430
2462 2431 li {
2463 2432 list-style-type: none;
2464 2433 }
2465 2434 }
2466 2435
2467 2436 .edit-file-fieldset .message textarea {
2468 2437 border: 1px solid #eeeeee;
2469 2438 }
2470 2439
2471 2440 #files_data .codeblock {
2472 2441 background-color: #F5F5F5;
2473 2442 }
2474 2443
2475 2444 #editor_preview {
2476 2445 background: white;
2477 2446 }
2478 2447
2479 2448 .show-editor {
2480 2449 padding: 10px;
2481 2450 background-color: white;
2482 2451
2483 2452 }
2484 2453
2485 2454 .show-preview {
2486 2455 padding: 10px;
2487 2456 background-color: white;
2488 2457 border-left: 1px solid #eeeeee;
2489 2458 }
2490 2459 // quick filter
2491 2460 .grid-quick-filter {
2492 2461 float: right;
2493 2462 position: relative;
2494 2463 }
2495 2464
2496 2465 .grid-filter-box {
2497 2466 display: flex;
2498 2467 padding: 0px;
2499 2468 border-radius: 3px;
2500 2469 margin-bottom: 0;
2501 2470
2502 2471 a {
2503 2472 border: none !important;
2504 2473 }
2505 2474
2506 2475 li {
2507 2476 list-style-type: none
2508 2477 }
2509 2478 }
2510 2479
2511 2480 .grid-filter-box-icon {
2512 2481 line-height: 33px;
2513 2482 padding: 0;
2514 2483 width: 20px;
2515 2484 position: absolute;
2516 2485 z-index: 11;
2517 2486 left: 5px;
2518 2487 }
2519 2488
2520 2489 .grid-filter-box-input {
2521 2490 margin-right: 0;
2522 2491
2523 2492 input {
2524 2493 border: 1px solid @white;
2525 2494 padding-left: 25px;
2526 2495 width: 145px;
2527 2496
2528 2497 &:hover {
2529 2498 border-color: @grey6;
2530 2499 }
2531 2500
2532 2501 &:focus {
2533 2502 border-color: @grey5;
2534 2503 }
2535 2504 }
2536 2505 }
2537 2506
2538 2507
2539 2508
2540 2509 // Search
2541 2510
2542 2511 .search-form{
2543 2512 #q {
2544 2513 width: @search-form-width;
2545 2514 }
2546 2515 .fields{
2547 2516 margin: 0 0 @space;
2548 2517 }
2549 2518
2550 2519 label{
2551 2520 display: inline-block;
2552 2521 margin-right: @textmargin;
2553 2522 padding-top: 0.25em;
2554 2523 }
2555 2524
2556 2525
2557 2526 .results{
2558 2527 clear: both;
2559 2528 margin: 0 0 @padding;
2560 2529 }
2561 2530
2562 2531 .search-tags {
2563 2532 padding: 5px 0;
2564 2533 }
2565 2534 }
2566 2535
2567 2536 div.search-feedback-items {
2568 2537 display: inline-block;
2569 2538 }
2570 2539
2571 2540 div.search-code-body {
2572 2541 background-color: #ffffff; padding: 5px 0 5px 10px;
2573 2542 pre {
2574 2543 .match { background-color: #faffa6;}
2575 2544 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
2576 2545 }
2577 2546 }
2578 2547
2579 2548 .expand_commit.search {
2580 2549 .show_more.open {
2581 2550 height: auto;
2582 2551 max-height: none;
2583 2552 }
2584 2553 }
2585 2554
2586 2555 .search-results {
2587 2556
2588 2557 h2 {
2589 2558 margin-bottom: 0;
2590 2559 }
2591 2560 .codeblock {
2592 2561 border: none;
2593 2562 background: transparent;
2594 2563 }
2595 2564
2596 2565 .codeblock-header {
2597 2566 border: none;
2598 2567 background: transparent;
2599 2568 }
2600 2569
2601 2570 .code-body {
2602 2571 border: @border-thickness solid @grey6;
2603 2572 .border-radius(@border-radius);
2604 2573 }
2605 2574
2606 2575 .td-commit {
2607 2576 &:extend(pre);
2608 2577 border-bottom: @border-thickness solid @border-default-color;
2609 2578 }
2610 2579
2611 2580 .message {
2612 2581 height: auto;
2613 2582 max-width: 350px;
2614 2583 white-space: normal;
2615 2584 text-overflow: initial;
2616 2585 overflow: visible;
2617 2586
2618 2587 .match { background-color: #faffa6;}
2619 2588 .break { background-color: #DDE7EF; width: 100%; color: #747474; display: block; }
2620 2589 }
2621 2590
2622 2591 .path {
2623 2592 border-bottom: none !important;
2624 2593 border-left: 1px solid @grey6 !important;
2625 2594 border-right: 1px solid @grey6 !important;
2626 2595 }
2627 2596 }
2628 2597
2629 2598 table.rctable td.td-search-results div {
2630 2599 max-width: 100%;
2631 2600 }
2632 2601
2633 2602 #tip-box, .tip-box{
2634 2603 padding: @menupadding/2;
2635 2604 display: block;
2636 2605 border: @border-thickness solid @border-highlight-color;
2637 2606 .border-radius(@border-radius);
2638 2607 background-color: white;
2639 2608 z-index: 99;
2640 2609 white-space: pre-wrap;
2641 2610 }
2642 2611
2643 2612 #linktt {
2644 2613 width: 79px;
2645 2614 }
2646 2615
2647 2616 #help_kb .modal-content{
2648 2617 max-width: 750px;
2649 2618 margin: 10% auto;
2650 2619
2651 2620 table{
2652 2621 td,th{
2653 2622 border-bottom: none;
2654 2623 line-height: 2.5em;
2655 2624 }
2656 2625 th{
2657 2626 padding-bottom: @textmargin/2;
2658 2627 }
2659 2628 td.keys{
2660 2629 text-align: center;
2661 2630 }
2662 2631 }
2663 2632
2664 2633 .block-left{
2665 2634 width: 45%;
2666 2635 margin-right: 5%;
2667 2636 }
2668 2637 .modal-footer{
2669 2638 clear: both;
2670 2639 }
2671 2640 .key.tag{
2672 2641 padding: 0.5em;
2673 2642 background-color: @rcblue;
2674 2643 color: white;
2675 2644 border-color: @rcblue;
2676 2645 .box-shadow(none);
2677 2646 }
2678 2647 }
2679 2648
2680 2649
2681 2650
2682 2651 //--- IMPORTS FOR REFACTORED STYLES ------------------//
2683 2652
2684 2653 @import 'statistics-graph';
2685 2654 @import 'tables';
2686 2655 @import 'forms';
2687 2656 @import 'diff';
2688 2657 @import 'summary';
2689 2658 @import 'navigation';
2690 2659
2691 2660 //--- SHOW/HIDE SECTIONS --//
2692 2661
2693 2662 .btn-collapse {
2694 2663 float: right;
2695 2664 text-align: right;
2696 2665 font-family: @text-light;
2697 2666 font-size: @basefontsize;
2698 2667 cursor: pointer;
2699 2668 border: none;
2700 2669 color: @rcblue;
2701 2670 }
2702 2671
2703 2672 table.rctable,
2704 2673 table.dataTable {
2705 2674 .btn-collapse {
2706 2675 float: right;
2707 2676 text-align: right;
2708 2677 }
2709 2678 }
2710 2679
2711 2680 table.rctable {
2712 2681 &.permissions {
2713 2682
2714 2683 th.td-owner {
2715 2684 padding: 0;
2716 2685 }
2717 2686
2718 2687 th {
2719 2688 font-weight: normal;
2720 2689 padding: 0 5px;
2721 2690 }
2722 2691
2723 2692 }
2724 2693 }
2725 2694
2726 2695
2727 2696 // TODO: johbo: Fix for IE10, this avoids that we see a border
2728 2697 // and padding around checkboxes and radio boxes. Move to the right place,
2729 2698 // or better: Remove this once we did the form refactoring.
2730 2699 input[type=checkbox],
2731 2700 input[type=radio] {
2732 2701 padding: 0;
2733 2702 border: none;
2734 2703 }
2735 2704
2736 2705 .toggle-ajax-spinner{
2737 2706 height: 16px;
2738 2707 width: 16px;
2739 2708 }
2740 2709
2741 2710
2742 2711 .markup-form .clearfix {
2743 2712 .border-radius(@border-radius);
2744 2713 margin: 0px;
2745 2714 }
2746 2715
2747 2716 .markup-form-area {
2748 2717 padding: 8px 12px;
2749 2718 border: 1px solid @grey4;
2750 2719 .border-radius(@border-radius);
2751 2720 }
2752 2721
2753 2722 .markup-form-area-header .nav-links {
2754 2723 display: flex;
2755 2724 flex-flow: row wrap;
2756 2725 -webkit-flex-flow: row wrap;
2757 2726 width: 100%;
2758 2727 }
2759 2728
2760 2729 .markup-form-area-footer {
2761 2730 display: flex;
2762 2731 }
2763 2732
2764 2733 .markup-form-area-footer .toolbar {
2765 2734
2766 2735 }
2767 2736
2768 2737 // markup Form
2769 2738 div.markup-form {
2770 2739 margin-top: 20px;
2771 2740 }
2772 2741
2773 2742 .markup-form strong {
2774 2743 display: block;
2775 2744 margin-bottom: 15px;
2776 2745 }
2777 2746
2778 2747 .markup-form textarea {
2779 2748 width: 100%;
2780 2749 height: 100px;
2781 2750 font-family: @text-monospace;
2782 2751 }
2783 2752
2784 2753 form.markup-form {
2785 2754 margin-top: 10px;
2786 2755 margin-left: 10px;
2787 2756 }
2788 2757
2789 2758 .markup-form .comment-block-ta,
2790 2759 .markup-form .preview-box {
2791 2760 .border-radius(@border-radius);
2792 2761 .box-sizing(border-box);
2793 2762 background-color: white;
2794 2763 }
2795 2764
2796 2765 .markup-form .preview-box.unloaded {
2797 2766 height: 50px;
2798 2767 text-align: center;
2799 2768 padding: 20px;
2800 2769 background-color: white;
2801 2770 }
2802 2771
2803 2772
2804 2773 .dropzone-wrapper {
2805 2774 border: 1px solid @grey5;
2806 2775 padding: 20px;
2807 2776 }
2808 2777
2809 2778 .dropzone,
2810 2779 .dropzone-pure {
2811 2780 border: 2px dashed @grey5;
2812 2781 border-radius: 5px;
2813 2782 background: white;
2814 2783 min-height: 200px;
2815 2784 padding: 54px;
2816 2785
2817 2786 .dz-message {
2818 2787 font-weight: 700;
2819 2788 text-align: center;
2820 2789 margin: 2em 0;
2821 2790 }
2822 2791
2823 2792 }
2824 2793
2825 2794 .dz-preview {
2826 2795 margin: 10px 0 !important;
2827 2796 position: relative;
2828 2797 vertical-align: top;
2829 2798 padding: 10px;
2830 2799 border-bottom: 1px solid @grey5;
2831 2800 }
2832 2801
2833 2802 .dz-filename {
2834 2803 font-weight: 700;
2835 2804 float:left;
2836 2805 }
2837 2806
2838 2807 .dz-sending {
2839 2808 float: right;
2840 2809 }
2841 2810
2842 2811 .dz-response {
2843 2812 clear:both
2844 2813 }
2845 2814
2846 2815 .dz-filename-size {
2847 2816 float:right
2848 2817 }
2849 2818
2850 2819 .dz-error-message {
2851 2820 color: @alert2;
2852 2821 padding-top: 10px;
2853 2822 clear: both;
2854 2823 }
@@ -1,242 +1,234 b''
1 1 // select2.less
2 2 // For use in RhodeCode application drop down select boxes;
3 3 // see style guide documentation for guidelines.
4 4
5 5
6 6 // SELECT2 DROPDOWN MENUS
7 7
8 8 //Select2 Dropdown
9 9 .select2-results{
10 10 .box-sizing(border-box);
11 11 overflow-y: scroll;
12 12 }
13 13
14 14 .select2-container{margin: 0; position: relative; display: inline-block; zoom: 1;}
15 15 .select2-container,
16 16 .select2-drop,
17 17 .select2-search,
18 18 .select2-search input {.box-sizing(border-box);}
19 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 20 .main .select2-container .select2-choice { background-color: white; box-shadow: @button-shadow;}
21 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 22 .select2-container.select2-allowclear .select2-choice abbr {display: inline-block;}
23 23 .select2-container .select2-choice abbr:hover { background-position: right -11px; cursor: pointer; }
24 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 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 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 27 .select2-drop-active { border: @border-thickness solid #5897fb; border-top: none; }
28 28 .select2-drop.select2-drop-above.select2-drop-active {border-top: @border-thickness solid #5897fb;}
29 29 .select2-drop-auto-width { border-top: @border-thickness solid #aaa; width: auto; }
30 30 .select2-drop-auto-width .select2-search {padding-top: 4px;}
31 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 32 html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {background-position: 2px 1px;}
33 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 34 .select2-search input { width: 100%; height: auto !important; min-height: 26px; padding: 4px 20px 4px 5px; margin: 0; outline: 0; }
35 35 html[dir="rtl"] .select2-search input { padding: 4px 5px 4px 20px; background: #fff url('../images/select2.png') no-repeat -37px -22px; }
36 36 .select2-drop.select2-drop-above .select2-search input {margin-top: 4px;}
37 37 .select2-dropdown-open .select2-choice .select2-arrow { background: transparent; border-left: none; filter: none; }
38 38 html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {border-right: none;}
39 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 40 /* results */
41 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 42 html[dir="rtl"] .select2-results { padding: 0 4px 0 0; margin: 4px 0 4px 4px; }
43 43 .select2-results .select2-disabled{background:@grey6;display:list-item;cursor:default}
44 44 .select2-results .select2-selected{display:none}
45 45 .select2-more-results.select2-active{background:#f4f4f4 url('../images/select2-spinner.gif') no-repeat 100%}
46 46 .select2-container.select2-container-disabled .select2-choice abbr{display:none}
47 47 .select2-container.select2-container-disabled {background:@grey6;cursor:default}
48 48 .select2-container.select2-container-disabled .select2-choice {background:@grey6;cursor:default}
49 49 .select2-container-multi .select2-choices li{float:left;list-style:none}
50 50 .select2-container-multi .select2-choices .select2-search-field{margin:0;padding:0;white-space:nowrap}
51 51 .select2-container-multi .select2-choices .select2-search-choice .select2-chosen{cursor:default}
52 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 53 .select2-container-multi .select2-search-choice-close{left:3px}
54 54 .select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover{background-position:right -11px}
55 55 .select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close{background-position:right -11px}
56 56 .select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close{display:none;background:none}
57 57 .select2-offscreen,.select2-offscreen:focus{clip:rect(0 0 0 0) !important;width:1px !important;height:1px !important;
58 58 border:0 !important;margin:0 !important;padding:0 !important;overflow:hidden !important;
59 59 position: absolute !important;outline:0 !important;left:0 !important;top:0 !important}
60 60 .select2-display-none,
61 61 .select2-search-hidden {display:none}
62 62 .select2-search input { border-color: @rclightblue; }
63 63
64 64 .select2-measure-scrollbar{position:absolute;top:-10000px;left:-10000px;width:100px;height:100px;overflow:scroll}
65 65 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
66 66 only screen and (min-resolution:144dpi){
67 67 .select2-search input,
68 68 .select2-search-choice-close,
69 69 .select2-container .select2-choice abbr,
70 70 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
71 71 .select2-search input{background-position:100% -21px}
72 72 }
73 73 [class^="input-"] [class^="select2-choice"]>div{display:none}
74 74 [class^="input-"] .select2-offscreen{position:absolute}
75 75 select.select2{height:28px;visibility:hidden}
76 76 .autocomplete-suggestions{overflow:auto}
77 77 .autocomplete-suggestion{white-space:nowrap;overflow:hidden}
78 78
79 79 /* Retina-ize icons */
80 80 @media only screen and (-webkit-min-device-pixel-ratio:1.5),
81 81 only screen and (min-resolution:144dpi){
82 82 .select2-search input,
83 83 .select2-search-choice-close,
84 84 .select2-container .select2-choice abbr,
85 85 .select2-container .select2-choice .select2-arrow b{background-image:url('../images/select2x2.png');background-repeat:no-repeat;background-size:60px 40px;}
86 86 .select2-search input{background-position:100% -21px}
87 87 }
88 88
89 89 //Internal Select2 Dropdown Menus
90 90
91 91 .drop-menu-core {
92 92 min-width: 160px;
93 93 margin: 0 @padding 0 0;
94 94 padding: 0;
95 95 border: @border-thickness solid @grey5;
96 96 border-radius: @border-radius;
97 97 color: @grey2;
98 98 background-color: white;
99 99
100 100 a {
101 101 color: @grey2;
102 102
103 103 &:hover {
104 104 color: @rcdarkblue;
105 105 }
106 106 }
107 107 }
108 108
109 109 .drop-menu-dropdown {
110 110 .drop-menu-core;
111
112 .flag_status {
113 margin-top: 0;
114 }
115 111 }
116 112
117 113 .drop-menu-base {
118 114 .drop-menu-core;
119 115 position: relative;
120 116 display: inline-block;
121 117 line-height: 1em;
122 118 z-index: 2;
123 119 cursor: pointer;
124 120
125 .flag_status {
126 margin-top: 0;
127 }
128
129 121 a {
130 122 display:block;
131 123 padding: .7em;
132 124 padding-right: 2em;
133 125 position: relative;
134 126
135 127 &:after {
136 128 position: absolute;
137 129 content: "\00A0\25BE";
138 130 right: .1em;
139 131 line-height: 1em;
140 132 top: 0.2em;
141 133 width: 1em;
142 134 font-size: 20px;
143 135 }
144 136 }
145 137 }
146 138
147 139 .drop-menu {
148 140 .drop-menu-base;
149 141 width: auto !important;
150 142 }
151 143
152 144 .drop-menu-no-width {
153 145 .drop-menu-base;
154 146 width: auto;
155 147 min-width: 0;
156 148 margin: 0;
157 149 }
158 150
159 151 .field-sm .drop-menu {
160 152 padding: 1px 0 0 0;
161 153 a {
162 154 padding: 6px;
163 155 };
164 156 }
165 157
166 158 .select2-search input {
167 159 width: 100%;
168 160 margin: .5em 0;
169 161 padding: .5em;
170 162 border-color: @grey4;
171 163
172 164 &:focus, &:hover {
173 165 border-color: @rcblue;
174 166 box-shadow: @button-shadow;
175 167 }
176 168 }
177 169
178 170 .select2-no-results {
179 171 padding: .5em;
180 172 }
181 173
182 174 .drop-menu-dropdown ul {
183 175 width: auto;
184 176 margin: 0;
185 177 padding: 0;
186 178 z-index: 50;
187 179
188 180 li {
189 181 margin: 0;
190 182 line-height: 1em;
191 183 list-style-type: none;
192 184
193 185 &:hover,
194 186 &.select2-highlighted {
195 187 background-color: @grey7;
196 188
197 189 .select2-result-label {
198 190 &:hover {
199 191 color: @grey1!important;
200 192 }
201 193 }
202 194 }
203 195
204 196 &.select2-result-with-children {
205 197 &:hover {
206 198 background-color: white;
207 199 }
208 200 }
209 201
210 202 .select2-result-label {
211 203 display:block;
212 204 padding: 8px;
213 205 font-family: @text-regular;
214 206 color: @grey2;
215 207 cursor: pointer;
216 208 }
217 209 &.select2-result-with-children {
218 210
219 211 .select2-result-label {
220 212 color: @rcdarkblue;
221 213 cursor: default;
222 214 font-weight: @text-semibold-weight;
223 215 font-family: @text-semibold;
224 216 }
225 217
226 218 ul.select2-result-sub li .select2-result-label {
227 219 padding-left: 16px;
228 220 font-family: @text-regular;
229 221 color: @grey2;
230 222 cursor: pointer;
231 223 }
232 224 }
233 225 }
234 226 }
235 227
236 228 .side-by-side-selector {
237 229 .left-group,
238 230 .middle-group,
239 231 .right-group {
240 232 margin-bottom: @padding;
241 233 }
242 234 }
@@ -1,843 +1,844 b''
1 1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 2 // #
3 3 // # This program is free software: you can redistribute it and/or modify
4 4 // # it under the terms of the GNU Affero General Public License, version 3
5 5 // # (only), as published by the Free Software Foundation.
6 6 // #
7 7 // # This program is distributed in the hope that it will be useful,
8 8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 // # GNU General Public License for more details.
11 11 // #
12 12 // # You should have received a copy of the GNU Affero General Public License
13 13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 // #
15 15 // # This program is dual-licensed. If you wish to learn more about the
16 16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 /**
20 20 * Code Mirror
21 21 */
22 22 // global code-mirror logger;, to enable run
23 23 // Logger.get('CodeMirror').setLevel(Logger.DEBUG)
24 24
25 25 cmLog = Logger.get('CodeMirror');
26 26 cmLog.setLevel(Logger.OFF);
27 27
28 28
29 29 //global cache for inline forms
30 30 var userHintsCache = {};
31 31
32 32 // global timer, used to cancel async loading
33 33 var CodeMirrorLoadUserHintTimer;
34 34
35 35 var escapeRegExChars = function(value) {
36 36 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
37 37 };
38 38
39 39 /**
40 40 * Load hints from external source returns an array of objects in a format
41 41 * that hinting lib requires
42 42 * @returns {Array}
43 43 */
44 44 var CodeMirrorLoadUserHints = function(query, triggerHints) {
45 45 cmLog.debug('Loading mentions users via AJAX');
46 46 var _users = [];
47 47 $.ajax({
48 48 type: 'GET',
49 49 data: {query: query},
50 50 url: pyroutes.url('user_autocomplete_data'),
51 51 headers: {'X-PARTIAL-XHR': true},
52 52 async: true
53 53 })
54 54 .done(function(data) {
55 55 var tmpl = '<img class="gravatar" src="{0}"/>{1}';
56 56 $.each(data.suggestions, function(i) {
57 57 var userObj = data.suggestions[i];
58 58
59 59 if (userObj.username !== "default") {
60 60 _users.push({
61 61 text: userObj.username + " ",
62 62 org_text: userObj.username,
63 63 displayText: userObj.value_display, // search that field
64 64 // internal caches
65 65 _icon_link: userObj.icon_link,
66 66 _text: userObj.value_display,
67 67
68 68 render: function(elt, data, completion) {
69 69 var el = document.createElement('div');
70 70 el.className = "CodeMirror-hint-entry";
71 71 el.innerHTML = tmpl.format(
72 72 completion._icon_link, completion._text);
73 73 elt.appendChild(el);
74 74 }
75 75 });
76 76 }
77 77 });
78 78 cmLog.debug('Mention users loaded');
79 79 // set to global cache
80 80 userHintsCache[query] = _users;
81 81 triggerHints(userHintsCache[query]);
82 82 })
83 83 .fail(function(data, textStatus, xhr) {
84 84 alert("error processing request. \n" +
85 85 "Error code {0} ({1}).".format(data.status, data.statusText));
86 86 });
87 87 };
88 88
89 89 /**
90 90 * filters the results based on the current context
91 91 * @param users
92 92 * @param context
93 93 * @returns {Array}
94 94 */
95 95 var CodeMirrorFilterUsers = function(users, context) {
96 96 var MAX_LIMIT = 10;
97 97 var filtered_users = [];
98 98 var curWord = context.string;
99 99
100 100 cmLog.debug('Filtering users based on query:', curWord);
101 101 $.each(users, function(i) {
102 102 var match = users[i];
103 103 var searchText = match.displayText;
104 104
105 105 if (!curWord ||
106 106 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
107 107 // reset state
108 108 match._text = match.displayText;
109 109 if (curWord) {
110 110 // do highlighting
111 111 var pattern = '(' + escapeRegExChars(curWord) + ')';
112 112 match._text = searchText.replace(
113 113 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
114 114 }
115 115
116 116 filtered_users.push(match);
117 117 }
118 118 // to not return to many results, use limit of filtered results
119 119 if (filtered_users.length > MAX_LIMIT) {
120 120 return false;
121 121 }
122 122 });
123 123
124 124 return filtered_users;
125 125 };
126 126
127 127 var CodeMirrorMentionHint = function(editor, callback, options) {
128 128 var cur = editor.getCursor();
129 129 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
130 130
131 131 // match on @ +1char
132 132 var tokenMatch = new RegExp(
133 133 '(^@| @)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*)$').exec(curLine);
134 134
135 135 var tokenStr = '';
136 136 if (tokenMatch !== null && tokenMatch.length > 0){
137 137 tokenStr = tokenMatch[0].strip();
138 138 } else {
139 139 // skip if we didn't match our token
140 140 return;
141 141 }
142 142
143 143 var context = {
144 144 start: (cur.ch - tokenStr.length) + 1,
145 145 end: cur.ch,
146 146 string: tokenStr.slice(1),
147 147 type: null
148 148 };
149 149
150 150 // case when we put the @sign in fron of a string,
151 151 // eg <@ we put it here>sometext then we need to prepend to text
152 152 if (context.end > cur.ch) {
153 153 context.start = context.start + 1; // we add to the @ sign
154 154 context.end = cur.ch; // don't eat front part just append
155 155 context.string = context.string.slice(1, cur.ch - context.start);
156 156 }
157 157
158 158 cmLog.debug('Mention context', context);
159 159
160 160 var triggerHints = function(userHints){
161 161 return callback({
162 162 list: CodeMirrorFilterUsers(userHints, context),
163 163 from: CodeMirror.Pos(cur.line, context.start),
164 164 to: CodeMirror.Pos(cur.line, context.end)
165 165 });
166 166 };
167 167
168 168 var queryBasedHintsCache = undefined;
169 169 // if we have something in the cache, try to fetch the query based cache
170 170 if (userHintsCache !== {}){
171 171 queryBasedHintsCache = userHintsCache[context.string];
172 172 }
173 173
174 174 if (queryBasedHintsCache !== undefined) {
175 175 cmLog.debug('Users loaded from cache');
176 176 triggerHints(queryBasedHintsCache);
177 177 } else {
178 178 // this takes care for async loading, and then displaying results
179 179 // and also propagates the userHintsCache
180 180 window.clearTimeout(CodeMirrorLoadUserHintTimer);
181 181 CodeMirrorLoadUserHintTimer = setTimeout(function() {
182 182 CodeMirrorLoadUserHints(context.string, triggerHints);
183 183 }, 300);
184 184 }
185 185 };
186 186
187 187 var CodeMirrorCompleteAfter = function(cm, pred) {
188 188 var options = {
189 189 completeSingle: false,
190 190 async: true,
191 191 closeOnUnfocus: true
192 192 };
193 193 var cur = cm.getCursor();
194 194 setTimeout(function() {
195 195 if (!cm.state.completionActive) {
196 196 cmLog.debug('Trigger mentions hinting');
197 197 CodeMirror.showHint(cm, CodeMirror.hint.mentions, options);
198 198 }
199 199 }, 100);
200 200
201 201 // tell CodeMirror we didn't handle the key
202 202 // trick to trigger on a char but still complete it
203 203 return CodeMirror.Pass;
204 204 };
205 205
206 206 var initCodeMirror = function(textAreadId, resetUrl, focus, options) {
207 207 if (textAreadId.substr(0,1) === "#"){
208 208 var ta = $(textAreadId).get(0);
209 209 }else {
210 210 var ta = $('#' + textAreadId).get(0);
211 211 }
212 212
213 213 if (focus === undefined) {
214 214 focus = true;
215 215 }
216 216
217 217 // default options
218 218 var codeMirrorOptions = {
219 219 mode: "null",
220 220 lineNumbers: true,
221 221 indentUnit: 4,
222 222 autofocus: focus
223 223 };
224 224
225 225 if (options !== undefined) {
226 226 // extend with custom options
227 227 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
228 228 }
229 229
230 230 var myCodeMirror = CodeMirror.fromTextArea(ta, codeMirrorOptions);
231 231
232 232 $('#reset').on('click', function(e) {
233 233 window.location = resetUrl;
234 234 });
235 235
236 236 return myCodeMirror;
237 237 };
238 238
239 239
240 240 var initMarkupCodeMirror = function(textAreadId, focus, options) {
241 241 var initialHeight = 100;
242 242
243 243 var ta = $(textAreadId).get(0);
244 244 if (focus === undefined) {
245 245 focus = true;
246 246 }
247 247
248 248 // default options
249 249 var codeMirrorOptions = {
250 250 lineNumbers: false,
251 251 indentUnit: 4,
252 252 viewportMargin: 30,
253 253 // this is a trick to trigger some logic behind codemirror placeholder
254 254 // it influences styling and behaviour.
255 255 placeholder: " ",
256 256 lineWrapping: true,
257 257 autofocus: focus
258 258 };
259 259
260 260 if (options !== undefined) {
261 261 // extend with custom options
262 262 codeMirrorOptions = $.extend(true, codeMirrorOptions, options);
263 263 }
264 264
265 265 var cm = CodeMirror.fromTextArea(ta, codeMirrorOptions);
266 266 cm.setSize(null, initialHeight);
267 267 cm.setOption("mode", DEFAULT_RENDERER);
268 268 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
269 269 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
270 270
271 271 // start listening on changes to make auto-expanded editor
272 272 cm.on("change", function(instance, changeObj) {
273 273 var height = initialHeight;
274 274 var lines = instance.lineCount();
275 275 if ( lines > 6 && lines < 20) {
276 276 height = "auto";
277 277 }
278 278 else if (lines >= 20){
279 279 zheight = 20*15;
280 280 }
281 281 instance.setSize(null, height);
282 282
283 283 // detect if the change was trigger by auto desc, or user input
284 284 var changeOrigin = changeObj.origin;
285 285
286 286 if (changeOrigin === "setValue") {
287 287 cmLog.debug('Change triggered by setValue');
288 288 }
289 289 else {
290 290 cmLog.debug('user triggered change !');
291 291 // set special marker to indicate user has created an input.
292 292 instance._userDefinedValue = true;
293 293 }
294 294
295 295 });
296 296
297 297 return cm;
298 298 };
299 299
300 300
301 301 var initCommentBoxCodeMirror = function(CommentForm, textAreaId, triggerActions){
302 302 var initialHeight = 100;
303 303
304 304 if (typeof userHintsCache === "undefined") {
305 305 userHintsCache = {};
306 306 cmLog.debug('Init empty cache for mentions');
307 307 }
308 308 if (!$(textAreaId).get(0)) {
309 309 cmLog.debug('Element for textarea not found', textAreaId);
310 310 return;
311 311 }
312 312 /**
313 313 * Filter action based on typed in text
314 314 * @param actions
315 315 * @param context
316 316 * @returns {Array}
317 317 */
318 318
319 319 var filterActions = function(actions, context){
320 320
321 321 var MAX_LIMIT = 10;
322 322 var filtered_actions = [];
323 323 var curWord = context.string;
324 324
325 325 cmLog.debug('Filtering actions based on query:', curWord);
326 326 $.each(actions, function(i) {
327 327 var match = actions[i];
328 328 var searchText = match.searchText;
329 329
330 330 if (!curWord ||
331 331 searchText.toLowerCase().lastIndexOf(curWord) !== -1) {
332 332 // reset state
333 333 match._text = match.displayText;
334 334 if (curWord) {
335 335 // do highlighting
336 336 var pattern = '(' + escapeRegExChars(curWord) + ')';
337 337 match._text = searchText.replace(
338 338 new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
339 339 }
340 340
341 341 filtered_actions.push(match);
342 342 }
343 343 // to not return to many results, use limit of filtered results
344 344 if (filtered_actions.length > MAX_LIMIT) {
345 345 return false;
346 346 }
347 347 });
348 348
349 349 return filtered_actions;
350 350 };
351 351
352 352 var submitForm = function(cm, pred) {
353 353 $(cm.display.input.textarea.form).submit();
354 354 return CodeMirror.Pass;
355 355 };
356 356
357 357 var completeActions = function(actions){
358 358
359 359 var registeredActions = [];
360 360 var allActions = [
361 361 {
362 362 text: "approve",
363 363 searchText: "status approved",
364 364 displayText: _gettext('Set status to Approved'),
365 365 hint: function(CodeMirror, data, completion) {
366 366 CodeMirror.replaceRange("", completion.from || data.from,
367 367 completion.to || data.to, "complete");
368 368 $(CommentForm.statusChange).select2("val", 'approved').trigger('change');
369 369 },
370 370 render: function(elt, data, completion) {
371 var el = document.createElement('div');
372 el.className = "flag_status flag_status_comment_box approved pull-left";
371 var el = document.createElement('i');
372
373 el.className = "icon-circle review-status-approved";
373 374 elt.appendChild(el);
374 375
375 376 el = document.createElement('span');
376 377 el.innerHTML = completion.displayText;
377 378 elt.appendChild(el);
378 379 }
379 380 },
380 381 {
381 382 text: "reject",
382 383 searchText: "status rejected",
383 384 displayText: _gettext('Set status to Rejected'),
384 385 hint: function(CodeMirror, data, completion) {
385 386 CodeMirror.replaceRange("", completion.from || data.from,
386 387 completion.to || data.to, "complete");
387 388 $(CommentForm.statusChange).select2("val", 'rejected').trigger('change');
388 389 },
389 390 render: function(elt, data, completion) {
390 var el = document.createElement('div');
391 el.className = "flag_status flag_status_comment_box rejected pull-left";
391 var el = document.createElement('i');
392 el.className = "icon-circle review-status-rejected";
392 393 elt.appendChild(el);
393 394
394 395 el = document.createElement('span');
395 396 el.innerHTML = completion.displayText;
396 397 elt.appendChild(el);
397 398 }
398 399 },
399 400 {
400 401 text: "as_todo",
401 402 searchText: "todo comment",
402 403 displayText: _gettext('TODO comment'),
403 404 hint: function(CodeMirror, data, completion) {
404 405 CodeMirror.replaceRange("", completion.from || data.from,
405 406 completion.to || data.to, "complete");
406 407
407 408 $(CommentForm.commentType).val('todo');
408 409 },
409 410 render: function(elt, data, completion) {
410 411 var el = document.createElement('div');
411 412 el.className = "pull-left";
412 413 elt.appendChild(el);
413 414
414 415 el = document.createElement('span');
415 416 el.innerHTML = completion.displayText;
416 417 elt.appendChild(el);
417 418 }
418 419 },
419 420 {
420 421 text: "as_note",
421 422 searchText: "note comment",
422 423 displayText: _gettext('Note Comment'),
423 424 hint: function(CodeMirror, data, completion) {
424 425 CodeMirror.replaceRange("", completion.from || data.from,
425 426 completion.to || data.to, "complete");
426 427
427 428 $(CommentForm.commentType).val('note');
428 429 },
429 430 render: function(elt, data, completion) {
430 431 var el = document.createElement('div');
431 432 el.className = "pull-left";
432 433 elt.appendChild(el);
433 434
434 435 el = document.createElement('span');
435 436 el.innerHTML = completion.displayText;
436 437 elt.appendChild(el);
437 438 }
438 439 }
439 440 ];
440 441
441 442 $.each(allActions, function(index, value){
442 443 var actionData = allActions[index];
443 444 if (actions.indexOf(actionData['text']) != -1) {
444 445 registeredActions.push(actionData);
445 446 }
446 447 });
447 448
448 449 return function(cm, pred) {
449 450 var cur = cm.getCursor();
450 451 var options = {
451 452 closeOnUnfocus: true,
452 453 registeredActions: registeredActions
453 454 };
454 455 setTimeout(function() {
455 456 if (!cm.state.completionActive) {
456 457 cmLog.debug('Trigger actions hinting');
457 458 CodeMirror.showHint(cm, CodeMirror.hint.actions, options);
458 459 }
459 460 }, 100);
460 461
461 462 // tell CodeMirror we didn't handle the key
462 463 // trick to trigger on a char but still complete it
463 464 return CodeMirror.Pass;
464 465 }
465 466 };
466 467
467 468 var extraKeys = {
468 469 "'@'": CodeMirrorCompleteAfter,
469 470 Tab: function(cm) {
470 471 // space indent instead of TABS
471 472 var spaces = new Array(cm.getOption("indentUnit") + 1).join(" ");
472 473 cm.replaceSelection(spaces);
473 474 }
474 475 };
475 476 // submit form on Meta-Enter
476 477 if (OSType === "mac") {
477 478 extraKeys["Cmd-Enter"] = submitForm;
478 479 }
479 480 else {
480 481 extraKeys["Ctrl-Enter"] = submitForm;
481 482 }
482 483
483 484 if (triggerActions) {
484 485 // register triggerActions for this instance
485 486 extraKeys["'/'"] = completeActions(triggerActions);
486 487 }
487 488
488 489 var cm = CodeMirror.fromTextArea($(textAreaId).get(0), {
489 490 lineNumbers: false,
490 491 indentUnit: 4,
491 492 viewportMargin: 30,
492 493 // this is a trick to trigger some logic behind codemirror placeholder
493 494 // it influences styling and behaviour.
494 495 placeholder: " ",
495 496 extraKeys: extraKeys,
496 497 lineWrapping: true
497 498 });
498 499
499 500 cm.setSize(null, initialHeight);
500 501 cm.setOption("mode", DEFAULT_RENDERER);
501 502 CodeMirror.autoLoadMode(cm, DEFAULT_RENDERER); // load rst or markdown mode
502 503 cmLog.debug('Loading codemirror mode', DEFAULT_RENDERER);
503 504 // start listening on changes to make auto-expanded editor
504 505 cm.on("change", function(self) {
505 506 var height = initialHeight;
506 507 var lines = self.lineCount();
507 508 if ( lines > 6 && lines < 20) {
508 509 height = "auto";
509 510 }
510 511 else if (lines >= 20){
511 512 zheight = 20*15;
512 513 }
513 514 self.setSize(null, height);
514 515 });
515 516
516 517 var actionHint = function(editor, options) {
517 518
518 519 var cur = editor.getCursor();
519 520 var curLine = editor.getLine(cur.line).slice(0, cur.ch);
520 521
521 522 // match only on /+1 character minimum
522 523 var tokenMatch = new RegExp('(^/\|/\)([a-zA-Z]*)$').exec(curLine);
523 524
524 525 var tokenStr = '';
525 526 if (tokenMatch !== null && tokenMatch.length > 0){
526 527 tokenStr = tokenMatch[2].strip();
527 528 }
528 529
529 530 var context = {
530 531 start: (cur.ch - tokenStr.length) - 1,
531 532 end: cur.ch,
532 533 string: tokenStr,
533 534 type: null
534 535 };
535 536
536 537 return {
537 538 list: filterActions(options.registeredActions, context),
538 539 from: CodeMirror.Pos(cur.line, context.start),
539 540 to: CodeMirror.Pos(cur.line, context.end)
540 541 };
541 542
542 543 };
543 544 CodeMirror.registerHelper("hint", "mentions", CodeMirrorMentionHint);
544 545 CodeMirror.registerHelper("hint", "actions", actionHint);
545 546 return cm;
546 547 };
547 548
548 549 var setCodeMirrorMode = function(codeMirrorInstance, mode) {
549 550 CodeMirror.autoLoadMode(codeMirrorInstance, mode);
550 551 codeMirrorInstance.setOption("mode", mode);
551 552 };
552 553
553 554 var setCodeMirrorLineWrap = function(codeMirrorInstance, line_wrap) {
554 555 codeMirrorInstance.setOption("lineWrapping", line_wrap);
555 556 };
556 557
557 558 var setCodeMirrorModeFromSelect = function(
558 559 targetSelect, targetFileInput, codeMirrorInstance, callback){
559 560
560 561 $(targetSelect).on('change', function(e) {
561 562 cmLog.debug('codemirror select2 mode change event !');
562 563 var selected = e.currentTarget;
563 564 var node = selected.options[selected.selectedIndex];
564 565 var mimetype = node.value;
565 566 cmLog.debug('picked mimetype', mimetype);
566 567 var new_mode = $(node).attr('mode');
567 568 setCodeMirrorMode(codeMirrorInstance, new_mode);
568 569 cmLog.debug('set new mode', new_mode);
569 570
570 571 //propose filename from picked mode
571 572 cmLog.debug('setting mimetype', mimetype);
572 573 var proposed_ext = getExtFromMimeType(mimetype);
573 574 cmLog.debug('file input', $(targetFileInput).val());
574 575 var file_data = getFilenameAndExt($(targetFileInput).val());
575 576 var filename = file_data.filename || 'filename1';
576 577 $(targetFileInput).val(filename + proposed_ext);
577 578 cmLog.debug('proposed file', filename + proposed_ext);
578 579
579 580
580 581 if (typeof(callback) === 'function') {
581 582 try {
582 583 cmLog.debug('running callback', callback);
583 584 callback(filename, mimetype, new_mode);
584 585 } catch (err) {
585 586 console.log('failed to run callback', callback, err);
586 587 }
587 588 }
588 589 cmLog.debug('finish iteration...');
589 590 });
590 591 };
591 592
592 593 var setCodeMirrorModeFromInput = function(
593 594 targetSelect, targetFileInput, codeMirrorInstance, callback) {
594 595
595 596 // on type the new filename set mode
596 597 $(targetFileInput).on('keyup', function(e) {
597 598 var file_data = getFilenameAndExt(this.value);
598 599 if (file_data.ext === null) {
599 600 return;
600 601 }
601 602
602 603 var mimetypes = getMimeTypeFromExt(file_data.ext, true);
603 604 cmLog.debug('mimetype from file', file_data, mimetypes);
604 605 var detected_mode;
605 606 var detected_option;
606 607 for (var i in mimetypes) {
607 608 var mt = mimetypes[i];
608 609 if (!detected_mode) {
609 610 detected_mode = detectCodeMirrorMode(this.value, mt);
610 611 }
611 612
612 613 if (!detected_option) {
613 614 cmLog.debug('#mimetype option[value="{0}"]'.format(mt));
614 615 if ($(targetSelect).find('option[value="{0}"]'.format(mt)).length) {
615 616 detected_option = mt;
616 617 }
617 618 }
618 619 }
619 620
620 621 cmLog.debug('detected mode', detected_mode);
621 622 cmLog.debug('detected option', detected_option);
622 623 if (detected_mode && detected_option){
623 624
624 625 $(targetSelect).select2("val", detected_option);
625 626 setCodeMirrorMode(codeMirrorInstance, detected_mode);
626 627
627 628 if(typeof(callback) === 'function'){
628 629 try{
629 630 cmLog.debug('running callback', callback);
630 631 var filename = file_data.filename + "." + file_data.ext;
631 632 callback(filename, detected_option, detected_mode);
632 633 }catch (err){
633 634 console.log('failed to run callback', callback, err);
634 635 }
635 636 }
636 637 }
637 638
638 639 });
639 640 };
640 641
641 642 var fillCodeMirrorOptions = function(targetSelect) {
642 643 //inject new modes, based on codeMirrors modeInfo object
643 644 var modes_select = $(targetSelect);
644 645 for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
645 646 var m = CodeMirror.modeInfo[i];
646 647 var opt = new Option(m.name, m.mime);
647 648 $(opt).attr('mode', m.mode);
648 649 modes_select.append(opt);
649 650 }
650 651 };
651 652
652 653
653 654 /* markup form */
654 655 (function(mod) {
655 656
656 657 if (typeof exports == "object" && typeof module == "object") {
657 658 // CommonJS
658 659 module.exports = mod();
659 660 }
660 661 else {
661 662 // Plain browser env
662 663 (this || window).MarkupForm = mod();
663 664 }
664 665
665 666 })(function() {
666 667 "use strict";
667 668
668 669 function MarkupForm(textareaId) {
669 670 if (!(this instanceof MarkupForm)) {
670 671 return new MarkupForm(textareaId);
671 672 }
672 673
673 674 // bind the element instance to our Form
674 675 $('#' + textareaId).get(0).MarkupForm = this;
675 676
676 677 this.withSelectorId = function(selector) {
677 678 var selectorId = textareaId;
678 679 return selector + '_' + selectorId;
679 680 };
680 681
681 682 this.previewButton = this.withSelectorId('#preview-btn');
682 683 this.previewContainer = this.withSelectorId('#preview-container');
683 684
684 685 this.previewBoxSelector = this.withSelectorId('#preview-box');
685 686
686 687 this.editButton = this.withSelectorId('#edit-btn');
687 688 this.editContainer = this.withSelectorId('#edit-container');
688 689
689 690 this.cmBox = textareaId;
690 691 this.cm = initMarkupCodeMirror('#' + textareaId);
691 692
692 693 this.previewUrl = pyroutes.url('markup_preview');
693 694
694 695 // FUNCTIONS and helpers
695 696 var self = this;
696 697
697 698 this.getCmInstance = function(){
698 699 return this.cm
699 700 };
700 701
701 702 this.setPlaceholder = function(placeholder) {
702 703 var cm = this.getCmInstance();
703 704 if (cm){
704 705 cm.setOption('placeholder', placeholder);
705 706 }
706 707 };
707 708
708 709 this.initStatusChangeSelector = function(){
709 710 var formatChangeStatus = function(state, escapeMarkup) {
710 711 var originalOption = state.element;
711 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
712 '<span>' + escapeMarkup(state.text) + '</span>';
712 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
713 return tmpl
713 714 };
714 715 var formatResult = function(result, container, query, escapeMarkup) {
715 716 return formatChangeStatus(result, escapeMarkup);
716 717 };
717 718
718 719 var formatSelection = function(data, container, escapeMarkup) {
719 720 return formatChangeStatus(data, escapeMarkup);
720 721 };
721 722
722 723 $(this.submitForm).find(this.statusChange).select2({
723 724 placeholder: _gettext('Status Review'),
724 725 formatResult: formatResult,
725 726 formatSelection: formatSelection,
726 727 containerCssClass: "drop-menu status_box_menu",
727 728 dropdownCssClass: "drop-menu-dropdown",
728 729 dropdownAutoWidth: true,
729 730 minimumResultsForSearch: -1
730 731 });
731 732 $(this.submitForm).find(this.statusChange).on('change', function() {
732 733 var status = self.getCommentStatus();
733 734
734 735 if (status && !self.isInline()) {
735 736 $(self.submitButton).prop('disabled', false);
736 737 }
737 738
738 739 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
739 740 self.setPlaceholder(placeholderText)
740 741 })
741 742 };
742 743
743 744 // reset the text area into it's original state
744 745 this.resetMarkupFormState = function(content) {
745 746 content = content || '';
746 747
747 748 $(this.editContainer).show();
748 749 $(this.editButton).parent().addClass('active');
749 750
750 751 $(this.previewContainer).hide();
751 752 $(this.previewButton).parent().removeClass('active');
752 753
753 754 this.setActionButtonsDisabled(true);
754 755 self.cm.setValue(content);
755 756 self.cm.setOption("readOnly", false);
756 757 };
757 758
758 759 this.previewSuccessCallback = function(o) {
759 760 $(self.previewBoxSelector).html(o);
760 761 $(self.previewBoxSelector).removeClass('unloaded');
761 762
762 763 // swap buttons, making preview active
763 764 $(self.previewButton).parent().addClass('active');
764 765 $(self.editButton).parent().removeClass('active');
765 766
766 767 // unlock buttons
767 768 self.setActionButtonsDisabled(false);
768 769 };
769 770
770 771 this.setActionButtonsDisabled = function(state) {
771 772 $(this.editButton).prop('disabled', state);
772 773 $(this.previewButton).prop('disabled', state);
773 774 };
774 775
775 776 // lock preview/edit/submit buttons on load, but exclude cancel button
776 777 var excludeCancelBtn = true;
777 778 this.setActionButtonsDisabled(true);
778 779
779 780 // anonymous users don't have access to initialized CM instance
780 781 if (this.cm !== undefined){
781 782 this.cm.on('change', function(cMirror) {
782 783 if (cMirror.getValue() === "") {
783 784 self.setActionButtonsDisabled(true)
784 785 } else {
785 786 self.setActionButtonsDisabled(false)
786 787 }
787 788 });
788 789 }
789 790
790 791 $(this.editButton).on('click', function(e) {
791 792 e.preventDefault();
792 793
793 794 $(self.previewButton).parent().removeClass('active');
794 795 $(self.previewContainer).hide();
795 796
796 797 $(self.editButton).parent().addClass('active');
797 798 $(self.editContainer).show();
798 799
799 800 });
800 801
801 802 $(this.previewButton).on('click', function(e) {
802 803 e.preventDefault();
803 804 var text = self.cm.getValue();
804 805
805 806 if (text === "") {
806 807 return;
807 808 }
808 809
809 810 var postData = {
810 811 'text': text,
811 812 'renderer': templateContext.visual.default_renderer,
812 813 'csrf_token': CSRF_TOKEN
813 814 };
814 815
815 816 // lock ALL buttons on preview
816 817 self.setActionButtonsDisabled(true);
817 818
818 819 $(self.previewBoxSelector).addClass('unloaded');
819 820 $(self.previewBoxSelector).html(_gettext('Loading ...'));
820 821
821 822 $(self.editContainer).hide();
822 823 $(self.previewContainer).show();
823 824
824 825 // by default we reset state of comment preserving the text
825 826 var previewFailCallback = function(data){
826 827 alert(
827 828 "Error while submitting preview.\n" +
828 829 "Error code {0} ({1}).".format(data.status, data.statusText)
829 830 );
830 831 self.resetMarkupFormState(text)
831 832 };
832 833 _submitAjaxPOST(
833 834 self.previewUrl, postData, self.previewSuccessCallback,
834 835 previewFailCallback);
835 836
836 837 $(self.previewButton).parent().addClass('active');
837 838 $(self.editButton).parent().removeClass('active');
838 839 });
839 840
840 841 }
841 842
842 843 return MarkupForm;
843 844 });
@@ -1,838 +1,838 b''
1 1 // # Copyright (C) 2010-2019 RhodeCode GmbH
2 2 // #
3 3 // # This program is free software: you can redistribute it and/or modify
4 4 // # it under the terms of the GNU Affero General Public License, version 3
5 5 // # (only), as published by the Free Software Foundation.
6 6 // #
7 7 // # This program is distributed in the hope that it will be useful,
8 8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 // # GNU General Public License for more details.
11 11 // #
12 12 // # You should have received a copy of the GNU Affero General Public License
13 13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 // #
15 15 // # This program is dual-licensed. If you wish to learn more about the
16 16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 var firefoxAnchorFix = function() {
20 20 // hack to make anchor links behave properly on firefox, in our inline
21 21 // comments generation when comments are injected firefox is misbehaving
22 22 // when jumping to anchor links
23 23 if (location.href.indexOf('#') > -1) {
24 24 location.href += '';
25 25 }
26 26 };
27 27
28 28 var linkifyComments = function(comments) {
29 29 var firstCommentId = null;
30 30 if (comments) {
31 31 firstCommentId = $(comments[0]).data('comment-id');
32 32 }
33 33
34 34 if (firstCommentId){
35 35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
36 36 }
37 37 };
38 38
39 39 var bindToggleButtons = function() {
40 40 $('.comment-toggle').on('click', function() {
41 41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
42 42 });
43 43 };
44 44
45 45
46 46
47 47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
48 48 failHandler = failHandler || function() {};
49 49 postData = toQueryString(postData);
50 50 var request = $.ajax({
51 51 url: url,
52 52 type: 'POST',
53 53 data: postData,
54 54 headers: {'X-PARTIAL-XHR': true}
55 55 })
56 56 .done(function (data) {
57 57 successHandler(data);
58 58 })
59 59 .fail(function (data, textStatus, errorThrown) {
60 60 failHandler(data, textStatus, errorThrown)
61 61 });
62 62 return request;
63 63 };
64 64
65 65
66 66
67 67
68 68 /* Comment form for main and inline comments */
69 69 (function(mod) {
70 70
71 71 if (typeof exports == "object" && typeof module == "object") {
72 72 // CommonJS
73 73 module.exports = mod();
74 74 }
75 75 else {
76 76 // Plain browser env
77 77 (this || window).CommentForm = mod();
78 78 }
79 79
80 80 })(function() {
81 81 "use strict";
82 82
83 83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
84 84 if (!(this instanceof CommentForm)) {
85 85 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
86 86 }
87 87
88 88 // bind the element instance to our Form
89 89 $(formElement).get(0).CommentForm = this;
90 90
91 91 this.withLineNo = function(selector) {
92 92 var lineNo = this.lineNo;
93 93 if (lineNo === undefined) {
94 94 return selector
95 95 } else {
96 96 return selector + '_' + lineNo;
97 97 }
98 98 };
99 99
100 100 this.commitId = commitId;
101 101 this.pullRequestId = pullRequestId;
102 102 this.lineNo = lineNo;
103 103 this.initAutocompleteActions = initAutocompleteActions;
104 104
105 105 this.previewButton = this.withLineNo('#preview-btn');
106 106 this.previewContainer = this.withLineNo('#preview-container');
107 107
108 108 this.previewBoxSelector = this.withLineNo('#preview-box');
109 109
110 110 this.editButton = this.withLineNo('#edit-btn');
111 111 this.editContainer = this.withLineNo('#edit-container');
112 112 this.cancelButton = this.withLineNo('#cancel-btn');
113 113 this.commentType = this.withLineNo('#comment_type');
114 114
115 115 this.resolvesId = null;
116 116 this.resolvesActionId = null;
117 117
118 118 this.closesPr = '#close_pull_request';
119 119
120 120 this.cmBox = this.withLineNo('#text');
121 121 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
122 122
123 123 this.statusChange = this.withLineNo('#change_status');
124 124
125 125 this.submitForm = formElement;
126 126 this.submitButton = $(this.submitForm).find('input[type="submit"]');
127 127 this.submitButtonText = this.submitButton.val();
128 128
129 129 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
130 130 {'repo_name': templateContext.repo_name,
131 131 'commit_id': templateContext.commit_data.commit_id});
132 132
133 133 if (resolvesCommentId){
134 134 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
135 135 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
136 136 $(this.commentType).prop('disabled', true);
137 137 $(this.commentType).addClass('disabled');
138 138
139 139 // disable select
140 140 setTimeout(function() {
141 141 $(self.statusChange).select2('readonly', true);
142 142 }, 10);
143 143
144 144 var resolvedInfo = (
145 145 '<li class="resolve-action">' +
146 146 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
147 147 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
148 148 '</li>'
149 149 ).format(resolvesCommentId, _gettext('resolve comment'));
150 150 $(resolvedInfo).insertAfter($(this.commentType).parent());
151 151 }
152 152
153 153 // based on commitId, or pullRequestId decide where do we submit
154 154 // out data
155 155 if (this.commitId){
156 156 this.submitUrl = pyroutes.url('repo_commit_comment_create',
157 157 {'repo_name': templateContext.repo_name,
158 158 'commit_id': this.commitId});
159 159 this.selfUrl = pyroutes.url('repo_commit',
160 160 {'repo_name': templateContext.repo_name,
161 161 'commit_id': this.commitId});
162 162
163 163 } else if (this.pullRequestId) {
164 164 this.submitUrl = pyroutes.url('pullrequest_comment_create',
165 165 {'repo_name': templateContext.repo_name,
166 166 'pull_request_id': this.pullRequestId});
167 167 this.selfUrl = pyroutes.url('pullrequest_show',
168 168 {'repo_name': templateContext.repo_name,
169 169 'pull_request_id': this.pullRequestId});
170 170
171 171 } else {
172 172 throw new Error(
173 173 'CommentForm requires pullRequestId, or commitId to be specified.')
174 174 }
175 175
176 176 // FUNCTIONS and helpers
177 177 var self = this;
178 178
179 179 this.isInline = function(){
180 180 return this.lineNo && this.lineNo != 'general';
181 181 };
182 182
183 183 this.getCmInstance = function(){
184 184 return this.cm
185 185 };
186 186
187 187 this.setPlaceholder = function(placeholder) {
188 188 var cm = this.getCmInstance();
189 189 if (cm){
190 190 cm.setOption('placeholder', placeholder);
191 191 }
192 192 };
193 193
194 194 this.getCommentStatus = function() {
195 195 return $(this.submitForm).find(this.statusChange).val();
196 196 };
197 197 this.getCommentType = function() {
198 198 return $(this.submitForm).find(this.commentType).val();
199 199 };
200 200
201 201 this.getResolvesId = function() {
202 202 return $(this.submitForm).find(this.resolvesId).val() || null;
203 203 };
204 204
205 205 this.getClosePr = function() {
206 206 return $(this.submitForm).find(this.closesPr).val() || null;
207 207 };
208 208
209 209 this.markCommentResolved = function(resolvedCommentId){
210 210 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
211 211 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
212 212 };
213 213
214 214 this.isAllowedToSubmit = function() {
215 215 return !$(this.submitButton).prop('disabled');
216 216 };
217 217
218 218 this.initStatusChangeSelector = function(){
219 219 var formatChangeStatus = function(state, escapeMarkup) {
220 220 var originalOption = state.element;
221 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
222 '<span>' + escapeMarkup(state.text) + '</span>';
221 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
222 return tmpl
223 223 };
224 224 var formatResult = function(result, container, query, escapeMarkup) {
225 225 return formatChangeStatus(result, escapeMarkup);
226 226 };
227 227
228 228 var formatSelection = function(data, container, escapeMarkup) {
229 229 return formatChangeStatus(data, escapeMarkup);
230 230 };
231 231
232 232 $(this.submitForm).find(this.statusChange).select2({
233 233 placeholder: _gettext('Status Review'),
234 234 formatResult: formatResult,
235 235 formatSelection: formatSelection,
236 236 containerCssClass: "drop-menu status_box_menu",
237 237 dropdownCssClass: "drop-menu-dropdown",
238 238 dropdownAutoWidth: true,
239 239 minimumResultsForSearch: -1
240 240 });
241 241 $(this.submitForm).find(this.statusChange).on('change', function() {
242 242 var status = self.getCommentStatus();
243 243
244 244 if (status && !self.isInline()) {
245 245 $(self.submitButton).prop('disabled', false);
246 246 }
247 247
248 248 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
249 249 self.setPlaceholder(placeholderText)
250 250 })
251 251 };
252 252
253 253 // reset the comment form into it's original state
254 254 this.resetCommentFormState = function(content) {
255 255 content = content || '';
256 256
257 257 $(this.editContainer).show();
258 258 $(this.editButton).parent().addClass('active');
259 259
260 260 $(this.previewContainer).hide();
261 261 $(this.previewButton).parent().removeClass('active');
262 262
263 263 this.setActionButtonsDisabled(true);
264 264 self.cm.setValue(content);
265 265 self.cm.setOption("readOnly", false);
266 266
267 267 if (this.resolvesId) {
268 268 // destroy the resolve action
269 269 $(this.resolvesId).parent().remove();
270 270 }
271 271 // reset closingPR flag
272 272 $('.close-pr-input').remove();
273 273
274 274 $(this.statusChange).select2('readonly', false);
275 275 };
276 276
277 277 this.globalSubmitSuccessCallback = function(){
278 278 // default behaviour is to call GLOBAL hook, if it's registered.
279 279 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
280 280 commentFormGlobalSubmitSuccessCallback()
281 281 }
282 282 };
283 283
284 284 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
285 285 return _submitAjaxPOST(url, postData, successHandler, failHandler);
286 286 };
287 287
288 288 // overwrite a submitHandler, we need to do it for inline comments
289 289 this.setHandleFormSubmit = function(callback) {
290 290 this.handleFormSubmit = callback;
291 291 };
292 292
293 293 // overwrite a submitSuccessHandler
294 294 this.setGlobalSubmitSuccessCallback = function(callback) {
295 295 this.globalSubmitSuccessCallback = callback;
296 296 };
297 297
298 298 // default handler for for submit for main comments
299 299 this.handleFormSubmit = function() {
300 300 var text = self.cm.getValue();
301 301 var status = self.getCommentStatus();
302 302 var commentType = self.getCommentType();
303 303 var resolvesCommentId = self.getResolvesId();
304 304 var closePullRequest = self.getClosePr();
305 305
306 306 if (text === "" && !status) {
307 307 return;
308 308 }
309 309
310 310 var excludeCancelBtn = false;
311 311 var submitEvent = true;
312 312 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
313 313 self.cm.setOption("readOnly", true);
314 314
315 315 var postData = {
316 316 'text': text,
317 317 'changeset_status': status,
318 318 'comment_type': commentType,
319 319 'csrf_token': CSRF_TOKEN
320 320 };
321 321
322 322 if (resolvesCommentId) {
323 323 postData['resolves_comment_id'] = resolvesCommentId;
324 324 }
325 325
326 326 if (closePullRequest) {
327 327 postData['close_pull_request'] = true;
328 328 }
329 329
330 330 var submitSuccessCallback = function(o) {
331 331 // reload page if we change status for single commit.
332 332 if (status && self.commitId) {
333 333 location.reload(true);
334 334 } else {
335 335 $('#injected_page_comments').append(o.rendered_text);
336 336 self.resetCommentFormState();
337 337 timeagoActivate();
338 338
339 339 // mark visually which comment was resolved
340 340 if (resolvesCommentId) {
341 341 self.markCommentResolved(resolvesCommentId);
342 342 }
343 343 }
344 344
345 345 // run global callback on submit
346 346 self.globalSubmitSuccessCallback();
347 347
348 348 };
349 349 var submitFailCallback = function(data) {
350 350 alert(
351 351 "Error while submitting comment.\n" +
352 352 "Error code {0} ({1}).".format(data.status, data.statusText)
353 353 );
354 354 self.resetCommentFormState(text);
355 355 };
356 356 self.submitAjaxPOST(
357 357 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
358 358 };
359 359
360 360 this.previewSuccessCallback = function(o) {
361 361 $(self.previewBoxSelector).html(o);
362 362 $(self.previewBoxSelector).removeClass('unloaded');
363 363
364 364 // swap buttons, making preview active
365 365 $(self.previewButton).parent().addClass('active');
366 366 $(self.editButton).parent().removeClass('active');
367 367
368 368 // unlock buttons
369 369 self.setActionButtonsDisabled(false);
370 370 };
371 371
372 372 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
373 373 excludeCancelBtn = excludeCancelBtn || false;
374 374 submitEvent = submitEvent || false;
375 375
376 376 $(this.editButton).prop('disabled', state);
377 377 $(this.previewButton).prop('disabled', state);
378 378
379 379 if (!excludeCancelBtn) {
380 380 $(this.cancelButton).prop('disabled', state);
381 381 }
382 382
383 383 var submitState = state;
384 384 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
385 385 // if the value of commit review status is set, we allow
386 386 // submit button, but only on Main form, isInline means inline
387 387 submitState = false
388 388 }
389 389
390 390 $(this.submitButton).prop('disabled', submitState);
391 391 if (submitEvent) {
392 392 $(this.submitButton).val(_gettext('Submitting...'));
393 393 } else {
394 394 $(this.submitButton).val(this.submitButtonText);
395 395 }
396 396
397 397 };
398 398
399 399 // lock preview/edit/submit buttons on load, but exclude cancel button
400 400 var excludeCancelBtn = true;
401 401 this.setActionButtonsDisabled(true, excludeCancelBtn);
402 402
403 403 // anonymous users don't have access to initialized CM instance
404 404 if (this.cm !== undefined){
405 405 this.cm.on('change', function(cMirror) {
406 406 if (cMirror.getValue() === "") {
407 407 self.setActionButtonsDisabled(true, excludeCancelBtn)
408 408 } else {
409 409 self.setActionButtonsDisabled(false, excludeCancelBtn)
410 410 }
411 411 });
412 412 }
413 413
414 414 $(this.editButton).on('click', function(e) {
415 415 e.preventDefault();
416 416
417 417 $(self.previewButton).parent().removeClass('active');
418 418 $(self.previewContainer).hide();
419 419
420 420 $(self.editButton).parent().addClass('active');
421 421 $(self.editContainer).show();
422 422
423 423 });
424 424
425 425 $(this.previewButton).on('click', function(e) {
426 426 e.preventDefault();
427 427 var text = self.cm.getValue();
428 428
429 429 if (text === "") {
430 430 return;
431 431 }
432 432
433 433 var postData = {
434 434 'text': text,
435 435 'renderer': templateContext.visual.default_renderer,
436 436 'csrf_token': CSRF_TOKEN
437 437 };
438 438
439 439 // lock ALL buttons on preview
440 440 self.setActionButtonsDisabled(true);
441 441
442 442 $(self.previewBoxSelector).addClass('unloaded');
443 443 $(self.previewBoxSelector).html(_gettext('Loading ...'));
444 444
445 445 $(self.editContainer).hide();
446 446 $(self.previewContainer).show();
447 447
448 448 // by default we reset state of comment preserving the text
449 449 var previewFailCallback = function(data){
450 450 alert(
451 451 "Error while preview of comment.\n" +
452 452 "Error code {0} ({1}).".format(data.status, data.statusText)
453 453 );
454 454 self.resetCommentFormState(text)
455 455 };
456 456 self.submitAjaxPOST(
457 457 self.previewUrl, postData, self.previewSuccessCallback,
458 458 previewFailCallback);
459 459
460 460 $(self.previewButton).parent().addClass('active');
461 461 $(self.editButton).parent().removeClass('active');
462 462 });
463 463
464 464 $(this.submitForm).submit(function(e) {
465 465 e.preventDefault();
466 466 var allowedToSubmit = self.isAllowedToSubmit();
467 467 if (!allowedToSubmit){
468 468 return false;
469 469 }
470 470 self.handleFormSubmit();
471 471 });
472 472
473 473 }
474 474
475 475 return CommentForm;
476 476 });
477 477
478 478 /* comments controller */
479 479 var CommentsController = function() {
480 480 var mainComment = '#text';
481 481 var self = this;
482 482
483 483 this.cancelComment = function(node) {
484 484 var $node = $(node);
485 485 var $td = $node.closest('td');
486 486 $node.closest('.comment-inline-form').remove();
487 487 return false;
488 488 };
489 489
490 490 this.getLineNumber = function(node) {
491 491 var $node = $(node);
492 492 var lineNo = $node.closest('td').attr('data-line-no');
493 493 if (lineNo === undefined && $node.data('commentInline')){
494 494 lineNo = $node.data('commentLineNo')
495 495 }
496 496
497 497 return lineNo
498 498 };
499 499
500 500 this.scrollToComment = function(node, offset, outdated) {
501 501 if (offset === undefined) {
502 502 offset = 0;
503 503 }
504 504 var outdated = outdated || false;
505 505 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
506 506
507 507 if (!node) {
508 508 node = $('.comment-selected');
509 509 if (!node.length) {
510 510 node = $('comment-current')
511 511 }
512 512 }
513 513 $wrapper = $(node).closest('div.comment');
514 514 $comment = $(node).closest(klass);
515 515 $comments = $(klass);
516 516
517 517 // show hidden comment when referenced.
518 518 if (!$wrapper.is(':visible')){
519 519 $wrapper.show();
520 520 }
521 521
522 522 $('.comment-selected').removeClass('comment-selected');
523 523
524 524 var nextIdx = $(klass).index($comment) + offset;
525 525 if (nextIdx >= $comments.length) {
526 526 nextIdx = 0;
527 527 }
528 528 var $next = $(klass).eq(nextIdx);
529 529
530 530 var $cb = $next.closest('.cb');
531 531 $cb.removeClass('cb-collapsed');
532 532
533 533 var $filediffCollapseState = $cb.closest('.filediff').prev();
534 534 $filediffCollapseState.prop('checked', false);
535 535 $next.addClass('comment-selected');
536 536 scrollToElement($next);
537 537 return false;
538 538 };
539 539
540 540 this.nextComment = function(node) {
541 541 return self.scrollToComment(node, 1);
542 542 };
543 543
544 544 this.prevComment = function(node) {
545 545 return self.scrollToComment(node, -1);
546 546 };
547 547
548 548 this.nextOutdatedComment = function(node) {
549 549 return self.scrollToComment(node, 1, true);
550 550 };
551 551
552 552 this.prevOutdatedComment = function(node) {
553 553 return self.scrollToComment(node, -1, true);
554 554 };
555 555
556 556 this.deleteComment = function(node) {
557 557 if (!confirm(_gettext('Delete this comment?'))) {
558 558 return false;
559 559 }
560 560 var $node = $(node);
561 561 var $td = $node.closest('td');
562 562 var $comment = $node.closest('.comment');
563 563 var comment_id = $comment.attr('data-comment-id');
564 564 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
565 565 var postData = {
566 566 'csrf_token': CSRF_TOKEN
567 567 };
568 568
569 569 $comment.addClass('comment-deleting');
570 570 $comment.hide('fast');
571 571
572 572 var success = function(response) {
573 573 $comment.remove();
574 574 return false;
575 575 };
576 576 var failure = function(data, textStatus, xhr) {
577 577 alert("error processing request: " + textStatus);
578 578 $comment.show('fast');
579 579 $comment.removeClass('comment-deleting');
580 580 return false;
581 581 };
582 582 ajaxPOST(url, postData, success, failure);
583 583 };
584 584
585 585 this.toggleWideMode = function (node) {
586 586 if ($('#content').hasClass('wrapper')) {
587 587 $('#content').removeClass("wrapper");
588 588 $('#content').addClass("wide-mode-wrapper");
589 589 $(node).addClass('btn-success');
590 590 return true
591 591 } else {
592 592 $('#content').removeClass("wide-mode-wrapper");
593 593 $('#content').addClass("wrapper");
594 594 $(node).removeClass('btn-success');
595 595 return false
596 596 }
597 597
598 598 };
599 599
600 600 this.toggleComments = function(node, show) {
601 601 var $filediff = $(node).closest('.filediff');
602 602 if (show === true) {
603 603 $filediff.removeClass('hide-comments');
604 604 } else if (show === false) {
605 605 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
606 606 $filediff.addClass('hide-comments');
607 607 } else {
608 608 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
609 609 $filediff.toggleClass('hide-comments');
610 610 }
611 611 return false;
612 612 };
613 613
614 614 this.toggleLineComments = function(node) {
615 615 self.toggleComments(node, true);
616 616 var $node = $(node);
617 617 // mark outdated comments as visible before the toggle;
618 618 $(node.closest('tr')).find('.comment-outdated').show();
619 619 $node.closest('tr').toggleClass('hide-line-comments');
620 620 };
621 621
622 622 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
623 623 var pullRequestId = templateContext.pull_request_data.pull_request_id;
624 624 var commitId = templateContext.commit_data.commit_id;
625 625
626 626 var commentForm = new CommentForm(
627 627 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
628 628 var cm = commentForm.getCmInstance();
629 629
630 630 if (resolvesCommentId){
631 631 var placeholderText = _gettext('Leave a comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
632 632 }
633 633
634 634 setTimeout(function() {
635 635 // callbacks
636 636 if (cm !== undefined) {
637 637 commentForm.setPlaceholder(placeholderText);
638 638 if (commentForm.isInline()) {
639 639 cm.focus();
640 640 cm.refresh();
641 641 }
642 642 }
643 643 }, 10);
644 644
645 645 // trigger scrolldown to the resolve comment, since it might be away
646 646 // from the clicked
647 647 if (resolvesCommentId){
648 648 var actionNode = $(commentForm.resolvesActionId).offset();
649 649
650 650 setTimeout(function() {
651 651 if (actionNode) {
652 652 $('body, html').animate({scrollTop: actionNode.top}, 10);
653 653 }
654 654 }, 100);
655 655 }
656 656
657 657 return commentForm;
658 658 };
659 659
660 660 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
661 661
662 662 var tmpl = $('#cb-comment-general-form-template').html();
663 663 tmpl = tmpl.format(null, 'general');
664 664 var $form = $(tmpl);
665 665
666 666 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
667 667 var curForm = $formPlaceholder.find('form');
668 668 if (curForm){
669 669 curForm.remove();
670 670 }
671 671 $formPlaceholder.append($form);
672 672
673 673 var _form = $($form[0]);
674 674 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
675 675 var commentForm = this.createCommentForm(
676 676 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId);
677 677 commentForm.initStatusChangeSelector();
678 678
679 679 return commentForm;
680 680 };
681 681
682 682 this.createComment = function(node, resolutionComment) {
683 683 var resolvesCommentId = resolutionComment || null;
684 684 var $node = $(node);
685 685 var $td = $node.closest('td');
686 686 var $form = $td.find('.comment-inline-form');
687 687
688 688 if (!$form.length) {
689 689
690 690 var $filediff = $node.closest('.filediff');
691 691 $filediff.removeClass('hide-comments');
692 692 var f_path = $filediff.attr('data-f-path');
693 693 var lineno = self.getLineNumber(node);
694 694 // create a new HTML from template
695 695 var tmpl = $('#cb-comment-inline-form-template').html();
696 696 tmpl = tmpl.format(escapeHtml(f_path), lineno);
697 697 $form = $(tmpl);
698 698
699 699 var $comments = $td.find('.inline-comments');
700 700 if (!$comments.length) {
701 701 $comments = $(
702 702 $('#cb-comments-inline-container-template').html());
703 703 $td.append($comments);
704 704 }
705 705
706 706 $td.find('.cb-comment-add-button').before($form);
707 707
708 708 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
709 709 var _form = $($form[0]).find('form');
710 710 var autocompleteActions = ['as_note', 'as_todo'];
711 711 var commentForm = this.createCommentForm(
712 712 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId);
713 713
714 714 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
715 715 form: _form,
716 716 parent: $td[0],
717 717 lineno: lineno,
718 718 f_path: f_path}
719 719 );
720 720
721 721 // set a CUSTOM submit handler for inline comments.
722 722 commentForm.setHandleFormSubmit(function(o) {
723 723 var text = commentForm.cm.getValue();
724 724 var commentType = commentForm.getCommentType();
725 725 var resolvesCommentId = commentForm.getResolvesId();
726 726
727 727 if (text === "") {
728 728 return;
729 729 }
730 730
731 731 if (lineno === undefined) {
732 732 alert('missing line !');
733 733 return;
734 734 }
735 735 if (f_path === undefined) {
736 736 alert('missing file path !');
737 737 return;
738 738 }
739 739
740 740 var excludeCancelBtn = false;
741 741 var submitEvent = true;
742 742 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
743 743 commentForm.cm.setOption("readOnly", true);
744 744 var postData = {
745 745 'text': text,
746 746 'f_path': f_path,
747 747 'line': lineno,
748 748 'comment_type': commentType,
749 749 'csrf_token': CSRF_TOKEN
750 750 };
751 751 if (resolvesCommentId){
752 752 postData['resolves_comment_id'] = resolvesCommentId;
753 753 }
754 754
755 755 var submitSuccessCallback = function(json_data) {
756 756 $form.remove();
757 757 try {
758 758 var html = json_data.rendered_text;
759 759 var lineno = json_data.line_no;
760 760 var target_id = json_data.target_id;
761 761
762 762 $comments.find('.cb-comment-add-button').before(html);
763 763
764 764 //mark visually which comment was resolved
765 765 if (resolvesCommentId) {
766 766 commentForm.markCommentResolved(resolvesCommentId);
767 767 }
768 768
769 769 // run global callback on submit
770 770 commentForm.globalSubmitSuccessCallback();
771 771
772 772 } catch (e) {
773 773 console.error(e);
774 774 }
775 775
776 776 // re trigger the linkification of next/prev navigation
777 777 linkifyComments($('.inline-comment-injected'));
778 778 timeagoActivate();
779 779
780 780 if (window.updateSticky !== undefined) {
781 781 // potentially our comments change the active window size, so we
782 782 // notify sticky elements
783 783 updateSticky()
784 784 }
785 785
786 786 commentForm.setActionButtonsDisabled(false);
787 787
788 788 };
789 789 var submitFailCallback = function(data){
790 790 alert(
791 791 "Error while submitting comment.\n" +
792 792 "Error code {0} ({1}).".format(data.status, data.statusText)
793 793 );
794 794 commentForm.resetCommentFormState(text)
795 795 };
796 796 commentForm.submitAjaxPOST(
797 797 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
798 798 });
799 799 }
800 800
801 801 $form.addClass('comment-inline-form-open');
802 802 };
803 803
804 804 this.createResolutionComment = function(commentId){
805 805 // hide the trigger text
806 806 $('#resolve-comment-{0}'.format(commentId)).hide();
807 807
808 808 var comment = $('#comment-'+commentId);
809 809 var commentData = comment.data();
810 810 if (commentData.commentInline) {
811 811 this.createComment(comment, commentId)
812 812 } else {
813 813 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
814 814 }
815 815
816 816 return false;
817 817 };
818 818
819 819 this.submitResolution = function(commentId){
820 820 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
821 821 var commentForm = form.get(0).CommentForm;
822 822
823 823 var cm = commentForm.getCmInstance();
824 824 var renderer = templateContext.visual.default_renderer;
825 825 if (renderer == 'rst'){
826 826 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
827 827 } else if (renderer == 'markdown') {
828 828 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
829 829 } else {
830 830 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
831 831 }
832 832
833 833 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
834 834 form.submit();
835 835 return false;
836 836 };
837 837
838 838 };
@@ -1,407 +1,407 b''
1 1 ## -*- coding: utf-8 -*-
2 2 ## usage:
3 3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
4 4 ## ${comment.comment_block(comment)}
5 5 ##
6 6 <%namespace name="base" file="/base/base.mako"/>
7 7
8 8 <%def name="comment_block(comment, inline=False)">
9 9 <% pr_index_ver = comment.get_index_version(getattr(c, 'versions', [])) %>
10 10 <% latest_ver = len(getattr(c, 'versions', [])) %>
11 11 % if inline:
12 12 <% outdated_at_ver = comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
13 13 % else:
14 14 <% outdated_at_ver = comment.older_than_version(getattr(c, 'at_version_num', None)) %>
15 15 % endif
16 16
17 17
18 18 <div class="comment
19 19 ${'comment-inline' if inline else 'comment-general'}
20 20 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
21 21 id="comment-${comment.comment_id}"
22 22 line="${comment.line_no}"
23 23 data-comment-id="${comment.comment_id}"
24 24 data-comment-type="${comment.comment_type}"
25 25 data-comment-line-no="${comment.line_no}"
26 26 data-comment-inline=${h.json.dumps(inline)}
27 27 style="${'display: none;' if outdated_at_ver else ''}">
28 28
29 29 <div class="meta">
30 30 <div class="comment-type-label">
31 31 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}" title="line: ${comment.line_no}">
32 32 % if comment.comment_type == 'todo':
33 33 % if comment.resolved:
34 34 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
35 35 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
36 36 </div>
37 37 % else:
38 38 <div class="resolved tooltip" style="display: none">
39 39 <span>${comment.comment_type}</span>
40 40 </div>
41 41 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to resolve this comment')}">
42 42 ${comment.comment_type}
43 43 </div>
44 44 % endif
45 45 % else:
46 46 % if comment.resolved_comment:
47 47 fix
48 48 % else:
49 49 ${comment.comment_type or 'note'}
50 50 % endif
51 51 % endif
52 52 </div>
53 53 </div>
54 54
55 55 <div class="author ${'author-inline' if inline else 'author-general'}">
56 56 ${base.gravatar_with_user(comment.author.email, 16)}
57 57 </div>
58 58 <div class="date">
59 59 ${h.age_component(comment.modified_at, time_is_local=True)}
60 60 </div>
61 61 % if inline:
62 62 <span></span>
63 63 % else:
64 64 <div class="status-change">
65 65 % if comment.pull_request:
66 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 67 % if comment.status_change:
68 68 ${_('pull request #%s') % comment.pull_request.pull_request_id}:
69 69 % else:
70 70 ${_('pull request #%s') % comment.pull_request.pull_request_id}
71 71 % endif
72 72 </a>
73 73 % else:
74 74 % if comment.status_change:
75 75 ${_('Status change on commit')}:
76 76 % endif
77 77 % endif
78 78 </div>
79 79 % endif
80 80
81 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 83 <div title="${_('Commit status')}" class="changeset-status-lbl">
84 84 ${comment.status_change[0].status_lbl}
85 85 </div>
86 86 % endif
87 87
88 88 % if comment.resolved_comment:
89 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 90 ${_('resolves comment #{}').format(comment.resolved_comment.comment_id)}
91 91 </a>
92 92 % endif
93 93
94 94 <a class="permalink" href="#comment-${comment.comment_id}"> &para;</a>
95 95
96 96 <div class="comment-links-block">
97 97 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
98 98 <span class="tag authortag tooltip" title="${_('Pull request author')}">
99 99 ${_('author')}
100 100 </span>
101 101 |
102 102 % endif
103 103 % if inline:
104 104 <div class="pr-version-inline">
105 105 <a href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
106 106 % if outdated_at_ver:
107 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 108 outdated ${'v{}'.format(pr_index_ver)} |
109 109 </code>
110 110 % elif pr_index_ver:
111 111 <code class="pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
112 112 ${'v{}'.format(pr_index_ver)} |
113 113 </code>
114 114 % endif
115 115 </a>
116 116 </div>
117 117 % else:
118 118 % if comment.pull_request_version_id and pr_index_ver:
119 119 |
120 120 <div class="pr-version">
121 121 % if comment.outdated:
122 122 <a href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}">
123 123 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}
124 124 </a>
125 125 % else:
126 126 <div title="${_('Comment from pull request version v{0}, latest v{1}').format(pr_index_ver, latest_ver)}">
127 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 128 <code class="pr-version-num">
129 129 ${'v{}'.format(pr_index_ver)}
130 130 </code>
131 131 </a>
132 132 </div>
133 133 % endif
134 134 </div>
135 135 % endif
136 136 % endif
137 137
138 138 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
139 139 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
140 140 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
141 141 ## permissions to delete
142 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 143 ## TODO: dan: add edit comment here
144 144 <a onclick="return Rhodecode.comments.deleteComment(this);" class="delete-comment"> ${_('Delete')}</a>
145 145 %else:
146 146 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
147 147 %endif
148 148 %else:
149 149 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
150 150 %endif
151 151
152 152 % if outdated_at_ver:
153 153 | <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="prev-comment"> ${_('Prev')}</a>
154 154 | <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="next-comment"> ${_('Next')}</a>
155 155 % else:
156 156 | <a onclick="return Rhodecode.comments.prevComment(this);" class="prev-comment"> ${_('Prev')}</a>
157 157 | <a onclick="return Rhodecode.comments.nextComment(this);" class="next-comment"> ${_('Next')}</a>
158 158 % endif
159 159
160 160 </div>
161 161 </div>
162 162 <div class="text">
163 163 ${h.render(comment.text, renderer=comment.renderer, mentions=True)}
164 164 </div>
165 165
166 166 </div>
167 167 </%def>
168 168
169 169 ## generate main comments
170 170 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
171 171 <div class="general-comments" id="comments">
172 172 %for comment in comments:
173 173 <div id="comment-tr-${comment.comment_id}">
174 174 ## only render comments that are not from pull request, or from
175 175 ## pull request and a status change
176 176 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
177 177 ${comment_block(comment)}
178 178 %endif
179 179 </div>
180 180 %endfor
181 181 ## to anchor ajax comments
182 182 <div id="injected_page_comments"></div>
183 183 </div>
184 184 </%def>
185 185
186 186
187 187 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
188 188
189 189 <div class="comments">
190 190 <%
191 191 if is_pull_request:
192 192 placeholder = _('Leave a comment on this Pull Request.')
193 193 elif is_compare:
194 194 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
195 195 else:
196 196 placeholder = _('Leave a comment on this Commit.')
197 197 %>
198 198
199 199 % if c.rhodecode_user.username != h.DEFAULT_USER:
200 200 <div class="js-template" id="cb-comment-general-form-template">
201 201 ## template generated for injection
202 202 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
203 203 </div>
204 204
205 205 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
206 206 ## inject form here
207 207 </div>
208 208 <script type="text/javascript">
209 209 var lineNo = 'general';
210 210 var resolvesCommentId = null;
211 211 var generalCommentForm = Rhodecode.comments.createGeneralComment(
212 212 lineNo, "${placeholder}", resolvesCommentId);
213 213
214 214 // set custom success callback on rangeCommit
215 215 % if is_compare:
216 216 generalCommentForm.setHandleFormSubmit(function(o) {
217 217 var self = generalCommentForm;
218 218
219 219 var text = self.cm.getValue();
220 220 var status = self.getCommentStatus();
221 221 var commentType = self.getCommentType();
222 222
223 223 if (text === "" && !status) {
224 224 return;
225 225 }
226 226
227 227 // we can pick which commits we want to make the comment by
228 228 // selecting them via click on preview pane, this will alter the hidden inputs
229 229 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
230 230
231 231 var commitIds = [];
232 232 $('#changeset_compare_view_content .compare_select').each(function(el) {
233 233 var commitId = this.id.replace('row-', '');
234 234 if ($(this).hasClass('hl') || !cherryPicked) {
235 235 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
236 236 commitIds.push(commitId);
237 237 } else {
238 238 $("input[data-commit-id='{0}']".format(commitId)).val('')
239 239 }
240 240 });
241 241
242 242 self.setActionButtonsDisabled(true);
243 243 self.cm.setOption("readOnly", true);
244 244 var postData = {
245 245 'text': text,
246 246 'changeset_status': status,
247 247 'comment_type': commentType,
248 248 'commit_ids': commitIds,
249 249 'csrf_token': CSRF_TOKEN
250 250 };
251 251
252 252 var submitSuccessCallback = function(o) {
253 253 location.reload(true);
254 254 };
255 255 var submitFailCallback = function(){
256 256 self.resetCommentFormState(text)
257 257 };
258 258 self.submitAjaxPOST(
259 259 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
260 260 });
261 261 % endif
262 262
263 263
264 264 </script>
265 265 % else:
266 266 ## form state when not logged in
267 267 <div class="comment-form ac">
268 268
269 269 <div class="comment-area">
270 270 <div class="comment-area-header">
271 271 <ul class="nav-links clearfix">
272 272 <li class="active">
273 273 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
274 274 </li>
275 275 <li class="">
276 276 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
277 277 </li>
278 278 </ul>
279 279 </div>
280 280
281 281 <div class="comment-area-write" style="display: block;">
282 282 <div id="edit-container">
283 283 <div style="padding: 40px 0">
284 284 ${_('You need to be logged in to leave comments.')}
285 285 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
286 286 </div>
287 287 </div>
288 288 <div id="preview-container" class="clearfix" style="display: none;">
289 289 <div id="preview-box" class="preview-box"></div>
290 290 </div>
291 291 </div>
292 292
293 293 <div class="comment-area-footer">
294 294 <div class="toolbar">
295 295 <div class="toolbar-text">
296 296 </div>
297 297 </div>
298 298 </div>
299 299 </div>
300 300
301 301 <div class="comment-footer">
302 302 </div>
303 303
304 304 </div>
305 305 % endif
306 306
307 307 <script type="text/javascript">
308 308 bindToggleButtons();
309 309 </script>
310 310 </div>
311 311 </%def>
312 312
313 313
314 314 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
315 315 ## comment injected based on assumption that user is logged in
316 316
317 317 <form ${'id="{}"'.format(form_id) if form_id else '' |n} action="#" method="GET">
318 318
319 319 <div class="comment-area">
320 320 <div class="comment-area-header">
321 321 <ul class="nav-links clearfix">
322 322 <li class="active">
323 323 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
324 324 </li>
325 325 <li class="">
326 326 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
327 327 </li>
328 328 <li class="pull-right">
329 329 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
330 330 % for val in c.visual.comment_types:
331 331 <option value="${val}">${val.upper()}</option>
332 332 % endfor
333 333 </select>
334 334 </li>
335 335 </ul>
336 336 </div>
337 337
338 338 <div class="comment-area-write" style="display: block;">
339 339 <div id="edit-container_${lineno_id}">
340 340 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
341 341 </div>
342 342 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
343 343 <div id="preview-box_${lineno_id}" class="preview-box"></div>
344 344 </div>
345 345 </div>
346 346
347 347 <div class="comment-area-footer">
348 348 <div class="toolbar">
349 349 <div class="toolbar-text">
350 350 ${(_('Comments parsed using %s syntax with %s, and %s actions support.') % (
351 351 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
352 352 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user')),
353 353 ('<span class="tooltip" title="%s">`/`</span>' % _('Start typing with / for certain actions to be triggered via text box.'))
354 354 )
355 355 )|n}
356 356 </div>
357 357 </div>
358 358 </div>
359 359 </div>
360 360
361 361 <div class="comment-footer">
362 362
363 363 % if review_statuses:
364 364 <div class="status_box">
365 365 <select id="change_status_${lineno_id}" name="changeset_status">
366 366 <option></option> ## Placeholder
367 367 % for status, lbl in review_statuses:
368 368 <option value="${status}" data-status="${status}">${lbl}</option>
369 369 %if is_pull_request and change_status and status in ('approved', 'rejected'):
370 370 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
371 371 %endif
372 372 % endfor
373 373 </select>
374 374 </div>
375 375 % endif
376 376
377 377 ## inject extra inputs into the form
378 378 % if form_extras and isinstance(form_extras, (list, tuple)):
379 379 <div id="comment_form_extras">
380 380 % for form_ex_el in form_extras:
381 381 ${form_ex_el|n}
382 382 % endfor
383 383 </div>
384 384 % endif
385 385
386 386 <div class="action-buttons">
387 387 ## inline for has a file, and line-number together with cancel hide button.
388 388 % if form_type == 'inline':
389 389 <input type="hidden" name="f_path" value="{0}">
390 390 <input type="hidden" name="line" value="${lineno_id}">
391 391 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
392 392 ${_('Cancel')}
393 393 </button>
394 394 % endif
395 395
396 396 % if form_type != 'inline':
397 397 <div class="action-buttons-extra"></div>
398 398 % endif
399 399
400 400 ${h.submit('save', _('Comment'), class_='btn btn-success comment-button-input')}
401 401
402 402 </div>
403 403 </div>
404 404
405 405 </form>
406 406
407 407 </%def> No newline at end of file
@@ -1,159 +1,159 b''
1 1 ## small box that displays changed/added/removed details fetched by AJAX
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3
4 4 % if c.prev_page:
5 5 <tr>
6 6 <td colspan="10" class="load-more-commits">
7 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 8 ${_('load previous')}
9 9 </a>
10 10 </td>
11 11 </tr>
12 12 % endif
13 13
14 14 ## to speed up lookups cache some functions before the loop
15 15 <%
16 16 active_patterns = h.get_active_pattern_entries(c.repo_name)
17 17 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
18 18 %>
19 19
20 20 % for cnt,commit in enumerate(c.pagination):
21 21 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
22 22
23 23 <td class="td-checkbox">
24 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 25 </td>
26 26 ##
27 27 <td class="td-graphbox">
28 28
29 29 </td>
30 30
31 31 <td class="td-status">
32 32 %if c.statuses.get(commit.raw_id):
33 33 <div class="changeset-status-ico">
34 34 %if c.statuses.get(commit.raw_id)[2]:
35 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 37 </a>
38 38 %else:
39 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 41 </a>
42 42 %endif
43 43 </div>
44 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 46 %endif
47 47 </td>
48 48
49 49 <td class="td-hash">
50 50 <code>
51 51
52 52 <a href="${h.route_path('repo_commit',repo_name=c.repo_name,commit_id=commit.raw_id)}">
53 53 <span class="${'commit_hash obsolete' if getattr(commit, 'obsolete', None) else 'commit_hash'}">${h.show_id(commit)}</span>
54 54 </a>
55 55
56 56 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${commit.raw_id}" title="${_('Copy the full commit id')}"></i>
57 57
58 58 ## COMMIT PHASES
59 59
60 60 ## Draft
61 61 % if hasattr(commit, 'phase'):
62 62 % if commit.phase != 'public':
63 63 <span class="tag phase-${commit.phase} tooltip" title="${_('{} commit phase').format(commit.phase)}">${commit.phase[0].upper()}</span>
64 64 % endif
65 65 % endif
66 66
67 67 ## obsolete commits
68 68 % if hasattr(commit, 'obsolete') and commit.obsolete:
69 69 <span class="tag obsolete-${commit.obsolete} tooltip" title="${_('Obsolete Evolve State')}">O</span>
70 70 % endif
71 71
72 72 ## hidden commits
73 73 % if hasattr(commit, 'hidden') and commit.hidden:
74 74 <span class="tag obsolete-${commit.hidden} tooltip" title="${_('Hidden Evolve State')}">H</span>
75 75 % endif
76 76
77 77 </code>
78 78 </td>
79 79
80 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 81 <i class="icon-expand-linked"></i>&nbsp;
82 82 </td>
83 83 <td class="td-description mid">
84 84 <div class="log-container truncate-wrap">
85 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 86 </div>
87 87 </td>
88 88
89 89 <td class="td-time">
90 90 ${h.age_component(commit.date)}
91 91 </td>
92 92 <td class="td-user">
93 93 ${base.gravatar_with_user(commit.author)}
94 94 </td>
95 95
96 96 <td class="td-tags tags-col">
97 97 <div id="t-${commit.raw_id}">
98 98
99 99 ## merge
100 100 %if commit.merge:
101 101 <span class="tag mergetag">
102 102 <i class="icon-merge"></i>${_('merge')}
103 103 </span>
104 104 %endif
105 105
106 106 ## branch
107 107 %if commit.branch:
108 108 <span class="tag branchtag" title="${h.tooltip(_('Branch %s') % commit.branch)}">
109 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 110 </span>
111 111 %endif
112 112
113 113 ## bookmarks
114 114 %if h.is_hg(c.rhodecode_repo):
115 115 %for book in commit.bookmarks:
116 116 <span class="tag booktag" title="${h.tooltip(_('Bookmark %s') % book)}">
117 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 118 </span>
119 119 %endfor
120 120 %endif
121 121
122 122 ## tags
123 123 %for tag in commit.tags:
124 124 <span class="tag tagtag" title="${h.tooltip(_('Tag %s') % tag)}">
125 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 126 </span>
127 127 %endfor
128 128
129 129 </div>
130 130 </td>
131 131
132 132 <td class="td-comments comments-col">
133 133 <% cs_comments = c.comments.get(commit.raw_id,[]) %>
134 134 % if cs_comments:
135 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 136 <i class="icon-comment"></i> ${len(cs_comments)}
137 137 </a>
138 138 % else:
139 139 <i class="icon-comment"></i> ${len(cs_comments)}
140 140 % endif
141 141 </td>
142 142
143 143 </tr>
144 144 % endfor
145 145
146 146 % if c.next_page:
147 147 <tr>
148 148 <td colspan="10" class="load-more-commits">
149 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 150 ${_('load next')}
151 151 </a>
152 152 </td>
153 153 </tr>
154 154 % endif
155 155 <tr class="chunk-graph-data" style="display:none"
156 156 data-graph='${c.graph_data|n}'
157 157 data-node='${c.prev_page}:${c.next_page}'
158 158 data-commits='${c.graph_commits|n}'>
159 159 </tr> No newline at end of file
@@ -1,452 +1,453 b''
1 1 ## DATA TABLE RE USABLE ELEMENTS
2 2 ## usage:
3 3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 4 <%namespace name="base" file="/base/base.mako"/>
5 5
6 6 <%def name="metatags_help()">
7 7 <table>
8 8 <%
9 9 example_tags = [
10 10 ('state','[stable]'),
11 11 ('state','[stale]'),
12 12 ('state','[featured]'),
13 13 ('state','[dev]'),
14 14 ('state','[dead]'),
15 15 ('state','[deprecated]'),
16 16
17 17 ('label','[personal]'),
18 18 ('generic','[v2.0.0]'),
19 19
20 20 ('lang','[lang =&gt; JavaScript]'),
21 21 ('license','[license =&gt; LicenseName]'),
22 22
23 23 ('ref','[requires =&gt; RepoName]'),
24 24 ('ref','[recommends =&gt; GroupName]'),
25 25 ('ref','[conflicts =&gt; SomeName]'),
26 26 ('ref','[base =&gt; SomeName]'),
27 27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
28 28 ('see','[see =&gt; http://rhodecode.com]'),
29 29 ]
30 30 %>
31 31 % for tag_type, tag in example_tags:
32 32 <tr>
33 33 <td>${tag|n}</td>
34 34 <td>${h.style_metatag(tag_type, tag)|n}</td>
35 35 </tr>
36 36 % endfor
37 37 </table>
38 38 </%def>
39 39
40 40 ## REPOSITORY RENDERERS
41 41 <%def name="quick_menu(repo_name)">
42 42 <i class="icon-more"></i>
43 43 <div class="menu_items_container hidden">
44 44 <ul class="menu_items">
45 45 <li>
46 46 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
47 47 <span>${_('Summary')}</span>
48 48 </a>
49 49 </li>
50 50 <li>
51 51 <a title="${_('Commits')}" href="${h.route_path('repo_commits',repo_name=repo_name)}">
52 52 <span>${_('Commits')}</span>
53 53 </a>
54 54 </li>
55 55 <li>
56 56 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
57 57 <span>${_('Files')}</span>
58 58 </a>
59 59 </li>
60 60 <li>
61 61 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
62 62 <span>${_('Fork')}</span>
63 63 </a>
64 64 </li>
65 65 </ul>
66 66 </div>
67 67 </%def>
68 68
69 69 <%def name="repo_name(name,rtype,rstate,private,archived,fork_of,short_name=False,admin=False)">
70 70 <%
71 71 def get_name(name,short_name=short_name):
72 72 if short_name:
73 73 return name.split('/')[-1]
74 74 else:
75 75 return name
76 76 %>
77 77 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
78 78 ##NAME
79 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 81 ##TYPE OF REPO
82 82 %if h.is_hg(rtype):
83 83 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
84 84 %elif h.is_git(rtype):
85 85 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
86 86 %elif h.is_svn(rtype):
87 87 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
88 88 %endif
89 89
90 90 ##PRIVATE/PUBLIC
91 91 %if private is True and c.visual.show_private_icon:
92 92 <i class="icon-lock" title="${_('Private repository')}"></i>
93 93 %elif private is False and c.visual.show_public_icon:
94 94 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
95 95 %else:
96 96 <span></span>
97 97 %endif
98 98 ${get_name(name)}
99 99 </a>
100 100 %if fork_of:
101 101 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
102 102 %endif
103 103 %if rstate == 'repo_state_pending':
104 104 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
105 105 (${_('creating...')})
106 106 </span>
107 107 %endif
108 108
109 109 </div>
110 110 </%def>
111 111
112 112 <%def name="repo_desc(description, stylify_metatags)">
113 113 <%
114 114 tags, description = h.extract_metatags(description)
115 115 %>
116 116
117 117 <div class="truncate-wrap">
118 118 % if stylify_metatags:
119 119 % for tag_type, tag in tags:
120 120 ${h.style_metatag(tag_type, tag)|n}
121 121 % endfor
122 122 % endif
123 123 ${description}
124 124 </div>
125 125
126 126 </%def>
127 127
128 128 <%def name="last_change(last_change)">
129 129 ${h.age_component(last_change, time_is_local=True)}
130 130 </%def>
131 131
132 132 <%def name="revision(name,rev,tip,author,last_msg, commit_date)">
133 133 <div>
134 134 %if rev >= 0:
135 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 136 %else:
137 137 ${_('No commits yet')}
138 138 %endif
139 139 </div>
140 140 </%def>
141 141
142 142 <%def name="rss(name)">
143 143 %if c.rhodecode_user.username != h.DEFAULT_USER:
144 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 145 %else:
146 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 147 %endif
148 148 </%def>
149 149
150 150 <%def name="atom(name)">
151 151 %if c.rhodecode_user.username != h.DEFAULT_USER:
152 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 153 %else:
154 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 155 %endif
156 156 </%def>
157 157
158 158 <%def name="user_gravatar(email, size=16)">
159 159 <div class="rc-user tooltip" title="${h.tooltip(h.author_string(email))}">
160 160 ${base.gravatar(email, 16)}
161 161 </div>
162 162 </%def>
163 163
164 164 <%def name="repo_actions(repo_name, super_user=True)">
165 165 <div>
166 166 <div class="grid_edit">
167 167 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
168 168 Edit
169 169 </a>
170 170 </div>
171 171 <div class="grid_delete">
172 172 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
173 173 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger",
174 174 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
175 175 ${h.end_form()}
176 176 </div>
177 177 </div>
178 178 </%def>
179 179
180 180 <%def name="repo_state(repo_state)">
181 181 <div>
182 182 %if repo_state == 'repo_state_pending':
183 183 <div class="tag tag4">${_('Creating')}</div>
184 184 %elif repo_state == 'repo_state_created':
185 185 <div class="tag tag1">${_('Created')}</div>
186 186 %else:
187 187 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
188 188 %endif
189 189 </div>
190 190 </%def>
191 191
192 192
193 193 ## REPO GROUP RENDERERS
194 194 <%def name="quick_repo_group_menu(repo_group_name)">
195 195 <i class="icon-more"></i>
196 196 <div class="menu_items_container hidden">
197 197 <ul class="menu_items">
198 198 <li>
199 199 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
200 200 </li>
201 201
202 202 </ul>
203 203 </div>
204 204 </%def>
205 205
206 206 <%def name="repo_group_name(repo_group_name, children_groups=None)">
207 207 <div>
208 208 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
209 209 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
210 210 %if children_groups:
211 211 ${h.literal(' &raquo; '.join(children_groups))}
212 212 %else:
213 213 ${repo_group_name}
214 214 %endif
215 215 </a>
216 216 </div>
217 217 </%def>
218 218
219 219 <%def name="repo_group_desc(description, personal, stylify_metatags)">
220 220
221 221 <%
222 222 tags, description = h.extract_metatags(description)
223 223 %>
224 224
225 225 <div class="truncate-wrap">
226 226 % if personal:
227 227 <div class="metatag" tag="personal">${_('personal')}</div>
228 228 % endif
229 229
230 230 % if stylify_metatags:
231 231 % for tag_type, tag in tags:
232 232 ${h.style_metatag(tag_type, tag)|n}
233 233 % endfor
234 234 % endif
235 235 ${description}
236 236 </div>
237 237
238 238 </%def>
239 239
240 240 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
241 241 <div class="grid_edit">
242 242 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
243 243 </div>
244 244 <div class="grid_delete">
245 245 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
246 246 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger",
247 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 248 ${h.end_form()}
249 249 </div>
250 250 </%def>
251 251
252 252
253 253 <%def name="user_actions(user_id, username)">
254 254 <div class="grid_edit">
255 255 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
256 256 ${_('Edit')}
257 257 </a>
258 258 </div>
259 259 <div class="grid_delete">
260 260 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
261 261 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger",
262 262 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
263 263 ${h.end_form()}
264 264 </div>
265 265 </%def>
266 266
267 267 <%def name="user_group_actions(user_group_id, user_group_name)">
268 268 <div class="grid_edit">
269 269 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
270 270 </div>
271 271 <div class="grid_delete">
272 272 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
273 273 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
274 274 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
275 275 ${h.end_form()}
276 276 </div>
277 277 </%def>
278 278
279 279
280 280 <%def name="user_name(user_id, username)">
281 281 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
282 282 </%def>
283 283
284 284 <%def name="user_profile(username)">
285 285 ${base.gravatar_with_user(username, 16)}
286 286 </%def>
287 287
288 288 <%def name="user_group_name(user_group_name)">
289 289 <div>
290 290 <i class="icon-user-group" title="${_('User group')}"></i>
291 291 ${h.link_to_group(user_group_name)}
292 292 </div>
293 293 </%def>
294 294
295 295
296 296 ## GISTS
297 297
298 298 <%def name="gist_gravatar(full_contact)">
299 299 <div class="gist_gravatar">
300 300 ${base.gravatar(full_contact, 30)}
301 301 </div>
302 302 </%def>
303 303
304 304 <%def name="gist_access_id(gist_access_id, full_contact)">
305 305 <div>
306 306 <b>
307 307 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">gist: ${gist_access_id}</a>
308 308 </b>
309 309 </div>
310 310 </%def>
311 311
312 312 <%def name="gist_author(full_contact, created_on, expires)">
313 313 ${base.gravatar_with_user(full_contact, 16)}
314 314 </%def>
315 315
316 316
317 317 <%def name="gist_created(created_on)">
318 318 <div class="created">
319 319 ${h.age_component(created_on, time_is_local=True)}
320 320 </div>
321 321 </%def>
322 322
323 323 <%def name="gist_expires(expires)">
324 324 <div class="created">
325 325 %if expires == -1:
326 326 ${_('never')}
327 327 %else:
328 328 ${h.age_component(h.time_to_utcdatetime(expires))}
329 329 %endif
330 330 </div>
331 331 </%def>
332 332
333 333 <%def name="gist_type(gist_type)">
334 334 %if gist_type != 'public':
335 335 <div class="tag">${_('Private')}</div>
336 336 %endif
337 337 </%def>
338 338
339 339 <%def name="gist_description(gist_description)">
340 340 ${gist_description}
341 341 </%def>
342 342
343 343
344 344 ## PULL REQUESTS GRID RENDERERS
345 345
346 346 <%def name="pullrequest_target_repo(repo_name)">
347 347 <div class="truncate">
348 348 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
349 349 </div>
350 350 </%def>
351
351 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 354 </%def>
354 355
355 356 <%def name="pullrequest_title(title, description)">
356 357 ${title}
357 358 </%def>
358 359
359 360 <%def name="pullrequest_comments(comments_nr)">
360 361 <i class="icon-comment"></i> ${comments_nr}
361 362 </%def>
362 363
363 364 <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)">
364 365 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
365 366 % if short:
366 367 #${pull_request_id}
367 368 % else:
368 369 ${_('Pull request #%(pr_number)s') % {'pr_number': pull_request_id,}}
369 370 % endif
370 371 </a>
371 372 </%def>
372 373
373 374 <%def name="pullrequest_updated_on(updated_on)">
374 375 ${h.age_component(h.time_to_utcdatetime(updated_on))}
375 376 </%def>
376 377
377 378 <%def name="pullrequest_author(full_contact)">
378 379 ${base.gravatar_with_user(full_contact, 16)}
379 380 </%def>
380 381
381 382
382 383 ## ARTIFACT RENDERERS
383 384
384 385 <%def name="repo_artifact_uid(repo_name, file_uid)">
385 386 <code><a href="${h.route_path('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}">${file_uid}</a></code>
386 387 </%def>
387 388
388 389 <%def name="repo_artifact_uid_action(repo_name, file_uid)">
389 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 391 </%def>
391 392
392 393 <%def name="repo_artifact_actions(repo_name, file_store_id, file_uid)">
393 394 ## <div class="grid_edit">
394 395 ## <a href="#Edit" title="${_('Edit')}">${_('Edit')}</a>
395 396 ## </div>
396 397 % if h.HasRepoPermissionAny('repository.admin')(c.repo_name):
397 398 <div class="grid_delete">
398 399 ${h.secure_form(h.route_path('repo_artifacts_delete', repo_name=repo_name, uid=file_store_id), request=request)}
399 400 ${h.submit('remove_',_('Delete'),id="remove_artifact_%s" % file_store_id, class_="btn btn-link btn-danger",
400 401 onclick="return confirm('"+_('Confirm to delete this artifact: %s') % file_uid+"');")}
401 402 ${h.end_form()}
402 403 </div>
403 404 % endif
404 405 </%def>
405 406
406 407 <%def name="markup_form(form_id, form_text='', help_text=None)">
407 408
408 409 <div class="markup-form">
409 410 <div class="markup-form-area">
410 411 <div class="markup-form-area-header">
411 412 <ul class="nav-links clearfix">
412 413 <li class="active">
413 414 <a href="#edit-text" tabindex="-1" id="edit-btn_${form_id}">${_('Write')}</a>
414 415 </li>
415 416 <li class="">
416 417 <a href="#preview-text" tabindex="-1" id="preview-btn_${form_id}">${_('Preview')}</a>
417 418 </li>
418 419 </ul>
419 420 </div>
420 421
421 422 <div class="markup-form-area-write" style="display: block;">
422 423 <div id="edit-container_${form_id}">
423 424 <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea>
424 425 </div>
425 426 <div id="preview-container_${form_id}" class="clearfix" style="display: none;">
426 427 <div id="preview-box_${form_id}" class="preview-box"></div>
427 428 </div>
428 429 </div>
429 430
430 431 <div class="markup-form-area-footer">
431 432 <div class="toolbar">
432 433 <div class="toolbar-text">
433 434 ${(_('Parsed using %s syntax') % (
434 435 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
435 436 )
436 437 )|n}
437 438 </div>
438 439 </div>
439 440 </div>
440 441 </div>
441 442
442 443 <div class="markup-form-footer">
443 444 % if help_text:
444 445 <span class="help-block">${help_text}</span>
445 446 % endif
446 447 </div>
447 448 </div>
448 449 <script type="text/javascript">
449 450 new MarkupForm('${form_id}');
450 451 </script>
451 452
452 453 </%def>
@@ -1,841 +1,841 b''
1 1 <%inherit file="/base/base.mako"/>
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 4
5 5 <%def name="title()">
6 6 ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)}
7 7 %if c.rhodecode_name:
8 8 &middot; ${h.branding(c.rhodecode_name)}
9 9 %endif
10 10 </%def>
11 11
12 12 <%def name="breadcrumbs_links()">
13 13 <span id="pr-title">
14 14 ${c.pull_request.title}
15 15 %if c.pull_request.is_closed():
16 16 (${_('Closed')})
17 17 %endif
18 18 </span>
19 19 <div id="pr-title-edit" class="input" style="display: none;">
20 20 ${h.text('pullrequest_title', id_="pr-title-input", class_="large", value=c.pull_request.title)}
21 21 </div>
22 22 </%def>
23 23
24 24 <%def name="menu_bar_nav()">
25 25 ${self.menu_items(active='repositories')}
26 26 </%def>
27 27
28 28 <%def name="menu_bar_subnav()">
29 29 ${self.repo_menu(active='showpullrequest')}
30 30 </%def>
31 31
32 32 <%def name="main()">
33 33
34 34 <script type="text/javascript">
35 35 // TODO: marcink switch this to pyroutes
36 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 37 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
38 38 </script>
39 39 <div class="box">
40 40
41 41 ${self.breadcrumbs()}
42 42
43 43 <div class="box pr-summary">
44 44
45 45 <div class="summary-details block-left">
46 46 <% summary = lambda n:{False:'summary-short'}.get(n) %>
47 47 <div class="pr-details-title">
48 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 49 %if c.allowed_to_update:
50 50 <div id="delete_pullrequest" class="pull-right action_button ${'' if c.allowed_to_delete else 'disabled' }" style="clear:inherit;padding: 0">
51 51 % if c.allowed_to_delete:
52 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 53 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete'),
54 54 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
55 55 ${h.end_form()}
56 56 % else:
57 57 ${_('Delete')}
58 58 % endif
59 59 </div>
60 60 <div id="open_edit_pullrequest" class="pull-right action_button">${_('Edit')}</div>
61 61 <div id="close_edit_pullrequest" class="pull-right action_button" style="display: none;padding: 0">${_('Cancel')}</div>
62 62 %endif
63 63 </div>
64 64
65 65 <div id="summary" class="fields pr-details-content">
66 66 <div class="field">
67 67 <div class="label-summary">
68 68 <label>${_('Source')}:</label>
69 69 </div>
70 70 <div class="input">
71 71 <div class="pr-origininfo">
72 72 ## branch link is only valid if it is a branch
73 73 <span class="tag">
74 74 %if c.pull_request.source_ref_parts.type == 'branch':
75 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 76 %else:
77 77 ${c.pull_request.source_ref_parts.type}: ${c.pull_request.source_ref_parts.name}
78 78 %endif
79 79 </span>
80 80 <span class="clone-url">
81 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 82 </span>
83 83 <br/>
84 84 % if c.ancestor_commit:
85 85 ${_('Common ancestor')}:
86 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 87 % endif
88 88 </div>
89 89 %if h.is_hg(c.pull_request.source_repo):
90 90 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
91 91 %elif h.is_git(c.pull_request.source_repo):
92 92 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
93 93 %endif
94 94
95 95 <div class="">
96 96 <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
97 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 98 </div>
99 99
100 100 </div>
101 101 </div>
102 102 <div class="field">
103 103 <div class="label-summary">
104 104 <label>${_('Target')}:</label>
105 105 </div>
106 106 <div class="input">
107 107 <div class="pr-targetinfo">
108 108 ## branch link is only valid if it is a branch
109 109 <span class="tag">
110 110 %if c.pull_request.target_ref_parts.type == 'branch':
111 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 112 %else:
113 113 ${c.pull_request.target_ref_parts.type}: ${c.pull_request.target_ref_parts.name}
114 114 %endif
115 115 </span>
116 116 <span class="clone-url">
117 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 118 </span>
119 119 </div>
120 120 </div>
121 121 </div>
122 122
123 123 ## Link to the shadow repository.
124 124 <div class="field">
125 125 <div class="label-summary">
126 126 <label>${_('Merge')}:</label>
127 127 </div>
128 128 <div class="input">
129 129 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
130 130 %if h.is_hg(c.pull_request.target_repo):
131 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 132 %elif h.is_git(c.pull_request.target_repo):
133 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 134 %endif
135 135 <div class="">
136 136 <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
137 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 138 </div>
139 139 % else:
140 140 <div class="">
141 141 ${_('Shadow repository data not available')}.
142 142 </div>
143 143 % endif
144 144 </div>
145 145 </div>
146 146
147 147 <div class="field">
148 148 <div class="label-summary">
149 149 <label>${_('Review')}:</label>
150 150 </div>
151 151 <div class="input">
152 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 154 <span class="changeset-status-lbl tooltip">
155 155 %if c.pull_request.is_closed():
156 156 ${_('Closed')},
157 157 %endif
158 158 ${h.commit_status_lbl(c.pull_request_review_status)}
159 159 </span>
160 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 161 %endif
162 162 </div>
163 163 </div>
164 164 <div class="field">
165 165 <div class="pr-description-label label-summary" title="${_('Rendered using {} renderer').format(c.renderer)}">
166 166 <label>${_('Description')}:</label>
167 167 </div>
168 168 <div id="pr-desc" class="input">
169 169 <div class="pr-description">${h.render(c.pull_request.description, renderer=c.renderer)}</div>
170 170 </div>
171 171 <div id="pr-desc-edit" class="input textarea editor" style="display: none;">
172 172 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
173 173 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
174 174 </div>
175 175 </div>
176 176
177 177 <div class="field">
178 178 <div class="label-summary">
179 179 <label>${_('Versions')}:</label>
180 180 </div>
181 181
182 182 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
183 183 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
184 184
185 185 <div class="pr-versions">
186 186 % if c.show_version_changes:
187 187 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
188 188 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
189 189 <a id="show-pr-versions" class="input" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
190 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 191 data-toggle-off="${_('Hide all versions of this pull request')}">
192 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 193 </a>
194 194 <table>
195 195 ## SHOW ALL VERSIONS OF PR
196 196 <% ver_pr = None %>
197 197
198 198 % for data in reversed(list(enumerate(c.versions, 1))):
199 199 <% ver_pos = data[0] %>
200 200 <% ver = data[1] %>
201 201 <% ver_pr = ver.pull_request_version_id %>
202 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 204 <tr class="version-pr" style="display: ${display_row}">
205 205 <td>
206 206 <code>
207 207 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
208 208 </code>
209 209 </td>
210 210 <td>
211 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 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 213 </td>
214 214 <td>
215 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 217 </div>
218 218 </td>
219 219 <td>
220 220 % if c.at_version_num != ver_pr:
221 221 <i class="icon-comment"></i>
222 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 223 G:${len(c.comment_versions[ver_pr]['at'])} / I:${len(c.inline_versions[ver_pr]['at'])}
224 224 </code>
225 225 % endif
226 226 </td>
227 227 <td>
228 228 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
229 229 </td>
230 230 <td>
231 231 ${h.age_component(ver.updated_on, time_is_local=True)}
232 232 </td>
233 233 </tr>
234 234 % endfor
235 235
236 236 <tr>
237 237 <td colspan="6">
238 238 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
239 239 data-label-text-locked="${_('select versions to show changes')}"
240 240 data-label-text-diff="${_('show changes between versions')}"
241 241 data-label-text-show="${_('show pull request for this version')}"
242 242 >
243 243 ${_('select versions to show changes')}
244 244 </button>
245 245 </td>
246 246 </tr>
247 247
248 248 ## show comment/inline comments summary
249 249 <%def name="comments_summary()">
250 250 <tr>
251 251 <td colspan="6" class="comments-summary-td">
252 252
253 253 % if c.at_version:
254 254 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %>
255 255 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['display']) %>
256 256 ${_('Comments at this version')}:
257 257 % else:
258 258 <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['until']) %>
259 259 <% general_comm_count_ver = len(c.comment_versions[c.at_version_num]['until']) %>
260 260 ${_('Comments for this pull request')}:
261 261 % endif
262 262
263 263
264 264 %if general_comm_count_ver:
265 265 <a href="#comments">${_("%d General ") % general_comm_count_ver}</a>
266 266 %else:
267 267 ${_("%d General ") % general_comm_count_ver}
268 268 %endif
269 269
270 270 %if inline_comm_count_ver:
271 271 , <a href="#" onclick="return Rhodecode.comments.nextComment();" id="inline-comments-counter">${_("%d Inline") % inline_comm_count_ver}</a>
272 272 %else:
273 273 , ${_("%d Inline") % inline_comm_count_ver}
274 274 %endif
275 275
276 276 %if outdated_comm_count_ver:
277 277 , <a href="#" onclick="showOutdated(); Rhodecode.comments.nextOutdatedComment(); return false;">${_("%d Outdated") % outdated_comm_count_ver}</a>
278 278 <a href="#" class="showOutdatedComments" onclick="showOutdated(this); return false;"> | ${_('show outdated comments')}</a>
279 279 <a href="#" class="hideOutdatedComments" style="display: none" onclick="hideOutdated(this); return false;"> | ${_('hide outdated comments')}</a>
280 280 %else:
281 281 , ${_("%d Outdated") % outdated_comm_count_ver}
282 282 %endif
283 283 </td>
284 284 </tr>
285 285 </%def>
286 286 ${comments_summary()}
287 287 </table>
288 288 % else:
289 289 <div class="input">
290 290 ${_('Pull request versions not available')}.
291 291 </div>
292 292 <div>
293 293 <table>
294 294 ${comments_summary()}
295 295 </table>
296 296 </div>
297 297 % endif
298 298 </div>
299 299 </div>
300 300
301 301 <div id="pr-save" class="field" style="display: none;">
302 302 <div class="label-summary"></div>
303 303 <div class="input">
304 304 <span id="edit_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</span>
305 305 </div>
306 306 </div>
307 307 </div>
308 308 </div>
309 309 <div>
310 310 ## AUTHOR
311 311 <div class="reviewers-title block-right">
312 312 <div class="pr-details-title">
313 313 ${_('Author of this pull request')}
314 314 </div>
315 315 </div>
316 316 <div class="block-right pr-details-content reviewers">
317 317 <ul class="group_members">
318 318 <li>
319 319 ${self.gravatar_with_user(c.pull_request.author.email, 16)}
320 320 </li>
321 321 </ul>
322 322 </div>
323 323
324 324 ## REVIEW RULES
325 325 <div id="review_rules" style="display: none" class="reviewers-title block-right">
326 326 <div class="pr-details-title">
327 327 ${_('Reviewer rules')}
328 328 %if c.allowed_to_update:
329 329 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
330 330 %endif
331 331 </div>
332 332 <div class="pr-reviewer-rules">
333 333 ## review rules will be appended here, by default reviewers logic
334 334 </div>
335 335 <input id="review_data" type="hidden" name="review_data" value="">
336 336 </div>
337 337
338 338 ## REVIEWERS
339 339 <div class="reviewers-title block-right">
340 340 <div class="pr-details-title">
341 341 ${_('Pull request reviewers')}
342 342 %if c.allowed_to_update:
343 343 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
344 344 %endif
345 345 </div>
346 346 </div>
347 347 <div id="reviewers" class="block-right pr-details-content reviewers">
348 348
349 349 ## members redering block
350 350 <input type="hidden" name="__start__" value="review_members:sequence">
351 351 <ul id="review_members" class="group_members">
352 352
353 353 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
354 354 <script>
355 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 356 var status = "${(status[0][1].status if status else 'not_reviewed')}";
357 357 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
358 358 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
359 359
360 360 var entry = renderTemplate('reviewMemberEntry', {
361 361 'member': member,
362 362 'mandatory': member.mandatory,
363 363 'reasons': member.reasons,
364 364 'allowed_to_update': allowed_to_update,
365 365 'review_status': status,
366 366 'review_status_label': status_lbl,
367 367 'user_group': member.user_group,
368 368 'create': false
369 369 });
370 370 $('#review_members').append(entry)
371 371 </script>
372 372
373 373 % endfor
374 374
375 375 </ul>
376 376 <input type="hidden" name="__end__" value="review_members:sequence">
377 377 ## end members redering block
378 378
379 379 %if not c.pull_request.is_closed():
380 380 <div id="add_reviewer" class="ac" style="display: none;">
381 381 %if c.allowed_to_update:
382 382 % if not c.forbid_adding_reviewers:
383 383 <div id="add_reviewer_input" class="reviewer_ac">
384 384 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
385 385 <div id="reviewers_container"></div>
386 386 </div>
387 387 % endif
388 388 <div class="pull-right">
389 389 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
390 390 </div>
391 391 %endif
392 392 </div>
393 393 %endif
394 394 </div>
395 395 </div>
396 396 </div>
397 397 <div class="box">
398 398 ##DIFF
399 399 <div class="table" >
400 400 <div id="changeset_compare_view_content">
401 401 ##CS
402 402 % if c.missing_requirements:
403 403 <div class="box">
404 404 <div class="alert alert-warning">
405 405 <div>
406 406 <strong>${_('Missing requirements:')}</strong>
407 407 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
408 408 </div>
409 409 </div>
410 410 </div>
411 411 % elif c.missing_commits:
412 412 <div class="box">
413 413 <div class="alert alert-warning">
414 414 <div>
415 415 <strong>${_('Missing commits')}:</strong>
416 416 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
417 417 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
418 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 419 </div>
420 420 </div>
421 421 </div>
422 422 % endif
423 423
424 424 <div class="compare_view_commits_title">
425 425 % if not c.compare_mode:
426 426
427 427 % if c.at_version_pos:
428 428 <h4>
429 429 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
430 430 </h4>
431 431 % endif
432 432
433 433 <div class="pull-left">
434 434 <div class="btn-group">
435 435 <a
436 436 class="btn"
437 437 href="#"
438 438 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
439 439 ${_ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
440 440 </a>
441 441 <a
442 442 class="btn"
443 443 href="#"
444 444 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
445 445 ${_ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
446 446 </a>
447 447 </div>
448 448 </div>
449 449
450 450 <div class="pull-right">
451 451 % if c.allowed_to_update and not c.pull_request.is_closed():
452 452 <a id="update_commits" class="btn btn-primary no-margin pull-right">${_('Update commits')}</a>
453 453 % else:
454 454 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
455 455 % endif
456 456
457 457 </div>
458 458 % endif
459 459 </div>
460 460
461 461 % if not c.missing_commits:
462 462 % if c.compare_mode:
463 463 % if c.at_version:
464 464 <h4>
465 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 466 </h4>
467 467
468 468 <div class="subtitle-compare">
469 469 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
470 470 </div>
471 471
472 472 <div class="container">
473 473 <table class="rctable compare_view_commits">
474 474 <tr>
475 475 <th></th>
476 476 <th>${_('Time')}</th>
477 477 <th>${_('Author')}</th>
478 478 <th>${_('Commit')}</th>
479 479 <th></th>
480 480 <th>${_('Description')}</th>
481 481 </tr>
482 482
483 483 % for c_type, commit in c.commit_changes:
484 484 % if c_type in ['a', 'r']:
485 485 <%
486 486 if c_type == 'a':
487 487 cc_title = _('Commit added in displayed changes')
488 488 elif c_type == 'r':
489 489 cc_title = _('Commit removed in displayed changes')
490 490 else:
491 491 cc_title = ''
492 492 %>
493 493 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
494 494 <td>
495 495 <div class="commit-change-indicator color-${c_type}-border">
496 496 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
497 497 ${c_type.upper()}
498 498 </div>
499 499 </div>
500 500 </td>
501 501 <td class="td-time">
502 502 ${h.age_component(commit.date)}
503 503 </td>
504 504 <td class="td-user">
505 505 ${base.gravatar_with_user(commit.author, 16)}
506 506 </td>
507 507 <td class="td-hash">
508 508 <code>
509 509 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
510 510 r${commit.idx}:${h.short_id(commit.raw_id)}
511 511 </a>
512 512 ${h.hidden('revisions', commit.raw_id)}
513 513 </code>
514 514 </td>
515 515 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
516 516 <i class="icon-expand-linked"></i>
517 517 </td>
518 518 <td class="mid td-description">
519 519 <div class="log-container truncate-wrap">
520 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 521 </div>
522 522 </td>
523 523 </tr>
524 524 % endif
525 525 % endfor
526 526 </table>
527 527 </div>
528 528
529 529 % endif
530 530
531 531 % else:
532 532 <%include file="/compare/compare_commits.mako" />
533 533 % endif
534 534
535 535 <div class="cs_files">
536 536 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
537 537
538 538 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
539 539
540 540 % if c.range_diff_on:
541 541 % for commit in c.commit_ranges:
542 542 ${cbdiffs.render_diffset(
543 543 c.changes[commit.raw_id],
544 544 commit=commit, use_comments=True,
545 545 collapse_when_files_over=5,
546 546 disable_new_comments=True,
547 547 deleted_files_comments=c.deleted_files_comments,
548 548 inline_comments=c.inline_comments)}
549 549 % endfor
550 550 % else:
551 551 ${cbdiffs.render_diffset(
552 552 c.diffset, use_comments=True,
553 553 collapse_when_files_over=30,
554 554 disable_new_comments=not c.allowed_to_comment,
555 555 deleted_files_comments=c.deleted_files_comments,
556 556 inline_comments=c.inline_comments)}
557 557 % endif
558 558
559 559 </div>
560 560 % else:
561 561 ## skipping commits we need to clear the view for missing commits
562 562 <div style="clear:both;"></div>
563 563 % endif
564 564
565 565 </div>
566 566 </div>
567 567
568 568 ## template for inline comment form
569 569 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
570 570
571 571 ## render general comments
572 572
573 573 <div id="comment-tr-show">
574 574 <div class="comment">
575 575 % if general_outdated_comm_count_ver:
576 576 <div class="meta">
577 577 % if general_outdated_comm_count_ver == 1:
578 578 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
579 579 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
580 580 % else:
581 581 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
582 582 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
583 583 % endif
584 584 </div>
585 585 % endif
586 586 </div>
587 587 </div>
588 588
589 589 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
590 590
591 591 % if not c.pull_request.is_closed():
592 592 ## merge status, and merge action
593 593 <div class="pull-request-merge">
594 594 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
595 595 </div>
596 596
597 597 ## main comment form and it status
598 598 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
599 599 pull_request_id=c.pull_request.pull_request_id),
600 600 c.pull_request_review_status,
601 601 is_pull_request=True, change_status=c.allowed_to_change_status)}
602 602 %endif
603 603
604 604 <script type="text/javascript">
605 605 if (location.hash) {
606 606 var result = splitDelimitedHash(location.hash);
607 607 var line = $('html').find(result.loc);
608 608 // show hidden comments if we use location.hash
609 609 if (line.hasClass('comment-general')) {
610 610 $(line).show();
611 611 } else if (line.hasClass('comment-inline')) {
612 612 $(line).show();
613 613 var $cb = $(line).closest('.cb');
614 614 $cb.removeClass('cb-collapsed')
615 615 }
616 616 if (line.length > 0){
617 617 offsetScroll(line, 70);
618 618 }
619 619 }
620 620
621 621 versionController = new VersionController();
622 622 versionController.init();
623 623
624 624 reviewersController = new ReviewersController();
625 625 commitsController = new CommitsController();
626 626
627 627 $(function(){
628 628
629 629 // custom code mirror
630 630 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
631 631
632 632 var PRDetails = {
633 633 editButton: $('#open_edit_pullrequest'),
634 634 closeButton: $('#close_edit_pullrequest'),
635 635 deleteButton: $('#delete_pullrequest'),
636 636 viewFields: $('#pr-desc, #pr-title'),
637 637 editFields: $('#pr-desc-edit, #pr-title-edit, #pr-save'),
638 638
639 639 init: function() {
640 640 var that = this;
641 641 this.editButton.on('click', function(e) { that.edit(); });
642 642 this.closeButton.on('click', function(e) { that.view(); });
643 643 },
644 644
645 645 edit: function(event) {
646 646 this.viewFields.hide();
647 647 this.editButton.hide();
648 648 this.deleteButton.hide();
649 649 this.closeButton.show();
650 650 this.editFields.show();
651 651 codeMirrorInstance.refresh();
652 652 },
653 653
654 654 view: function(event) {
655 655 this.editButton.show();
656 656 this.deleteButton.show();
657 657 this.editFields.hide();
658 658 this.closeButton.hide();
659 659 this.viewFields.show();
660 660 }
661 661 };
662 662
663 663 var ReviewersPanel = {
664 664 editButton: $('#open_edit_reviewers'),
665 665 closeButton: $('#close_edit_reviewers'),
666 666 addButton: $('#add_reviewer'),
667 667 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
668 668
669 669 init: function() {
670 670 var self = this;
671 671 this.editButton.on('click', function(e) { self.edit(); });
672 672 this.closeButton.on('click', function(e) { self.close(); });
673 673 },
674 674
675 675 edit: function(event) {
676 676 this.editButton.hide();
677 677 this.closeButton.show();
678 678 this.addButton.show();
679 679 this.removeButtons.css('visibility', 'visible');
680 680 // review rules
681 681 reviewersController.loadReviewRules(
682 682 ${c.pull_request.reviewer_data_json | n});
683 683 },
684 684
685 685 close: function(event) {
686 686 this.editButton.show();
687 687 this.closeButton.hide();
688 688 this.addButton.hide();
689 689 this.removeButtons.css('visibility', 'hidden');
690 690 // hide review rules
691 691 reviewersController.hideReviewRules()
692 692 }
693 693 };
694 694
695 695 PRDetails.init();
696 696 ReviewersPanel.init();
697 697
698 698 showOutdated = function(self){
699 699 $('.comment-inline.comment-outdated').show();
700 700 $('.filediff-outdated').show();
701 701 $('.showOutdatedComments').hide();
702 702 $('.hideOutdatedComments').show();
703 703 };
704 704
705 705 hideOutdated = function(self){
706 706 $('.comment-inline.comment-outdated').hide();
707 707 $('.filediff-outdated').hide();
708 708 $('.hideOutdatedComments').hide();
709 709 $('.showOutdatedComments').show();
710 710 };
711 711
712 712 refreshMergeChecks = function(){
713 713 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
714 714 $('.pull-request-merge').css('opacity', 0.3);
715 715 $('.action-buttons-extra').css('opacity', 0.3);
716 716
717 717 $('.pull-request-merge').load(
718 718 loadUrl, function() {
719 719 $('.pull-request-merge').css('opacity', 1);
720 720
721 721 $('.action-buttons-extra').css('opacity', 1);
722 722 injectCloseAction();
723 723 }
724 724 );
725 725 };
726 726
727 727 injectCloseAction = function() {
728 728 var closeAction = $('#close-pull-request-action').html();
729 729 var $actionButtons = $('.action-buttons-extra');
730 730 // clear the action before
731 731 $actionButtons.html("");
732 732 $actionButtons.html(closeAction);
733 733 };
734 734
735 735 closePullRequest = function (status) {
736 736 // inject closing flag
737 737 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
738 738 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
739 739 $(generalCommentForm.submitForm).submit();
740 740 };
741 741
742 742 $('#show-outdated-comments').on('click', function(e){
743 743 var button = $(this);
744 744 var outdated = $('.comment-outdated');
745 745
746 746 if (button.html() === "(Show)") {
747 747 button.html("(Hide)");
748 748 outdated.show();
749 749 } else {
750 750 button.html("(Show)");
751 751 outdated.hide();
752 752 }
753 753 });
754 754
755 755 $('.show-inline-comments').on('change', function(e){
756 756 var show = 'none';
757 757 var target = e.currentTarget;
758 758 if(target.checked){
759 759 show = ''
760 760 }
761 761 var boxid = $(target).attr('id_for');
762 762 var comments = $('#{0} .inline-comments'.format(boxid));
763 763 var fn_display = function(idx){
764 764 $(this).css('display', show);
765 765 };
766 766 $(comments).each(fn_display);
767 767 var btns = $('#{0} .inline-comments-button'.format(boxid));
768 768 $(btns).each(fn_display);
769 769 });
770 770
771 771 $('#merge_pull_request_form').submit(function() {
772 772 if (!$('#merge_pull_request').attr('disabled')) {
773 773 $('#merge_pull_request').attr('disabled', 'disabled');
774 774 }
775 775 return true;
776 776 });
777 777
778 778 $('#edit_pull_request').on('click', function(e){
779 779 var title = $('#pr-title-input').val();
780 780 var description = codeMirrorInstance.getValue();
781 781 var renderer = $('#pr-renderer-input').val();
782 782 editPullRequest(
783 783 "${c.repo_name}", "${c.pull_request.pull_request_id}",
784 784 title, description, renderer);
785 785 });
786 786
787 787 $('#update_pull_request').on('click', function(e){
788 788 $(this).attr('disabled', 'disabled');
789 789 $(this).addClass('disabled');
790 790 $(this).html(_gettext('Saving...'));
791 791 reviewersController.updateReviewers(
792 792 "${c.repo_name}", "${c.pull_request.pull_request_id}");
793 793 });
794 794
795 795 $('#update_commits').on('click', function(e){
796 796 var isDisabled = !$(e.currentTarget).attr('disabled');
797 797 $(e.currentTarget).attr('disabled', 'disabled');
798 798 $(e.currentTarget).addClass('disabled');
799 799 $(e.currentTarget).removeClass('btn-primary');
800 800 $(e.currentTarget).text(_gettext('Updating...'));
801 801 if(isDisabled){
802 802 updateCommits(
803 803 "${c.repo_name}", "${c.pull_request.pull_request_id}");
804 804 }
805 805 });
806 806 // fixing issue with caches on firefox
807 807 $('#update_commits').removeAttr("disabled");
808 808
809 809 $('.show-inline-comments').on('click', function(e){
810 810 var boxid = $(this).attr('data-comment-id');
811 811 var button = $(this);
812 812
813 813 if(button.hasClass("comments-visible")) {
814 814 $('#{0} .inline-comments'.format(boxid)).each(function(index){
815 815 $(this).hide();
816 816 });
817 817 button.removeClass("comments-visible");
818 818 } else {
819 819 $('#{0} .inline-comments'.format(boxid)).each(function(index){
820 820 $(this).show();
821 821 });
822 822 button.addClass("comments-visible");
823 823 }
824 824 });
825 825
826 826 // register submit callback on commentForm form to track TODOs
827 827 window.commentFormGlobalSubmitSuccessCallback = function(){
828 828 refreshMergeChecks();
829 829 };
830 830 // initial injection
831 831 injectCloseAction();
832 832
833 833 ReviewerAutoComplete('#user');
834 834
835 835 })
836 836 </script>
837 837
838 838 </div>
839 839 </div>
840 840
841 841 </%def>
@@ -1,167 +1,167 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%namespace name="base" file="/base/base.mako"/>
3 3 %if c.repo_commits:
4 4 <table class="rctable repo_summary table_disp">
5 5 <tr>
6 6
7 7 <th class="status"></th>
8 8 <th>${_('Commit')}</th>
9 9 <th>${_('Commit message')}</th>
10 10 <th>${_('Age')}</th>
11 11 <th>${_('Author')}</th>
12 12 <th colspan="2">${_('Refs')}</th>
13 13 </tr>
14 14
15 15 ## to speed up lookups cache some functions before the loop
16 16 <%
17 17 active_patterns = h.get_active_pattern_entries(c.repo_name)
18 18 urlify_commit_message = h.partial(h.urlify_commit_message, active_pattern_entries=active_patterns)
19 19 %>
20 20 %for cnt,cs in enumerate(c.repo_commits):
21 21 <tr class="parity${cnt%2}">
22 22
23 23 <td class="td-status">
24 24 %if c.statuses.get(cs.raw_id):
25 25 <div class="changeset-status-ico shortlog">
26 26 %if c.statuses.get(cs.raw_id)[2]:
27 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 29 </a>
30 30 %else:
31 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 33 </a>
34 34 %endif
35 35 </div>
36 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 38 %endif
39 39 </td>
40 40 <td class="td-commit">
41 41 <code>
42 42 <a href="${h.route_path('repo_commit', repo_name=c.repo_name, commit_id=cs.raw_id)}">${h.show_id(cs)}</a>
43 43 <i class="tooltip icon-clipboard clipboard-action" data-clipboard-text="${cs.raw_id}" title="${_('Copy the full commit id')}"></i>
44 44 </code>
45 45 </td>
46 46
47 47 <td class="td-description mid">
48 48 <div class="log-container truncate-wrap">
49 49 <div class="message truncate" id="c-${cs.raw_id}">${urlify_commit_message(cs.message, c.repo_name)}</div>
50 50 </div>
51 51 </td>
52 52
53 53 <td class="td-time">
54 54 ${h.age_component(cs.date)}
55 55 </td>
56 56 <td class="td-user author">
57 57 ${base.gravatar_with_user(cs.author)}
58 58 </td>
59 59
60 60 <td class="td-tags">
61 61 <div class="autoexpand">
62 62 %if h.is_hg(c.rhodecode_repo):
63 63 %for book in cs.bookmarks:
64 64 <span class="booktag tag" title="${h.tooltip(_('Bookmark %s') % book)}">
65 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 66 </span>
67 67 %endfor
68 68 %endif
69 69 ## tags
70 70 %for tag in cs.tags:
71 71 <span class="tagtag tag" title="${h.tooltip(_('Tag %s') % tag)}">
72 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 73 </span>
74 74 %endfor
75 75
76 76 ## branch
77 77 %if cs.branch:
78 78 <span class="branchtag tag" title="${h.tooltip(_('Branch %s') % cs.branch)}">
79 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 80 </span>
81 81 %endif
82 82 </div>
83 83 </td>
84 84 <td class="td-comments">
85 85 <% cs_comments = c.comments.get(cs.raw_id,[]) %>
86 86 % if cs_comments:
87 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 88 <i class="icon-comment"></i> ${len(cs_comments)}
89 89 </a>
90 90 % else:
91 91 <i class="icon-comment"></i> ${len(cs_comments)}
92 92 % endif
93 93 </td>
94 94 </tr>
95 95 %endfor
96 96
97 97 </table>
98 98
99 99 <script type="text/javascript">
100 100 $(document).pjax('#shortlog_data .pager_link','#shortlog_data', {timeout: 5000, scrollTo: false, push: false});
101 101 $(document).on('pjax:success', function(){ timeagoActivate(); });
102 102 $(document).on('pjax:timeout', function(event) {
103 103 // Prevent default timeout redirection behavior
104 104 event.preventDefault()
105 105 })
106 106
107 107 </script>
108 108
109 109 <div class="pagination-wh pagination-left">
110 110 ${c.repo_commits.pager('$link_previous ~2~ $link_next')}
111 111 </div>
112 112 %else:
113 113
114 114 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name):
115 115 <div class="quick_start">
116 116 <div class="fieldset">
117 117 <p><b>${_('Add or upload files directly via RhodeCode:')}</b></p>
118 118 <div class="pull-left">
119 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 120 </div>
121 121 <div class="pull-left">
122 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 123 </div>
124 124 %endif
125 125 </div>
126 126
127 127 <div class="fieldset">
128 128 <p><b>${_('Push new repo:')}</b></p>
129 129 <pre>
130 130 %if h.is_git(c.rhodecode_repo):
131 131 git clone ${c.clone_repo_url}
132 132 git add README # add first file
133 133 git commit -m "Initial commit" # commit with message
134 134 git remote add origin ${c.clone_repo_url}
135 135 git push -u origin master # push changes back to default master branch
136 136 %elif h.is_hg(c.rhodecode_repo):
137 137 hg clone ${c.clone_repo_url}
138 138 hg add README # add first file
139 139 hg commit -m "Initial commit" # commit with message
140 140 hg push ${c.clone_repo_url}
141 141 %elif h.is_svn(c.rhodecode_repo):
142 142 svn co ${c.clone_repo_url}
143 143 svn add README # add first file
144 144 svn commit -m "Initial commit"
145 145 svn commit # send changes back to the server
146 146 %endif
147 147 </pre>
148 148 </div>
149 149
150 150 <div class="fieldset">
151 151 <p><b>${_('Existing repository?')}</b></p>
152 152 <pre>
153 153 %if h.is_git(c.rhodecode_repo):
154 154 git remote add origin ${c.clone_repo_url}
155 155 git push -u origin master
156 156 %elif h.is_hg(c.rhodecode_repo):
157 157 hg push ${c.clone_repo_url}
158 158 %elif h.is_svn(c.rhodecode_repo):
159 159 svn co ${c.clone_repo_url}
160 160 %endif
161 161 </pre>
162 162
163 163 </div>
164 164
165 165
166 166 </div>
167 167 %endif
General Comments 0
You need to be logged in to leave comments. Login now