diff --git a/hypha/apply/activity/templates/activity/include/listing_base.html b/hypha/apply/activity/templates/activity/include/listing_base.html index ff5e7d815ddf3cb7629883f0c302f8ef11976b64..19b0f9b598ceefc4ad98263ed18c618453cb2189 100644 --- a/hypha/apply/activity/templates/activity/include/listing_base.html +++ b/hypha/apply/activity/templates/activity/include/listing_base.html @@ -22,12 +22,10 @@ </p> {% endif %} - {% if activity.private %} - <p class="feed__meta-item feed__meta-item--right"> + <p class="feed__meta-item feed__meta-item--right" {% if not activity.private %} hidden {% endif %}> <svg class="icon icon--eye"><use xlink:href="#eye"></use></svg> - {{ activity.visibility }} + <span class="js-comment-visibility">{{ activity.visibility }}</span> </p> - {% endif %} </div> <p class="feed__heading"> @@ -36,7 +34,10 @@ {% endif %} {% if editable %} - <div class="feed__comment js-comment" data-id="{{activity.id}}" data-comment="{{activity|display_for:request.user|to_markdown}}" data-edit-url="{% url 'api:v1:comments:edit' pk=activity.pk %}"> + <div class="feed__comment js-comment" data-id="{{activity.id}}" data-comment="{{activity|display_for:request.user|to_markdown}}" + data-visibility-options="{{activity|visibility_options:activity.user}}" + data-visibility="{{activity.visibility}}" + data-edit-url="{% url 'api:v1:comments:edit' pk=activity.pk %}"> {{ activity|display_for:request.user|submission_links|markdown|bleach }} </div> diff --git a/hypha/apply/activity/templatetags/activity_tags.py b/hypha/apply/activity/templatetags/activity_tags.py index db7c6d4f28a0267203f699f2a55d0fc8c5d2bfe0..2df2a15d1c8c19f9020ff1f86e0bc93ac3e36fff 100644 --- a/hypha/apply/activity/templatetags/activity_tags.py +++ b/hypha/apply/activity/templatetags/activity_tags.py @@ -49,3 +49,9 @@ def display_for(activity, user): return message_data[TEAM] return message_data[ALL] + + +@register.filter +def visibility_options(activity, user): + choices = activity.visibility_choices_for(user) + return json.dumps(choices) diff --git a/hypha/apply/api/v1/serializers.py b/hypha/apply/api/v1/serializers.py index ba8ccc4530a85689f73cb742f45a1d493d43ecb2..8778d56b575e6e49f87275bb9b4d8deade44f253 100644 --- a/hypha/apply/api/v1/serializers.py +++ b/hypha/apply/api/v1/serializers.py @@ -232,4 +232,4 @@ class CommentCreateSerializer(serializers.ModelSerializer): class CommentEditSerializer(CommentCreateSerializer): class Meta(CommentCreateSerializer.Meta): - read_only_fields = ('timestamp', 'visibility', 'edited',) + read_only_fields = ('timestamp', 'edited',) diff --git a/hypha/apply/api/v1/tests/test_views.py b/hypha/apply/api/v1/tests/test_views.py index 07e356baffcbbdf31508f392be66bf0c924bfcad..a33947f1d98c39ed897785c269d3cd55fbdcb54e 100644 --- a/hypha/apply/api/v1/tests/test_views.py +++ b/hypha/apply/api/v1/tests/test_views.py @@ -44,15 +44,22 @@ class TestCommentEdit(TestCase): response = self.post_to_edit(10000) self.assertEqual(response.status_code, 403, response.json()) - def test_does_nothing_if_same_message(self): + def test_does_nothing_if_same_message_and_visibility(self): user = UserFactory() comment = CommentFactory(user=user) self.client.force_login(user) - self.post_to_edit(comment.pk, comment.message) + self.client.post( + reverse_lazy('api:v1:comments:edit', kwargs={'pk': comment.pk}), + secure=True, + data={ + 'message': comment.message, + 'visibility': comment.visibility, + }) + self.assertEqual(Activity.objects.count(), 1) - def test_cant_change_visibility(self): + def test_can_change_visibility(self): user = UserFactory() comment = CommentFactory(user=user, visibility=APPLICANT) self.client.force_login(user) @@ -67,7 +74,7 @@ class TestCommentEdit(TestCase): ) self.assertEqual(response.status_code, 200, response.json()) - self.assertEqual(response.json()['visibility'], APPLICANT) + self.assertEqual(response.json()['visibility'], ALL) def test_out_of_order_does_nothing(self): user = UserFactory() diff --git a/hypha/apply/api/v1/views.py b/hypha/apply/api/v1/views.py index 10785391db7c52ae8127595a24e1360b4dd6ae0e..e4b247cfb744fa2cf074badbb6d9d9b4f25da691 100644 --- a/hypha/apply/api/v1/views.py +++ b/hypha/apply/api/v1/views.py @@ -239,7 +239,7 @@ class CommentEdit( serializer = self.get_serializer(comment_to_edit, data=request.data) serializer.is_valid(raise_exception=True) - if serializer.validated_data['message'] != comment_to_update.message: + if (serializer.validated_data['message'] != comment_to_update.message) or (serializer.validated_data['visibility'] != comment_to_update.visibility): self.perform_create(serializer) comment_to_update.current = False comment_to_update.save() diff --git a/hypha/static_src/src/javascript/apply/edit-comment.js b/hypha/static_src/src/javascript/apply/edit-comment.js index 1153847edc52f19fd222ed7c4f079b7ad77a7b71..03cee852a5129b773cb8b8a0dec5279085d98477 100644 --- a/hypha/static_src/src/javascript/apply/edit-comment.js +++ b/hypha/static_src/src/javascript/apply/edit-comment.js @@ -7,6 +7,7 @@ const feedMeta = '.js-feed-meta'; const editBlock = '.js-edit-block'; const lastEdited = '.js-last-edited'; + const commentVisibility = '.js-comment-visibility'; const editButton = '.js-edit-comment'; const feedContent = '.js-feed-content'; const commentError = '.js-comment-error'; @@ -22,6 +23,8 @@ const editBlockWrapper = $(this).closest(feedContent).find(editBlock); const commentWrapper = $(this).closest(feedContent).find(comment); const commentContents = $(commentWrapper).attr('data-comment'); + const visibilityOptions = $.parseJSON($(commentWrapper).attr('data-visibility-options')); + const currentVisibility = $(commentWrapper).attr('data-visibility'); // hide the edit link and original comment $(this).parent().hide(); @@ -32,15 +35,36 @@ <div id="wmd-button-bar-edit-comment" class="wmd-button-bar"></div> <textarea id="wmd-input-edit-comment" class="wmd-input" rows="10">${commentContents}</textarea> <div id="wmd-preview-edit-comment" class="wmd-preview"></div> + <br> + <div>Visible to:</div> + </div> + `; + + const radioButtonsDiv = '<div id="edit-comment-visibility"></div>'; + let key = ''; + let label = ''; + let radioButtons = ''; + + $.each(visibilityOptions, function (idx, value) { + key = value[0]; + label = value[1]; + radioButtons += ` + <input type="radio" name='radio-visibility' value=${key} id='visible-to-${key}' /> + <label for="visible-to-${key}">${label}</label><br>`; + }); + + const buttons = ` <div class="wrapper--outer-space-medium"> <button class="button button--primary js-submit-edit" type="submit">Update</button> <button class="button button--white js-cancel-edit">Cancel</button> </div> - </div> `; // add the comment to the editor - $(editBlockWrapper).append(markup); + const markupEditor = $(markup).append(radioButtonsDiv).append(buttons); + $(editBlockWrapper).append(markupEditor); + $('#edit-comment-visibility').html(radioButtons); + $(`#visible-to-${currentVisibility}`).prop('checked', true); // ensure current visibility is checked // run the editor initEditor(); @@ -60,6 +84,7 @@ $(document).on('click', submitEditButton, function () { const commentContainer = $(this).closest(editBlock).siblings(comment); const editedComment = $(this).closest(pageDown).find('.wmd-preview').html(); + const editedVisibility = $('input[name="radio-visibility"]:checked').val(); const commentMD = $(this).closest(editBlock).find('textarea').val(); const editUrl = $(commentContainer).attr('data-edit-url'); @@ -70,7 +95,8 @@ 'X-CSRFToken': window.Cookies.get('csrftoken') }, body: JSON.stringify({ - message: editedComment + message: editedComment, + visibility: editedVisibility }) }).then(response => { if (!response.ok) { @@ -82,7 +108,8 @@ } return response.json(); }).then(data => { - updateComment(commentContainer, data.id, data.message, data.edit_url, commentMD); + updateComment(commentContainer, data.id, data.message, data.visibility, data.edit_url, commentMD); + updateVisibility(this, data.visibility); updateLastEdited(this, data.edited); showComment(this); showEditButton(this); @@ -120,6 +147,17 @@ $(el).closest(editBlock).siblings(comment).show(); }; + const updateVisibility = (el, visibility) => { + if (visibility !== 'all') { + $(el).closest(feedContent).find(commentVisibility).parent().attr('hidden', false); + $(el).closest(feedContent).find(commentVisibility).text(visibility); + } + else { + $(el).closest(feedContent).find(commentVisibility).parent().attr('hidden', true); + $(el).closest(feedContent).find(commentVisibility).html(`${visibility}`); + } + }; + const updateLastEdited = (el, date) => { const parsedDate = new Date(date).toISOString().split('T')[0]; const time = new Date(date).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'}); @@ -127,11 +165,12 @@ $(el).closest(feedContent).find(lastEdited).html(`${parsedDate} ${time}`); }; - const updateComment = (el, id, comment, editUrl, commentMarkdown) => { + const updateComment = (el, id, comment, visibility, editUrl, commentMarkdown) => { $(el).html(comment); $(el).attr('data-id', id); $(el).attr('data-edit-url', editUrl); $(el).attr('data-comment', commentMarkdown); + $(el).attr('data-visibility', visibility); }; const closeAllEditors = () => { diff --git a/hypha/static_src/src/sass/apply/components/_feed.scss b/hypha/static_src/src/sass/apply/components/_feed.scss index a16d9f5ee359adebbccfe5b72851c041ac34466a..3d195ae311176d11d658bcef2fa326beb1577f37 100644 --- a/hypha/static_src/src/sass/apply/components/_feed.scss +++ b/hypha/static_src/src/sass/apply/components/_feed.scss @@ -117,6 +117,10 @@ &--right { margin-left: auto; + + span { + font-weight: $weight--normal; + } } &--progress {