• 
      

    Dramatically improve the experience for admins with other users' drafts.

    Review Request #14020 — Created July 10, 2024 and submitted

    Information

    Review Board
    release-7.x

    Reviewers

    For a very long time, we've had an annoying situation with privileged
    users and drafts. Users who are admins or have the
    can_edit_reviewrequest privilege have permission to create or edit
    drafts on other people's review requests, but we had some
    inconsistencies that made the experience less than desirable:

    • The vast majority of the time, users with privileges really just want
      to operate as if they were a normal user doing reviews. Seeing the
      draft data was annoying in this case.
    • Loading the diff attached to a draft would fail. We'd happily send the
      user the diff context, but the diff fragment view was not properly
      loading the draft, and would return 404s.
    • It was not clear at all that the admin user was seeing draft data.
      Even as someone who has been using Review Board for all of its
      existence, I frequently got confused.

    This change makes a huge improvement to the user experience here. When
    loading a review request, privileged users will see the published data
    rather than the draft, but the unified banner will have a note that
    there's an unpublished draft, with a link to reload the page with a new
    ?view-draft=1 parameter. When viewing the draft, that note tells them
    that they're viewing a draft on a review request owned by another user,
    and gives them a link to go back to the public data.

    In cases where there is no public data to go back to (for example,
    viewing a review request which has never been published, or a file
    attachment which only exists on the draft), the notice is shown to the
    user but there's no link in the banner.

    This ends up adding three new pieces of data to the reviewable page
    context:

    • user_draft_exists will be True if the review request is owned by
      another user but there exists a draft which is accessible by the
      person viewing the page.
    • viewing_user_draft will be True if the person viewing the page is
      currently viewing data which is contained in the draft. This will
      happen either if the current data is only available in the draft (such
      as an unpublished review request) or if they explicitly wanted to see
      it by including ?view-draft=1 in the URL.
    • force_view_user_draft will be True if the current page is only
      available in draft form, and we want to suppress the link to go back
      to published data.

    While adding those to the context, I've also moved more things into the
    make_review_request_context method in order to be more consistent
    about how stuff ends up in the ReviewRequestContext dict, since we
    were repeating ourselves a fair bit in each of the views that calls it.

    There's one major piece of implementation left to do. This does not yet
    change anything about the admin user actually making changes to the
    review request/draft data. Now that the admin user will see non-draft
    data by default, we will need some logic about what to do when they
    start making changes, especially in the case where there's already a
    draft present. This will be done in a separate change because this one
    is already way too big.

    There are also a couple of bugs I've discovered while implementing this,
    which will be fixed in their own changes.

    • Ran Python unit tests.
    • Ran JS unit tests.
    • Created review requests with various draft states and checked access
      from the owner user, an admin user, and a regular user. These draft
      states include unpublished review requests that include both diffs and
      file attachments, and draft updates to review requests that include
      new revisions of diffs, new file attachments, or new revisions of
      public file attachments.
    Summary ID
    Dramatically improve the experience for admins with other users' drafts.
    For a very long time, we've had an annoying situation with privileged users and drafts. Users who are admins or have the `can_edit_reviewrequest` privilege have permission to create or edit drafts on other people's review requests, but we had some inconsistencies that made the experience less than desirable: - The vast majority of the time, users with privileges really just want to operate as if they were a normal user doing reviews. Seeing the draft data was annoying in this case. - Loading the diff attached to a draft would fail. We'd happily send the user the diff context, but the diff fragment view was not properly loading the draft, and would return 404s. - It was not clear at all that the admin user was seeing draft data. Even as someone who has been using Review Board for all of its existence, I frequently got confused. This change makes a huge improvement to the user experience here. When loading a review request, privileged users will see the published data rather than the draft, but the unified banner will have a note that there's an unpublished draft, with a link to reload the page with a new `?view-draft=1` parameter. When viewing the draft, that note tells them that they're viewing a draft on a review request owned by another user, and gives them a link to go back to the public data. In cases where there is no public data to go back to (for example, viewing a review request which has never been published, or a file attachment which only exists on the draft), the notice is shown to the user but there's no link in the banner. This ends up adding three new pieces of data to the reviewable page context: * `user_draft_exists` will be `True` if the review request is owned by another user but there exists a draft which is accessible by the person viewing the page. * `viewing_user_draft` will be `True` if the person viewing the page is currently viewing data which is contained in the draft. This will happen either if the current data is only available in the draft (such as an unpublished review request) or if they explicitly wanted to see it by including `?view-draft=1` in the URL. * `force_view_user_draft` will be `True` if the current page is only available in draft form, and we want to suppress the link to go back to published data. While adding those to the context, I've also moved more things into the `make_review_request_context` method in order to be more consistent about how stuff ends up in the `ReviewRequestContext` dict, since we were repeating ourselves a fair bit in each of the views that calls it. There's one major piece of implementation left to do. This does not yet change anything about the admin user actually making changes to the review request/draft data. Now that the admin user will see non-draft data by default, we will need some logic about what to do when they start making changes, especially in the case where there's already a draft present. This will be done in a separate change because this one is already way too big. There are also a couple of bugs I've discovered while implementing this, which will be fixed in their own changes. Testing Done: - Ran Python unit tests. - Ran JS unit tests. - Created review requests with various draft states and checked access from the owner user, an admin user, and a regular user. These draft states include unpublished review requests that include both diffs and file attachments, and draft updates to review requests that include new revisions of diffs, new file attachments, or new revisions of public file attachments. Fixes bugs 4659 and 4770.
    7068b1886f96b2e8cb850c810be9b3dbc49fc3d8

    Description From Last Updated

    I feel like a different banner colour here would be nicer, make it stand out more. Maybe ink-p-accent-info-bg or ink-p-accent-highlight-bg?

    maubin maubin

    Can you update this bottom border colour to match the new banner colour (--ink-p-accent-info-border-color)

    maubin maubin

    continuation line unaligned for hanging indent Column: 5 Error code: E131

    reviewbot reviewbot

    continuation line unaligned for hanging indent Column: 5 Error code: E131

    reviewbot reviewbot

    continuation line unaligned for hanging indent Column: 5 Error code: E131

    reviewbot reviewbot

    line too long (80 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (80 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (83 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    continuation line missing indentation or outdented Column: 13 Error code: E122

    reviewbot reviewbot

    line too long (86 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (80 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    missing whitespace around operator Column: 30 Error code: E225

    reviewbot reviewbot

    undefined name 'Diffset' Column: 33 Error code: F821

    reviewbot reviewbot

    Should we also do an admin check here? I know that we do checks later so that when a regular …

    maubin maubin

    To reduce the number of lines and code repetition, you could turn this into a function that takes context, draft, …

    maubin maubin

    For TypedDicts elsewhere, we've been making sure new fields have the Version Added directly.

    chipx86 chipx86

    I don't see anything replacing this variable.

    chipx86 chipx86

    These need to be explicitly typed as bool or they can end up as Literal[False].

    chipx86 chipx86

    Can we use keyword arguments for this?

    chipx86 chipx86

    Can we make these keyword-only?

    chipx86 chipx86

    Just a suggestion, but maybe move all of these inside an if draft, so that there's only one False code …

    chipx86 chipx86

    We check this in a couple of places. It might be nice to have a function somewhere that just wraps …

    chipx86 chipx86

    Version Added?

    chipx86 chipx86

    Version Added?

    chipx86 chipx86

    To keep tests speedy, let's fetch these at once. We can do: users = User.objects.in_bulk( ['doc', 'grumpy', 'admin', 'dopey'], field_name='username') …

    chipx86 chipx86

    Since this is a private method, it should go after the public methods.

    chipx86 chipx86

    """ should be on the next line. Same with the other tests below.

    chipx86 chipx86

    Rather than the cast every time, maybe the util function should just take a dictionary and then check for the …

    chipx86 chipx86

    Needs a Version Added.

    chipx86 chipx86

    Needs Version Added.

    chipx86 chipx86

    Needs Version Added.

    chipx86 chipx86

    Needs a Version Added.

    chipx86 chipx86

    We have model locally, so we can use that.

    chipx86 chipx86

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot
    Checks run (1 failed, 1 succeeded)
    flake8 failed.
    JSHint passed.

    flake8

    david
    Review request changed
    Commits:
    Summary ID
    Dramatically improve the experience for admins with other users' drafts.
    For a very long time, we've had an annoying situation with privileged users and drafts. Users who are admins or have the `can_edit_reviewrequest` privilege have permission to create or edit drafts on other people's review requests, but we had some inconsistencies that made the experience less than desirable: - The vast majority of the time, users with privileges really just want to operate as if they were a normal user doing reviews. Seeing the draft data was annoying in this case. - Loading the diff attached to a draft would fail. We'd happily send the user the diff context, but the diff fragment view was not properly loading the draft, and would return 404s. - It was not clear at all that the admin user was seeing draft data. Even as someone who has been using Review Board for all of its existence, I frequently got confused. This change makes a huge improvement to the user experience here. When loading a review request, privileged users will see the published data rather than the draft, but the unified banner will have a note that there's an unpublished draft, with a link to reload the page with a new `?view-draft=1` parameter. When viewing the draft, that note tells them that they're viewing a draft on a review request owned by another user, and gives them a link to go back to the public data. In cases where there is no public data to go back to (for example, viewing a review request which has never been published, or a file attachment which only exists on the draft), the notice is shown to the user but there's no link in the banner. This ends up adding three new pieces of data to the reviewable page context: * `user_draft_exists` will be `True` if the review request is owned by another user but there exists a draft which is accessible by the person viewing the page. * `viewing_user_draft` will be `True` if the person viewing the page is currently viewing data which is contained in the draft. This will happen either if the current data is only available in the draft (such as an unpublished review request) or if they explicitly wanted to see it by including `?view-draft=1` in the URL. * `force_view_user_draft` will be `True` if the current page is only available in draft form, and we want to suppress the link to go back to published data. While adding those to the context, I've also moved more things into the `make_review_request_context` method in order to be more consistent about how stuff ends up in the `ReviewRequestContext` dict, since we were repeating ourselves a fair bit in each of the views that calls it. There's one major piece of implementation left to do. This does not yet change anything about the admin user actually making changes to the review request/draft data. Now that the admin user will see non-draft data by default, we will need some logic about what to do when they start making changes, especially in the case where there's already a draft present. This will be done in a separate change because this one is already way too big. There are also a couple of bugs I've discovered while implementing this, which will be fixed in their own changes. Testing Done: - Ran Python unit tests. - Ran JS unit tests. - Created review requests with various draft states and checked access from the owner user, an admin user, and a regular user. These draft states include unpublished review requests that include both diffs and file attachments, and draft updates to review requests that include new revisions of diffs, new file attachments, or new revisions of public file attachments.
    355e48fae8a2c941e5812d2f1d1c786b9e340a81
    Dramatically improve the experience for admins with other users' drafts.
    For a very long time, we've had an annoying situation with privileged users and drafts. Users who are admins or have the `can_edit_reviewrequest` privilege have permission to create or edit drafts on other people's review requests, but we had some inconsistencies that made the experience less than desirable: - The vast majority of the time, users with privileges really just want to operate as if they were a normal user doing reviews. Seeing the draft data was annoying in this case. - Loading the diff attached to a draft would fail. We'd happily send the user the diff context, but the diff fragment view was not properly loading the draft, and would return 404s. - It was not clear at all that the admin user was seeing draft data. Even as someone who has been using Review Board for all of its existence, I frequently got confused. This change makes a huge improvement to the user experience here. When loading a review request, privileged users will see the published data rather than the draft, but the unified banner will have a note that there's an unpublished draft, with a link to reload the page with a new `?view-draft=1` parameter. When viewing the draft, that note tells them that they're viewing a draft on a review request owned by another user, and gives them a link to go back to the public data. In cases where there is no public data to go back to (for example, viewing a review request which has never been published, or a file attachment which only exists on the draft), the notice is shown to the user but there's no link in the banner. This ends up adding three new pieces of data to the reviewable page context: * `user_draft_exists` will be `True` if the review request is owned by another user but there exists a draft which is accessible by the person viewing the page. * `viewing_user_draft` will be `True` if the person viewing the page is currently viewing data which is contained in the draft. This will happen either if the current data is only available in the draft (such as an unpublished review request) or if they explicitly wanted to see it by including `?view-draft=1` in the URL. * `force_view_user_draft` will be `True` if the current page is only available in draft form, and we want to suppress the link to go back to published data. While adding those to the context, I've also moved more things into the `make_review_request_context` method in order to be more consistent about how stuff ends up in the `ReviewRequestContext` dict, since we were repeating ourselves a fair bit in each of the views that calls it. There's one major piece of implementation left to do. This does not yet change anything about the admin user actually making changes to the review request/draft data. Now that the admin user will see non-draft data by default, we will need some logic about what to do when they start making changes, especially in the case where there's already a draft present. This will be done in a separate change because this one is already way too big. There are also a couple of bugs I've discovered while implementing this, which will be fixed in their own changes. Testing Done: - Ran Python unit tests. - Ran JS unit tests. - Created review requests with various draft states and checked access from the owner user, an admin user, and a regular user. These draft states include unpublished review requests that include both diffs and file attachments, and draft updates to review requests that include new revisions of diffs, new file attachments, or new revisions of public file attachments.
    b316920b0740112d1aef2b697cd63c0105bbcfa1

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    david
    maubin
    1. 
        
    2. Show all issues

      I feel like a different banner colour here would be nicer, make it stand out more. Maybe ink-p-accent-info-bg or ink-p-accent-highlight-bg?

    3. reviewboard/reviews/context.py (Diff revision 3)
       
       
       
       
      Show all issues

      Should we also do an admin check here? I know that we do checks later so that when a regular user actually tries to view someone's draft, they can't. But if a caller were to use this function and assume these were the only checks to be done, it would lead to the problem where regular users can see everyone's drafts. Either we do an admin check here too, or say in the docs that this does not check for whether the user has admin permissions.

      1. The access control happens in review_request.get_draft(). I don't think it's helpful to do it twice.

    4. reviewboard/reviews/tests/test_other_user_drafts.py (Diff revision 3)
       
       
       
       
       
       
       
       
      Show all issues

      To reduce the number of lines and code repetition, you could turn this into a function that takes context, draft, mutable_by_user, force_view_user_draft, and etc as arguments. Can default all of the booleans to False and then for each test pass in True when needed.

      I've done this in the past and I know its a bit tedious to switch everything over :p but makes for much cleaner code, and if you ever have to add any new assertions, you only need to do it in one spot instead of having to repeat it for each unit test.

    5. 
        
    david
    maubin
    1. 
        
    2. Show all issues

      Can you update this bottom border colour to match the new banner colour (--ink-p-accent-info-border-color)

      1. Unfortunately this border is owned by the unified banner, not this notice.

    3. 
        
    david
    david
    david
    maubin
    1. I still wish that we could fix the bottom border of the banner to match the new colour somehow, but other than that looks good.

      Maybe in a separate change we could add some flag to the unified banner whenever this unpublished draft banner is present, and use that to change the bottom border colour?

      1. We could opportunistically do it with a :has(...) CSS rule. Since it's pure style and not important for layout, it'd be safe.

    2. 
        
    chipx86
    1. 
        
    2. reviewboard/reviews/context.py (Diff revision 5)
       
       
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      For TypedDicts elsewhere, we've been making sure new fields have the Version Added directly.

    3. reviewboard/reviews/context.py (Diff revision 5)
       
       
       
      Show all issues

      I don't see anything replacing this variable.

      1. This wasn't used anywhere. I think it's a relic from long before we had the review request fields abstraction.

    4. reviewboard/reviews/context.py (Diff revision 5)
       
       
       
      Show all issues

      These need to be explicitly typed as bool or they can end up as Literal[False].

    5. reviewboard/reviews/context.py (Diff revision 5)
       
       
      Show all issues

      Can we use keyword arguments for this?

    6. reviewboard/reviews/context.py (Diff revision 5)
       
       
       
       
      Show all issues

      Can we make these keyword-only?

    7. reviewboard/reviews/context.py (Diff revision 5)
       
       
       
       
       
       
       
      Show all issues

      Just a suggestion, but maybe move all of these inside an if draft, so that there's only one False code path?

    8. reviewboard/reviews/detail.py (Diff revision 5)
       
       
      Show all issues

      We check this in a couple of places. It might be nice to have a function somewhere that just wraps this, so the logic never differs anywhere.

      1. Turns out this code was just left over from before I added the should_view_draft method.

    9. Show all issues

      Version Added?

    10. Show all issues

      Version Added?

      1. I don't see the point of adding those for test code.

      2. Not super important, just we've been doing that so far with new test files and classes. Mostly it's just useful when we have to figure out when things were introduced, more than anything.

    11. reviewboard/reviews/tests/test_other_user_drafts.py (Diff revision 5)
       
       
       
       
       
      Show all issues

      To keep tests speedy, let's fetch these at once.

      We can do:

      users = User.objects.in_bulk(
          ['doc', 'grumpy', 'admin', 'dopey'],
          field_name='username')
      

      And then either just use that or we can assign each via a lookup in the dictionary.

    12. Show all issues

      Since this is a private method, it should go after the public methods.

    13. Show all issues

      """ should be on the next line.

      Same with the other tests below.

    14. Show all issues

      Rather than the cast every time, maybe the util function should just take a dictionary and then check for the appropriate keys.

      1. cast is a no-op, and is purely a hint for type checkers.

      2. Yeah, it's just noisy to have to repeat it everywhere. I don't feel strongly.

    15. Show all issues

      Needs a Version Added.

    16. reviewboard/static/rb/js/reviews/models/reviewRequestEditorModel.ts (Diff revision 5)
       
       
       
       
       
       
       
       
       
       
       
      Show all issues

      Needs Version Added.

    17. Show all issues

      Needs Version Added.

    18. Show all issues

      Needs a Version Added.

    19. Show all issues

      We have model locally, so we can use that.

    20. 
        
    david
    Review request changed
    Commits:
    Summary ID
    Dramatically improve the experience for admins with other users' drafts.
    For a very long time, we've had an annoying situation with privileged users and drafts. Users who are admins or have the `can_edit_reviewrequest` privilege have permission to create or edit drafts on other people's review requests, but we had some inconsistencies that made the experience less than desirable: - The vast majority of the time, users with privileges really just want to operate as if they were a normal user doing reviews. Seeing the draft data was annoying in this case. - Loading the diff attached to a draft would fail. We'd happily send the user the diff context, but the diff fragment view was not properly loading the draft, and would return 404s. - It was not clear at all that the admin user was seeing draft data. Even as someone who has been using Review Board for all of its existence, I frequently got confused. This change makes a huge improvement to the user experience here. When loading a review request, privileged users will see the published data rather than the draft, but the unified banner will have a note that there's an unpublished draft, with a link to reload the page with a new `?view-draft=1` parameter. When viewing the draft, that note tells them that they're viewing a draft on a review request owned by another user, and gives them a link to go back to the public data. In cases where there is no public data to go back to (for example, viewing a review request which has never been published, or a file attachment which only exists on the draft), the notice is shown to the user but there's no link in the banner. This ends up adding three new pieces of data to the reviewable page context: * `user_draft_exists` will be `True` if the review request is owned by another user but there exists a draft which is accessible by the person viewing the page. * `viewing_user_draft` will be `True` if the person viewing the page is currently viewing data which is contained in the draft. This will happen either if the current data is only available in the draft (such as an unpublished review request) or if they explicitly wanted to see it by including `?view-draft=1` in the URL. * `force_view_user_draft` will be `True` if the current page is only available in draft form, and we want to suppress the link to go back to published data. While adding those to the context, I've also moved more things into the `make_review_request_context` method in order to be more consistent about how stuff ends up in the `ReviewRequestContext` dict, since we were repeating ourselves a fair bit in each of the views that calls it. There's one major piece of implementation left to do. This does not yet change anything about the admin user actually making changes to the review request/draft data. Now that the admin user will see non-draft data by default, we will need some logic about what to do when they start making changes, especially in the case where there's already a draft present. This will be done in a separate change because this one is already way too big. There are also a couple of bugs I've discovered while implementing this, which will be fixed in their own changes. Testing Done: - Ran Python unit tests. - Ran JS unit tests. - Created review requests with various draft states and checked access from the owner user, an admin user, and a regular user. These draft states include unpublished review requests that include both diffs and file attachments, and draft updates to review requests that include new revisions of diffs, new file attachments, or new revisions of public file attachments.
    04149ed84208e48038ad2b8ad49291a667ca6bd8
    Dramatically improve the experience for admins with other users' drafts.
    For a very long time, we've had an annoying situation with privileged users and drafts. Users who are admins or have the `can_edit_reviewrequest` privilege have permission to create or edit drafts on other people's review requests, but we had some inconsistencies that made the experience less than desirable: - The vast majority of the time, users with privileges really just want to operate as if they were a normal user doing reviews. Seeing the draft data was annoying in this case. - Loading the diff attached to a draft would fail. We'd happily send the user the diff context, but the diff fragment view was not properly loading the draft, and would return 404s. - It was not clear at all that the admin user was seeing draft data. Even as someone who has been using Review Board for all of its existence, I frequently got confused. This change makes a huge improvement to the user experience here. When loading a review request, privileged users will see the published data rather than the draft, but the unified banner will have a note that there's an unpublished draft, with a link to reload the page with a new `?view-draft=1` parameter. When viewing the draft, that note tells them that they're viewing a draft on a review request owned by another user, and gives them a link to go back to the public data. In cases where there is no public data to go back to (for example, viewing a review request which has never been published, or a file attachment which only exists on the draft), the notice is shown to the user but there's no link in the banner. This ends up adding three new pieces of data to the reviewable page context: * `user_draft_exists` will be `True` if the review request is owned by another user but there exists a draft which is accessible by the person viewing the page. * `viewing_user_draft` will be `True` if the person viewing the page is currently viewing data which is contained in the draft. This will happen either if the current data is only available in the draft (such as an unpublished review request) or if they explicitly wanted to see it by including `?view-draft=1` in the URL. * `force_view_user_draft` will be `True` if the current page is only available in draft form, and we want to suppress the link to go back to published data. While adding those to the context, I've also moved more things into the `make_review_request_context` method in order to be more consistent about how stuff ends up in the `ReviewRequestContext` dict, since we were repeating ourselves a fair bit in each of the views that calls it. There's one major piece of implementation left to do. This does not yet change anything about the admin user actually making changes to the review request/draft data. Now that the admin user will see non-draft data by default, we will need some logic about what to do when they start making changes, especially in the case where there's already a draft present. This will be done in a separate change because this one is already way too big. There are also a couple of bugs I've discovered while implementing this, which will be fixed in their own changes. Testing Done: - Ran Python unit tests. - Ran JS unit tests. - Created review requests with various draft states and checked access from the owner user, an admin user, and a regular user. These draft states include unpublished review requests that include both diffs and file attachments, and draft updates to review requests that include new revisions of diffs, new file attachments, or new revisions of public file attachments. Fixes bugs 4659 and 4770.
    64d2e05d92ee127610054c95cee76fd839671f52

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    david
    chipx86
    1. Ship It!
    2. 
        
    david
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to release-7.x (f695895)