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