##// END OF EJS Templates
comments: UX improvements for comment buttons.
milka -
r4585:99c6054f stable
parent child Browse files
Show More
@@ -1,600 +1,626 b''
1
1
2
2
3 //BUTTONS
3 //BUTTONS
4 button,
4 button,
5 .btn,
5 .btn,
6 input[type="button"] {
6 input[type="button"] {
7 -webkit-appearance: none;
7 -webkit-appearance: none;
8 display: inline-block;
8 display: inline-block;
9 margin: 0 @padding/3 0 0;
9 margin: 0 @padding/3 0 0;
10 padding: @button-padding;
10 padding: @button-padding;
11 text-align: center;
11 text-align: center;
12 font-size: @basefontsize;
12 font-size: @basefontsize;
13 line-height: 1em;
13 line-height: 1em;
14 font-family: @text-light;
14 font-family: @text-light;
15 text-decoration: none;
15 text-decoration: none;
16 text-shadow: none;
16 text-shadow: none;
17 color: @grey2;
17 color: @grey2;
18 background-color: white;
18 background-color: white;
19 background-image: none;
19 background-image: none;
20 border: none;
20 border: none;
21 .border ( @border-thickness-buttons, @grey5 );
21 .border ( @border-thickness-buttons, @grey5 );
22 .border-radius (@border-radius);
22 .border-radius (@border-radius);
23 cursor: pointer;
23 cursor: pointer;
24 white-space: nowrap;
24 white-space: nowrap;
25 -webkit-transition: background .3s,color .3s;
25 -webkit-transition: background .3s,color .3s;
26 -moz-transition: background .3s,color .3s;
26 -moz-transition: background .3s,color .3s;
27 -o-transition: background .3s,color .3s;
27 -o-transition: background .3s,color .3s;
28 transition: background .3s,color .3s;
28 transition: background .3s,color .3s;
29 box-shadow: @button-shadow;
29 box-shadow: @button-shadow;
30 -webkit-box-shadow: @button-shadow;
30 -webkit-box-shadow: @button-shadow;
31
31
32
32
33
33
34 a {
34 a {
35 display: block;
35 display: block;
36 margin: 0;
36 margin: 0;
37 padding: 0;
37 padding: 0;
38 color: inherit;
38 color: inherit;
39 text-decoration: none;
39 text-decoration: none;
40
40
41 &:hover {
41 &:hover {
42 text-decoration: none;
42 text-decoration: none;
43 }
43 }
44 }
44 }
45
45
46 &:focus,
46 &:focus,
47 &:active {
47 &:active {
48 outline:none;
48 outline:none;
49 }
49 }
50
50
51 &:hover {
51 &:hover {
52 color: @rcdarkblue;
52 color: @rcdarkblue;
53 background-color: @grey6;
53 background-color: @grey6;
54
54
55 }
55 }
56
56
57 &.btn-active {
57 &.btn-active {
58 color: @rcdarkblue;
58 color: @rcdarkblue;
59 background-color: @grey6;
59 background-color: @grey6;
60 }
60 }
61
61
62 .icon-remove {
62 .icon-remove {
63 display: none;
63 display: none;
64 }
64 }
65
65
66 //disabled buttons
66 //disabled buttons
67 //last; overrides any other styles
67 //last; overrides any other styles
68 &:disabled {
68 &:disabled {
69 opacity: .7;
69 opacity: .7;
70 cursor: auto;
70 cursor: auto;
71 background-color: white;
71 background-color: white;
72 color: @grey4;
72 color: @grey4;
73 text-shadow: none;
73 text-shadow: none;
74 }
74 }
75
75
76 &.no-margin {
76 &.no-margin {
77 margin: 0 0 0 0;
77 margin: 0 0 0 0;
78 }
78 }
79
79
80
80
81
81
82 }
82 }
83
83
84
84
85 .btn-default {
85 .btn-default {
86 border: @border-thickness solid @grey5;
86 border: @border-thickness solid @grey5;
87 background-image: none;
87 background-image: none;
88 color: @grey2;
88 color: @grey2;
89
89
90 a {
90 a {
91 color: @grey2;
91 color: @grey2;
92 }
92 }
93
93
94 &:hover,
94 &:hover,
95 &.active {
95 &.active {
96 color: @rcdarkblue;
96 color: @rcdarkblue;
97 background-color: @white;
97 background-color: @white;
98 .border ( @border-thickness, @grey4 );
98 .border ( @border-thickness, @grey4 );
99
99
100 a {
100 a {
101 color: @grey2;
101 color: @grey2;
102 }
102 }
103 }
103 }
104 &:disabled {
104 &:disabled {
105 .border ( @border-thickness-buttons, @grey5 );
105 .border ( @border-thickness-buttons, @grey5 );
106 background-color: transparent;
106 background-color: transparent;
107 }
107 }
108 &.btn-active {
108 &.btn-active {
109 color: @rcdarkblue;
109 color: @rcdarkblue;
110 background-color: @white;
110 background-color: @white;
111 .border ( @border-thickness, @rcdarkblue );
111 .border ( @border-thickness, @rcdarkblue );
112 }
112 }
113 }
113 }
114
114
115 .btn-primary,
115 .btn-primary,
116 .btn-small, /* TODO: anderson: remove .btn-small to not mix with the new btn-sm */
116 .btn-small, /* TODO: anderson: remove .btn-small to not mix with the new btn-sm */
117 .btn-success {
117 .btn-success {
118 .border ( @border-thickness, @rcblue );
118 .border ( @border-thickness, @rcblue );
119 background-color: @rcblue;
119 background-color: @rcblue;
120 color: white;
120 color: white;
121
121
122 a {
122 a {
123 color: white;
123 color: white;
124 }
124 }
125
125
126 &:hover,
126 &:hover,
127 &.active {
127 &.active {
128 .border ( @border-thickness, @rcdarkblue );
128 .border ( @border-thickness, @rcdarkblue );
129 color: white;
129 color: white;
130 background-color: @rcdarkblue;
130 background-color: @rcdarkblue;
131
131
132 a {
132 a {
133 color: white;
133 color: white;
134 }
134 }
135 }
135 }
136 &:disabled {
136 &:disabled {
137 background-color: @rcblue;
137 background-color: @rcblue;
138 }
138 }
139 }
139 }
140
140
141 .btn-secondary {
141 .btn-secondary {
142 &:extend(.btn-default);
142 &:extend(.btn-default);
143
143
144 background-color: white;
144 background-color: white;
145
145
146 &:focus {
146 &:focus {
147 outline: 0;
147 outline: 0;
148 }
148 }
149
149
150 &:hover {
150 &:hover {
151 &:extend(.btn-default:hover);
151 &:extend(.btn-default:hover);
152 }
152 }
153
153
154 &.btn-link {
154 &.btn-link {
155 &:extend(.btn-link);
155 &:extend(.btn-link);
156 color: @rcblue;
156 color: @rcblue;
157 }
157 }
158
158
159 &:disabled {
159 &:disabled {
160 color: @rcblue;
160 color: @rcblue;
161 background-color: white;
161 background-color: white;
162 }
162 }
163 }
163 }
164
164
165 .btn-danger,
165 .btn-danger,
166 .revoke_perm,
166 .revoke_perm,
167 .btn-x,
167 .btn-x,
168 .form .action_button.btn-x {
168 .form .action_button.btn-x {
169 .border ( @border-thickness, @alert2 );
169 .border ( @border-thickness, @alert2 );
170 background-color: white;
170 background-color: white;
171 color: @alert2;
171 color: @alert2;
172
172
173 a {
173 a {
174 color: @alert2;
174 color: @alert2;
175 }
175 }
176
176
177 &:hover,
177 &:hover,
178 &.active {
178 &.active {
179 .border ( @border-thickness, @alert2 );
179 .border ( @border-thickness, @alert2 );
180 color: white;
180 color: white;
181 background-color: @alert2;
181 background-color: @alert2;
182
182
183 a {
183 a {
184 color: white;
184 color: white;
185 }
185 }
186 }
186 }
187
187
188 i {
188 i {
189 display:none;
189 display:none;
190 }
190 }
191
191
192 &:disabled {
192 &:disabled {
193 background-color: white;
193 background-color: white;
194 color: @alert2;
194 color: @alert2;
195 }
195 }
196 }
196 }
197
197
198 .btn-warning {
198 .btn-warning {
199 .border ( @border-thickness, @alert3 );
199 .border ( @border-thickness, @alert3 );
200 background-color: white;
200 background-color: white;
201 color: @alert3;
201 color: @alert3;
202
202
203 a {
203 a {
204 color: @alert3;
204 color: @alert3;
205 }
205 }
206
206
207 &:hover,
207 &:hover,
208 &.active {
208 &.active {
209 .border ( @border-thickness, @alert3 );
209 .border ( @border-thickness, @alert3 );
210 color: white;
210 color: white;
211 background-color: @alert3;
211 background-color: @alert3;
212
212
213 a {
213 a {
214 color: white;
214 color: white;
215 }
215 }
216 }
216 }
217
217
218 i {
218 i {
219 display:none;
219 display:none;
220 }
220 }
221
221
222 &:disabled {
222 &:disabled {
223 background-color: white;
223 background-color: white;
224 color: @alert3;
224 color: @alert3;
225 }
225 }
226 }
226 }
227
227
228
228 .btn-approved-status {
229 .btn-approved-status {
229 .border ( @border-thickness, @alert1 );
230 .border ( @border-thickness, @alert1 );
230 background-color: white;
231 background-color: white;
231 color: @alert1;
232 color: @alert1;
232
233
233 }
234 }
234
235
235 .btn-rejected-status {
236 .btn-rejected-status {
236 .border ( @border-thickness, @alert2 );
237 .border ( @border-thickness, @alert2 );
237 background-color: white;
238 background-color: white;
238 color: @alert2;
239 color: @alert2;
239 }
240 }
240
241
241 .btn-sm,
242 .btn-sm,
242 .btn-mini,
243 .btn-mini,
243 .field-sm .btn {
244 .field-sm .btn {
244 padding: @padding/3;
245 padding: @padding/3;
245 }
246 }
246
247
247 .btn-xs {
248 .btn-xs {
248 padding: @padding/4;
249 padding: @padding/4;
249 }
250 }
250
251
251 .btn-lg {
252 .btn-lg {
252 padding: @padding * 1.2;
253 padding: @padding * 1.2;
253 }
254 }
254
255
255 .btn-group {
256 .btn-group {
256 display: inline-block;
257 display: inline-block;
257 .btn {
258 .btn {
258 float: left;
259 float: left;
259 margin: 0 0 0 0;
260 margin: 0 0 0 0;
260 // first item
261 // first item
261 &:first-of-type:not(:last-of-type) {
262 &:first-of-type:not(:last-of-type) {
262 border-radius: @border-radius 0 0 @border-radius;
263 border-radius: @border-radius 0 0 @border-radius;
263
264
264 }
265 }
265 // middle elements
266 // middle elements
266 &:not(:first-of-type):not(:last-of-type) {
267 &:not(:first-of-type):not(:last-of-type) {
267 border-radius: 0;
268 border-radius: 0;
268 border-left-width: 0;
269 border-left-width: 0;
269 border-right-width: 0;
270 border-right-width: 0;
270 }
271 }
271 // last item
272 // last item
272 &:last-of-type:not(:first-of-type) {
273 &:last-of-type:not(:first-of-type) {
273 border-radius: 0 @border-radius @border-radius 0;
274 border-radius: 0 @border-radius @border-radius 0;
274 }
275 }
275
276
276 &:only-child {
277 &:only-child {
277 border-radius: @border-radius;
278 border-radius: @border-radius;
278 }
279 }
279 }
280 }
280
281
281 }
282 }
282
283
283
284
284 .btn-group-actions {
285 .btn-group-actions {
285 position: relative;
286 position: relative;
286 z-index: 50;
287 z-index: 50;
287
288
288 &:not(.open) .btn-action-switcher-container {
289 &:not(.open) .btn-action-switcher-container {
289 display: none;
290 display: none;
290 }
291 }
291
292
292 .btn-more-option {
293 .btn-more-option {
293 margin-left: -1px;
294 margin-left: -1px;
294 padding-left: 2px;
295 padding-left: 2px;
295 padding-right: 2px;
296 padding-right: 2px;
296 }
297 }
297 }
298 }
298
299
299
300
300 .btn-action-switcher-container {
301 .btn-action-switcher-container {
301 position: absolute;
302 position: absolute;
302 top: 100%;
303 top: 100%;
303
304
304 &.left-align {
305 &.left-align {
305 left: 0;
306 left: 0;
306 }
307 }
307 &.right-align {
308 &.right-align {
308 right: 0;
309 right: 0;
309 }
310 }
310
311
311 }
312 }
312
313
313 .btn-action-switcher {
314 .btn-action-switcher {
314 display: block;
315 display: block;
315 position: relative;
316 position: relative;
316 z-index: 300;
317 z-index: 300;
317 max-width: 600px;
318 max-width: 600px;
318 margin-top: 4px;
319 margin-top: 4px;
319 margin-bottom: 24px;
320 margin-bottom: 24px;
320 font-size: 14px;
321 font-size: 14px;
321 font-weight: 400;
322 font-weight: 400;
322 padding: 8px 0;
323 padding: 8px 0;
323 background-color: #fff;
324 background-color: #fff;
324 border: 1px solid @grey4;
325 border: 1px solid @grey4;
325 border-radius: 3px;
326 border-radius: 3px;
326 box-shadow: @dropdown-shadow;
327 box-shadow: @dropdown-shadow;
327 overflow: auto;
328 overflow: auto;
328
329
329 li {
330 li {
330 display: block;
331 display: block;
331 text-align: left;
332 text-align: left;
332 list-style: none;
333 list-style: none;
333 padding: 5px 10px;
334 padding: 5px 10px;
334 }
335 }
335
336
336 li .action-help-block {
337 li .action-help-block {
337 font-size: 10px;
338 font-size: 10px;
338 line-height: normal;
339 line-height: normal;
339 color: @grey4;
340 color: @grey4;
340 }
341 }
341
342
342 }
343 }
343
344
344 .btn-link {
345 .btn-link {
345 background: transparent;
346 background: transparent;
346 border: none;
347 border: none;
347 padding: 0;
348 padding: 0;
348 color: @rcblue;
349 color: @rcblue;
349
350
350 &:hover {
351 &:hover {
351 background: transparent;
352 background: transparent;
352 border: none;
353 border: none;
353 color: @rcdarkblue;
354 color: @rcdarkblue;
354 }
355 }
355
356
356 //disabled buttons
357 //disabled buttons
357 //last; overrides any other styles
358 //last; overrides any other styles
358 &:disabled {
359 &:disabled {
359 opacity: .7;
360 opacity: .7;
360 cursor: auto;
361 cursor: auto;
361 background-color: white;
362 background-color: white;
362 color: @grey4;
363 color: @grey4;
363 text-shadow: none;
364 text-shadow: none;
364 }
365 }
365
366
366 // TODO: johbo: Check if we can avoid this, indicates that the structure
367 // TODO: johbo: Check if we can avoid this, indicates that the structure
367 // is not yet good.
368 // is not yet good.
368 // lisa: The button CSS reflects the button HTML; both need a cleanup.
369 // lisa: The button CSS reflects the button HTML; both need a cleanup.
369 &.btn-danger {
370 &.btn-danger {
370 color: @alert2;
371 color: @alert2;
371
372
372 &:hover {
373 &:hover {
373 color: darken(@alert2, 30%);
374 color: darken(@alert2, 30%);
374 }
375 }
375
376
376 &:disabled {
377 &:disabled {
377 color: @alert2;
378 color: @alert2;
378 }
379 }
379 }
380 }
380 }
381 }
381
382
382 .btn-social {
383 .btn-social {
383 &:extend(.btn-default);
384 &:extend(.btn-default);
384 margin: 5px 5px 5px 0px;
385 margin: 5px 5px 5px 0px;
385 min-width: 160px;
386 min-width: 160px;
386 }
387 }
387
388
388 // TODO: johbo: check these exceptions
389 // TODO: johbo: check these exceptions
389
390
390 .links {
391 .links {
391
392
392 .btn + .btn {
393 .btn + .btn {
393 margin-top: @padding;
394 margin-top: @padding;
394 }
395 }
395 }
396 }
396
397
397
398
398 .action_button {
399 .action_button {
399 display:inline;
400 display:inline;
400 margin: 0;
401 margin: 0;
401 padding: 0 1em 0 0;
402 padding: 0 1em 0 0;
402 font-size: inherit;
403 font-size: inherit;
403 color: @rcblue;
404 color: @rcblue;
404 border: none;
405 border: none;
405 border-radius: 0;
406 border-radius: 0;
406 background-color: transparent;
407 background-color: transparent;
407
408
408 &.last-item {
409 &.last-item {
409 border: none;
410 border: none;
410 padding: 0 0 0 0;
411 padding: 0 0 0 0;
411 }
412 }
412
413
413 &:last-child {
414 &:last-child {
414 border: none;
415 border: none;
415 padding: 0 0 0 0;
416 padding: 0 0 0 0;
416 }
417 }
417
418
418 &:hover {
419 &:hover {
419 color: @rcdarkblue;
420 color: @rcdarkblue;
420 background-color: transparent;
421 background-color: transparent;
421 border: none;
422 border: none;
422 }
423 }
423 .noselect
424 .noselect
424 }
425 }
425
426
426 .grid_delete {
427 .grid_delete {
427 .action_button {
428 .action_button {
428 border: none;
429 border: none;
429 }
430 }
430 }
431 }
431
432
433 input[type="submit"].btn-draft {
434 .border ( @border-thickness, @rcblue );
435 background-color: white;
436 color: @rcblue;
437
438 a {
439 color: @rcblue;
440 }
441
442 &:hover,
443 &.active {
444 .border ( @border-thickness, @rcdarkblue );
445 background-color: white;
446 color: @rcdarkblue;
447
448 a {
449 color: @rcdarkblue;
450 }
451 }
452
453 &:disabled {
454 background-color: white;
455 color: @rcblue;
456 }
457 }
432
458
433 input[type="submit"].btn-warning {
459 input[type="submit"].btn-warning {
434 &:extend(.btn-warning);
460 &:extend(.btn-warning);
435
461
436 &:focus {
462 &:focus {
437 outline: 0;
463 outline: 0;
438 }
464 }
439
465
440 &:hover {
466 &:hover {
441 &:extend(.btn-warning:hover);
467 &:extend(.btn-warning:hover);
442 }
468 }
443
469
444 &.btn-link {
470 &.btn-link {
445 &:extend(.btn-link);
471 &:extend(.btn-link);
446 color: @alert3;
472 color: @alert3;
447
473
448 &:disabled {
474 &:disabled {
449 color: @alert3;
475 color: @alert3;
450 background-color: transparent;
476 background-color: transparent;
451 }
477 }
452 }
478 }
453
479
454 &:disabled {
480 &:disabled {
455 .border ( @border-thickness-buttons, @alert3 );
481 .border ( @border-thickness-buttons, @alert3 );
456 background-color: white;
482 background-color: white;
457 color: @alert3;
483 color: @alert3;
458 opacity: 0.5;
484 opacity: 0.5;
459 }
485 }
460 }
486 }
461
487
462
488
463
489
464 // TODO: johbo: Form button tweaks, check if we can use the classes instead
490 // TODO: johbo: Form button tweaks, check if we can use the classes instead
465 input[type="submit"] {
491 input[type="submit"] {
466 &:extend(.btn-primary);
492 &:extend(.btn-primary);
467
493
468 &:focus {
494 &:focus {
469 outline: 0;
495 outline: 0;
470 }
496 }
471
497
472 &:hover {
498 &:hover {
473 &:extend(.btn-primary:hover);
499 &:extend(.btn-primary:hover);
474 }
500 }
475
501
476 &.btn-link {
502 &.btn-link {
477 &:extend(.btn-link);
503 &:extend(.btn-link);
478 color: @rcblue;
504 color: @rcblue;
479
505
480 &:disabled {
506 &:disabled {
481 color: @rcblue;
507 color: @rcblue;
482 background-color: transparent;
508 background-color: transparent;
483 }
509 }
484 }
510 }
485
511
486 &:disabled {
512 &:disabled {
487 .border ( @border-thickness-buttons, @rcblue );
513 .border ( @border-thickness-buttons, @rcblue );
488 background-color: @rcblue;
514 background-color: @rcblue;
489 color: white;
515 color: white;
490 opacity: 0.5;
516 opacity: 0.5;
491 }
517 }
492 }
518 }
493
519
494 input[type="reset"] {
520 input[type="reset"] {
495 &:extend(.btn-default);
521 &:extend(.btn-default);
496
522
497 // TODO: johbo: Check if this tweak can be avoided.
523 // TODO: johbo: Check if this tweak can be avoided.
498 background: transparent;
524 background: transparent;
499
525
500 &:focus {
526 &:focus {
501 outline: 0;
527 outline: 0;
502 }
528 }
503
529
504 &:hover {
530 &:hover {
505 &:extend(.btn-default:hover);
531 &:extend(.btn-default:hover);
506 }
532 }
507
533
508 &.btn-link {
534 &.btn-link {
509 &:extend(.btn-link);
535 &:extend(.btn-link);
510 color: @rcblue;
536 color: @rcblue;
511
537
512 &:disabled {
538 &:disabled {
513 border: none;
539 border: none;
514 }
540 }
515 }
541 }
516
542
517 &:disabled {
543 &:disabled {
518 .border ( @border-thickness-buttons, @rcblue );
544 .border ( @border-thickness-buttons, @rcblue );
519 background-color: white;
545 background-color: white;
520 color: @rcblue;
546 color: @rcblue;
521 }
547 }
522 }
548 }
523
549
524 input[type="submit"],
550 input[type="submit"],
525 input[type="reset"] {
551 input[type="reset"] {
526 &.btn-danger {
552 &.btn-danger {
527 &:extend(.btn-danger);
553 &:extend(.btn-danger);
528
554
529 &:focus {
555 &:focus {
530 outline: 0;
556 outline: 0;
531 }
557 }
532
558
533 &:hover {
559 &:hover {
534 &:extend(.btn-danger:hover);
560 &:extend(.btn-danger:hover);
535 }
561 }
536
562
537 &.btn-link {
563 &.btn-link {
538 &:extend(.btn-link);
564 &:extend(.btn-link);
539 color: @alert2;
565 color: @alert2;
540
566
541 &:hover {
567 &:hover {
542 color: darken(@alert2,30%);
568 color: darken(@alert2,30%);
543 }
569 }
544 }
570 }
545
571
546 &:disabled {
572 &:disabled {
547 color: @alert2;
573 color: @alert2;
548 background-color: white;
574 background-color: white;
549 }
575 }
550 }
576 }
551 &.btn-danger-action {
577 &.btn-danger-action {
552 .border ( @border-thickness, @alert2 );
578 .border ( @border-thickness, @alert2 );
553 background-color: @alert2;
579 background-color: @alert2;
554 color: white;
580 color: white;
555
581
556 a {
582 a {
557 color: white;
583 color: white;
558 }
584 }
559
585
560 &:hover {
586 &:hover {
561 background-color: darken(@alert2,20%);
587 background-color: darken(@alert2,20%);
562 }
588 }
563
589
564 &.active {
590 &.active {
565 .border ( @border-thickness, @alert2 );
591 .border ( @border-thickness, @alert2 );
566 color: white;
592 color: white;
567 background-color: @alert2;
593 background-color: @alert2;
568
594
569 a {
595 a {
570 color: white;
596 color: white;
571 }
597 }
572 }
598 }
573
599
574 &:disabled {
600 &:disabled {
575 background-color: white;
601 background-color: white;
576 color: @alert2;
602 color: @alert2;
577 }
603 }
578 }
604 }
579 }
605 }
580
606
581
607
582 .button-links {
608 .button-links {
583 float: left;
609 float: left;
584 display: inline;
610 display: inline;
585 margin: 0;
611 margin: 0;
586 padding-left: 0;
612 padding-left: 0;
587 list-style: none;
613 list-style: none;
588 text-align: right;
614 text-align: right;
589
615
590 li {
616 li {
591
617
592
618
593 }
619 }
594
620
595 li.active {
621 li.active {
596 background-color: @grey6;
622 background-color: @grey6;
597 .border ( @border-thickness, @grey4 );
623 .border ( @border-thickness, @grey4 );
598 }
624 }
599
625
600 }
626 }
@@ -1,557 +1,557 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 ## usage:
2 ## usage:
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
4 ## ${comment.comment_block(comment)}
4 ## ${comment.comment_block(comment)}
5 ##
5 ##
6 <%namespace name="base" file="/base/base.mako"/>
6 <%namespace name="base" file="/base/base.mako"/>
7
7
8 <%!
8 <%!
9 from rhodecode.lib import html_filters
9 from rhodecode.lib import html_filters
10 %>
10 %>
11
11
12
12
13 <%def name="comment_block(comment, inline=False, active_pattern_entries=None, is_new=False)">
13 <%def name="comment_block(comment, inline=False, active_pattern_entries=None, is_new=False)">
14
14
15 <%
15 <%
16 from rhodecode.model.comment import CommentsModel
16 from rhodecode.model.comment import CommentsModel
17 comment_model = CommentsModel()
17 comment_model = CommentsModel()
18
18
19 comment_ver = comment.get_index_version(getattr(c, 'versions', []))
19 comment_ver = comment.get_index_version(getattr(c, 'versions', []))
20 latest_ver = len(getattr(c, 'versions', []))
20 latest_ver = len(getattr(c, 'versions', []))
21 visible_for_user = True
21 visible_for_user = True
22 if comment.draft:
22 if comment.draft:
23 visible_for_user = comment.user_id == c.rhodecode_user.user_id
23 visible_for_user = comment.user_id == c.rhodecode_user.user_id
24 %>
24 %>
25
25
26 % if inline:
26 % if inline:
27 <% outdated_at_ver = comment.outdated_at_version(c.at_version_num) %>
27 <% outdated_at_ver = comment.outdated_at_version(c.at_version_num) %>
28 % else:
28 % else:
29 <% outdated_at_ver = comment.older_than_version(c.at_version_num) %>
29 <% outdated_at_ver = comment.older_than_version(c.at_version_num) %>
30 % endif
30 % endif
31
31
32 % if visible_for_user:
32 % if visible_for_user:
33 <div class="comment
33 <div class="comment
34 ${'comment-inline' if inline else 'comment-general'}
34 ${'comment-inline' if inline else 'comment-general'}
35 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
35 ${'comment-outdated' if outdated_at_ver else 'comment-current'}"
36 id="comment-${comment.comment_id}"
36 id="comment-${comment.comment_id}"
37 line="${comment.line_no}"
37 line="${comment.line_no}"
38 data-comment-id="${comment.comment_id}"
38 data-comment-id="${comment.comment_id}"
39 data-comment-type="${comment.comment_type}"
39 data-comment-type="${comment.comment_type}"
40 data-comment-draft=${h.json.dumps(comment.draft)}
40 data-comment-draft=${h.json.dumps(comment.draft)}
41 data-comment-renderer="${comment.renderer}"
41 data-comment-renderer="${comment.renderer}"
42 data-comment-text="${comment.text | html_filters.base64,n}"
42 data-comment-text="${comment.text | html_filters.base64,n}"
43 data-comment-f-path="${comment.f_path}"
43 data-comment-f-path="${comment.f_path}"
44 data-comment-line-no="${comment.line_no}"
44 data-comment-line-no="${comment.line_no}"
45 data-comment-inline=${h.json.dumps(inline)}
45 data-comment-inline=${h.json.dumps(inline)}
46 style="${'display: none;' if outdated_at_ver else ''}">
46 style="${'display: none;' if outdated_at_ver else ''}">
47
47
48 <div class="meta">
48 <div class="meta">
49 <div class="comment-type-label">
49 <div class="comment-type-label">
50 % if comment.draft:
50 % if comment.draft:
51 <div class="tooltip comment-draft" title="${_('Draft comments are only visible to the author until submitted')}.">
51 <div class="tooltip comment-draft" title="${_('Draft comments are only visible to the author until submitted')}.">
52 DRAFT
52 DRAFT
53 </div>
53 </div>
54 % elif is_new:
54 % elif is_new:
55 <div class="tooltip comment-new" title="${_('This comment was added while you browsed this page')}.">
55 <div class="tooltip comment-new" title="${_('This comment was added while you browsed this page')}.">
56 NEW
56 NEW
57 </div>
57 </div>
58 % endif
58 % endif
59
59
60 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}">
60 <div class="comment-label ${comment.comment_type or 'note'}" id="comment-label-${comment.comment_id}">
61
61
62 ## TODO COMMENT
62 ## TODO COMMENT
63 % if comment.comment_type == 'todo':
63 % if comment.comment_type == 'todo':
64 % if comment.resolved:
64 % if comment.resolved:
65 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
65 <div class="resolved tooltip" title="${_('Resolved by comment #{}').format(comment.resolved.comment_id)}">
66 <i class="icon-flag-filled"></i>
66 <i class="icon-flag-filled"></i>
67 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
67 <a href="#comment-${comment.resolved.comment_id}">${comment.comment_type}</a>
68 </div>
68 </div>
69 % else:
69 % else:
70 <div class="resolved tooltip" style="display: none">
70 <div class="resolved tooltip" style="display: none">
71 <span>${comment.comment_type}</span>
71 <span>${comment.comment_type}</span>
72 </div>
72 </div>
73 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to create resolution comment.')}">
73 <div class="resolve tooltip" onclick="return Rhodecode.comments.createResolutionComment(${comment.comment_id});" title="${_('Click to create resolution comment.')}">
74 <i class="icon-flag-filled"></i>
74 <i class="icon-flag-filled"></i>
75 ${comment.comment_type}
75 ${comment.comment_type}
76 </div>
76 </div>
77 % endif
77 % endif
78 ## NOTE COMMENT
78 ## NOTE COMMENT
79 % else:
79 % else:
80 ## RESOLVED NOTE
80 ## RESOLVED NOTE
81 % if comment.resolved_comment:
81 % if comment.resolved_comment:
82 <div class="tooltip" title="${_('This comment resolves TODO #{}').format(comment.resolved_comment.comment_id)}">
82 <div class="tooltip" title="${_('This comment resolves TODO #{}').format(comment.resolved_comment.comment_id)}">
83 fix
83 fix
84 <a href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
84 <a href="#comment-${comment.resolved_comment.comment_id}" onclick="Rhodecode.comments.scrollToComment($('#comment-${comment.resolved_comment.comment_id}'), 0, ${h.json.dumps(comment.resolved_comment.outdated)})">
85 <span style="text-decoration: line-through">#${comment.resolved_comment.comment_id}</span>
85 <span style="text-decoration: line-through">#${comment.resolved_comment.comment_id}</span>
86 </a>
86 </a>
87 </div>
87 </div>
88 ## STATUS CHANGE NOTE
88 ## STATUS CHANGE NOTE
89 % elif not comment.is_inline and comment.status_change:
89 % elif not comment.is_inline and comment.status_change:
90 <%
90 <%
91 if comment.pull_request:
91 if comment.pull_request:
92 status_change_title = 'Status of review for pull request !{}'.format(comment.pull_request.pull_request_id)
92 status_change_title = 'Status of review for pull request !{}'.format(comment.pull_request.pull_request_id)
93 else:
93 else:
94 status_change_title = 'Status of review for commit {}'.format(h.short_id(comment.commit_id))
94 status_change_title = 'Status of review for commit {}'.format(h.short_id(comment.commit_id))
95 %>
95 %>
96
96
97 <i class="icon-circle review-status-${comment.review_status}"></i>
97 <i class="icon-circle review-status-${comment.review_status}"></i>
98 <div class="changeset-status-lbl tooltip" title="${status_change_title}">
98 <div class="changeset-status-lbl tooltip" title="${status_change_title}">
99 ${comment.review_status_lbl}
99 ${comment.review_status_lbl}
100 </div>
100 </div>
101 % else:
101 % else:
102 <div>
102 <div>
103 <i class="icon-comment"></i>
103 <i class="icon-comment"></i>
104 ${(comment.comment_type or 'note')}
104 ${(comment.comment_type or 'note')}
105 </div>
105 </div>
106 % endif
106 % endif
107 % endif
107 % endif
108
108
109 </div>
109 </div>
110 </div>
110 </div>
111 ## NOTE 0 and .. => because we disable it for now until UI ready
111 ## NOTE 0 and .. => because we disable it for now until UI ready
112 % if 0 and comment.status_change:
112 % if 0 and comment.status_change:
113 <div class="pull-left">
113 <div class="pull-left">
114 <span class="tag authortag tooltip" title="${_('Status from pull request.')}">
114 <span class="tag authortag tooltip" title="${_('Status from pull request.')}">
115 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
115 <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}">
116 ${'!{}'.format(comment.pull_request.pull_request_id)}
116 ${'!{}'.format(comment.pull_request.pull_request_id)}
117 </a>
117 </a>
118 </span>
118 </span>
119 </div>
119 </div>
120 % endif
120 % endif
121 ## Since only author can see drafts, we don't show it
121 ## Since only author can see drafts, we don't show it
122 % if not comment.draft:
122 % if not comment.draft:
123 <div class="author ${'author-inline' if inline else 'author-general'}">
123 <div class="author ${'author-inline' if inline else 'author-general'}">
124 ${base.gravatar_with_user(comment.author.email, 16, tooltip=True)}
124 ${base.gravatar_with_user(comment.author.email, 16, tooltip=True)}
125 </div>
125 </div>
126 % endif
126 % endif
127
127
128 <div class="date">
128 <div class="date">
129 ${h.age_component(comment.modified_at, time_is_local=True)}
129 ${h.age_component(comment.modified_at, time_is_local=True)}
130 </div>
130 </div>
131
131
132 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
132 % if comment.pull_request and comment.pull_request.author.user_id == comment.author.user_id:
133 <span class="tag authortag tooltip" title="${_('Pull request author')}">
133 <span class="tag authortag tooltip" title="${_('Pull request author')}">
134 ${_('author')}
134 ${_('author')}
135 </span>
135 </span>
136 % endif
136 % endif
137
137
138 <%
138 <%
139 comment_version_selector = 'comment_versions_{}'.format(comment.comment_id)
139 comment_version_selector = 'comment_versions_{}'.format(comment.comment_id)
140 %>
140 %>
141
141
142 % if comment.history:
142 % if comment.history:
143 <div class="date">
143 <div class="date">
144
144
145 <input id="${comment_version_selector}" name="${comment_version_selector}"
145 <input id="${comment_version_selector}" name="${comment_version_selector}"
146 type="hidden"
146 type="hidden"
147 data-last-version="${comment.history[-1].version}">
147 data-last-version="${comment.history[-1].version}">
148
148
149 <script type="text/javascript">
149 <script type="text/javascript">
150
150
151 var preLoadVersionData = [
151 var preLoadVersionData = [
152 % for comment_history in comment.history:
152 % for comment_history in comment.history:
153 {
153 {
154 id: ${comment_history.comment_history_id},
154 id: ${comment_history.comment_history_id},
155 text: 'v${comment_history.version}',
155 text: 'v${comment_history.version}',
156 action: function () {
156 action: function () {
157 Rhodecode.comments.showVersion(
157 Rhodecode.comments.showVersion(
158 "${comment.comment_id}",
158 "${comment.comment_id}",
159 "${comment_history.comment_history_id}"
159 "${comment_history.comment_history_id}"
160 )
160 )
161 },
161 },
162 comment_version: "${comment_history.version}",
162 comment_version: "${comment_history.version}",
163 comment_author_username: "${comment_history.author.username}",
163 comment_author_username: "${comment_history.author.username}",
164 comment_author_gravatar: "${h.gravatar_url(comment_history.author.email, 16)}",
164 comment_author_gravatar: "${h.gravatar_url(comment_history.author.email, 16)}",
165 comment_created_on: '${h.age_component(comment_history.created_on, time_is_local=True)}',
165 comment_created_on: '${h.age_component(comment_history.created_on, time_is_local=True)}',
166 },
166 },
167 % endfor
167 % endfor
168 ]
168 ]
169 initVersionSelector("#${comment_version_selector}", {results: preLoadVersionData});
169 initVersionSelector("#${comment_version_selector}", {results: preLoadVersionData});
170
170
171 </script>
171 </script>
172
172
173 </div>
173 </div>
174 % else:
174 % else:
175 <div class="date" style="display: none">
175 <div class="date" style="display: none">
176 <input id="${comment_version_selector}" name="${comment_version_selector}"
176 <input id="${comment_version_selector}" name="${comment_version_selector}"
177 type="hidden"
177 type="hidden"
178 data-last-version="0">
178 data-last-version="0">
179 </div>
179 </div>
180 %endif
180 %endif
181
181
182 <div class="comment-links-block">
182 <div class="comment-links-block">
183
183
184 % if inline:
184 % if inline:
185 <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
185 <a class="pr-version-inline" href="${request.current_route_path(_query=dict(version=comment.pull_request_version_id), _anchor='comment-{}'.format(comment.comment_id))}">
186 % if outdated_at_ver:
186 % if outdated_at_ver:
187 <strong class="comment-outdated-label">outdated</strong> <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
187 <strong class="comment-outdated-label">outdated</strong> <code class="tooltip pr-version-num" title="${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
188 <code class="action-divider">|</code>
188 <code class="action-divider">|</code>
189 % elif comment_ver:
189 % elif comment_ver:
190 <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
190 <code class="tooltip pr-version-num" title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}">${'v{}'.format(comment_ver)}</code>
191 <code class="action-divider">|</code>
191 <code class="action-divider">|</code>
192 % endif
192 % endif
193 </a>
193 </a>
194 % else:
194 % else:
195 % if comment_ver:
195 % if comment_ver:
196
196
197 % if comment.outdated:
197 % if comment.outdated:
198 <a class="pr-version"
198 <a class="pr-version"
199 href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}"
199 href="?version=${comment.pull_request_version_id}#comment-${comment.comment_id}"
200 >
200 >
201 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}
201 ${_('Outdated comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}
202 </a>
202 </a>
203 <code class="action-divider">|</code>
203 <code class="action-divider">|</code>
204 % else:
204 % else:
205 <a class="tooltip pr-version"
205 <a class="tooltip pr-version"
206 title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"
206 title="${_('Comment from pull request version v{0}, latest v{1}').format(comment_ver, latest_ver)}"
207 href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}"
207 href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}"
208 >
208 >
209 <code class="pr-version-num">${'v{}'.format(comment_ver)}</code>
209 <code class="pr-version-num">${'v{}'.format(comment_ver)}</code>
210 </a>
210 </a>
211 <code class="action-divider">|</code>
211 <code class="action-divider">|</code>
212 % endif
212 % endif
213
213
214 % endif
214 % endif
215 % endif
215 % endif
216
216
217 <details class="details-reset details-inline-block">
217 <details class="details-reset details-inline-block">
218 <summary class="noselect"><i class="icon-options cursor-pointer"></i></summary>
218 <summary class="noselect"><i class="icon-options cursor-pointer"></i></summary>
219 <details-menu class="details-dropdown">
219 <details-menu class="details-dropdown">
220
220
221 <div class="dropdown-item">
221 <div class="dropdown-item">
222 ${_('Comment')} #${comment.comment_id}
222 ${_('Comment')} #${comment.comment_id}
223 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${comment_model.get_url(comment,request, permalink=True, anchor='comment-{}'.format(comment.comment_id))}" title="${_('Copy permalink')}"></span>
223 <span class="pull-right icon-clipboard clipboard-action" data-clipboard-text="${comment_model.get_url(comment,request, permalink=True, anchor='comment-{}'.format(comment.comment_id))}" title="${_('Copy permalink')}"></span>
224 </div>
224 </div>
225
225
226 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
226 ## show delete comment if it's not a PR (regular comments) or it's PR that is not closed
227 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
227 ## only super-admin, repo admin OR comment owner can delete, also hide delete if currently viewed comment is outdated
228 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
228 %if not outdated_at_ver and (not comment.pull_request or (comment.pull_request and not comment.pull_request.is_closed())):
229 ## permissions to delete
229 ## permissions to delete
230 %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id):
230 %if comment.immutable is False and (c.is_super_admin or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or comment.author.user_id == c.rhodecode_user.user_id):
231 <div class="dropdown-divider"></div>
231 <div class="dropdown-divider"></div>
232 <div class="dropdown-item">
232 <div class="dropdown-item">
233 <a onclick="return Rhodecode.comments.editComment(this, '${comment.line_no}', '${comment.f_path}');" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a>
233 <a onclick="return Rhodecode.comments.editComment(this, '${comment.line_no}', '${comment.f_path}');" class="btn btn-link btn-sm edit-comment">${_('Edit')}</a>
234 </div>
234 </div>
235 <div class="dropdown-item">
235 <div class="dropdown-item">
236 <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a>
236 <a onclick="return Rhodecode.comments.deleteComment(this);" class="btn btn-link btn-sm btn-danger delete-comment">${_('Delete')}</a>
237 </div>
237 </div>
238 ## Only available in EE edition
238 ## Only available in EE edition
239 % if comment.draft and c.rhodecode_edition_id == 'EE':
239 % if comment.draft and c.rhodecode_edition_id == 'EE':
240 <div class="dropdown-item">
240 <div class="dropdown-item">
241 <a onclick="return Rhodecode.comments.finalizeDrafts([${comment.comment_id}]);" class="btn btn-link btn-sm finalize-draft-comment">${_('Submit draft')}</a>
241 <a onclick="return Rhodecode.comments.finalizeDrafts([${comment.comment_id}]);" class="btn btn-link btn-sm finalize-draft-comment">${_('Submit draft')}</a>
242 </div>
242 </div>
243 % endif
243 % endif
244 %else:
244 %else:
245 <div class="dropdown-divider"></div>
245 <div class="dropdown-divider"></div>
246 <div class="dropdown-item">
246 <div class="dropdown-item">
247 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
247 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
248 </div>
248 </div>
249 <div class="dropdown-item">
249 <div class="dropdown-item">
250 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
250 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
251 </div>
251 </div>
252 %endif
252 %endif
253 %else:
253 %else:
254 <div class="dropdown-divider"></div>
254 <div class="dropdown-divider"></div>
255 <div class="dropdown-item">
255 <div class="dropdown-item">
256 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
256 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Edit')}</a>
257 </div>
257 </div>
258 <div class="dropdown-item">
258 <div class="dropdown-item">
259 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
259 <a class="tooltip edit-comment link-disabled" disabled="disabled" title="${_('Action unavailable')}">${_('Delete')}</a>
260 </div>
260 </div>
261 %endif
261 %endif
262 </details-menu>
262 </details-menu>
263 </details>
263 </details>
264
264
265 <code class="action-divider">|</code>
265 <code class="action-divider">|</code>
266 % if outdated_at_ver:
266 % if outdated_at_ver:
267 <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous outdated comment')}"> <i class="icon-angle-left"></i> </a>
267 <a onclick="return Rhodecode.comments.prevOutdatedComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous outdated comment')}"> <i class="icon-angle-left"></i> </a>
268 <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="tooltip next-comment" title="${_('Jump to the next outdated comment')}"> <i class="icon-angle-right"></i></a>
268 <a onclick="return Rhodecode.comments.nextOutdatedComment(this);" class="tooltip next-comment" title="${_('Jump to the next outdated comment')}"> <i class="icon-angle-right"></i></a>
269 % else:
269 % else:
270 <a onclick="return Rhodecode.comments.prevComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous comment')}"> <i class="icon-angle-left"></i></a>
270 <a onclick="return Rhodecode.comments.prevComment(this);" class="tooltip prev-comment" title="${_('Jump to the previous comment')}"> <i class="icon-angle-left"></i></a>
271 <a onclick="return Rhodecode.comments.nextComment(this);" class="tooltip next-comment" title="${_('Jump to the next comment')}"> <i class="icon-angle-right"></i></a>
271 <a onclick="return Rhodecode.comments.nextComment(this);" class="tooltip next-comment" title="${_('Jump to the next comment')}"> <i class="icon-angle-right"></i></a>
272 % endif
272 % endif
273
273
274 </div>
274 </div>
275 </div>
275 </div>
276 <div class="text">
276 <div class="text">
277 ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None), active_pattern_entries=active_pattern_entries)}
277 ${h.render(comment.text, renderer=comment.renderer, mentions=True, repo_name=getattr(c, 'repo_name', None), active_pattern_entries=active_pattern_entries)}
278 </div>
278 </div>
279
279
280 </div>
280 </div>
281 % endif
281 % endif
282 </%def>
282 </%def>
283
283
284 ## generate main comments
284 ## generate main comments
285 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
285 <%def name="generate_comments(comments, include_pull_request=False, is_pull_request=False)">
286 <%
286 <%
287 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
287 active_pattern_entries = h.get_active_pattern_entries(getattr(c, 'repo_name', None))
288 %>
288 %>
289
289
290 <div class="general-comments" id="comments">
290 <div class="general-comments" id="comments">
291 %for comment in comments:
291 %for comment in comments:
292 <div id="comment-tr-${comment.comment_id}">
292 <div id="comment-tr-${comment.comment_id}">
293 ## only render comments that are not from pull request, or from
293 ## only render comments that are not from pull request, or from
294 ## pull request and a status change
294 ## pull request and a status change
295 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
295 %if not comment.pull_request or (comment.pull_request and comment.status_change) or include_pull_request:
296 ${comment_block(comment, active_pattern_entries=active_pattern_entries)}
296 ${comment_block(comment, active_pattern_entries=active_pattern_entries)}
297 %endif
297 %endif
298 </div>
298 </div>
299 %endfor
299 %endfor
300 ## to anchor ajax comments
300 ## to anchor ajax comments
301 <div id="injected_page_comments"></div>
301 <div id="injected_page_comments"></div>
302 </div>
302 </div>
303 </%def>
303 </%def>
304
304
305
305
306 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
306 <%def name="comments(post_url, cur_status, is_pull_request=False, is_compare=False, change_status=True, form_extras=None)">
307
307
308 <div class="comments">
308 <div class="comments">
309 <%
309 <%
310 if is_pull_request:
310 if is_pull_request:
311 placeholder = _('Leave a comment on this Pull Request.')
311 placeholder = _('Leave a comment on this Pull Request.')
312 elif is_compare:
312 elif is_compare:
313 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
313 placeholder = _('Leave a comment on {} commits in this range.').format(len(form_extras))
314 else:
314 else:
315 placeholder = _('Leave a comment on this Commit.')
315 placeholder = _('Leave a comment on this Commit.')
316 %>
316 %>
317
317
318 % if c.rhodecode_user.username != h.DEFAULT_USER:
318 % if c.rhodecode_user.username != h.DEFAULT_USER:
319 <div class="js-template" id="cb-comment-general-form-template">
319 <div class="js-template" id="cb-comment-general-form-template">
320 ## template generated for injection
320 ## template generated for injection
321 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
321 ${comment_form(form_type='general', review_statuses=c.commit_statuses, form_extras=form_extras)}
322 </div>
322 </div>
323
323
324 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
324 <div id="cb-comment-general-form-placeholder" class="comment-form ac">
325 ## inject form here
325 ## inject form here
326 </div>
326 </div>
327 <script type="text/javascript">
327 <script type="text/javascript">
328 var resolvesCommentId = null;
328 var resolvesCommentId = null;
329 var generalCommentForm = Rhodecode.comments.createGeneralComment(
329 var generalCommentForm = Rhodecode.comments.createGeneralComment(
330 'general', "${placeholder}", resolvesCommentId);
330 'general', "${placeholder}", resolvesCommentId);
331
331
332 // set custom success callback on rangeCommit
332 // set custom success callback on rangeCommit
333 % if is_compare:
333 % if is_compare:
334 generalCommentForm.setHandleFormSubmit(function(o) {
334 generalCommentForm.setHandleFormSubmit(function(o) {
335 var self = generalCommentForm;
335 var self = generalCommentForm;
336
336
337 var text = self.cm.getValue();
337 var text = self.cm.getValue();
338 var status = self.getCommentStatus();
338 var status = self.getCommentStatus();
339 var commentType = self.getCommentType();
339 var commentType = self.getCommentType();
340 var isDraft = self.getDraftState();
340 var isDraft = self.getDraftState();
341
341
342 if (text === "" && !status) {
342 if (text === "" && !status) {
343 return;
343 return;
344 }
344 }
345
345
346 // we can pick which commits we want to make the comment by
346 // we can pick which commits we want to make the comment by
347 // selecting them via click on preview pane, this will alter the hidden inputs
347 // selecting them via click on preview pane, this will alter the hidden inputs
348 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
348 var cherryPicked = $('#changeset_compare_view_content .compare_select.hl').length > 0;
349
349
350 var commitIds = [];
350 var commitIds = [];
351 $('#changeset_compare_view_content .compare_select').each(function(el) {
351 $('#changeset_compare_view_content .compare_select').each(function(el) {
352 var commitId = this.id.replace('row-', '');
352 var commitId = this.id.replace('row-', '');
353 if ($(this).hasClass('hl') || !cherryPicked) {
353 if ($(this).hasClass('hl') || !cherryPicked) {
354 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
354 $("input[data-commit-id='{0}']".format(commitId)).val(commitId);
355 commitIds.push(commitId);
355 commitIds.push(commitId);
356 } else {
356 } else {
357 $("input[data-commit-id='{0}']".format(commitId)).val('')
357 $("input[data-commit-id='{0}']".format(commitId)).val('')
358 }
358 }
359 });
359 });
360
360
361 self.setActionButtonsDisabled(true);
361 self.setActionButtonsDisabled(true);
362 self.cm.setOption("readOnly", true);
362 self.cm.setOption("readOnly", true);
363 var postData = {
363 var postData = {
364 'text': text,
364 'text': text,
365 'changeset_status': status,
365 'changeset_status': status,
366 'comment_type': commentType,
366 'comment_type': commentType,
367 'draft': isDraft,
367 'draft': isDraft,
368 'commit_ids': commitIds,
368 'commit_ids': commitIds,
369 'csrf_token': CSRF_TOKEN
369 'csrf_token': CSRF_TOKEN
370 };
370 };
371
371
372 var submitSuccessCallback = function(o) {
372 var submitSuccessCallback = function(o) {
373 location.reload(true);
373 location.reload(true);
374 };
374 };
375 var submitFailCallback = function(){
375 var submitFailCallback = function(){
376 self.resetCommentFormState(text)
376 self.resetCommentFormState(text)
377 };
377 };
378 self.submitAjaxPOST(
378 self.submitAjaxPOST(
379 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
379 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
380 });
380 });
381 % endif
381 % endif
382
382
383 </script>
383 </script>
384 % else:
384 % else:
385 ## form state when not logged in
385 ## form state when not logged in
386 <div class="comment-form ac">
386 <div class="comment-form ac">
387
387
388 <div class="comment-area">
388 <div class="comment-area">
389 <div class="comment-area-header">
389 <div class="comment-area-header">
390 <ul class="nav-links clearfix">
390 <ul class="nav-links clearfix">
391 <li class="active">
391 <li class="active">
392 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
392 <a class="disabled" href="#edit-btn" disabled="disabled" onclick="return false">${_('Write')}</a>
393 </li>
393 </li>
394 <li class="">
394 <li class="">
395 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
395 <a class="disabled" href="#preview-btn" disabled="disabled" onclick="return false">${_('Preview')}</a>
396 </li>
396 </li>
397 </ul>
397 </ul>
398 </div>
398 </div>
399
399
400 <div class="comment-area-write" style="display: block;">
400 <div class="comment-area-write" style="display: block;">
401 <div id="edit-container">
401 <div id="edit-container">
402 <div style="padding: 20px 0px 0px 0;">
402 <div style="padding: 20px 0px 0px 0;">
403 ${_('You need to be logged in to leave comments.')}
403 ${_('You need to be logged in to leave comments.')}
404 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
404 <a href="${h.route_path('login', _query={'came_from': h.current_route_path(request)})}">${_('Login now')}</a>
405 </div>
405 </div>
406 </div>
406 </div>
407 <div id="preview-container" class="clearfix" style="display: none;">
407 <div id="preview-container" class="clearfix" style="display: none;">
408 <div id="preview-box" class="preview-box"></div>
408 <div id="preview-box" class="preview-box"></div>
409 </div>
409 </div>
410 </div>
410 </div>
411
411
412 <div class="comment-area-footer">
412 <div class="comment-area-footer">
413 <div class="toolbar">
413 <div class="toolbar">
414 <div class="toolbar-text">
414 <div class="toolbar-text">
415 </div>
415 </div>
416 </div>
416 </div>
417 </div>
417 </div>
418 </div>
418 </div>
419
419
420 <div class="comment-footer">
420 <div class="comment-footer">
421 </div>
421 </div>
422
422
423 </div>
423 </div>
424 % endif
424 % endif
425
425
426 <script type="text/javascript">
426 <script type="text/javascript">
427 bindToggleButtons();
427 bindToggleButtons();
428 </script>
428 </script>
429 </div>
429 </div>
430 </%def>
430 </%def>
431
431
432
432
433 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
433 <%def name="comment_form(form_type, form_id='', lineno_id='{1}', review_statuses=None, form_extras=None)">
434
434
435 ## comment injected based on assumption that user is logged in
435 ## comment injected based on assumption that user is logged in
436 <form ${('id="{}"'.format(form_id) if form_id else '') |n} action="#" method="GET">
436 <form ${('id="{}"'.format(form_id) if form_id else '') |n} action="#" method="GET">
437
437
438 <div class="comment-area">
438 <div class="comment-area">
439 <div class="comment-area-header">
439 <div class="comment-area-header">
440 <div class="pull-left">
440 <div class="pull-left">
441 <ul class="nav-links clearfix">
441 <ul class="nav-links clearfix">
442 <li class="active">
442 <li class="active">
443 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
443 <a href="#edit-btn" tabindex="-1" id="edit-btn_${lineno_id}">${_('Write')}</a>
444 </li>
444 </li>
445 <li class="">
445 <li class="">
446 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
446 <a href="#preview-btn" tabindex="-1" id="preview-btn_${lineno_id}">${_('Preview')}</a>
447 </li>
447 </li>
448 </ul>
448 </ul>
449 </div>
449 </div>
450 <div class="pull-right">
450 <div class="pull-right">
451 <span class="comment-area-text">${_('Mark as')}:</span>
451 <span class="comment-area-text">${_('Mark as')}:</span>
452 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
452 <select class="comment-type" id="comment_type_${lineno_id}" name="comment_type">
453 % for val in c.visual.comment_types:
453 % for val in c.visual.comment_types:
454 <option value="${val}">${val.upper()}</option>
454 <option value="${val}">${val.upper()}</option>
455 % endfor
455 % endfor
456 </select>
456 </select>
457 </div>
457 </div>
458 </div>
458 </div>
459
459
460 <div class="comment-area-write" style="display: block;">
460 <div class="comment-area-write" style="display: block;">
461 <div id="edit-container_${lineno_id}" style="margin-top: -1px">
461 <div id="edit-container_${lineno_id}" style="margin-top: -1px">
462 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
462 <textarea id="text_${lineno_id}" name="text" class="comment-block-ta ac-input"></textarea>
463 </div>
463 </div>
464 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
464 <div id="preview-container_${lineno_id}" class="clearfix" style="display: none;">
465 <div id="preview-box_${lineno_id}" class="preview-box"></div>
465 <div id="preview-box_${lineno_id}" class="preview-box"></div>
466 </div>
466 </div>
467 </div>
467 </div>
468
468
469 <div class="comment-area-footer comment-attachment-uploader">
469 <div class="comment-area-footer comment-attachment-uploader">
470 <div class="toolbar">
470 <div class="toolbar">
471
471
472 <div class="comment-attachment-text">
472 <div class="comment-attachment-text">
473 <div class="dropzone-text">
473 <div class="dropzone-text">
474 ${_("Drag'n Drop files here or")} <span class="link pick-attachment">${_('Choose your files')}</span>.<br>
474 ${_("Drag'n Drop files here or")} <span class="link pick-attachment">${_('Choose your files')}</span>.<br>
475 </div>
475 </div>
476 <div class="dropzone-upload" style="display:none">
476 <div class="dropzone-upload" style="display:none">
477 <i class="icon-spin animate-spin"></i> ${_('uploading...')}
477 <i class="icon-spin animate-spin"></i> ${_('uploading...')}
478 </div>
478 </div>
479 </div>
479 </div>
480
480
481 ## comments dropzone template, empty on purpose
481 ## comments dropzone template, empty on purpose
482 <div style="display: none" class="comment-attachment-uploader-template">
482 <div style="display: none" class="comment-attachment-uploader-template">
483 <div class="dz-file-preview" style="margin: 0">
483 <div class="dz-file-preview" style="margin: 0">
484 <div class="dz-error-message"></div>
484 <div class="dz-error-message"></div>
485 </div>
485 </div>
486 </div>
486 </div>
487
487
488 </div>
488 </div>
489 </div>
489 </div>
490 </div>
490 </div>
491
491
492 <div class="comment-footer">
492 <div class="comment-footer">
493
493
494 ## inject extra inputs into the form
494 ## inject extra inputs into the form
495 % if form_extras and isinstance(form_extras, (list, tuple)):
495 % if form_extras and isinstance(form_extras, (list, tuple)):
496 <div id="comment_form_extras">
496 <div id="comment_form_extras">
497 % for form_ex_el in form_extras:
497 % for form_ex_el in form_extras:
498 ${form_ex_el|n}
498 ${form_ex_el|n}
499 % endfor
499 % endfor
500 </div>
500 </div>
501 % endif
501 % endif
502
502
503 <div class="action-buttons">
503 <div class="action-buttons">
504 % if form_type != 'inline':
504 % if form_type != 'inline':
505 <div class="action-buttons-extra"></div>
505 <div class="action-buttons-extra"></div>
506 % endif
506 % endif
507
507
508 <input class="btn btn-success comment-button-input submit-comment-action" id="save_${lineno_id}" name="save" type="submit" value="${_('Add comment')}" data-is-draft=false onclick="$(this).addClass('submitter')">
508 <input class="btn btn-success comment-button-input submit-comment-action" id="save_${lineno_id}" name="save" type="submit" value="${_('Add comment')}" data-is-draft=false onclick="$(this).addClass('submitter')">
509
509
510 % if form_type == 'inline':
510 % if form_type == 'inline':
511 % if c.rhodecode_edition_id == 'EE':
511 % if c.rhodecode_edition_id == 'EE':
512 ## Disable the button for CE, the "real" validation is in the backend code anyway
512 ## Disable the button for CE, the "real" validation is in the backend code anyway
513 <input class="btn btn-warning comment-button-input submit-draft-action" id="save_draft_${lineno_id}" name="save_draft" type="submit" value="${_('Add draft')}" data-is-draft=true onclick="$(this).addClass('submitter')">
513 <input class="btn btn-draft comment-button-input submit-draft-action" id="save_draft_${lineno_id}" name="save_draft" type="submit" value="${_('Add draft')}" data-is-draft=true onclick="$(this).addClass('submitter')">
514 % else:
514 % else:
515 <input class="btn btn-warning comment-button-input submit-draft-action disabled" disabled="disabled" type="submit" value="${_('Add draft')}" onclick="return false;" title="Draft comments only available in EE edition of RhodeCode">
515 <input class="btn btn-draft comment-button-input submit-draft-action disabled" disabled="disabled" type="submit" value="${_('Add draft')}" onclick="return false;" title="Draft comments only available in EE edition of RhodeCode">
516 % endif
516 % endif
517 % endif
517 % endif
518
518
519 % if review_statuses:
519 % if review_statuses:
520 <div class="comment-status-box">
520 <div class="comment-status-box">
521 <select id="change_status_${lineno_id}" name="changeset_status">
521 <select id="change_status_${lineno_id}" name="changeset_status">
522 <option></option> ## Placeholder
522 <option></option> ## Placeholder
523 % for status, lbl in review_statuses:
523 % for status, lbl in review_statuses:
524 <option value="${status}" data-status="${status}">${lbl}</option>
524 <option value="${status}" data-status="${status}">${lbl}</option>
525 %if is_pull_request and change_status and status in ('approved', 'rejected'):
525 %if is_pull_request and change_status and status in ('approved', 'rejected'):
526 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
526 <option value="${status}_closed" data-status="${status}">${lbl} & ${_('Closed')}</option>
527 %endif
527 %endif
528 % endfor
528 % endfor
529 </select>
529 </select>
530 </div>
530 </div>
531 % endif
531 % endif
532
532
533 ## inline for has a file, and line-number together with cancel hide button.
533 ## inline for has a file, and line-number together with cancel hide button.
534 % if form_type == 'inline':
534 % if form_type == 'inline':
535 <input type="hidden" name="f_path" value="{0}">
535 <input type="hidden" name="f_path" value="{0}">
536 <input type="hidden" name="line" value="${lineno_id}">
536 <input type="hidden" name="line" value="${lineno_id}">
537 <button type="button" class="cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
537 <span class="cursor-pointer action_button cb-comment-cancel" onclick="return Rhodecode.comments.cancelComment(this);">
538 <i class="icon-cancel-circled2"></i>
538 ${_('dismiss')}
539 </button>
539 </span>
540 % endif
540 % endif
541 </div>
541 </div>
542
542
543 <div class="toolbar-text">
543 <div class="toolbar-text">
544 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
544 <% renderer_url = '<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper()) %>
545 <span>${_('{} is supported.').format(renderer_url)|n}
545 <span>${_('{} is supported.').format(renderer_url)|n}
546
546
547 <i class="icon-info-circled tooltip-hovercard"
547 <i class="icon-info-circled tooltip-hovercard"
548 data-hovercard-alt="ALT"
548 data-hovercard-alt="ALT"
549 data-hovercard-url="javascript:commentHelp('${c.visual.default_renderer.upper()}')"
549 data-hovercard-url="javascript:commentHelp('${c.visual.default_renderer.upper()}')"
550 data-comment-json-b64='${h.b64(h.json.dumps({}))}'></i>
550 data-comment-json-b64='${h.b64(h.json.dumps({}))}'></i>
551 </span>
551 </span>
552 </div>
552 </div>
553 </div>
553 </div>
554
554
555 </form>
555 </form>
556
556
557 </%def> No newline at end of file
557 </%def>
General Comments 0
You need to be logged in to leave comments. Login now