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