Support handling fine-grained rich text values in the UI.

Review Request #6462 — Created Oct. 18, 2014 and submitted — Latest diff uploaded

Information

Review Board
release-2.0.x
34cfb32...

Reviewers

Now that the models and API support fine-grained rich text values,
the UI needs to be updated to handle those.

With this change, any plain-text fields will be auto-escaped for editing
in Markdown, and will then be saved as Markdown when the user saves the
field. This is the same behavior as before, but operates per-field,
instead of assuming all fields have the same rich text value.

As part of this, the rich text states are now kept solely in the models.
There is no longer a data-rich-text= attribute.

There are some backwards-incompatible changes for extension writers.
Custom fields registered in JavaScript must now use the allowMarkdown
setting instead of editMarkdown. They are also expected to take a
fourth option (called fieldOptions) in formatter, which must be
passed as an option to formatText.

This change does not yet provide compatibility for custom fields. That
will be covered in another change.

Tested editing every single editable field for all objects.

Tested with that field being in an initial state (new review requests,
new comments, new replies, etc.). Saved and saw that the rich_text field
was set.

Tested with that field having rich_text=true. Saw that no escaping occurred.
Saved and saw that the rich_text field was set to true. Reloaded and saw that
the text was rendered as Markdown.

Tested with that field having rich_text=false. Saw that escaping occurred.
Saved and saw that the rich_text field was set to true. Reloaded and saw that
the text was rendered as Markdown.

Unit tests pass.

reviewboard/reviews/context.py
Revision 46ce3ce1aeb6f22e61872e7788842f1029bd965e New Change
1
from __future__ import unicode_literals
1
from __future__ import unicode_literals
2

    
   
2

   
3
from django.utils import six
3
from django.utils import six
4 1
from django.utils.html import escape
4
from django.utils.html import escape
5

    
   
5

   
6
from reviewboard.attachments.forms import CommentFileForm, UploadFileForm
6
from reviewboard.attachments.forms import CommentFileForm, UploadFileForm
7
from reviewboard.diffviewer.models import DiffSet
7
from reviewboard.diffviewer.models import DiffSet
8
from reviewboard.reviews.forms import UploadDiffForm, UploadScreenshotForm
8
from reviewboard.reviews.forms import UploadDiffForm, UploadScreenshotForm
9
from reviewboard.reviews.models import BaseComment
9
from reviewboard.reviews.models import BaseComment

    
   
10
from reviewboard.reviews.templatetags.reviewtags import markdown_escape_filter
10

    
   
11

   
11

    
   
12

   
12
def comment_counts(user, all_comments, filediff, interfilediff=None):
13
def comment_counts(user, all_comments, filediff, interfilediff=None):
13
    """
14
    """
14
    Returns an array of current comments for a filediff, sorted by line number.
15
    Returns an array of current comments for a filediff, sorted by line number.
15

    
   
16

   
16
    Each entry in the array has a dictionary containing the following keys:
17
    Each entry in the array has a dictionary containing the following keys:
17

    
   
18

   
18
      =========== ==================================================
19
      =========== ==================================================
19
      Key                Description
20
      Key                Description
20
      =========== ==================================================
21
      =========== ==================================================
21
      comment_id         The ID of the comment
22
      comment_id         The ID of the comment
22
      text               The text of the comment
23
      text               The plain or rich text of the comment

    
   
24
      rich_text          The rich text flag for the comment
23
      line               The first line number
25
      line               The first line number
24
      num_lines          The number of lines this comment spans
26
      num_lines          The number of lines this comment spans
25
      user               A dictionary containing "username" and "name" keys
27
      user               A dictionary containing "username" and "name" keys
26
                         for the user
28
                         for the user
27
      url                The URL to the comment
29
      url                The URL to the comment
16 lines
def comment_counts(user, all_comments, filediff, interfilediff=None):
44
        if review and (review.public or review.user == user):
46
        if review and (review.public or review.user == user):
45
            key = (comment.first_line, comment.num_lines)
47
            key = (comment.first_line, comment.num_lines)
46

    
   
48

   
47
            comment_dict.setdefault(key, []).append({
49
            comment_dict.setdefault(key, []).append({
48
                'comment_id': comment.id,
50
                'comment_id': comment.id,
49 1
                'text': escape(comment.text),
51
                'text': markdown_escape_filter(comment.text, comment.rich_text),

    
   
52
                'rich_text': comment.rich_text,
50
                'line': comment.first_line,
53
                'line': comment.first_line,
51
                'num_lines': comment.num_lines,
54
                'num_lines': comment.num_lines,
52
                'user': {
55
                'user': {
53
                    'username': review.user.username,
56
                    'username': review.user.username,
54
                    'name': (review.user.get_full_name() or
57
                    'name': (review.user.get_full_name() or
131 lines
reviewboard/reviews/fields.py
reviewboard/reviews/templatetags/reviewtags.py
reviewboard/static/rb/js/models/reviewReplyEditorModel.js
reviewboard/static/rb/js/models/reviewRequestEditorModel.js
reviewboard/static/rb/js/pages/views/reviewablePageView.js
reviewboard/static/rb/js/utils/textUtils.js
reviewboard/static/rb/js/views/reviewDialogView.js
reviewboard/static/rb/js/views/reviewReplyEditorView.js
reviewboard/static/rb/js/views/reviewRequestEditorView.js
reviewboard/static/rb/js/views/tests/reviewRequestEditorViewTests.js
reviewboard/templates/reviews/review_header.html
reviewboard/templates/reviews/review_reply.html
reviewboard/templates/reviews/reviewable_page_data.js
reviewboard/templates/reviews/boxes/change.html
reviewboard/templates/reviews/boxes/review.html
Loading...