##// END OF EJS Templates
comments: improved comments form layout....
marcink -
r1281:71c01ca9 default
parent child Browse files
Show More
@@ -1,1199 +1,1198 b''
1 1 // Default styles
2 2
3 3 .diff-collapse {
4 4 margin: @padding 0;
5 5 text-align: right;
6 6 }
7 7
8 8 .diff-container {
9 9 margin-bottom: @space;
10 10
11 11 .diffblock {
12 12 margin-bottom: @space;
13 13 }
14 14
15 15 &.hidden {
16 16 display: none;
17 17 overflow: hidden;
18 18 }
19 19 }
20 20
21 21 .compare_view_files {
22 22
23 23 .diff-container {
24 24
25 25 .diffblock {
26 26 margin-bottom: 0;
27 27 }
28 28 }
29 29 }
30 30
31 31 div.diffblock .sidebyside {
32 32 background: #ffffff;
33 33 }
34 34
35 35 div.diffblock {
36 36 overflow-x: auto;
37 37 overflow-y: hidden;
38 38 clear: both;
39 39 padding: 0px;
40 40 background: @grey6;
41 41 border: @border-thickness solid @grey5;
42 42 -webkit-border-radius: @border-radius @border-radius 0px 0px;
43 43 border-radius: @border-radius @border-radius 0px 0px;
44 44
45 45
46 46 .comments-number {
47 47 float: right;
48 48 }
49 49
50 50 // BEGIN CODE-HEADER STYLES
51 51
52 52 .code-header {
53 53 background: @grey6;
54 54 padding: 10px 0 10px 0;
55 55 height: auto;
56 56 width: 100%;
57 57
58 58 .hash {
59 59 float: left;
60 60 padding: 2px 0 0 2px;
61 61 }
62 62
63 63 .date {
64 64 float: left;
65 65 text-transform: uppercase;
66 66 padding: 4px 0px 0px 2px;
67 67 }
68 68
69 69 div {
70 70 margin-left: 4px;
71 71 }
72 72
73 73 div.compare_header {
74 74 min-height: 40px;
75 75 margin: 0;
76 76 padding: 0 @padding;
77 77
78 78 .drop-menu {
79 79 float:left;
80 80 display: block;
81 81 margin:0 0 @padding 0;
82 82 }
83 83
84 84 .compare-label {
85 85 float: left;
86 86 clear: both;
87 87 display: inline-block;
88 88 min-width: 5em;
89 89 margin: 0;
90 90 padding: @button-padding @button-padding @button-padding 0;
91 91 font-family: @text-semibold;
92 92 }
93 93
94 94 .compare-buttons {
95 95 float: left;
96 96 margin: 0;
97 97 padding: 0 0 @padding;
98 98
99 99 .btn {
100 100 margin: 0 @padding 0 0;
101 101 }
102 102 }
103 103 }
104 104
105 105 }
106 106
107 107 .parents {
108 108 float: left;
109 109 width: 100px;
110 110 font-weight: 400;
111 111 vertical-align: middle;
112 112 padding: 0px 2px 0px 2px;
113 113 background-color: @grey6;
114 114
115 115 #parent_link {
116 116 margin: 00px 2px;
117 117
118 118 &.double {
119 119 margin: 0px 2px;
120 120 }
121 121
122 122 &.disabled{
123 123 margin-right: @padding;
124 124 }
125 125 }
126 126 }
127 127
128 128 .children {
129 129 float: right;
130 130 width: 100px;
131 131 font-weight: 400;
132 132 vertical-align: middle;
133 133 text-align: right;
134 134 padding: 0px 2px 0px 2px;
135 135 background-color: @grey6;
136 136
137 137 #child_link {
138 138 margin: 0px 2px;
139 139
140 140 &.double {
141 141 margin: 0px 2px;
142 142 }
143 143
144 144 &.disabled{
145 145 margin-right: @padding;
146 146 }
147 147 }
148 148 }
149 149
150 150 .changeset_header {
151 151 height: 16px;
152 152
153 153 & > div{
154 154 margin-right: @padding;
155 155 }
156 156 }
157 157
158 158 .changeset_file {
159 159 text-align: left;
160 160 float: left;
161 161 padding: 0;
162 162
163 163 a{
164 164 display: inline-block;
165 165 margin-right: 0.5em;
166 166 }
167 167
168 168 #selected_mode{
169 169 margin-left: 0;
170 170 }
171 171 }
172 172
173 173 .diff-menu-wrapper {
174 174 float: left;
175 175 }
176 176
177 177 .diff-menu {
178 178 position: absolute;
179 179 background: none repeat scroll 0 0 #FFFFFF;
180 180 border-color: #003367 @grey3 @grey3;
181 181 border-right: 1px solid @grey3;
182 182 border-style: solid solid solid;
183 183 border-width: @border-thickness;
184 184 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
185 185 margin-top: 5px;
186 186 margin-left: 1px;
187 187 }
188 188
189 189 .diff-actions, .editor-actions {
190 190 float: left;
191 191
192 192 input{
193 193 margin: 0 0.5em 0 0;
194 194 }
195 195 }
196 196
197 197 // END CODE-HEADER STYLES
198 198
199 199 // BEGIN CODE-BODY STYLES
200 200
201 201 .code-body {
202 202 background: white;
203 203 padding: 0;
204 204 background-color: #ffffff;
205 205 position: relative;
206 206 max-width: none;
207 207 box-sizing: border-box;
208 208 // TODO: johbo: Parent has overflow: auto, this forces the child here
209 209 // to have the intended size and to scroll. Should be simplified.
210 210 width: 100%;
211 211 overflow-x: auto;
212 212 }
213 213
214 214 pre.raw {
215 215 background: white;
216 216 color: @grey1;
217 217 }
218 218 // END CODE-BODY STYLES
219 219
220 220 }
221 221
222 222
223 223 table.code-difftable {
224 224 border-collapse: collapse;
225 225 width: 99%;
226 226 border-radius: 0px !important;
227 227
228 228 td {
229 229 padding: 0 !important;
230 230 background: none !important;
231 231 border: 0 !important;
232 232 }
233 233
234 234 .context {
235 235 background: none repeat scroll 0 0 #DDE7EF;
236 236 }
237 237
238 238 .add {
239 239 background: none repeat scroll 0 0 #DDFFDD;
240 240
241 241 ins {
242 242 background: none repeat scroll 0 0 #AAFFAA;
243 243 text-decoration: none;
244 244 }
245 245 }
246 246
247 247 .del {
248 248 background: none repeat scroll 0 0 #FFDDDD;
249 249
250 250 del {
251 251 background: none repeat scroll 0 0 #FFAAAA;
252 252 text-decoration: none;
253 253 }
254 254 }
255 255
256 256 /** LINE NUMBERS **/
257 257 .lineno {
258 258 padding-left: 2px !important;
259 259 padding-right: 2px;
260 260 text-align: right;
261 261 width: 32px;
262 262 -moz-user-select: none;
263 263 -webkit-user-select: none;
264 264 border-right: @border-thickness solid @grey5 !important;
265 265 border-left: 0px solid #CCC !important;
266 266 border-top: 0px solid #CCC !important;
267 267 border-bottom: none !important;
268 268
269 269 a {
270 270 &:extend(pre);
271 271 text-align: right;
272 272 padding-right: 2px;
273 273 cursor: pointer;
274 274 display: block;
275 275 width: 32px;
276 276 }
277 277 }
278 278
279 279 .context {
280 280 cursor: auto;
281 281 &:extend(pre);
282 282 }
283 283
284 284 .lineno-inline {
285 285 background: none repeat scroll 0 0 #FFF !important;
286 286 padding-left: 2px;
287 287 padding-right: 2px;
288 288 text-align: right;
289 289 width: 30px;
290 290 -moz-user-select: none;
291 291 -webkit-user-select: none;
292 292 }
293 293
294 294 /** CODE **/
295 295 .code {
296 296 display: block;
297 297 width: 100%;
298 298
299 299 td {
300 300 margin: 0;
301 301 padding: 0;
302 302 }
303 303
304 304 pre {
305 305 margin: 0;
306 306 padding: 0;
307 307 margin-left: .5em;
308 308 }
309 309 }
310 310 }
311 311
312 312
313 313 // Comments
314 314
315 315 div.comment:target {
316 316 border-left: 6px solid @comment-highlight-color !important;
317 317 padding-left: 3px;
318 318 margin-left: -9px;
319 319 }
320 320
321 321 //TODO: anderson: can't get an absolute number out of anything, so had to put the
322 322 //current values that might change. But to make it clear I put as a calculation
323 323 @comment-max-width: 1065px;
324 324 @pr-extra-margin: 34px;
325 325 @pr-border-spacing: 4px;
326 326 @pr-comment-width: @comment-max-width - @pr-extra-margin - @pr-border-spacing;
327 327
328 328 // Pull Request
329 329 .cs_files .code-difftable {
330 330 border: @border-thickness solid @grey5; //borders only on PRs
331 331
332 332 .comment-inline-form,
333 333 div.comment {
334 334 width: @pr-comment-width;
335 335 }
336 336 }
337 337
338 338 // Changeset
339 339 .code-difftable {
340 340 .comment-inline-form,
341 341 div.comment {
342 342 width: @comment-max-width;
343 343 }
344 344 }
345 345
346 346 //Style page
347 347 @style-extra-margin: @sidebar-width + (@sidebarpadding * 3) + @padding;
348 348 #style-page .code-difftable{
349 349 .comment-inline-form,
350 350 div.comment {
351 351 width: @comment-max-width - @style-extra-margin;
352 352 }
353 353 }
354 354
355 355 #context-bar > h2 {
356 356 font-size: 20px;
357 357 }
358 358
359 359 #context-bar > h2> a {
360 360 font-size: 20px;
361 361 }
362 362 // end of defaults
363 363
364 364 .file_diff_buttons {
365 365 padding: 0 0 @padding;
366 366
367 367 .drop-menu {
368 368 float: left;
369 369 margin: 0 @padding 0 0;
370 370 }
371 371 .btn {
372 372 margin: 0 @padding 0 0;
373 373 }
374 374 }
375 375
376 376 .code-body.textarea.editor {
377 377 max-width: none;
378 378 padding: 15px;
379 379 }
380 380
381 381 td.injected_diff{
382 382 max-width: 1178px;
383 383 overflow-x: auto;
384 384 overflow-y: hidden;
385 385
386 386 div.diff-container,
387 387 div.diffblock{
388 388 max-width: 100%;
389 389 }
390 390
391 391 div.code-body {
392 392 max-width: 1124px;
393 393 overflow-x: auto;
394 394 overflow-y: hidden;
395 395 padding: 0;
396 396 }
397 397 div.diffblock {
398 398 border: none;
399 399 }
400 400
401 401 &.inline-form {
402 402 width: 99%
403 403 }
404 404 }
405 405
406 406
407 407 table.code-difftable {
408 408 width: 100%;
409 409 }
410 410
411 411 /** PYGMENTS COLORING **/
412 412 div.codeblock {
413 413
414 414 // TODO: johbo: Added interim to get rid of the margin around
415 415 // Select2 widgets. This needs further cleanup.
416 416 margin-top: @padding;
417 417
418 418 overflow: auto;
419 419 padding: 0px;
420 420 border: @border-thickness solid @grey5;
421 421 background: @grey6;
422 422 .border-radius(@border-radius);
423 423
424 424 #remove_gist {
425 425 float: right;
426 426 }
427 427
428 428 .author {
429 429 clear: both;
430 430 vertical-align: middle;
431 431 font-family: @text-bold;
432 432 }
433 433
434 434 .btn-mini {
435 435 float: left;
436 436 margin: 0 5px 0 0;
437 437 }
438 438
439 439 .code-header {
440 440 padding: @padding;
441 441 border-bottom: @border-thickness solid @grey5;
442 442
443 443 .rc-user {
444 444 min-width: 0;
445 445 margin-right: .5em;
446 446 }
447 447
448 448 .stats {
449 449 clear: both;
450 450 margin: 0 0 @padding 0;
451 451 padding: 0;
452 452 .left {
453 453 float: left;
454 454 clear: left;
455 455 max-width: 75%;
456 456 margin: 0 0 @padding 0;
457 457
458 458 &.item {
459 459 margin-right: @padding;
460 460 &.last { border-right: none; }
461 461 }
462 462 }
463 463 .buttons { float: right; }
464 464 .author {
465 465 height: 25px; margin-left: 15px; font-weight: bold;
466 466 }
467 467 }
468 468
469 469 .commit {
470 470 margin: 5px 0 0 26px;
471 471 font-weight: normal;
472 472 white-space: pre-wrap;
473 473 }
474 474 }
475 475
476 476 .message {
477 477 position: relative;
478 478 margin: @padding;
479 479
480 480 .codeblock-label {
481 481 margin: 0 0 1em 0;
482 482 }
483 483 }
484 484
485 485 .code-body {
486 486 padding: @padding;
487 487 background-color: #ffffff;
488 488 min-width: 100%;
489 489 box-sizing: border-box;
490 490 // TODO: johbo: Parent has overflow: auto, this forces the child here
491 491 // to have the intended size and to scroll. Should be simplified.
492 492 width: 100%;
493 493 overflow-x: auto;
494 494 }
495 495 }
496 496
497 497 .code-highlighttable,
498 498 div.codeblock {
499 499
500 500 &.readme {
501 501 background-color: white;
502 502 }
503 503
504 504 .markdown-block table {
505 505 border-collapse: collapse;
506 506
507 507 th,
508 508 td {
509 509 padding: .5em;
510 510 border: @border-thickness solid @border-default-color;
511 511 }
512 512 }
513 513
514 514 table {
515 515 border: 0px;
516 516 margin: 0;
517 517 letter-spacing: normal;
518 518
519 519
520 520 td {
521 521 border: 0px;
522 522 vertical-align: top;
523 523 }
524 524 }
525 525 }
526 526
527 527 div.codeblock .code-header .search-path { padding: 0 0 0 10px; }
528 528 div.search-code-body {
529 529 background-color: #ffffff; padding: 5px 0 5px 10px;
530 530 pre {
531 531 .match { background-color: #faffa6;}
532 532 .break { display: block; width: 100%; background-color: #DDE7EF; color: #747474; }
533 533 }
534 534 .code-highlighttable {
535 535 border-collapse: collapse;
536 536
537 537 tr:hover {
538 538 background: #fafafa;
539 539 }
540 540 td.code {
541 541 padding-left: 10px;
542 542 }
543 543 td.line {
544 544 border-right: 1px solid #ccc !important;
545 545 padding-right: 10px;
546 546 text-align: right;
547 547 font-family: "Lucida Console",Monaco,monospace;
548 548 span {
549 549 white-space: pre-wrap;
550 550 color: #666666;
551 551 }
552 552 }
553 553 }
554 554 }
555 555
556 556 div.annotatediv { margin-left: 2px; margin-right: 4px; }
557 557 .code-highlight {
558 558 margin: 0; padding: 0; border-left: @border-thickness solid @grey5;
559 559 pre, .linenodiv pre { padding: 0 5px; margin: 0; }
560 560 pre div:target {background-color: @comment-highlight-color !important;}
561 561 }
562 562
563 563 .linenos a { text-decoration: none; }
564 564
565 565 .CodeMirror-selected { background: @rchighlightblue; }
566 566 .CodeMirror-focused .CodeMirror-selected { background: @rchighlightblue; }
567 567 .CodeMirror ::selection { background: @rchighlightblue; }
568 568 .CodeMirror ::-moz-selection { background: @rchighlightblue; }
569 569
570 570 .code { display: block; border:0px !important; }
571 571 .code-highlight, /* TODO: dan: merge codehilite into code-highlight */
572 572 .codehilite {
573 573 .hll { background-color: #ffffcc }
574 574 .c { color: #408080; font-style: italic } /* Comment */
575 575 .err, .codehilite .err { border: @border-thickness solid #FF0000 } /* Error */
576 576 .k { color: #008000; font-weight: bold } /* Keyword */
577 577 .o { color: #666666 } /* Operator */
578 578 .cm { color: #408080; font-style: italic } /* Comment.Multiline */
579 579 .cp { color: #BC7A00 } /* Comment.Preproc */
580 580 .c1 { color: #408080; font-style: italic } /* Comment.Single */
581 581 .cs { color: #408080; font-style: italic } /* Comment.Special */
582 582 .gd { color: #A00000 } /* Generic.Deleted */
583 583 .ge { font-style: italic } /* Generic.Emph */
584 584 .gr { color: #FF0000 } /* Generic.Error */
585 585 .gh { color: #000080; font-weight: bold } /* Generic.Heading */
586 586 .gi { color: #00A000 } /* Generic.Inserted */
587 587 .go { color: #808080 } /* Generic.Output */
588 588 .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
589 589 .gs { font-weight: bold } /* Generic.Strong */
590 590 .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
591 591 .gt { color: #0040D0 } /* Generic.Traceback */
592 592 .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
593 593 .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
594 594 .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
595 595 .kp { color: #008000 } /* Keyword.Pseudo */
596 596 .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
597 597 .kt { color: #B00040 } /* Keyword.Type */
598 598 .m { color: #666666 } /* Literal.Number */
599 599 .s { color: #BA2121 } /* Literal.String */
600 600 .na { color: #7D9029 } /* Name.Attribute */
601 601 .nb { color: #008000 } /* Name.Builtin */
602 602 .nc { color: #0000FF; font-weight: bold } /* Name.Class */
603 603 .no { color: #880000 } /* Name.Constant */
604 604 .nd { color: #AA22FF } /* Name.Decorator */
605 605 .ni { color: #999999; font-weight: bold } /* Name.Entity */
606 606 .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
607 607 .nf { color: #0000FF } /* Name.Function */
608 608 .nl { color: #A0A000 } /* Name.Label */
609 609 .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
610 610 .nt { color: #008000; font-weight: bold } /* Name.Tag */
611 611 .nv { color: #19177C } /* Name.Variable */
612 612 .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
613 613 .w { color: #bbbbbb } /* Text.Whitespace */
614 614 .mf { color: #666666 } /* Literal.Number.Float */
615 615 .mh { color: #666666 } /* Literal.Number.Hex */
616 616 .mi { color: #666666 } /* Literal.Number.Integer */
617 617 .mo { color: #666666 } /* Literal.Number.Oct */
618 618 .sb { color: #BA2121 } /* Literal.String.Backtick */
619 619 .sc { color: #BA2121 } /* Literal.String.Char */
620 620 .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
621 621 .s2 { color: #BA2121 } /* Literal.String.Double */
622 622 .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
623 623 .sh { color: #BA2121 } /* Literal.String.Heredoc */
624 624 .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
625 625 .sx { color: #008000 } /* Literal.String.Other */
626 626 .sr { color: #BB6688 } /* Literal.String.Regex */
627 627 .s1 { color: #BA2121 } /* Literal.String.Single */
628 628 .ss { color: #19177C } /* Literal.String.Symbol */
629 629 .bp { color: #008000 } /* Name.Builtin.Pseudo */
630 630 .vc { color: #19177C } /* Name.Variable.Class */
631 631 .vg { color: #19177C } /* Name.Variable.Global */
632 632 .vi { color: #19177C } /* Name.Variable.Instance */
633 633 .il { color: #666666 } /* Literal.Number.Integer.Long */
634 634 }
635 635
636 636 /* customized pre blocks for markdown/rst */
637 637 pre.literal-block, .codehilite pre{
638 638 padding: @padding;
639 639 border: 1px solid @grey6;
640 640 .border-radius(@border-radius);
641 641 background-color: @grey7;
642 642 }
643 643
644 644
645 645 /* START NEW CODE BLOCK CSS */
646 646
647 647 @cb-line-height: 18px;
648 648 @cb-line-code-padding: 10px;
649 649 @cb-text-padding: 5px;
650 650
651 651 @pill-padding: 2px 7px;
652 652
653 653 input.filediff-collapse-state {
654 654 display: none;
655 655
656 656 &:checked + .filediff { /* file diff is collapsed */
657 657 .cb {
658 658 display: none
659 659 }
660 660 .filediff-collapse-indicator {
661 661 width: 0;
662 662 height: 0;
663 663 border-style: solid;
664 664 border-width: 6.5px 0 6.5px 11.3px;
665 665 border-color: transparent transparent transparent #ccc;
666 666 }
667 667 .filediff-menu {
668 668 display: none;
669 669 }
670 670 margin: 10px 0 0 0;
671 671 }
672 672
673 673 &+ .filediff { /* file diff is expanded */
674 674 .filediff-collapse-indicator {
675 675 width: 0;
676 676 height: 0;
677 677 border-style: solid;
678 678 border-width: 11.3px 6.5px 0 6.5px;
679 679 border-color: #ccc transparent transparent transparent;
680 680 }
681 681 .filediff-menu {
682 682 display: block;
683 683 }
684 684 margin: 10px 0;
685 685 &:nth-child(2) {
686 686 margin: 0;
687 687 }
688 688 }
689 689 }
690 690 .cs_files {
691 691 clear: both;
692 692 }
693 693
694 694 .diffset-menu {
695 695 margin-bottom: 20px;
696 696 }
697 697 .diffset {
698 698 margin: 20px auto;
699 699 .diffset-heading {
700 700 border: 1px solid @grey5;
701 701 margin-bottom: -1px;
702 702 // margin-top: 20px;
703 703 h2 {
704 704 margin: 0;
705 705 line-height: 38px;
706 706 padding-left: 10px;
707 707 }
708 708 .btn {
709 709 margin: 0;
710 710 }
711 711 background: @grey6;
712 712 display: block;
713 713 padding: 5px;
714 714 }
715 715 .diffset-heading-warning {
716 716 background: @alert3-inner;
717 717 border: 1px solid @alert3;
718 718 }
719 719 &.diffset-comments-disabled {
720 720 .cb-comment-box-opener, .comment-inline-form, .cb-comment-add-button {
721 721 display: none !important;
722 722 }
723 723 }
724 724 }
725 725
726 726 .pill {
727 727 display: block;
728 728 float: left;
729 729 padding: @pill-padding;
730 730 }
731 731 .pill-group {
732 732 .pill {
733 733 opacity: .8;
734 734 &:first-child {
735 735 border-radius: @border-radius 0 0 @border-radius;
736 736 }
737 737 &:last-child {
738 738 border-radius: 0 @border-radius @border-radius 0;
739 739 }
740 740 &:only-child {
741 741 border-radius: @border-radius;
742 742 }
743 743 }
744 744 }
745 745
746 746 /* Main comments*/
747 747 #comments {
748 748 .comment-selected {
749 749 border-left: 6px solid @comment-highlight-color;
750 750 padding-left: 3px;
751 751 margin-left: -9px;
752 752 }
753 753 }
754 754
755 755 .filediff {
756 756 border: 1px solid @grey5;
757 757
758 758 /* START OVERRIDES */
759 759 .code-highlight {
760 760 border: none; // TODO: remove this border from the global
761 761 // .code-highlight, it doesn't belong there
762 762 }
763 763 label {
764 764 margin: 0; // TODO: remove this margin definition from global label
765 765 // it doesn't belong there - if margin on labels
766 766 // are needed for a form they should be defined
767 767 // in the form's class
768 768 }
769 769 /* END OVERRIDES */
770 770
771 771 * {
772 772 box-sizing: border-box;
773 773 }
774 774 .filediff-anchor {
775 775 visibility: hidden;
776 776 }
777 777 &:hover {
778 778 .filediff-anchor {
779 779 visibility: visible;
780 780 }
781 781 }
782 782
783 783 .filediff-collapse-indicator {
784 784 border-style: solid;
785 785 float: left;
786 786 margin: 4px 0px 0 0;
787 787 cursor: pointer;
788 788 }
789 789
790 790 .filediff-heading {
791 791 background: @grey7;
792 792 cursor: pointer;
793 793 display: block;
794 794 padding: 5px 10px;
795 795 }
796 796 .filediff-heading:after {
797 797 content: "";
798 798 display: table;
799 799 clear: both;
800 800 }
801 801 .filediff-heading:hover {
802 802 background: #e1e9f4 !important;
803 803 }
804 804
805 805 .filediff-menu {
806 806 float: right;
807 807 text-align: right;
808 808 padding: 5px 5px 5px 0px;
809 809
810 810 &> a,
811 811 &> span {
812 812 padding: 1px;
813 813 }
814 814 }
815 815
816 816 .pill {
817 817 &[op="name"] {
818 818 background: none;
819 819 color: @grey2;
820 820 opacity: 1;
821 821 color: white;
822 822 }
823 823 &[op="limited"] {
824 824 background: @grey2;
825 825 color: white;
826 826 }
827 827 &[op="binary"] {
828 828 background: @color7;
829 829 color: white;
830 830 }
831 831 &[op="modified"] {
832 832 background: @alert1;
833 833 color: white;
834 834 }
835 835 &[op="renamed"] {
836 836 background: @color4;
837 837 color: white;
838 838 }
839 839 &[op="mode"] {
840 840 background: @grey3;
841 841 color: white;
842 842 }
843 843 &[op="symlink"] {
844 844 background: @color8;
845 845 color: white;
846 846 }
847 847
848 848 &[op="added"] { /* added lines */
849 849 background: @alert1;
850 850 color: white;
851 851 }
852 852 &[op="deleted"] { /* deleted lines */
853 853 background: @alert2;
854 854 color: white;
855 855 }
856 856
857 857 &[op="created"] { /* created file */
858 858 background: @alert1;
859 859 color: white;
860 860 }
861 861 &[op="removed"] { /* deleted file */
862 862 background: @color5;
863 863 color: white;
864 864 }
865 865 }
866 866
867 867 .filediff-collapse-button, .filediff-expand-button {
868 868 cursor: pointer;
869 869 }
870 870 .filediff-collapse-button {
871 871 display: inline;
872 872 }
873 873 .filediff-expand-button {
874 874 display: none;
875 875 }
876 876 .filediff-collapsed .filediff-collapse-button {
877 877 display: none;
878 878 }
879 879 .filediff-collapsed .filediff-expand-button {
880 880 display: inline;
881 881 }
882 882
883 883 @comment-padding: 5px;
884 884
885 885 /**** COMMENTS ****/
886 886
887 887 .filediff-menu {
888 888 .show-comment-button {
889 889 display: none;
890 890 }
891 891 }
892 892 &.hide-comments {
893 893 .inline-comments {
894 894 display: none;
895 895 }
896 896 .filediff-menu {
897 897 .show-comment-button {
898 898 display: inline;
899 899 }
900 900 .hide-comment-button {
901 901 display: none;
902 902 }
903 903 }
904 904 }
905 905
906 906 .hide-line-comments {
907 907 .inline-comments {
908 908 display: none;
909 909 }
910 910 }
911 911
912 912 .inline-comments {
913 913 border-radius: @border-radius;
914 background: @grey6;
915 914 .comment {
916 915 margin: 0;
917 916 border-radius: @border-radius;
918 917 }
919 918 .comment-outdated {
920 919 opacity: 0.5;
921 920 }
922 921
923 922 .comment-inline {
924 923 background: white;
925 924 padding: (@comment-padding + 3px) @comment-padding;
926 925 border: @comment-padding solid @grey6;
927 926
928 927 .text {
929 928 border: none;
930 929 }
931 930 .meta {
932 931 border-bottom: 1px solid @grey6;
933 932 padding-bottom: 10px;
934 933 }
935 934 }
936 935 .comment-selected {
937 936 border-left: 6px solid @comment-highlight-color;
938 937 }
939 938 .comment-inline-form {
940 939 padding: @comment-padding;
941 940 display: none;
942 941 }
943 942 .cb-comment-add-button {
944 943 margin: @comment-padding;
945 944 }
946 945 /* hide add comment button when form is open */
947 946 .comment-inline-form-open ~ .cb-comment-add-button {
948 947 display: none;
949 948 }
950 949 .comment-inline-form-open {
951 950 display: block;
952 951 }
953 952 /* hide add comment button when form but no comments */
954 953 .comment-inline-form:first-child + .cb-comment-add-button {
955 954 display: none;
956 955 }
957 956 /* hide add comment button when no comments or form */
958 957 .cb-comment-add-button:first-child {
959 958 display: none;
960 959 }
961 960 /* hide add comment button when only comment is being deleted */
962 961 .comment-deleting:first-child + .cb-comment-add-button {
963 962 display: none;
964 963 }
965 964 }
966 965 /**** END COMMENTS ****/
967 966
968 967 }
969 968
970 969 .filediff-outdated {
971 970 padding: 8px 0;
972 971
973 972 .filediff-heading {
974 973 opacity: .5;
975 974 }
976 975 }
977 976
978 977 table.cb {
979 978 width: 100%;
980 979 border-collapse: collapse;
981 980
982 981 .cb-text {
983 982 padding: @cb-text-padding;
984 983 }
985 984 .cb-hunk {
986 985 padding: @cb-text-padding;
987 986 }
988 987 .cb-expand {
989 988 display: none;
990 989 }
991 990 .cb-collapse {
992 991 display: inline;
993 992 }
994 993 &.cb-collapsed {
995 994 .cb-line {
996 995 display: none;
997 996 }
998 997 .cb-expand {
999 998 display: inline;
1000 999 }
1001 1000 .cb-collapse {
1002 1001 display: none;
1003 1002 }
1004 1003 }
1005 1004
1006 1005 /* intentionally general selector since .cb-line-selected must override it
1007 1006 and they both use !important since the td itself may have a random color
1008 1007 generated by annotation blocks. TLDR: if you change it, make sure
1009 1008 annotated block selection and line selection in file view still work */
1010 1009 .cb-line-fresh .cb-content {
1011 1010 background: white !important;
1012 1011 }
1013 1012 .cb-warning {
1014 1013 background: #fff4dd;
1015 1014 }
1016 1015
1017 1016 &.cb-diff-sideside {
1018 1017 td {
1019 1018 &.cb-content {
1020 1019 width: 50%;
1021 1020 }
1022 1021 }
1023 1022 }
1024 1023
1025 1024 tr {
1026 1025 &.cb-annotate {
1027 1026 border-top: 1px solid #eee;
1028 1027
1029 1028 &+ .cb-line {
1030 1029 border-top: 1px solid #eee;
1031 1030 }
1032 1031
1033 1032 &:first-child {
1034 1033 border-top: none;
1035 1034 &+ .cb-line {
1036 1035 border-top: none;
1037 1036 }
1038 1037 }
1039 1038 }
1040 1039
1041 1040 &.cb-hunk {
1042 1041 font-family: @font-family-monospace;
1043 1042 color: rgba(0, 0, 0, 0.3);
1044 1043
1045 1044 td {
1046 1045 &:first-child {
1047 1046 background: #edf2f9;
1048 1047 }
1049 1048 &:last-child {
1050 1049 background: #f4f7fb;
1051 1050 }
1052 1051 }
1053 1052 }
1054 1053 }
1055 1054
1056 1055
1057 1056 td {
1058 1057 vertical-align: top;
1059 1058 padding: 0;
1060 1059
1061 1060 &.cb-content {
1062 1061 font-size: 12.35px;
1063 1062
1064 1063 &.cb-line-selected .cb-code {
1065 1064 background: @comment-highlight-color !important;
1066 1065 }
1067 1066
1068 1067 span.cb-code {
1069 1068 line-height: @cb-line-height;
1070 1069 padding-left: @cb-line-code-padding;
1071 1070 padding-right: @cb-line-code-padding;
1072 1071 display: block;
1073 1072 white-space: pre-wrap;
1074 1073 font-family: @font-family-monospace;
1075 1074 word-break: break-word;
1076 1075 .nonl {
1077 1076 color: @color5;
1078 1077 }
1079 1078 }
1080 1079
1081 1080 &> button.cb-comment-box-opener {
1082 1081
1083 1082 padding: 2px 2px 1px 3px;
1084 1083 margin-left: -6px;
1085 1084 margin-top: -1px;
1086 1085
1087 1086 border-radius: @border-radius;
1088 1087 position: absolute;
1089 1088 display: none;
1090 1089 }
1091 1090 .cb-comment {
1092 1091 margin-top: 10px;
1093 1092 white-space: normal;
1094 1093 }
1095 1094 }
1096 1095 &:hover {
1097 1096 button.cb-comment-box-opener {
1098 1097 display: block;
1099 1098 }
1100 1099 &+ td button.cb-comment-box-opener {
1101 1100 display: block
1102 1101 }
1103 1102 }
1104 1103
1105 1104 &.cb-data {
1106 1105 text-align: right;
1107 1106 width: 30px;
1108 1107 font-family: @font-family-monospace;
1109 1108
1110 1109 .icon-comment {
1111 1110 cursor: pointer;
1112 1111 }
1113 1112 &.cb-line-selected > div {
1114 1113 display: block;
1115 1114 background: @comment-highlight-color !important;
1116 1115 line-height: @cb-line-height;
1117 1116 color: rgba(0, 0, 0, 0.3);
1118 1117 }
1119 1118 }
1120 1119
1121 1120 &.cb-lineno {
1122 1121 padding: 0;
1123 1122 width: 50px;
1124 1123 color: rgba(0, 0, 0, 0.3);
1125 1124 text-align: right;
1126 1125 border-right: 1px solid #eee;
1127 1126 font-family: @font-family-monospace;
1128 1127
1129 1128 a::before {
1130 1129 content: attr(data-line-no);
1131 1130 }
1132 1131 &.cb-line-selected a {
1133 1132 background: @comment-highlight-color !important;
1134 1133 }
1135 1134
1136 1135 a {
1137 1136 display: block;
1138 1137 padding-right: @cb-line-code-padding;
1139 1138 padding-left: @cb-line-code-padding;
1140 1139 line-height: @cb-line-height;
1141 1140 color: rgba(0, 0, 0, 0.3);
1142 1141 }
1143 1142 }
1144 1143
1145 1144 &.cb-empty {
1146 1145 background: @grey7;
1147 1146 }
1148 1147
1149 1148 ins {
1150 1149 color: black;
1151 1150 background: #a6f3a6;
1152 1151 text-decoration: none;
1153 1152 }
1154 1153 del {
1155 1154 color: black;
1156 1155 background: #f8cbcb;
1157 1156 text-decoration: none;
1158 1157 }
1159 1158 &.cb-addition {
1160 1159 background: #ecffec;
1161 1160
1162 1161 &.blob-lineno {
1163 1162 background: #ddffdd;
1164 1163 }
1165 1164 }
1166 1165 &.cb-deletion {
1167 1166 background: #ffecec;
1168 1167
1169 1168 &.blob-lineno {
1170 1169 background: #ffdddd;
1171 1170 }
1172 1171 }
1173 1172
1174 1173 &.cb-annotate-info {
1175 1174 width: 320px;
1176 1175 min-width: 320px;
1177 1176 max-width: 320px;
1178 1177 padding: 5px 2px;
1179 1178 font-size: 13px;
1180 1179
1181 1180 strong.cb-annotate-message {
1182 1181 padding: 5px 0;
1183 1182 white-space: pre-line;
1184 1183 display: inline-block;
1185 1184 }
1186 1185 .rc-user {
1187 1186 float: none;
1188 1187 padding: 0 6px 0 17px;
1189 1188 min-width: auto;
1190 1189 min-height: auto;
1191 1190 }
1192 1191 }
1193 1192
1194 1193 &.cb-annotate-revision {
1195 1194 cursor: pointer;
1196 1195 text-align: right;
1197 1196 }
1198 1197 }
1199 1198 }
@@ -1,345 +1,407 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 .comments {
8 8 width: 100%;
9 9 }
10 10
11 11 tr.inline-comments div {
12 12 max-width: 100%;
13 13
14 14 p {
15 15 white-space: normal;
16 16 }
17 17
18 18 code, pre, .code, dd {
19 19 overflow-x: auto;
20 20 width: 1062px;
21 21 }
22 22
23 23 dd {
24 24 width: auto;
25 25 }
26 26 }
27 27
28 28 #injected_page_comments {
29 29 .comment-previous-link,
30 30 .comment-next-link,
31 31 .comment-links-divider {
32 32 display: none;
33 33 }
34 34 }
35 35
36 36 .add-comment {
37 37 margin-bottom: 10px;
38 38 }
39 39 .hide-comment-button .add-comment {
40 40 display: none;
41 41 }
42 42
43 43 .comment-bubble {
44 44 color: @grey4;
45 45 margin-top: 4px;
46 46 margin-right: 30px;
47 47 visibility: hidden;
48 48 }
49 49
50 50 .comment {
51 51 margin: @padding 0;
52 52 padding: 4px 0 0 0;
53 53 line-height: 1em;
54 54
55 55 .rc-user {
56 56 min-width: 0;
57 57 margin: -2px .5em 0 0;
58 58 }
59 59
60 60 .meta {
61 61 position: relative;
62 62 width: 100%;
63 63 margin: 0 0 .5em 0;
64 64
65 65 &:hover .permalink {
66 66 visibility: visible;
67 67 color: @rcblue;
68 68 }
69 69 }
70 70
71 71 .author,
72 72 .date {
73 73 display: inline;
74 74 margin: 0 .5 0 0;
75 75 padding: 0 .5 0 0;
76 76
77 77 &:after {
78 78 content: ' | ';
79 79 color: @grey5;
80 80 }
81 81 }
82 82
83 83 .status-change,
84 84 .permalink,
85 85 .changeset-status-lbl {
86 86 display: inline;
87 87 }
88 88
89 89 .permalink {
90 90 visibility: hidden;
91 91 }
92 92
93 93 .comment-links-divider {
94 94 display: inline;
95 95 }
96 96
97 97 .comment-links-block {
98 98 float:right;
99 99 text-align: right;
100 100 min-width: 85px;
101 101
102 102 [class^="icon-"]:before,
103 103 [class*=" icon-"]:before {
104 104 margin-left: 0;
105 105 margin-right: 0;
106 106 }
107 107 }
108 108
109 109 .comment-previous-link {
110 110 display: inline-block;
111 111
112 112 .arrow_comment_link{
113 113 cursor: pointer;
114 114 i {
115 115 font-size:10px;
116 116 }
117 117 }
118 118 .arrow_comment_link.disabled {
119 119 cursor: default;
120 120 color: @grey5;
121 121 }
122 122 }
123 123
124 124 .comment-next-link {
125 125 display: inline-block;
126 126
127 127 .arrow_comment_link{
128 128 cursor: pointer;
129 129 i {
130 130 font-size:10px;
131 131 }
132 132 }
133 133 .arrow_comment_link.disabled {
134 134 cursor: default;
135 135 color: @grey5;
136 136 }
137 137 }
138 138
139 139 .flag_status {
140 140 display: inline-block;
141 141 margin: -2px .5em 0 .25em
142 142 }
143 143
144 144 .delete-comment {
145 145 display: inline-block;
146 146 color: @rcblue;
147 147
148 148 &:hover {
149 149 cursor: pointer;
150 150 }
151 151 }
152 152
153 153
154 154 .text {
155 155 clear: both;
156 156 border: @border-thickness solid @grey5;
157 157 .border-radius(@border-radius);
158 158 .box-sizing(border-box);
159 159
160 160 .markdown-block p,
161 161 .rst-block p {
162 162 margin: .5em 0 !important;
163 163 // TODO: lisa: This is needed because of other rst !important rules :[
164 164 }
165 165 }
166 166 }
167 167
168 168 .show-outdated-comments {
169 169 display: inline;
170 170 color: @rcblue;
171 171 }
172 172
173 173 // Comment Form
174 174 div.comment-form {
175 175 margin-top: 20px;
176 176 }
177 177
178 178 .comment-form strong {
179 179 display: block;
180 180 margin-bottom: 15px;
181 181 }
182 182
183 183 .comment-form textarea {
184 184 width: 100%;
185 185 height: 100px;
186 186 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
187 187 }
188 188
189 189 form.comment-form {
190 190 margin-top: 10px;
191 191 margin-left: 10px;
192 192 }
193 193
194 194 .comment-inline-form .comment-block-ta,
195 195 .comment-form .comment-block-ta,
196 196 .comment-form .preview-box {
197 border: @border-thickness solid @grey5;
198 197 .border-radius(@border-radius);
199 198 .box-sizing(border-box);
200 199 background-color: white;
201 200 }
202 201
203 202 .comment-form-submit {
204 203 margin-top: 5px;
205 204 margin-left: 525px;
206 205 }
207 206
208 207 .file-comments {
209 208 display: none;
210 209 }
211 210
212 211 .comment-form .preview-box.unloaded,
213 212 .comment-inline-form .preview-box.unloaded {
214 213 height: 50px;
215 214 text-align: center;
216 215 padding: 20px;
217 216 background-color: white;
218 217 }
219 218
220 219 .comment-footer {
221 220 position: relative;
222 221 width: 100%;
223 222 min-height: 42px;
224 223
225 224 .status_box,
226 225 .cancel-button {
227 226 float: left;
228 227 display: inline-block;
229 228 }
230 229
231 230 .action-buttons {
232 231 float: right;
233 232 display: inline-block;
234 233 }
235 234 }
236 235
237 236 .comment-form {
238 237
239 238 .comment {
240 239 margin-left: 10px;
241 240 }
242 241
243 242 .comment-help {
244 243 color: @grey4;
245 244 padding: 5px 0 5px 0;
246 245 }
247 246
248 247 .comment-title {
249 248 padding: 5px 0 5px 0;
250 249 }
251 250
252 251 .comment-button {
253 252 display: inline-block;
254 253 }
255 254
256 255 .comment-button .comment-button-input {
257 256 margin-right: 0;
258 257 }
259 258
260 259 .comment-footer {
261 260 margin-bottom: 110px;
261 margin-top: 10px;
262 262 }
263 263 }
264 264
265 265
266 266 .comment-form-login {
267 267 .comment-help {
268 268 padding: 0.9em; //same as the button
269 269 }
270 270
271 271 div.clearfix {
272 272 clear: both;
273 273 width: 100%;
274 274 display: block;
275 275 }
276 276 }
277 277
278 278 .preview-box {
279 padding: 10px;
280 min-height: 100px;
279 min-height: 105px;
281 280 margin-bottom: 15px;
282 281 background-color: white;
283 border: @border-thickness solid #ccc;
284 282 .border-radius(@border-radius);
285 283 .box-sizing(border-box);
286 284 }
287 285
288 286 .add-another-button {
289 287 margin-left: 10px;
290 288 margin-top: 10px;
291 289 margin-bottom: 10px;
292 290 }
293 291
294 292 .comment .buttons {
295 293 float: right;
296 294 margin: -1px 0px 0px 0px;
297 295 }
298 296
299 297 // Inline Comment Form
300 298 .injected_diff .comment-inline-form,
301 299 .comment-inline-form {
302 background-color: @grey6;
300 background-color: white;
303 301 margin-top: 10px;
304 302 margin-bottom: 20px;
305 303 }
306 304
307 305 .inline-form {
308 306 padding: 10px 7px;
309 307 }
310 308
311 309 .inline-form div {
312 310 max-width: 100%;
313 311 }
314 312
315 313 .overlay {
316 314 display: none;
317 315 position: absolute;
318 316 width: 100%;
319 317 text-align: center;
320 318 vertical-align: middle;
321 319 font-size: 16px;
322 320 background: none repeat scroll 0 0 white;
323 321
324 322 &.submitting {
325 323 display: block;
326 324 opacity: 0.5;
327 325 z-index: 100;
328 326 }
329 327 }
330 328 .comment-inline-form .overlay.submitting .overlay-text {
331 329 margin-top: 5%;
332 330 }
333 331
334 332 .comment-inline-form .clearfix,
335 333 .comment-form .clearfix {
336 334 .border-radius(@border-radius);
337 335 margin: 0px;
338 336 }
339 337
338 .comment-inline-form .comment-footer {
339 margin: 10px 0px 0px 0px;
340 }
341
340 342 .hide-inline-form-button {
341 343 margin-left: 5px;
342 344 }
343 345 .comment-button .hide-inline-form {
344 346 background: white;
345 347 }
348
349 .comment-area {
350 padding: 8px 12px;
351 border: 1px solid @grey5;
352 .border-radius(@border-radius);
353 }
354
355 .comment-area-header .nav-links {
356 display: flex;
357 flex-flow: row wrap;
358 -webkit-flex-flow: row wrap;
359 width: 100%;
360 }
361
362 .comment-area-footer {
363 display: flex;
364 }
365
366 .comment-footer .toolbar {
367
368 }
369
370 .nav-links {
371 padding: 0;
372 margin: 0;
373 list-style: none;
374 height: auto;
375 border-bottom: 1px solid @grey5;
376 }
377 .nav-links li {
378 display: inline-block;
379 }
380 .nav-links li:before {
381 content: "";
382 }
383 .nav-links li a.disabled {
384 cursor: not-allowed;
385 }
386
387 .nav-links li.active a {
388 border-bottom: 2px solid @rcblue;
389 color: #000;
390 font-weight: 600;
391 }
392 .nav-links li a {
393 display: inline-block;
394 padding: 0px 10px 5px 10px;
395 margin-bottom: -1px;
396 font-size: 14px;
397 line-height: 28px;
398 color: #8f8f8f;
399 border-bottom: 2px solid transparent;
400 }
401
402 .toolbar-text {
403 float: left;
404 margin: -5px 0px 0px 0px;
405 font-size: 12px;
406 }
407
@@ -1,651 +1,658 b''
1 1 // # Copyright (C) 2010-2017 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 // returns a node from given html;
29 29 var fromHTML = function(html){
30 30 var _html = document.createElement('element');
31 31 _html.innerHTML = html;
32 32 return _html;
33 33 };
34 34
35 35 var tableTr = function(cls, body){
36 36 var _el = document.createElement('div');
37 37 var _body = $(body).attr('id');
38 38 var comment_id = fromHTML(body).children[0].id.split('comment-')[1];
39 39 var id = 'comment-tr-{0}'.format(comment_id);
40 40 var _html = ('<table><tbody><tr id="{0}" class="{1}">'+
41 41 '<td class="add-comment-line tooltip tooltip" title="Add Comment"><span class="add-comment-content"></span></td>'+
42 42 '<td></td>'+
43 43 '<td></td>'+
44 44 '<td></td>'+
45 45 '<td>{2}</td>'+
46 46 '</tr></tbody></table>').format(id, cls, body);
47 47 $(_el).html(_html);
48 48 return _el.children[0].children[0].children[0];
49 49 };
50 50
51 51 function bindDeleteCommentButtons() {
52 52 $('.delete-comment').one('click', function() {
53 53 var comment_id = $(this).data("comment-id");
54 54
55 55 if (comment_id){
56 56 deleteComment(comment_id);
57 57 }
58 58 });
59 59 }
60 60
61 61 var deleteComment = function(comment_id) {
62 62 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
63 63 var postData = {
64 64 '_method': 'delete',
65 65 'csrf_token': CSRF_TOKEN
66 66 };
67 67
68 68 var success = function(o) {
69 69 window.location.reload();
70 70 };
71 71 ajaxPOST(url, postData, success);
72 72 };
73 73
74 74
75 75 var bindToggleButtons = function() {
76 76 $('.comment-toggle').on('click', function() {
77 77 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
78 78 });
79 79 };
80 80
81 81 var linkifyComments = function(comments) {
82 82 /* TODO: dan: remove this - it should no longer needed */
83 83 for (var i = 0; i < comments.length; i++) {
84 84 var comment_id = $(comments[i]).data('comment-id');
85 85 var prev_comment_id = $(comments[i - 1]).data('comment-id');
86 86 var next_comment_id = $(comments[i + 1]).data('comment-id');
87 87
88 88 // place next/prev links
89 89 if (prev_comment_id) {
90 90 $('#prev_c_' + comment_id).show();
91 91 $('#prev_c_' + comment_id + " a.arrow_comment_link").attr(
92 92 'href', '#comment-' + prev_comment_id).removeClass('disabled');
93 93 }
94 94 if (next_comment_id) {
95 95 $('#next_c_' + comment_id).show();
96 96 $('#next_c_' + comment_id + " a.arrow_comment_link").attr(
97 97 'href', '#comment-' + next_comment_id).removeClass('disabled');
98 98 }
99 99 // place a first link to the total counter
100 100 if (i === 0) {
101 101 $('#inline-comments-counter').attr('href', '#comment-' + comment_id);
102 102 }
103 103 }
104 104
105 105 };
106 106
107 107
108 108 /* Comment form for main and inline comments */
109 109 var CommentForm = (function() {
110 110 "use strict";
111 111
112 112 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions) {
113 113
114 114 this.withLineNo = function(selector) {
115 115 var lineNo = this.lineNo;
116 116 if (lineNo === undefined) {
117 117 return selector
118 118 } else {
119 119 return selector + '_' + lineNo;
120 120 }
121 121 };
122 122
123 123 this.commitId = commitId;
124 124 this.pullRequestId = pullRequestId;
125 125 this.lineNo = lineNo;
126 126 this.initAutocompleteActions = initAutocompleteActions;
127 127
128 128 this.previewButton = this.withLineNo('#preview-btn');
129 129 this.previewContainer = this.withLineNo('#preview-container');
130 130
131 131 this.previewBoxSelector = this.withLineNo('#preview-box');
132 132
133 133 this.editButton = this.withLineNo('#edit-btn');
134 134 this.editContainer = this.withLineNo('#edit-container');
135 135
136 136 this.cancelButton = this.withLineNo('#cancel-btn');
137 137
138 138 this.statusChange = '#change_status';
139 139 this.cmBox = this.withLineNo('#text');
140 140 this.cm = initCommentBoxCodeMirror(this.cmBox, this.initAutocompleteActions);
141 141
142 142 this.submitForm = formElement;
143 143 this.submitButton = $(this.submitForm).find('input[type="submit"]');
144 144 this.submitButtonText = this.submitButton.val();
145 145
146 146 this.previewUrl = pyroutes.url('changeset_comment_preview',
147 147 {'repo_name': templateContext.repo_name});
148 148
149 149 // based on commitId, or pullReuqestId decide where do we submit
150 150 // out data
151 151 if (this.commitId){
152 152 this.submitUrl = pyroutes.url('changeset_comment',
153 153 {'repo_name': templateContext.repo_name,
154 154 'revision': this.commitId});
155 155
156 156 } else if (this.pullRequestId) {
157 157 this.submitUrl = pyroutes.url('pullrequest_comment',
158 158 {'repo_name': templateContext.repo_name,
159 159 'pull_request_id': this.pullRequestId});
160 160
161 161 } else {
162 162 throw new Error(
163 163 'CommentForm requires pullRequestId, or commitId to be specified.')
164 164 }
165 165
166 166 this.getCmInstance = function(){
167 167 return this.cm
168 168 };
169 169
170 170 var self = this;
171 171
172 172 this.getCommentStatus = function() {
173 173 return $(this.submitForm).find(this.statusChange).val();
174 174 };
175 175
176 176 this.isAllowedToSubmit = function() {
177 177 return !$(this.submitButton).prop('disabled');
178 178 };
179 179
180 180 this.initStatusChangeSelector = function(){
181 181 var formatChangeStatus = function(state, escapeMarkup) {
182 182 var originalOption = state.element;
183 183 return '<div class="flag_status ' + $(originalOption).data('status') + ' pull-left"></div>' +
184 184 '<span>' + escapeMarkup(state.text) + '</span>';
185 185 };
186 186 var formatResult = function(result, container, query, escapeMarkup) {
187 187 return formatChangeStatus(result, escapeMarkup);
188 188 };
189 189
190 190 var formatSelection = function(data, container, escapeMarkup) {
191 191 return formatChangeStatus(data, escapeMarkup);
192 192 };
193 193
194 194 $(this.submitForm).find(this.statusChange).select2({
195 195 placeholder: _gettext('Status Review'),
196 196 formatResult: formatResult,
197 197 formatSelection: formatSelection,
198 198 containerCssClass: "drop-menu status_box_menu",
199 199 dropdownCssClass: "drop-menu-dropdown",
200 200 dropdownAutoWidth: true,
201 201 minimumResultsForSearch: -1
202 202 });
203 203 $(this.submitForm).find(this.statusChange).on('change', function() {
204 204 var status = self.getCommentStatus();
205 205 if (status && !self.lineNo) {
206 206 $(self.submitButton).prop('disabled', false);
207 207 }
208 208 //todo, fix this name
209 209 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
210 210 self.cm.setOption('placeholder', placeholderText);
211 211 })
212 212 };
213 213
214 214 // reset the comment form into it's original state
215 215 this.resetCommentFormState = function(content) {
216 216 content = content || '';
217 217
218 218 $(this.editContainer).show();
219 $(this.editButton).hide();
219 $(this.editButton).parent().addClass('active');
220 220
221 221 $(this.previewContainer).hide();
222 $(this.previewButton).show();
222 $(this.previewButton).parent().removeClass('active');
223 223
224 224 this.setActionButtonsDisabled(true);
225 225 self.cm.setValue(content);
226 226 self.cm.setOption("readOnly", false);
227 227 };
228 228
229 229 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
230 230 failHandler = failHandler || function() {};
231 231 var postData = toQueryString(postData);
232 232 var request = $.ajax({
233 233 url: url,
234 234 type: 'POST',
235 235 data: postData,
236 236 headers: {'X-PARTIAL-XHR': true}
237 237 })
238 238 .done(function(data) {
239 239 successHandler(data);
240 240 })
241 241 .fail(function(data, textStatus, errorThrown){
242 242 alert(
243 243 "Error while submitting comment.\n" +
244 244 "Error code {0} ({1}).".format(data.status, data.statusText));
245 245 failHandler()
246 246 });
247 247 return request;
248 248 };
249 249
250 250 // overwrite a submitHandler, we need to do it for inline comments
251 251 this.setHandleFormSubmit = function(callback) {
252 252 this.handleFormSubmit = callback;
253 253 };
254 254
255 255 // default handler for for submit for main comments
256 256 this.handleFormSubmit = function() {
257 257 var text = self.cm.getValue();
258 258 var status = self.getCommentStatus();
259 259
260 260 if (text === "" && !status) {
261 261 return;
262 262 }
263 263
264 264 var excludeCancelBtn = false;
265 265 var submitEvent = true;
266 266 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
267 267 self.cm.setOption("readOnly", true);
268 268 var postData = {
269 269 'text': text,
270 270 'changeset_status': status,
271 271 'csrf_token': CSRF_TOKEN
272 272 };
273 273
274 274 var submitSuccessCallback = function(o) {
275 275 if (status) {
276 276 location.reload(true);
277 277 } else {
278 278 $('#injected_page_comments').append(o.rendered_text);
279 279 self.resetCommentFormState();
280 280 bindDeleteCommentButtons();
281 281 timeagoActivate();
282 282 }
283 283 };
284 284 var submitFailCallback = function(){
285 285 self.resetCommentFormState(text)
286 286 };
287 287 self.submitAjaxPOST(
288 288 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
289 289 };
290 290
291 291 this.previewSuccessCallback = function(o) {
292 292 $(self.previewBoxSelector).html(o);
293 293 $(self.previewBoxSelector).removeClass('unloaded');
294 294
295 // swap buttons
296 $(self.previewButton).hide();
297 $(self.editButton).show();
295 // swap buttons, making preview active
296 $(self.previewButton).parent().addClass('active');
297 $(self.editButton).parent().removeClass('active');
298 298
299 299 // unlock buttons
300 300 self.setActionButtonsDisabled(false);
301 301 };
302 302
303 303 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
304 304 excludeCancelBtn = excludeCancelBtn || false;
305 305 submitEvent = submitEvent || false;
306 306
307 307 $(this.editButton).prop('disabled', state);
308 308 $(this.previewButton).prop('disabled', state);
309 309
310 310 if (!excludeCancelBtn) {
311 311 $(this.cancelButton).prop('disabled', state);
312 312 }
313 313
314 314 var submitState = state;
315 315 if (!submitEvent && this.getCommentStatus() && !this.lineNo) {
316 316 // if the value of commit review status is set, we allow
317 317 // submit button, but only on Main form, lineNo means inline
318 318 submitState = false
319 319 }
320 320 $(this.submitButton).prop('disabled', submitState);
321 321 if (submitEvent) {
322 322 $(this.submitButton).val(_gettext('Submitting...'));
323 323 } else {
324 324 $(this.submitButton).val(this.submitButtonText);
325 325 }
326 326
327 327 };
328 328
329 329 // lock preview/edit/submit buttons on load, but exclude cancel button
330 330 var excludeCancelBtn = true;
331 331 this.setActionButtonsDisabled(true, excludeCancelBtn);
332 332
333 333 // anonymous users don't have access to initialized CM instance
334 334 if (this.cm !== undefined){
335 335 this.cm.on('change', function(cMirror) {
336 336 if (cMirror.getValue() === "") {
337 337 self.setActionButtonsDisabled(true, excludeCancelBtn)
338 338 } else {
339 339 self.setActionButtonsDisabled(false, excludeCancelBtn)
340 340 }
341 341 });
342 342 }
343 343
344 344 $(this.editButton).on('click', function(e) {
345 345 e.preventDefault();
346 346
347 $(self.previewButton).show();
347 $(self.previewButton).parent().removeClass('active');
348 348 $(self.previewContainer).hide();
349 $(self.editButton).hide();
349
350 $(self.editButton).parent().addClass('active');
350 351 $(self.editContainer).show();
351 352
352 353 });
353 354
354 355 $(this.previewButton).on('click', function(e) {
355 356 e.preventDefault();
356 357 var text = self.cm.getValue();
357 358
358 359 if (text === "") {
359 360 return;
360 361 }
361 362
362 363 var postData = {
363 364 'text': text,
364 365 'renderer': DEFAULT_RENDERER,
365 366 'csrf_token': CSRF_TOKEN
366 367 };
367 368
368 369 // lock ALL buttons on preview
369 370 self.setActionButtonsDisabled(true);
370 371
371 372 $(self.previewBoxSelector).addClass('unloaded');
372 373 $(self.previewBoxSelector).html(_gettext('Loading ...'));
374
373 375 $(self.editContainer).hide();
374 376 $(self.previewContainer).show();
375 377
376 378 // by default we reset state of comment preserving the text
377 379 var previewFailCallback = function(){
378 380 self.resetCommentFormState(text)
379 381 };
380 382 self.submitAjaxPOST(
381 self.previewUrl, postData, self.previewSuccessCallback, previewFailCallback);
383 self.previewUrl, postData, self.previewSuccessCallback,
384 previewFailCallback);
382 385
386 $(self.previewButton).parent().addClass('active');
387 $(self.editButton).parent().removeClass('active');
383 388 });
384 389
385 390 $(this.submitForm).submit(function(e) {
386 391 e.preventDefault();
387 392 var allowedToSubmit = self.isAllowedToSubmit();
388 393 if (!allowedToSubmit){
389 394 return false;
390 395 }
391 396 self.handleFormSubmit();
392 397 });
393 398
394 399 }
395 400
396 401 return CommentForm;
397 402 })();
398 403
399 404 var CommentsController = function() { /* comments controller */
400 405 var self = this;
401 406
402 407 this.cancelComment = function(node) {
403 408 var $node = $(node);
404 409 var $td = $node.closest('td');
405 410 $node.closest('.comment-inline-form').removeClass('comment-inline-form-open');
406 411 return false;
407 412 };
408 413
409 414 this.getLineNumber = function(node) {
410 415 var $node = $(node);
411 416 return $node.closest('td').attr('data-line-number');
412 417 };
413 418
414 419 this.scrollToComment = function(node, offset, outdated) {
415 420 var outdated = outdated || false;
416 421 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
417 422
418 423 if (!node) {
419 424 node = $('.comment-selected');
420 425 if (!node.length) {
421 426 node = $('comment-current')
422 427 }
423 428 }
424 429 $comment = $(node).closest(klass);
425 430 $comments = $(klass);
426 431
427 432 $('.comment-selected').removeClass('comment-selected');
428 433
429 434 var nextIdx = $(klass).index($comment) + offset;
430 435 if (nextIdx >= $comments.length) {
431 436 nextIdx = 0;
432 437 }
433 438 var $next = $(klass).eq(nextIdx);
434 439 var $cb = $next.closest('.cb');
435 440 $cb.removeClass('cb-collapsed');
436 441
437 442 var $filediffCollapseState = $cb.closest('.filediff').prev();
438 443 $filediffCollapseState.prop('checked', false);
439 444 $next.addClass('comment-selected');
440 445 scrollToElement($next);
441 446 return false;
442 447 };
443 448
444 449 this.nextComment = function(node) {
445 450 return self.scrollToComment(node, 1);
446 451 };
447 452
448 453 this.prevComment = function(node) {
449 454 return self.scrollToComment(node, -1);
450 455 };
451 456
452 457 this.nextOutdatedComment = function(node) {
453 458 return self.scrollToComment(node, 1, true);
454 459 };
455 460
456 461 this.prevOutdatedComment = function(node) {
457 462 return self.scrollToComment(node, -1, true);
458 463 };
459 464
460 465 this.deleteComment = function(node) {
461 466 if (!confirm(_gettext('Delete this comment?'))) {
462 467 return false;
463 468 }
464 469 var $node = $(node);
465 470 var $td = $node.closest('td');
466 471 var $comment = $node.closest('.comment');
467 472 var comment_id = $comment.attr('data-comment-id');
468 473 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
469 474 var postData = {
470 475 '_method': 'delete',
471 476 'csrf_token': CSRF_TOKEN
472 477 };
473 478
474 479 $comment.addClass('comment-deleting');
475 480 $comment.hide('fast');
476 481
477 482 var success = function(response) {
478 483 $comment.remove();
479 484 return false;
480 485 };
481 486 var failure = function(data, textStatus, xhr) {
482 487 alert("error processing request: " + textStatus);
483 488 $comment.show('fast');
484 489 $comment.removeClass('comment-deleting');
485 490 return false;
486 491 };
487 492 ajaxPOST(url, postData, success, failure);
488 493 };
489 494
490 495 this.toggleWideMode = function (node) {
491 496 if ($('#content').hasClass('wrapper')) {
492 497 $('#content').removeClass("wrapper");
493 498 $('#content').addClass("wide-mode-wrapper");
494 499 $(node).addClass('btn-success');
495 500 } else {
496 501 $('#content').removeClass("wide-mode-wrapper");
497 502 $('#content').addClass("wrapper");
498 503 $(node).removeClass('btn-success');
499 504 }
500 505 return false;
501 506 };
502 507
503 508 this.toggleComments = function(node, show) {
504 509 var $filediff = $(node).closest('.filediff');
505 510 if (show === true) {
506 511 $filediff.removeClass('hide-comments');
507 512 } else if (show === false) {
508 513 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
509 514 $filediff.addClass('hide-comments');
510 515 } else {
511 516 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
512 517 $filediff.toggleClass('hide-comments');
513 518 }
514 519 return false;
515 520 };
516 521
517 522 this.toggleLineComments = function(node) {
518 523 self.toggleComments(node, true);
519 524 var $node = $(node);
520 525 $node.closest('tr').toggleClass('hide-line-comments');
521 526 };
522 527
523 528 this.createComment = function(node) {
524 529 var $node = $(node);
525 530 var $td = $node.closest('td');
526 531 var $form = $td.find('.comment-inline-form');
527 532
528 533 if (!$form.length) {
529 534 var tmpl = $('#cb-comment-inline-form-template').html();
530 535 var $filediff = $node.closest('.filediff');
531 536 $filediff.removeClass('hide-comments');
532 537 var f_path = $filediff.attr('data-f-path');
533 538 var lineno = self.getLineNumber(node);
534 539 tmpl = tmpl.format(f_path, lineno);
535 540 $form = $(tmpl);
536 541
537 542 var $comments = $td.find('.inline-comments');
538 543 if (!$comments.length) {
539 544 $comments = $(
540 545 $('#cb-comments-inline-container-template').html());
541 546 $td.append($comments);
542 547 }
543 548
544 549 $td.find('.cb-comment-add-button').before($form);
545 550
546 551 var pullRequestId = templateContext.pull_request_data.pull_request_id;
547 552 var commitId = templateContext.commit_data.commit_id;
548 553 var _form = $form[0];
549 554 var commentForm = new CommentForm(_form, commitId, pullRequestId, lineno, false);
550 555 var cm = commentForm.getCmInstance();
551 556
552 557 // set a CUSTOM submit handler for inline comments.
553 558 commentForm.setHandleFormSubmit(function(o) {
554 559 var text = commentForm.cm.getValue();
555 560
556 561 if (text === "") {
557 562 return;
558 563 }
559 564
560 565 if (lineno === undefined) {
561 566 alert('missing line !');
562 567 return;
563 568 }
564 569 if (f_path === undefined) {
565 570 alert('missing file path !');
566 571 return;
567 572 }
568 573
569 574 var excludeCancelBtn = false;
570 575 var submitEvent = true;
571 576 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
572 577 commentForm.cm.setOption("readOnly", true);
573 578 var postData = {
574 579 'text': text,
575 580 'f_path': f_path,
576 581 'line': lineno,
577 582 'csrf_token': CSRF_TOKEN
578 583 };
579 584 var submitSuccessCallback = function(json_data) {
580 585 $form.remove();
581 586 try {
582 587 var html = json_data.rendered_text;
583 588 var lineno = json_data.line_no;
584 589 var target_id = json_data.target_id;
585 590
586 591 $comments.find('.cb-comment-add-button').before(html);
587 592
588 593 } catch (e) {
589 594 console.error(e);
590 595 }
591 596
592 597 // re trigger the linkification of next/prev navigation
593 598 linkifyComments($('.inline-comment-injected'));
594 599 timeagoActivate();
595 600 bindDeleteCommentButtons();
596 601 commentForm.setActionButtonsDisabled(false);
597 602
598 603 };
599 604 var submitFailCallback = function(){
600 605 commentForm.resetCommentFormState(text)
601 606 };
602 607 commentForm.submitAjaxPOST(
603 608 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
604 609 });
605 610
606 611 setTimeout(function() {
607 612 // callbacks
608 613 if (cm !== undefined) {
614 cm.setOption('placeholder', _gettext('Leave a comment on line {0}.').format(lineno));
609 615 cm.focus();
616 cm.refresh();
610 617 }
611 618 }, 10);
612 619
613 620 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
614 621 form: _form,
615 622 parent: $td[0],
616 623 lineno: lineno,
617 624 f_path: f_path}
618 625 );
619 626 }
620 627
621 628 $form.addClass('comment-inline-form-open');
622 629 };
623 630
624 631 this.renderInlineComments = function(file_comments) {
625 632 show_add_button = typeof show_add_button !== 'undefined' ? show_add_button : true;
626 633
627 634 for (var i = 0; i < file_comments.length; i++) {
628 635 var box = file_comments[i];
629 636
630 637 var target_id = $(box).attr('target_id');
631 638
632 639 // actually comments with line numbers
633 640 var comments = box.children;
634 641
635 642 for (var j = 0; j < comments.length; j++) {
636 643 var data = {
637 644 'rendered_text': comments[j].outerHTML,
638 645 'line_no': $(comments[j]).attr('line'),
639 646 'target_id': target_id
640 647 };
641 648 }
642 649 }
643 650
644 651 // since order of injection is random, we're now re-iterating
645 652 // from correct order and filling in links
646 653 linkifyComments($('.inline-comment-injected'));
647 654 bindDeleteCommentButtons();
648 655 firefoxAnchorFix();
649 656 };
650 657
651 658 };
@@ -1,209 +1,264 b''
1 1 ## -*- coding: utf-8 -*-
2 2 ## usage:
3 3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
4 4 ## ${comment.comment_block(comment)}
5 5 ##
6 6 <%namespace name="base" file="/base/base.html"/>
7 7
8 8 <%def name="comment_block(comment, inline=False)">
9 9 <% outdated_at_ver = comment.outdated_at_version(getattr(c, 'at_version', None)) %>
10 10
11 11 <div class="comment
12 12 ${'comment-inline' if inline else ''}
13 13 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
14 14 id="comment-${comment.comment_id}"
15 15 line="${comment.line_no}"
16 16 data-comment-id="${comment.comment_id}"
17 17 style="${'display: none;' if outdated_at_ver else ''}">
18 18
19 19 <div class="meta">
20 20 <div class="author">
21 21 ${base.gravatar_with_user(comment.author.email, 16)}
22 22 </div>
23 23 <div class="date">
24 24 ${h.age_component(comment.modified_at, time_is_local=True)}
25 25 </div>
26 26 <div class="status-change">
27 27 % if comment.pull_request:
28 28 % if comment.outdated:
29 29 <a href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}">
30 30 ${_('Outdated comment from pull request version {}').format(comment.pull_request_version_id)}
31 31 </a>
32 32 % else:
33 33 <a href="${h.url('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
34 34 %if comment.status_change:
35 35 ${_('Vote on pull request #%s') % comment.pull_request.pull_request_id}:
36 36 %else:
37 37 ${_('Comment on pull request #%s') % comment.pull_request.pull_request_id}
38 38 %endif
39 39 </a>
40 40 % endif
41 41 % else:
42 42 % if comment.status_change:
43 43 ${_('Status change on commit')}:
44 44 % else:
45 45 ${_('Comment on commit')}
46 46 % endif
47 47 % endif
48 48 </div>
49 49 %if comment.status_change:
50 50 <div class="${'flag_status %s' % comment.status_change[0].status}"></div>
51 51 <div title="${_('Commit status')}" class="changeset-status-lbl">
52 52 ${comment.status_change[0].status_lbl}
53 53 </div>
54 54 %endif
55 55 <a class="permalink" href="#comment-${comment.comment_id}"> &para;</a>
56 56
57 57 <div class="comment-links-block">
58 58 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
59 59 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
60 60 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
61 61 ## permissions to delete
62 62 %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id:
63 63 ## TODO: dan: add edit comment here
64 64 <a onclick="return Rhodecode.comments.deleteComment(this);" class="delete-comment"> ${_('Delete')}</a>
65 65 %else:
66 66 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
67 67 %endif
68 68 %else:
69 69 <button class="btn-link" disabled="disabled"> ${_('Delete')}</button>
70 70 %endif
71 71
72 72 %if not outdated_at_ver:
73 73 | <a onclick="return Rhodecode.comments.prevComment(this);" class="prev-comment"> ${_('Prev')}</a>
74 74 | <a onclick="return Rhodecode.comments.nextComment(this);" class="next-comment"> ${_('Next')}</a>
75 75 %endif
76 76
77 77 </div>
78 78 </div>
79 79 <div class="text">
80 80 ${comment.render(mentions=True)|n}
81 81 </div>
82 82
83 83 </div>
84 84 </%def>
85 85 ## generate main comments
86 86 <%def name="generate_comments(include_pull_request=False, is_pull_request=False)">
87 87 <div id="comments">
88 88 %for comment in c.comments:
89 89 <div id="comment-tr-${comment.comment_id}">
90 90 ## only render comments that are not from pull request, or from
91 91 ## pull request and a status change
92 92 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
93 93 ${comment_block(comment)}
94 94 %endif
95 95 </div>
96 96 %endfor
97 97 ## to anchor ajax comments
98 98 <div id="injected_page_comments"></div>
99 99 </div>
100 100 </%def>
101 101
102 102 ## MAIN COMMENT FORM
103 103 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
104 104
105 105 %if is_compare:
106 106 <% form_id = "comments_form_compare" %>
107 107 %else:
108 108 <% form_id = "comments_form" %>
109 109 %endif
110 110
111 111
112 112 %if is_pull_request:
113 113 <div class="pull-request-merge">
114 114 %if c.allowed_to_merge:
115 115 <div class="pull-request-wrap">
116 116 <div class="pull-right">
117 117 ${h.secure_form(url('pullrequest_merge', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), id='merge_pull_request_form')}
118 118 <span data-role="merge-message">${c.pr_merge_msg} ${c.approval_msg if c.approval_msg else ''}</span>
119 119 <% merge_disabled = ' disabled' if c.pr_merge_status is False else '' %>
120 120 <input type="submit" id="merge_pull_request" value="${_('Merge Pull Request')}" class="btn${merge_disabled}"${merge_disabled}>
121 121 ${h.end_form()}
122 122 </div>
123 123 </div>
124 124 %else:
125 125 <div class="pull-request-wrap">
126 126 <div class="pull-right">
127 127 <span>${c.pr_merge_msg} ${c.approval_msg if c.approval_msg else ''}</span>
128 128 </div>
129 129 </div>
130 130 %endif
131 131 </div>
132 132 %endif
133 133 <div class="comments">
134 %if c.rhodecode_user.username != h.DEFAULT_USER:
134 <%
135 if is_pull_request:
136 placeholder = _('Leave a comment on this Pull Request.')
137 elif is_compare:
138 placeholder = _('Leave a comment on all commits in this range.')
139 else:
140 placeholder = _('Leave a comment on this Commit.')
141 %>
142 % if c.rhodecode_user.username != h.DEFAULT_USER:
135 143 <div class="comment-form ac">
136 144 ${h.secure_form(post_url, id_=form_id)}
137 <div id="edit-container" class="clearfix">
138 <div class="comment-title pull-left">
139 %if is_pull_request:
140 ${(_('Create a comment on this Pull Request.'))}
141 %elif is_compare:
142 ${(_('Create comments on this Commit range.'))}
143 %else:
144 ${(_('Create a comment on this Commit.'))}
145 %endif
145 <div class="comment-area">
146 <div class="comment-area-header">
147 <ul class="nav-links clearfix">
148 <li class="active">
149 <a href="#edit-btn" tabindex="-1" id="edit-btn">${_('Write')}</a>
150 </li>
151 <li class="">
152 <a href="#preview-btn" tabindex="-1" id="preview-btn">${_('Preview')}</a>
153 </li>
154 </ul>
146 155 </div>
147 <div class="comment-help pull-right">
148 ${(_('Comments parsed using %s syntax with %s support.') % (
149 ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
150 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
151 )
152 )|n
153 }
156
157 <div class="comment-area-write" style="display: block;">
158 <div id="edit-container">
159 <textarea id="text" name="text" class="comment-block-ta ac-input"></textarea>
160 </div>
161 <div id="preview-container" class="clearfix" style="display: none;">
162 <div id="preview-box" class="preview-box"></div>
163 </div>
154 164 </div>
155 <div style="clear: both"></div>
156 ${h.textarea('text', class_="comment-block-ta")}
157 </div>
158 165
159 <div id="preview-container" class="clearfix" style="display: none;">
160 <div class="comment-title">
161 ${_('Comment preview')}
166 <div class="comment-area-footer">
167 <div class="toolbar">
168 <div class="toolbar-text">
169 ${(_('Comments parsed using %s syntax with %s support.') % (
170 ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
171 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
172 )
173 )|n
174 }
175 </div>
176 </div>
162 177 </div>
163 <div id="preview-box" class="preview-box"></div>
164 178 </div>
165 179
166 180 <div id="comment_form_extras">
167 181 %if form_extras and isinstance(form_extras, (list, tuple)):
168 182 % for form_ex_el in form_extras:
169 183 ${form_ex_el|n}
170 184 % endfor
171 185 %endif
172 186 </div>
173 187 <div class="comment-footer">
174 188 %if change_status:
175 189 <div class="status_box">
176 190 <select id="change_status" name="changeset_status">
177 191 <option></option> # Placeholder
178 192 %for status,lbl in c.commit_statuses:
179 193 <option value="${status}" data-status="${status}">${lbl}</option>
180 194 %if is_pull_request and change_status and status in ('approved', 'rejected'):
181 195 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
182 196 %endif
183 197 %endfor
184 198 </select>
185 199 </div>
186 200 %endif
187 201 <div class="action-buttons">
188 <button id="preview-btn" class="btn btn-secondary">${_('Preview')}</button>
189 <button id="edit-btn" class="btn btn-secondary" style="display:none;">${_('Edit')}</button>
190 202 <div class="comment-button">${h.submit('save', _('Comment'), class_="btn btn-success comment-button-input")}</div>
191 203 </div>
192 204 </div>
193 205 ${h.end_form()}
194 206 </div>
195 %endif
207 % else:
208 <div class="comment-form ac">
209
210 <div class="comment-area">
211 <div class="comment-area-header">
212 <ul class="nav-links clearfix">
213 <li class="active">
214 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
215 </li>
216 <li class="">
217 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
218 </li>
219 </ul>
220 </div>
221
222 <div class="comment-area-write" style="display: block;">
223 <div id="edit-container">
224 <div style="padding: 40px 0">
225 ${_('You need to be logged in to leave comments.')}
226 <a href="${h.route_path('login', _query={'came_from': h.url.current()})}">${_('Login now')}</a>
227 </div>
228 </div>
229 <div id="preview-container" class="clearfix" style="display: none;">
230 <div id="preview-box" class="preview-box"></div>
231 </div>
232 </div>
233
234 <div class="comment-area-footer">
235 <div class="toolbar">
236 <div class="toolbar-text">
237 </div>
238 </div>
239 </div>
240 </div>
241
242 <div class="comment-footer">
243 </div>
244
245 </div>
246 % endif
247
196 248 </div>
249
197 250 <script>
198 251 // init active elements of commentForm
199 252 var commitId = templateContext.commit_data.commit_id;
200 253 var pullRequestId = templateContext.pull_request_data.pull_request_id;
201 254 var lineNo;
202 255
203 256 var mainCommentForm = new CommentForm(
204 257 "#${form_id}", commitId, pullRequestId, lineNo, true);
205 258
259 mainCommentForm.cm.setOption('placeholder', "${placeholder}");
260
206 261 mainCommentForm.initStatusChangeSelector();
207 262 bindToggleButtons();
208 263 </script>
209 264 </%def>
@@ -1,125 +1,125 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('%s Commits') % c.repo_name} -
6 6 r${c.commit_ranges[0].revision}:${h.short_id(c.commit_ranges[0].raw_id)}
7 7 ...
8 8 r${c.commit_ranges[-1].revision}:${h.short_id(c.commit_ranges[-1].raw_id)}
9 9 ${ungettext('(%s commit)','(%s commits)', len(c.commit_ranges)) % len(c.commit_ranges)}
10 10 %if c.rhodecode_name:
11 11 &middot; ${h.branding(c.rhodecode_name)}
12 12 %endif
13 13 </%def>
14 14
15 15 <%def name="breadcrumbs_links()">
16 16 ${_('Commits')} -
17 17 r${c.commit_ranges[0].revision}:${h.short_id(c.commit_ranges[0].raw_id)}
18 18 ...
19 19 r${c.commit_ranges[-1].revision}:${h.short_id(c.commit_ranges[-1].raw_id)}
20 20 ${ungettext('(%s commit)','(%s commits)', len(c.commit_ranges)) % len(c.commit_ranges)}
21 21 </%def>
22 22
23 23 <%def name="menu_bar_nav()">
24 24 ${self.menu_items(active='repositories')}
25 25 </%def>
26 26
27 27 <%def name="menu_bar_subnav()">
28 28 ${self.repo_menu(active='changelog')}
29 29 </%def>
30 30
31 31 <%def name="main()">
32 32 <div class="summary-header">
33 33 <div class="title">
34 34 ${self.repo_page_title(c.rhodecode_db_repo)}
35 35 </div>
36 36 </div>
37 37
38 38
39 39 <div class="summary changeset">
40 40 <div class="summary-detail">
41 41 <div class="summary-detail-header">
42 42 <span class="breadcrumbs files_location">
43 43 <h4>
44 44 ${_('Commit Range')}
45 45 <code>
46 46 r${c.commit_ranges[0].revision}:${h.short_id(c.commit_ranges[0].raw_id)}...r${c.commit_ranges[-1].revision}:${h.short_id(c.commit_ranges[-1].raw_id)}
47 47 </code>
48 48 </h4>
49 49 </span>
50 50 </div>
51 51
52 52 <div class="fieldset">
53 53 <div class="left-label">
54 54 ${_('Diff option')}:
55 55 </div>
56 56 <div class="right-content">
57 57 <div class="header-buttons">
58 58 <a href="${h.url('compare_url', repo_name=c.repo_name, source_ref_type='rev', source_ref=getattr(c.commit_ranges[0].parents[0] if c.commit_ranges[0].parents else h.EmptyCommit(), 'raw_id'), target_ref_type='rev', target_ref=c.commit_ranges[-1].raw_id)}">
59 59 ${_('Show combined compare')}
60 60 </a>
61 61 </div>
62 62 </div>
63 63 </div>
64 64
65 65 <%doc>
66 66 ##TODO(marcink): implement this and diff menus
67 67 <div class="fieldset">
68 68 <div class="left-label">
69 69 ${_('Diff options')}:
70 70 </div>
71 71 <div class="right-content">
72 72 <div class="diff-actions">
73 73 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
74 74 ${_('Raw Diff')}
75 75 </a>
76 76 |
77 77 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
78 78 ${_('Patch Diff')}
79 79 </a>
80 80 |
81 81 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
82 82 ${_('Download Diff')}
83 83 </a>
84 84 </div>
85 85 </div>
86 86 </div>
87 87 </%doc>
88 88 </div> <!-- end summary-detail -->
89 89
90 90 </div> <!-- end summary -->
91 91
92 <div id="changeset_compare_view_content">
92 <div id="changeset_compare_view_content">
93 93 <div class="pull-left">
94 94 <div class="btn-group">
95 95 <a
96 96 class="btn"
97 97 href="#"
98 98 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
99 99 ${ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
100 100 </a>
101 101 <a
102 102 class="btn"
103 103 href="#"
104 104 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
105 105 ${ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
106 106 </a>
107 107 </div>
108 108 </div>
109 109 ## Commit range generated below
110 110 <%include file="../compare/compare_commits.html"/>
111 111 <div class="cs_files">
112 112 <%namespace name="cbdiffs" file="/codeblocks/diffs.html"/>
113 113 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
114 114 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
115 115 ${cbdiffs.render_diffset_menu()}
116 116 %for commit in c.commit_ranges:
117 117 ${cbdiffs.render_diffset(
118 118 diffset=c.changes[commit.raw_id],
119 119 collapse_when_files_over=5,
120 120 commit=commit,
121 121 )}
122 122 %endfor
123 123 </div>
124 124 </div>
125 125 </%def>
@@ -1,692 +1,705 b''
1 1 <%def name="diff_line_anchor(filename, line, type)"><%
2 2 return '%s_%s_%i' % (h.safeid(filename), type, line)
3 3 %></%def>
4 4
5 5 <%def name="action_class(action)"><%
6 6 return {
7 7 '-': 'cb-deletion',
8 8 '+': 'cb-addition',
9 9 ' ': 'cb-context',
10 10 }.get(action, 'cb-empty')
11 11 %></%def>
12 12
13 13 <%def name="op_class(op_id)"><%
14 14 return {
15 15 DEL_FILENODE: 'deletion', # file deleted
16 16 BIN_FILENODE: 'warning' # binary diff hidden
17 17 }.get(op_id, 'addition')
18 18 %></%def>
19 19
20 20 <%def name="link_for(**kw)"><%
21 21 new_args = request.GET.mixed()
22 22 new_args.update(kw)
23 23 return h.url('', **new_args)
24 24 %></%def>
25 25
26 26 <%def name="render_diffset(diffset, commit=None,
27 27
28 28 # collapse all file diff entries when there are more than this amount of files in the diff
29 29 collapse_when_files_over=20,
30 30
31 31 # collapse lines in the diff when more than this amount of lines changed in the file diff
32 32 lines_changed_limit=500,
33 33
34 34 # add a ruler at to the output
35 35 ruler_at_chars=0,
36 36
37 37 # show inline comments
38 38 use_comments=False,
39 39
40 40 # disable new comments
41 41 disable_new_comments=False,
42 42
43 43 # special file-comments that were deleted in previous versions
44 44 # it's used for showing outdated comments for deleted files in a PR
45 45 deleted_files_comments=None
46 46
47 47 )">
48 48
49 49 %if use_comments:
50 50 <div id="cb-comments-inline-container-template" class="js-template">
51 51 ${inline_comments_container([])}
52 52 </div>
53 53 <div class="js-template" id="cb-comment-inline-form-template">
54 54 <div class="comment-inline-form ac">
55
55 56 %if c.rhodecode_user.username != h.DEFAULT_USER:
56 57 ${h.form('#', method='get')}
57 <div id="edit-container_{1}" class="clearfix">
58 <div class="comment-title pull-left">
59 ${_('Create a comment on line {1}.')}
60 </div>
61 <div class="comment-help pull-right">
62 ${(_('Comments parsed using %s syntax with %s support.') % (
63 ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
64 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
65 )
66 )|n
67 }
68 </div>
69 <div style="clear: both"></div>
70 <textarea id="text_{1}" name="text" class="comment-block-ta ac-input"></textarea>
58 <div class="comment-area">
59 <div class="comment-area-header">
60 <ul class="nav-links clearfix">
61 <li class="active">
62 <a href="#edit-btn" tabindex="-1" id="edit-btn_{1}">${_('Write')}</a>
63 </li>
64 <li class="">
65 <a href="#preview-btn" tabindex="-1" id="preview-btn_{1}">${_('Preview')}</a>
66 </li>
67 </ul>
68 </div>
69
70 <div class="comment-area-write" style="display: block;">
71 <div id="edit-container_{1}">
72 <textarea id="text_{1}" name="text" class="comment-block-ta ac-input"></textarea>
73 </div>
74 <div id="preview-container_{1}" class="clearfix" style="display: none;">
75 <div id="preview-box_{1}" class="preview-box"></div>
76 </div>
77 </div>
78
79 <div class="comment-area-footer">
80 <div class="toolbar">
81 <div class="toolbar-text">
82 ${(_('Comments parsed using %s syntax with %s support.') % (
83 ('<a href="%s">%s</a>' % (h.url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
84 ('<span class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
85 )
86 )|n
87 }
88 </div>
89 </div>
90 </div>
71 91 </div>
72 <div id="preview-container_{1}" class="clearfix" style="display: none;">
73 <div class="comment-help">
74 ${_('Comment preview')}
75 </div>
76 <div id="preview-box_{1}" class="preview-box"></div>
77 </div>
92
78 93 <div class="comment-footer">
79 94 <div class="action-buttons">
80 95 <input type="hidden" name="f_path" value="{0}">
81 96 <input type="hidden" name="line" value="{1}">
82 <button id="preview-btn_{1}" class="btn btn-secondary">${_('Preview')}</button>
83 <button id="edit-btn_{1}" class="btn btn-secondary" style="display: none;">${_('Edit')}</button>
84 ${h.submit('save', _('Comment'), class_='btn btn-success save-inline-form')}
85 </div>
86 <div class="comment-button">
87 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
88 ${_('Cancel')}
89 </button>
97 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
98 ${_('Cancel')}
99 </button>
100 ${h.submit('save', _('Comment'), class_='btn btn-success save-inline-form')}
90 101 </div>
91 102 ${h.end_form()}
92 103 </div>
93 104 %else:
94 105 ${h.form('', class_='inline-form comment-form-login', method='get')}
95 106 <div class="pull-left">
96 107 <div class="comment-help pull-right">
97 ${_('You need to be logged in to comment.')} <a href="${h.route_path('login', _query={'came_from': h.url.current()})}">${_('Login now')}</a>
108 ${_('You need to be logged in to leave comments.')} <a href="${h.route_path('login', _query={'came_from': h.url.current()})}">${_('Login now')}</a>
98 109 </div>
99 110 </div>
100 111 <div class="comment-button pull-right">
101 112 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
102 113 ${_('Cancel')}
103 114 </button>
104 115 </div>
105 116 <div class="clearfix"></div>
106 117 ${h.end_form()}
107 118 %endif
108 119 </div>
109 120 </div>
110 121
111 122 %endif
112 123 <%
113 124 collapse_all = len(diffset.files) > collapse_when_files_over
114 125 %>
115 126
116 127 %if c.diffmode == 'sideside':
117 128 <style>
118 129 .wrapper {
119 130 max-width: 1600px !important;
120 131 }
121 132 </style>
122 133 %endif
134
123 135 %if ruler_at_chars:
124 136 <style>
125 137 .diff table.cb .cb-content:after {
126 138 content: "";
127 139 border-left: 1px solid blue;
128 140 position: absolute;
129 141 top: 0;
130 142 height: 18px;
131 143 opacity: .2;
132 144 z-index: 10;
133 145 //## +5 to account for diff action (+/-)
134 146 left: ${ruler_at_chars + 5}ch;
135 147 </style>
136 148 %endif
149
137 150 <div class="diffset ${disable_new_comments and 'diffset-comments-disabled'}">
138 151 <div class="diffset-heading ${diffset.limited_diff and 'diffset-heading-warning' or ''}">
139 152 %if commit:
140 153 <div class="pull-right">
141 154 <a class="btn tooltip" title="${_('Browse Files at revision {}').format(commit.raw_id)}" href="${h.url('files_home',repo_name=diffset.repo_name, revision=commit.raw_id, f_path='')}">
142 155 ${_('Browse Files')}
143 156 </a>
144 157 </div>
145 158 %endif
146 159 <h2 class="clearinner">
147 160 %if commit:
148 161 <a class="tooltip revision" title="${h.tooltip(commit.message)}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">${'r%s:%s' % (commit.revision,h.short_id(commit.raw_id))}</a> -
149 162 ${h.age_component(commit.date)} -
150 163 %endif
151 164 %if diffset.limited_diff:
152 165 ${_('The requested commit is too big and content was truncated.')}
153 166
154 167 ${ungettext('%(num)s file changed.', '%(num)s files changed.', diffset.changed_files) % {'num': diffset.changed_files}}
155 168 <a href="${link_for(fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
156 169 %else:
157 170 ${ungettext('%(num)s file changed: %(linesadd)s inserted, ''%(linesdel)s deleted',
158 171 '%(num)s files changed: %(linesadd)s inserted, %(linesdel)s deleted', diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}}
159 172 %endif
160 173
161 174 <% at_ver = getattr(c, 'at_version_num', None) %>
162 175 % if at_ver:
163 176 <div class="pull-right">
164 177 ${_('Changes at version %d') % at_ver}
165 178 </div>
166 179 % endif
167 180
168 181 </h2>
169 182 </div>
170 183
171 184 %if not diffset.files:
172 185 <p class="empty_data">${_('No files')}</p>
173 186 %endif
174 187
175 188 <div class="filediffs">
176 189 %for i, filediff in enumerate(diffset.files):
177 190
178 191 <%
179 192 lines_changed = filediff['patch']['stats']['added'] + filediff['patch']['stats']['deleted']
180 193 over_lines_changed_limit = lines_changed > lines_changed_limit
181 194 %>
182 195 <input ${collapse_all and 'checked' or ''} class="filediff-collapse-state" id="filediff-collapse-${id(filediff)}" type="checkbox">
183 196 <div
184 197 class="filediff"
185 198 data-f-path="${filediff['patch']['filename']}"
186 199 id="a_${h.FID('', filediff['patch']['filename'])}">
187 200 <label for="filediff-collapse-${id(filediff)}" class="filediff-heading">
188 201 <div class="filediff-collapse-indicator"></div>
189 202 ${diff_ops(filediff)}
190 203 </label>
191 204 ${diff_menu(filediff, use_comments=use_comments)}
192 205 <table class="cb cb-diff-${c.diffmode} code-highlight ${over_lines_changed_limit and 'cb-collapsed' or ''}">
193 206 %if not filediff.hunks:
194 207 %for op_id, op_text in filediff['patch']['stats']['ops'].items():
195 208 <tr>
196 209 <td class="cb-text cb-${op_class(op_id)}" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}>
197 210 %if op_id == DEL_FILENODE:
198 211 ${_('File was deleted')}
199 212 %elif op_id == BIN_FILENODE:
200 213 ${_('Binary file hidden')}
201 214 %else:
202 215 ${op_text}
203 216 %endif
204 217 </td>
205 218 </tr>
206 219 %endfor
207 220 %endif
208 221 %if filediff.patch['is_limited_diff']:
209 222 <tr class="cb-warning cb-collapser">
210 223 <td class="cb-text" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}>
211 224 ${_('The requested commit is too big and content was truncated.')} <a href="${link_for(fulldiff=1)}" onclick="return confirm('${_("Showing a big diff might take some time and resources, continue?")}')">${_('Show full diff')}</a>
212 225 </td>
213 226 </tr>
214 227 %else:
215 228 %if over_lines_changed_limit:
216 229 <tr class="cb-warning cb-collapser">
217 230 <td class="cb-text" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=6'}>
218 231 ${_('This diff has been collapsed as it changes many lines, (%i lines changed)' % lines_changed)}
219 232 <a href="#" class="cb-expand"
220 233 onclick="$(this).closest('table').removeClass('cb-collapsed'); return false;">${_('Show them')}
221 234 </a>
222 235 <a href="#" class="cb-collapse"
223 236 onclick="$(this).closest('table').addClass('cb-collapsed'); return false;">${_('Hide them')}
224 237 </a>
225 238 </td>
226 239 </tr>
227 240 %endif
228 241 %endif
229 242
230 243 %for hunk in filediff.hunks:
231 244 <tr class="cb-hunk">
232 245 <td ${c.diffmode == 'unified' and 'colspan=3' or ''}>
233 246 ## TODO: dan: add ajax loading of more context here
234 247 ## <a href="#">
235 248 <i class="icon-more"></i>
236 249 ## </a>
237 250 </td>
238 251 <td ${c.diffmode == 'sideside' and 'colspan=5' or ''}>
239 252 @@
240 253 -${hunk.source_start},${hunk.source_length}
241 254 +${hunk.target_start},${hunk.target_length}
242 255 ${hunk.section_header}
243 256 </td>
244 257 </tr>
245 258 %if c.diffmode == 'unified':
246 259 ${render_hunk_lines_unified(hunk, use_comments=use_comments)}
247 260 %elif c.diffmode == 'sideside':
248 261 ${render_hunk_lines_sideside(hunk, use_comments=use_comments)}
249 262 %else:
250 263 <tr class="cb-line">
251 264 <td>unknown diff mode</td>
252 265 </tr>
253 266 %endif
254 267 %endfor
255 268
256 269 ## outdated comments that do not fit into currently displayed lines
257 270 % for lineno, comments in filediff.left_comments.items():
258 271
259 272 %if c.diffmode == 'unified':
260 273 <tr class="cb-line">
261 274 <td class="cb-data cb-context"></td>
262 275 <td class="cb-lineno cb-context"></td>
263 276 <td class="cb-lineno cb-context"></td>
264 277 <td class="cb-content cb-context">
265 278 ${inline_comments_container(comments)}
266 279 </td>
267 280 </tr>
268 281 %elif c.diffmode == 'sideside':
269 282 <tr class="cb-line">
270 283 <td class="cb-data cb-context"></td>
271 284 <td class="cb-lineno cb-context"></td>
272 285 <td class="cb-content cb-context"></td>
273 286
274 287 <td class="cb-data cb-context"></td>
275 288 <td class="cb-lineno cb-context"></td>
276 289 <td class="cb-content cb-context">
277 290 ${inline_comments_container(comments)}
278 291 </td>
279 292 </tr>
280 293 %endif
281 294
282 295 % endfor
283 296
284 297 </table>
285 298 </div>
286 299 %endfor
287 300
288 301 ## outdated comments that are made for a file that has been deleted
289 302 % for filename, comments_dict in (deleted_files_comments or {}).items():
290 303
291 304 <div class="filediffs filediff-outdated" style="display: none">
292 305 <input ${collapse_all and 'checked' or ''} class="filediff-collapse-state" id="filediff-collapse-${id(filename)}" type="checkbox">
293 306 <div class="filediff" data-f-path="${filename}" id="a_${h.FID('', filename)}">
294 307 <label for="filediff-collapse-${id(filename)}" class="filediff-heading">
295 308 <div class="filediff-collapse-indicator"></div>
296 309 <span class="pill">
297 310 ## file was deleted
298 311 <strong>${filename}</strong>
299 312 </span>
300 313 <span class="pill-group" style="float: left">
301 314 ## file op, doesn't need translation
302 315 <span class="pill" op="removed">removed in this version</span>
303 316 </span>
304 317 <a class="pill filediff-anchor" href="#a_${h.FID('', filename)}">ΒΆ</a>
305 318 <span class="pill-group" style="float: right">
306 319 <span class="pill" op="deleted">-${comments_dict['stats']}</span>
307 320 </span>
308 321 </label>
309 322
310 323 <table class="cb cb-diff-${c.diffmode} code-highlight ${over_lines_changed_limit and 'cb-collapsed' or ''}">
311 324 <tr>
312 325 % if c.diffmode == 'unified':
313 326 <td></td>
314 327 %endif
315 328
316 329 <td></td>
317 330 <td class="cb-text cb-${op_class(BIN_FILENODE)}" ${c.diffmode == 'unified' and 'colspan=4' or 'colspan=5'}>
318 331 ${_('File was deleted in this version, and outdated comments were made on it')}
319 332 </td>
320 333 </tr>
321 334 %if c.diffmode == 'unified':
322 335 <tr class="cb-line">
323 336 <td class="cb-data cb-context"></td>
324 337 <td class="cb-lineno cb-context"></td>
325 338 <td class="cb-lineno cb-context"></td>
326 339 <td class="cb-content cb-context">
327 340 ${inline_comments_container(comments_dict['comments'])}
328 341 </td>
329 342 </tr>
330 343 %elif c.diffmode == 'sideside':
331 344 <tr class="cb-line">
332 345 <td class="cb-data cb-context"></td>
333 346 <td class="cb-lineno cb-context"></td>
334 347 <td class="cb-content cb-context"></td>
335 348
336 349 <td class="cb-data cb-context"></td>
337 350 <td class="cb-lineno cb-context"></td>
338 351 <td class="cb-content cb-context">
339 352 ${inline_comments_container(comments_dict['comments'])}
340 353 </td>
341 354 </tr>
342 355 %endif
343 356 </table>
344 357 </div>
345 358 </div>
346 359 % endfor
347 360
348 361 </div>
349 362 </div>
350 363 </%def>
351 364
352 365 <%def name="diff_ops(filediff)">
353 366 <%
354 367 stats = filediff['patch']['stats']
355 368 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
356 369 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
357 370 %>
358 371 <span class="pill">
359 372 %if filediff.source_file_path and filediff.target_file_path:
360 373 %if filediff.source_file_path != filediff.target_file_path: # file was renamed
361 374 <strong>${filediff.target_file_path}</strong> β¬… <del>${filediff.source_file_path}</del>
362 375 %else:
363 376 ## file was modified
364 377 <strong>${filediff.source_file_path}</strong>
365 378 %endif
366 379 %else:
367 380 %if filediff.source_file_path:
368 381 ## file was deleted
369 382 <strong>${filediff.source_file_path}</strong>
370 383 %else:
371 384 ## file was added
372 385 <strong>${filediff.target_file_path}</strong>
373 386 %endif
374 387 %endif
375 388 </span>
376 389 <span class="pill-group" style="float: left">
377 390 %if filediff.patch['is_limited_diff']:
378 391 <span class="pill tooltip" op="limited" title="The stats for this diff are not complete">limited diff</span>
379 392 %endif
380 393 %if RENAMED_FILENODE in stats['ops']:
381 394 <span class="pill" op="renamed">renamed</span>
382 395 %endif
383 396
384 397 %if NEW_FILENODE in stats['ops']:
385 398 <span class="pill" op="created">created</span>
386 399 %if filediff['target_mode'].startswith('120'):
387 400 <span class="pill" op="symlink">symlink</span>
388 401 %else:
389 402 <span class="pill" op="mode">${nice_mode(filediff['target_mode'])}</span>
390 403 %endif
391 404 %endif
392 405
393 406 %if DEL_FILENODE in stats['ops']:
394 407 <span class="pill" op="removed">removed</span>
395 408 %endif
396 409
397 410 %if CHMOD_FILENODE in stats['ops']:
398 411 <span class="pill" op="mode">
399 412 ${nice_mode(filediff['source_mode'])} ➑ ${nice_mode(filediff['target_mode'])}
400 413 </span>
401 414 %endif
402 415 </span>
403 416
404 417 <a class="pill filediff-anchor" href="#a_${h.FID('', filediff.patch['filename'])}">ΒΆ</a>
405 418
406 419 <span class="pill-group" style="float: right">
407 420 %if BIN_FILENODE in stats['ops']:
408 421 <span class="pill" op="binary">binary</span>
409 422 %if MOD_FILENODE in stats['ops']:
410 423 <span class="pill" op="modified">modified</span>
411 424 %endif
412 425 %endif
413 426 %if stats['added']:
414 427 <span class="pill" op="added">+${stats['added']}</span>
415 428 %endif
416 429 %if stats['deleted']:
417 430 <span class="pill" op="deleted">-${stats['deleted']}</span>
418 431 %endif
419 432 </span>
420 433
421 434 </%def>
422 435
423 436 <%def name="nice_mode(filemode)">
424 437 ${filemode.startswith('100') and filemode[3:] or filemode}
425 438 </%def>
426 439
427 440 <%def name="diff_menu(filediff, use_comments=False)">
428 441 <div class="filediff-menu">
429 442 %if filediff.diffset.source_ref:
430 443 %if filediff.patch['operation'] in ['D', 'M']:
431 444 <a
432 445 class="tooltip"
433 446 href="${h.url('files_home',repo_name=filediff.diffset.repo_name,f_path=filediff.source_file_path,revision=filediff.diffset.source_ref)}"
434 447 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
435 448 >
436 449 ${_('Show file before')}
437 450 </a> |
438 451 %else:
439 452 <span
440 453 class="tooltip"
441 454 title="${h.tooltip(_('File no longer present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.source_ref[:12]})}"
442 455 >
443 456 ${_('Show file before')}
444 457 </span> |
445 458 %endif
446 459 %if filediff.patch['operation'] in ['A', 'M']:
447 460 <a
448 461 class="tooltip"
449 462 href="${h.url('files_home',repo_name=filediff.diffset.source_repo_name,f_path=filediff.target_file_path,revision=filediff.diffset.target_ref)}"
450 463 title="${h.tooltip(_('Show file at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
451 464 >
452 465 ${_('Show file after')}
453 466 </a> |
454 467 %else:
455 468 <span
456 469 class="tooltip"
457 470 title="${h.tooltip(_('File no longer present at commit: %(commit_id)s') % {'commit_id': filediff.diffset.target_ref[:12]})}"
458 471 >
459 472 ${_('Show file after')}
460 473 </span> |
461 474 %endif
462 475 <a
463 476 class="tooltip"
464 477 title="${h.tooltip(_('Raw diff'))}"
465 478 href="${h.url('files_diff_home',repo_name=filediff.diffset.repo_name,f_path=filediff.target_file_path,diff2=filediff.diffset.target_ref,diff1=filediff.diffset.source_ref,diff='raw')}"
466 479 >
467 480 ${_('Raw diff')}
468 481 </a> |
469 482 <a
470 483 class="tooltip"
471 484 title="${h.tooltip(_('Download diff'))}"
472 485 href="${h.url('files_diff_home',repo_name=filediff.diffset.repo_name,f_path=filediff.target_file_path,diff2=filediff.diffset.target_ref,diff1=filediff.diffset.source_ref,diff='download')}"
473 486 >
474 487 ${_('Download diff')}
475 488 </a>
476 489 % if use_comments:
477 490 |
478 491 % endif
479 492
480 493 ## TODO: dan: refactor ignorews_url and context_url into the diff renderer same as diffmode=unified/sideside. Also use ajax to load more context (by clicking hunks)
481 494 %if hasattr(c, 'ignorews_url'):
482 495 ${c.ignorews_url(request.GET, h.FID('', filediff['patch']['filename']))}
483 496 %endif
484 497 %if hasattr(c, 'context_url'):
485 498 ${c.context_url(request.GET, h.FID('', filediff['patch']['filename']))}
486 499 %endif
487 500
488 501 %if use_comments:
489 502 <a href="#" onclick="return Rhodecode.comments.toggleComments(this);">
490 503 <span class="show-comment-button">${_('Show comments')}</span><span class="hide-comment-button">${_('Hide comments')}</span>
491 504 </a>
492 505 %endif
493 506 %endif
494 507 </div>
495 508 </%def>
496 509
497 510
498 511 <%namespace name="commentblock" file="/changeset/changeset_file_comment.html"/>
499 512 <%def name="inline_comments_container(comments)">
500 513 <div class="inline-comments">
501 514 %for comment in comments:
502 515 ${commentblock.comment_block(comment, inline=True)}
503 516 %endfor
504 517
505 518 % if comments and comments[-1].outdated:
506 519 <span class="btn btn-secondary cb-comment-add-button comment-outdated}"
507 520 style="display: none;}">
508 521 ${_('Add another comment')}
509 522 </span>
510 523 % else:
511 524 <span onclick="return Rhodecode.comments.createComment(this)"
512 525 class="btn btn-secondary cb-comment-add-button">
513 526 ${_('Add another comment')}
514 527 </span>
515 528 % endif
516 529
517 530 </div>
518 531 </%def>
519 532
520 533
521 534 <%def name="render_hunk_lines_sideside(hunk, use_comments=False)">
522 535 %for i, line in enumerate(hunk.sideside):
523 536 <%
524 537 old_line_anchor, new_line_anchor = None, None
525 538 if line.original.lineno:
526 539 old_line_anchor = diff_line_anchor(hunk.filediff.source_file_path, line.original.lineno, 'o')
527 540 if line.modified.lineno:
528 541 new_line_anchor = diff_line_anchor(hunk.filediff.target_file_path, line.modified.lineno, 'n')
529 542 %>
530 543
531 544 <tr class="cb-line">
532 545 <td class="cb-data ${action_class(line.original.action)}"
533 546 data-line-number="${line.original.lineno}"
534 547 >
535 548 <div>
536 549 %if line.original.comments:
537 550 <i class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
538 551 %endif
539 552 </div>
540 553 </td>
541 554 <td class="cb-lineno ${action_class(line.original.action)}"
542 555 data-line-number="${line.original.lineno}"
543 556 %if old_line_anchor:
544 557 id="${old_line_anchor}"
545 558 %endif
546 559 >
547 560 %if line.original.lineno:
548 561 <a name="${old_line_anchor}" href="#${old_line_anchor}">${line.original.lineno}</a>
549 562 %endif
550 563 </td>
551 564 <td class="cb-content ${action_class(line.original.action)}"
552 565 data-line-number="o${line.original.lineno}"
553 566 >
554 567 %if use_comments and line.original.lineno:
555 568 ${render_add_comment_button()}
556 569 %endif
557 570 <span class="cb-code">${line.original.action} ${line.original.content or '' | n}</span>
558 571 %if use_comments and line.original.lineno and line.original.comments:
559 572 ${inline_comments_container(line.original.comments)}
560 573 %endif
561 574 </td>
562 575 <td class="cb-data ${action_class(line.modified.action)}"
563 576 data-line-number="${line.modified.lineno}"
564 577 >
565 578 <div>
566 579 %if line.modified.comments:
567 580 <i class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
568 581 %endif
569 582 </div>
570 583 </td>
571 584 <td class="cb-lineno ${action_class(line.modified.action)}"
572 585 data-line-number="${line.modified.lineno}"
573 586 %if new_line_anchor:
574 587 id="${new_line_anchor}"
575 588 %endif
576 589 >
577 590 %if line.modified.lineno:
578 591 <a name="${new_line_anchor}" href="#${new_line_anchor}">${line.modified.lineno}</a>
579 592 %endif
580 593 </td>
581 594 <td class="cb-content ${action_class(line.modified.action)}"
582 595 data-line-number="n${line.modified.lineno}"
583 596 >
584 597 %if use_comments and line.modified.lineno:
585 598 ${render_add_comment_button()}
586 599 %endif
587 600 <span class="cb-code">${line.modified.action} ${line.modified.content or '' | n}</span>
588 601 %if use_comments and line.modified.lineno and line.modified.comments:
589 602 ${inline_comments_container(line.modified.comments)}
590 603 %endif
591 604 </td>
592 605 </tr>
593 606 %endfor
594 607 </%def>
595 608
596 609
597 610 <%def name="render_hunk_lines_unified(hunk, use_comments=False)">
598 611 %for old_line_no, new_line_no, action, content, comments in hunk.unified:
599 612 <%
600 613 old_line_anchor, new_line_anchor = None, None
601 614 if old_line_no:
602 615 old_line_anchor = diff_line_anchor(hunk.filediff.source_file_path, old_line_no, 'o')
603 616 if new_line_no:
604 617 new_line_anchor = diff_line_anchor(hunk.filediff.target_file_path, new_line_no, 'n')
605 618 %>
606 619 <tr class="cb-line">
607 620 <td class="cb-data ${action_class(action)}">
608 621 <div>
609 622 %if comments:
610 623 <i class="icon-comment" onclick="return Rhodecode.comments.toggleLineComments(this)"></i>
611 624 %endif
612 625 </div>
613 626 </td>
614 627 <td class="cb-lineno ${action_class(action)}"
615 628 data-line-number="${old_line_no}"
616 629 %if old_line_anchor:
617 630 id="${old_line_anchor}"
618 631 %endif
619 632 >
620 633 %if old_line_anchor:
621 634 <a name="${old_line_anchor}" href="#${old_line_anchor}">${old_line_no}</a>
622 635 %endif
623 636 </td>
624 637 <td class="cb-lineno ${action_class(action)}"
625 638 data-line-number="${new_line_no}"
626 639 %if new_line_anchor:
627 640 id="${new_line_anchor}"
628 641 %endif
629 642 >
630 643 %if new_line_anchor:
631 644 <a name="${new_line_anchor}" href="#${new_line_anchor}">${new_line_no}</a>
632 645 %endif
633 646 </td>
634 647 <td class="cb-content ${action_class(action)}"
635 648 data-line-number="${new_line_no and 'n' or 'o'}${new_line_no or old_line_no}"
636 649 >
637 650 %if use_comments:
638 651 ${render_add_comment_button()}
639 652 %endif
640 653 <span class="cb-code">${action} ${content or '' | n}</span>
641 654 %if use_comments and comments:
642 655 ${inline_comments_container(comments)}
643 656 %endif
644 657 </td>
645 658 </tr>
646 659 %endfor
647 660 </%def>
648 661
649 662 <%def name="render_add_comment_button()">
650 663 <button class="btn btn-small btn-primary cb-comment-box-opener" onclick="return Rhodecode.comments.createComment(this)">
651 664 <span><i class="icon-comment"></i></span>
652 665 </button>
653 666 </%def>
654 667
655 668 <%def name="render_diffset_menu()">
656 669
657 670 <div class="diffset-menu clearinner">
658 671 <div class="pull-right">
659 672 <div class="btn-group">
660 673
661 674 <a
662 675 class="btn ${c.diffmode == 'sideside' and 'btn-primary'} tooltip"
663 676 title="${_('View side by side')}"
664 677 href="${h.url_replace(diffmode='sideside')}">
665 678 <span>${_('Side by Side')}</span>
666 679 </a>
667 680 <a
668 681 class="btn ${c.diffmode == 'unified' and 'btn-primary'} tooltip"
669 682 title="${_('View unified')}" href="${h.url_replace(diffmode='unified')}">
670 683 <span>${_('Unified')}</span>
671 684 </a>
672 685 </div>
673 686 </div>
674 687
675 688 <div class="pull-left">
676 689 <div class="btn-group">
677 690 <a
678 691 class="btn"
679 692 href="#"
680 693 onclick="$('input[class=filediff-collapse-state]').prop('checked', false); return false">${_('Expand All Files')}</a>
681 694 <a
682 695 class="btn"
683 696 href="#"
684 697 onclick="$('input[class=filediff-collapse-state]').prop('checked', true); return false">${_('Collapse All Files')}</a>
685 698 <a
686 699 class="btn"
687 700 href="#"
688 701 onclick="return Rhodecode.comments.toggleWideMode(this)">${_('Wide Mode Diff')}</a>
689 702 </div>
690 703 </div>
691 704 </div>
692 705 </%def>
@@ -1,370 +1,377 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.html"/>
3 3 <%namespace name="cbdiffs" file="/codeblocks/diffs.html"/>
4 4
5 5 <%def name="title()">
6 6 %if c.compare_home:
7 7 ${_('%s Compare') % c.repo_name}
8 8 %else:
9 9 ${_('%s Compare') % c.repo_name} - ${'%s@%s' % (c.source_repo.repo_name, c.source_ref)} &gt; ${'%s@%s' % (c.target_repo.repo_name, c.target_ref)}
10 10 %endif
11 11 %if c.rhodecode_name:
12 12 &middot; ${h.branding(c.rhodecode_name)}
13 13 %endif
14 14 </%def>
15 15
16 16 <%def name="breadcrumbs_links()">
17 17 ${ungettext('%s commit','%s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
18 18 </%def>
19 19
20 20 <%def name="menu_bar_nav()">
21 21 ${self.menu_items(active='repositories')}
22 22 </%def>
23 23
24 24 <%def name="menu_bar_subnav()">
25 25 ${self.repo_menu(active='compare')}
26 26 </%def>
27 27
28 28 <%def name="main()">
29 <script type="text/javascript">
30 // set fake commitId on this commit-range page
31 templateContext.commit_data.commit_id = "${h.EmptyCommit().raw_id}";
32 </script>
29 <script type="text/javascript">
30 // set fake commitId on this commit-range page
31 templateContext.commit_data.commit_id = "${h.EmptyCommit().raw_id}";
32 </script>
33 33
34 34 <div class="box">
35 35 <div class="title">
36 36 ${self.repo_page_title(c.rhodecode_db_repo)}
37 37 </div>
38 38
39 39 <div class="summary changeset">
40 40 <div class="summary-detail">
41 41 <div class="summary-detail-header">
42 42 <span class="breadcrumbs files_location">
43 43 <h4>
44 44 ${_('Compare Commits')}
45 45 % if c.file_path:
46 46 ${_('for file')} <a href="#${'a_' + h.FID('',c.file_path)}">${c.file_path}</a>
47 47 % endif
48 48
49 49 % if c.commit_ranges:
50 50 <code>
51 51 r${c.source_commit.revision}:${h.short_id(c.source_commit.raw_id)}...r${c.target_commit.revision}:${h.short_id(c.target_commit.raw_id)}
52 52 </code>
53 53 % endif
54 54 </h4>
55 55 </span>
56 56 </div>
57 57
58 58 <div class="fieldset">
59 59 <div class="left-label">
60 60 ${_('Target')}:
61 61 </div>
62 62 <div class="right-content">
63 63 <div>
64 64 <div class="code-header" >
65 65 <div class="compare_header">
66 66 ## The hidden elements are replaced with a select2 widget
67 67 ${h.hidden('compare_source')}
68 68 </div>
69 69 </div>
70 70 </div>
71 71 </div>
72 72 </div>
73 73
74 74 <div class="fieldset">
75 75 <div class="left-label">
76 76 ${_('Source')}:
77 77 </div>
78 78 <div class="right-content">
79 79 <div>
80 80 <div class="code-header" >
81 81 <div class="compare_header">
82 82 ## The hidden elements are replaced with a select2 widget
83 83 ${h.hidden('compare_target')}
84 84 </div>
85 85 </div>
86 86 </div>
87 87 </div>
88 88 </div>
89 89
90 90 <div class="fieldset">
91 91 <div class="left-label">
92 92 ${_('Actions')}:
93 93 </div>
94 94 <div class="right-content">
95 95 <div>
96 96 <div class="code-header" >
97 97 <div class="compare_header">
98 98
99 99 <div class="compare-buttons">
100 100 % if c.compare_home:
101 101 <a id="compare_revs" class="btn btn-primary"> ${_('Compare Commits')}</a>
102 102
103 103 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Swap')}</a>
104 104 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
105 105 <div id="changeset_compare_view_content">
106 106 <div class="help-block">${_('Compare commits, branches, bookmarks or tags.')}</div>
107 107 </div>
108 108
109 109 % elif c.preview_mode:
110 110 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Compare Commits')}</a>
111 111 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Swap')}</a>
112 112 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
113 113
114 114 % else:
115 115 <a id="compare_revs" class="btn btn-primary"> ${_('Compare Commits')}</a>
116 116 <a id="btn-swap" class="btn btn-primary" href="${c.swap_url}">${_('Swap')}</a>
117 117
118 118 ## allow comment only if there are commits to comment on
119 119 % if c.diffset and c.diffset.files and c.commit_ranges:
120 120 <a id="compare_changeset_status_toggle" class="btn btn-primary">${_('Comment')}</a>
121 121 % else:
122 122 <a class="btn disabled tooltip" disabled="disabled" title="${_('Action unavailable in current view')}">${_('Comment')}</a>
123 123 % endif
124 124 % endif
125 125 </div>
126 126 </div>
127 127 </div>
128 128 </div>
129 129 </div>
130 130 </div>
131 131
132 132 <%doc>
133 133 ##TODO(marcink): implement this and diff menus
134 134 <div class="fieldset">
135 135 <div class="left-label">
136 136 ${_('Diff options')}:
137 137 </div>
138 138 <div class="right-content">
139 139 <div class="diff-actions">
140 140 <a href="${h.url('changeset_raw_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Raw diff'))}">
141 141 ${_('Raw Diff')}
142 142 </a>
143 143 |
144 144 <a href="${h.url('changeset_patch_home',repo_name=c.repo_name,revision='?')}" class="tooltip" title="${h.tooltip(_('Patch diff'))}">
145 145 ${_('Patch Diff')}
146 146 </a>
147 147 |
148 148 <a href="${h.url('changeset_download_home',repo_name=c.repo_name,revision='?',diff='download')}" class="tooltip" title="${h.tooltip(_('Download diff'))}">
149 149 ${_('Download Diff')}
150 150 </a>
151 151 </div>
152 152 </div>
153 153 </div>
154 154 </%doc>
155 155
156 ## commit status form
157 <div class="fieldset" id="compare_changeset_status" style="display: none; margin-bottom: -80px;">
158 <div class="left-label">
159 ${_('Commit status')}:
160 </div>
161 <div class="right-content">
162 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
163 ## main comment form and it status
164 <%
165 def revs(_revs):
166 form_inputs = []
167 for cs in _revs:
168 tmpl = '<input type="hidden" data-commit-id="%(cid)s" name="commit_ids" value="%(cid)s">' % {'cid': cs.raw_id}
169 form_inputs.append(tmpl)
170 return form_inputs
171 %>
172 <div>
173 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
174 <script type="text/javascript">
175
176 mainCommentForm.setHandleFormSubmit(function(o) {
177 var text = mainCommentForm.cm.getValue();
178 var status = mainCommentForm.getCommentStatus();
179
180 if (text === "" && !status) {
181 return;
182 }
183
184 // we can pick which commits we want to make the comment by
185 // selecting them via click on preview pane, this will alter the hidden inputs
186 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
187
188 var commitIds = [];
189 $('#changeset_compare_view_content .compare_select').each(function(el) {
190 var commitId = this.id.replace('row-', '');
191 if ($(this).hasClass('hl') || !cherryPicked) {
192 $("input[data-commit-id='{0}']".format(commitId)).val(commitId)
193 commitIds.push(commitId);
194 } else {
195 $("input[data-commit-id='{0}']".format(commitId)).val('')
196 }
197 });
198
199 mainCommentForm.setActionButtonsDisabled(true);
200 mainCommentForm.cm.setOption("readOnly", true);
201 var postData = {
202 'text': text,
203 'changeset_status': status,
204 'commit_ids': commitIds,
205 'csrf_token': CSRF_TOKEN
206 };
207
208 var submitSuccessCallback = function(o) {
209 location.reload(true);
210 };
211 var submitFailCallback = function(){
212 mainCommentForm.resetCommentFormState(text)
213 };
214 mainCommentForm.submitAjaxPOST(
215 mainCommentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
216 });
217 </script>
218 </div>
219 </div>
220 </div>
221
156 222 </div> <!-- end summary-detail -->
157
158 223 </div> <!-- end summary -->
159 224
160
161 <div class="table">
162
163 ## use JS script to load it quickly before potentially large diffs render long time
164 ## this prevents from situation when large diffs block rendering of select2 fields
165 <script type="text/javascript">
225 ## use JS script to load it quickly before potentially large diffs render long time
226 ## this prevents from situation when large diffs block rendering of select2 fields
227 <script type="text/javascript">
166 228
167 229 var cache = {};
168 230
169 231 var formatSelection = function(repoName){
170 232 return function(data, container, escapeMarkup) {
171 233 var selection = data ? this.text(data) : "";
172 234 return escapeMarkup('{0}@{1}'.format(repoName, selection));
173 235 }
174 236 };
175 237
176 238 var feedCompareData = function(query, cachedValue){
177 239 var data = {results: []};
178 240 //filter results
179 241 $.each(cachedValue.results, function() {
180 242 var section = this.text;
181 243 var children = [];
182 244 $.each(this.children, function() {
183 245 if (query.term.length === 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0) {
184 246 children.push({
185 247 'id': this.id,
186 248 'text': this.text,
187 249 'type': this.type
188 250 })
189 251 }
190 252 });
191 253 data.results.push({
192 254 'text': section,
193 255 'children': children
194 256 })
195 257 });
196 258 //push the typed in changeset
197 259 data.results.push({
198 260 'text': _gettext('specify commit'),
199 261 'children': [{
200 262 'id': query.term,
201 263 'text': query.term,
202 264 'type': 'rev'
203 265 }]
204 266 });
205 267 query.callback(data);
206 268 };
207 269
208 270 var loadCompareData = function(repoName, query, cache){
209 271 $.ajax({
210 272 url: pyroutes.url('repo_refs_data', {'repo_name': repoName}),
211 273 data: {},
212 274 dataType: 'json',
213 275 type: 'GET',
214 276 success: function(data) {
215 277 cache[repoName] = data;
216 278 query.callback({results: data.results});
217 279 }
218 280 })
219 281 };
220 282
221 283 var enable_fields = ${"false" if c.preview_mode else "true"};
222 284 $("#compare_source").select2({
223 285 placeholder: "${'%s@%s' % (c.source_repo.repo_name, c.source_ref)}",
224 286 containerCssClass: "drop-menu",
225 287 dropdownCssClass: "drop-menu-dropdown",
226 288 formatSelection: formatSelection("${c.source_repo.repo_name}"),
227 289 dropdownAutoWidth: true,
228 290 query: function(query) {
229 291 var repoName = '${c.source_repo.repo_name}';
230 292 var cachedValue = cache[repoName];
231 293
232 294 if (cachedValue){
233 295 feedCompareData(query, cachedValue);
234 296 }
235 297 else {
236 298 loadCompareData(repoName, query, cache);
237 299 }
238 300 }
239 301 }).select2("enable", enable_fields);
240 302
241 303 $("#compare_target").select2({
242 304 placeholder: "${'%s@%s' % (c.target_repo.repo_name, c.target_ref)}",
243 305 dropdownAutoWidth: true,
244 306 containerCssClass: "drop-menu",
245 307 dropdownCssClass: "drop-menu-dropdown",
246 308 formatSelection: formatSelection("${c.target_repo.repo_name}"),
247 309 query: function(query) {
248 310 var repoName = '${c.target_repo.repo_name}';
249 311 var cachedValue = cache[repoName];
250 312
251 313 if (cachedValue){
252 314 feedCompareData(query, cachedValue);
253 315 }
254 316 else {
255 317 loadCompareData(repoName, query, cache);
256 318 }
257 319 }
258 320 }).select2("enable", enable_fields);
259 321 var initial_compare_source = {id: "${c.source_ref}", type:"${c.source_ref_type}"};
260 322 var initial_compare_target = {id: "${c.target_ref}", type:"${c.target_ref_type}"};
261 323
262 324 $('#compare_revs').on('click', function(e) {
263 325 var source = $('#compare_source').select2('data') || initial_compare_source;
264 326 var target = $('#compare_target').select2('data') || initial_compare_target;
265 327 if (source && target) {
266 328 var url_data = {
267 329 repo_name: "${c.repo_name}",
268 330 source_ref: source.id,
269 331 source_ref_type: source.type,
270 332 target_ref: target.id,
271 333 target_ref_type: target.type
272 334 };
273 335 window.location = pyroutes.url('compare_url', url_data);
274 336 }
275 337 });
276 338 $('#compare_changeset_status_toggle').on('click', function(e) {
277 339 $('#compare_changeset_status').toggle();
278 340 });
279 341
280 </script>
281
282 ## changeset status form
283 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
284 ## main comment form and it status
285 <%
286 def revs(_revs):
287 form_inputs = []
288 for cs in _revs:
289 tmpl = '<input type="hidden" data-commit-id="%(cid)s" name="commit_ids" value="%(cid)s">' % {'cid': cs.raw_id}
290 form_inputs.append(tmpl)
291 return form_inputs
292 %>
293 <div id="compare_changeset_status" style="display: none;">
294 ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision='0'*16), None, is_compare=True, form_extras=revs(c.commit_ranges))}
295 <script type="text/javascript">
296
297 mainCommentForm.setHandleFormSubmit(function(o) {
298 var text = mainCommentForm.cm.getValue();
299 var status = mainCommentForm.getCommentStatus();
300
301 if (text === "" && !status) {
302 return;
303 }
304
305 // we can pick which commits we want to make the comment by
306 // selecting them via click on preview pane, this will alter the hidden inputs
307 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
342 </script>
308 343
309 var commitIds = [];
310 $('#changeset_compare_view_content .compare_select').each(function(el) {
311 var commitId = this.id.replace('row-', '');
312 if ($(this).hasClass('hl') || !cherryPicked) {
313 $("input[data-commit-id='{0}']".format(commitId)).val(commitId)
314 commitIds.push(commitId);
315 } else {
316 $("input[data-commit-id='{0}']".format(commitId)).val('')
317 }
318 });
344 ## table diff data
345 <div class="table">
319 346
320 mainCommentForm.setActionButtonsDisabled(true);
321 mainCommentForm.cm.setOption("readOnly", true);
322 var postData = {
323 'text': text,
324 'changeset_status': status,
325 'commit_ids': commitIds,
326 'csrf_token': CSRF_TOKEN
327 };
328 347
329 var submitSuccessCallback = function(o) {
330 location.reload(true);
331 };
332 var submitFailCallback = function(){
333 mainCommentForm.resetCommentFormState(text)
334 };
335 mainCommentForm.submitAjaxPOST(
336 mainCommentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
337 });
338 </script>
339
340 </div>
341
342 %if not c.compare_home:
348 % if not c.compare_home:
343 349 <div id="changeset_compare_view_content">
344 350 <div class="pull-left">
345 351 <div class="btn-group">
346 352 <a
347 353 class="btn"
348 354 href="#"
349 355 onclick="$('.compare_select').show();$('.compare_select_hidden').hide(); return false">
350 356 ${ungettext('Expand %s commit','Expand %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
351 357 </a>
352 358 <a
353 359 class="btn"
354 360 href="#"
355 361 onclick="$('.compare_select').hide();$('.compare_select_hidden').show(); return false">
356 362 ${ungettext('Collapse %s commit','Collapse %s commits', len(c.commit_ranges)) % len(c.commit_ranges)}
357 363 </a>
358 364 </div>
359 365 </div>
360 366 <div style="padding:0 10px 10px 0px" class="pull-left"></div>
361 367 ## commit compare generated below
362 368 <%include file="compare_commits.html"/>
363 369 ${cbdiffs.render_diffset_menu()}
364 370 ${cbdiffs.render_diffset(c.diffset)}
365 371 </div>
366 %endif
372 % endif
373
367 374 </div>
368 375 </div>
369 </div>
370 </%def>
376
377 </%def> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now