Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Image Drag & Drop Cross-Wiring in Edit Comment Form #8897

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
63d200c
add test for comment image crosswiring
noi5e Dec 27, 2020
f34bc6b
wrap everything in comment-form-wrapper, assign .selected in drop lis…
noi5e Dec 29, 2020
68f820c
delete defunct function, fix indentation & spacing #8670
noi5e Dec 29, 2020
9814c32
rewrite tests that rely on comment-form-wrapper
noi5e Dec 29, 2020
2892710
remove deprecated code, comments; fix indent
noi5e Dec 30, 2020
24589fa
initialize on pageload (#8670)
noi5e Dec 30, 2020
fc8b950
rewrite for multiple file inputs
noi5e Dec 30, 2020
5a6a114
change test to focus on image drag & drop #8670
noi5e Dec 30, 2020
b9b8182
Merge branch 'main' into bug/edit-comment-select-image-crosswiring
noi5e Jan 6, 2021
5972fe8
restore E.initialize call in drop #8670
noi5e Jan 6, 2021
540f112
undo E.initialize call #8670
noi5e Jan 6, 2021
43139a4
assign unique IDs to comment form textareas #8670
noi5e Jan 7, 2021
5e1baea
change ID selectors to class ones to match new IDs #8670
noi5e Jan 7, 2021
20017fb
fix indentation #8670
noi5e Jan 7, 2021
bd6d4ef
change ID reference to class reference #8670
noi5e Jan 7, 2021
3a7a213
initialize E with parameters in drop listener #8670
noi5e Jan 7, 2021
5adc893
update tests for new text-input selectors #8670
noi5e Jan 7, 2021
f095373
Merge branch 'main' into bug/edit-comment-select-image-crosswiring
noi5e Jan 7, 2021
8eece2e
change ID text-input reference to class ref #8670
noi5e Jan 8, 2021
3ad1a7d
change text-input ID to class #8670
noi5e Jan 8, 2021
364beba
drop: initialize E with params #8670
noi5e Jan 8, 2021
8e67269
Merge remote-tracking branch 'origin/bug/edit-comment-select-image-cr…
noi5e Jan 8, 2021
42f2e05
remove semicolon
noi5e Jan 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 141 additions & 141 deletions app/views/comments/_edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,153 +1,153 @@
<div class="card card-body bg-light">
<form method="post" id="c<%= comment.id %>edit" style="display:none;" class="well" <% if comment.is_a?Answer %> action= "/answers/update/<%= comment.id %>" <% else %> action="/comment/update/<%= comment.id %>" <% end %>>
<div class="comment-form-wrapper">
<div class="card card-body bg-light">
<form method="post" id="c<%= comment.id %>edit" style="display:none;" class="well" <% if comment.is_a?Answer %> action= "/answers/update/<%= comment.id %>" <% else %> action="/comment/update/<%= comment.id %>" <% end %>>

<h4 style="margin-top:0;"><%= title %></h4>
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
<h4 style="margin-top:0;"><%= title %></h4>
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">

<style>
#imagebar {width:100%;}
</style>
<style>
#imagebar {width:100%;}
</style>


<%= render :partial => "editor/toolbar" %>

<div id="c<%= comment.id%>div" class="form-group">
<textarea aria-label="Edit Comment" onFocus="editing=true" name="body" class="form-control" id="c<%= comment.id%>text" rows="6" cols="40" placeholder="<%= placeholder %>"><%= !(comment.is_a?Answer) ? comment.comment : comment.content %></textarea>
<%= render :partial => "editor/toolbar" %>
<div id="c<%= comment.id%>div" class="form-group">
<textarea aria-label="Edit Comment" onFocus="editing=true" name="body" class="form-control" id="c<%= comment.id%>text" rows="6" cols="40" placeholder="<%= placeholder %>"><%= !(comment.is_a?Answer) ? comment.comment : comment.content %></textarea>

<div id="imagebar">
<div id="c<%= comment.id%>progress" style="display:none;" class="progress progress-striped active pull-right">
<div id="c<%= comment.id%>progress-bar" class="progress-bar" style="width: 0%;"></div>
</div>

<p>
<span id="c<%= comment.id%>uploading" class="uploading" style="display:none;">
<%= translation('comments._edit.uploading') %>
</span>
<span id="c<%= comment.id%>prompt" class="prompt">
<div id="imagebar">
<div id="c<%= comment.id%>progress" style="display:none;" class="progress progress-striped active pull-right">
<div id="c<%= comment.id%>progress-bar" class="progress-bar" style="width: 0%;"></div>
</div>

<span style="padding-right:4px;float:left;" class="hidden-xs">
<%= raw translation('comments._edit.drag_and_drop') %>
<p>
<span id="c<%= comment.id%>uploading" class="uploading" style="display:none;">
<%= translation('comments._edit.uploading') %>
</span>

<label id="c<%= comment.id%>input_label" for="c<%= comment.id%>input">
<input id="c<%= comment.id%>input" type="file" name="image[photo]" style="display:none;" />
<a class="hidden-xs"><%= translation('comments._edit.choose_one') %></a>
<span class="visible-xs">
<i class="fa fa-upload"></i>
<a><%= translation('comments._edit.upload_image') %></a>
<span id="c<%= comment.id%>prompt" class="prompt">
<span style="padding-right:4px;float:left;" class="hidden-xs">
<%= raw translation('comments._edit.drag_and_drop') %>
</span>
</label>

</span>
</p>
<label id="c<%= comment.id%>input_label" for="c<%= comment.id%>input">
<input id="c<%= comment.id%>input" type="file" name="image[photo]" style="display:none;" />
<a class="hidden-xs"><%= translation('comments._edit.choose_one') %></a>
<span class="visible-xs">
<i class="fa fa-upload"></i>
<a><%= translation('comments._edit.upload_image') %></a>
</span>
</label>
</span>
</p>
</div>
</div>
</div>
<script type="application/javascript">
jQuery(document).ready(function() {
$E.initialize();
});

function setInit(id) {
var args = {
'textarea': 'c'+id+'text',
'preview': 'c'+id+'preview'
}
$E.initialize(args);
}

$('#c<%= comment.id%>div').bind('dragover',function(e) {
e.preventDefault();
$('#c<%= comment.id%>div').addClass('hover');
});

$('#c<%= comment.id%>div').bind('dragout',function(e) {
$('#c<%= comment.id%>div').removeClass('hover');
});

$('#c<%= comment.id%>div').bind('drop',function(e) {
e.preventDefault();
setInit(<%= comment.id %>);
});

$('#c<%= comment.id%>div').fileupload({
url: "/images",
paramName: "image[photo]",
dropZone: $('#c<%= comment.id%>div'),
dataType: 'json',
formData: {
'uid':<%= current_user.uid %>,
'nid':<%= comment.uid %>
},
start: function(e) {
$('#c<%= comment.id%>progress').show()
$('#c<%= comment.id%>uploading').show()
$('#c<%= comment.id%>prompt').hide()
<script type="application/javascript">
jQuery(document).ready(function() {
$E.initialize();
});

function setInit(id) {
var args = {
'textarea': 'c'+id+'text',
'preview': 'c'+id+'preview'
}
$E.initialize(args);
}

$('#c<%= comment.id%>div').bind('dragover',function(e) {
e.preventDefault();
$('#c<%= comment.id%>div').addClass('hover');
});

$('#c<%= comment.id%>div').bind('dragout',function(e) {
$('#c<%= comment.id%>div').removeClass('hover');
},
done: function (e, data) {
$('#c<%= comment.id%>progress').hide()
$('#c<%= comment.id%>uploading').hide()
$('#c<%= comment.id%>prompt').show()
var is_image = false
if (data.result['filename'].substr(-3,3) == "jpg") is_image = true
if (data.result['filename'].substr(-4,4) == "jpeg") is_image = true
if (data.result['filename'].substr(-3,3) == "png") is_image = true
if (data.result['filename'].substr(-3,3) == "gif") is_image = true
if (data.result['filename'].substr(-3,3) == "JPG") is_image = true
if (data.result['filename'].substr(-4,4) == "JPEG") is_image = true
if (data.result['filename'].substr(-3,3) == "PNG") is_image = true
if (data.result['filename'].substr(-3,3) == "GIF") is_image = true

if (is_image) {
image_url = data.result.url.split('?')[0];
orig_image_url = image_url.replace('medium','original');
$E.wrap('[![',']('+image_url+')]('+orig_image_url+')', {'newline': true, 'fallback': data.result['filename']});
} else {
$E.wrap('<a href="'+data.result.url.split('?')[0]+'"><i class="fa fa-file"></i> ','</a>', {'newline': true, 'fallback': data.result['filename']});
});

$('#c<%= comment.id%>div').bind('drop',function(e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here bind is working? Or should we use ‘on’

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right! I believe bind has been working here, but it is deprecated and should be changed.

I changed it in dragdrop.js, but I'll change these ones soon... Just want to get this PR ready to merge first.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good we can consider this in a separate PR! good catch @Sagarpreet!!

e.preventDefault();
$D.selected = $(e.target).closest('div.comment-form-wrapper').eq(0);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice this additional line!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrapped everything in _edit.html.erb in a div.comment-form-wrapper.

The other major change is that now $D.selected is assigned in this eventListener bound to #c1div.

A major part of the drag-and-drop crosswiring is fixed. My tests (including the new one I wrote for this issue) are passing. I had to rewrite some of the system tests in this most recent push: 'edit comment' and 'delete comment' rely on .comment-form-wrapper for some reason.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, the tests aren't passing. I'll take a closer look tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is awesome

setInit(<%= comment.id %>);
});

$('#c<%= comment.id%>div').fileupload({
url: "/images",
paramName: "image[photo]",
dropZone: $('#c<%= comment.id%>div'),
dataType: 'json',
formData: {
'uid':<%= current_user.uid %>,
'nid':<%= comment.uid %>
},
start: function(e) {
$('#c<%= comment.id%>progress').show()
$('#c<%= comment.id%>uploading').show()
$('#c<%= comment.id%>prompt').hide()
$('#c<%= comment.id%>div').removeClass('hover');
},
done: function (e, data) {
$('#c<%= comment.id%>progress').hide()
$('#c<%= comment.id%>uploading').hide()
$('#c<%= comment.id%>prompt').show()
var is_image = false
if (data.result['filename'].substr(-3,3) == "jpg") is_image = true
if (data.result['filename'].substr(-4,4) == "jpeg") is_image = true
if (data.result['filename'].substr(-3,3) == "png") is_image = true
if (data.result['filename'].substr(-3,3) == "gif") is_image = true
if (data.result['filename'].substr(-3,3) == "JPG") is_image = true
if (data.result['filename'].substr(-4,4) == "JPEG") is_image = true
if (data.result['filename'].substr(-3,3) == "PNG") is_image = true
if (data.result['filename'].substr(-3,3) == "GIF") is_image = true

if (is_image) {
image_url = data.result.url.split('?')[0];
orig_image_url = image_url.replace('medium','original');
$E.wrap('[![',']('+image_url+')]('+orig_image_url+')', {'newline': true, 'fallback': data.result['filename']});
} else {
$E.wrap('<a href="'+data.result.url.split('?')[0]+'"><i class="fa fa-file"></i> ','</a>', {'newline': true, 'fallback': data.result['filename']});
}

if ($('#node_images').val() && $('#node_images').val().split(',').length > 1) $('#node_images').val([$('#node_images').val(),data.result.id].join(','));
else $('#node_images').val(data.result.id)
},

fileuploadfail: function(e,data) {},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#c<%= comment.id%>progress #c<%= comment.id%>progress-bar').css(
'width',
progress + '%'
);
}
});
</script>

if ($('#node_images').val() && $('#node_images').val().split(',').length > 1) $('#node_images').val([$('#node_images').val(),data.result.id].join(','));
else $('#node_images').val(data.result.id)
},

fileuploadfail: function(e,data) {},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#c<%= comment.id%>progress #c<%= comment.id%>progress-bar').css(
'width',
progress + '%'
);
}
});
</script>

<div class="well col-md-11" id="c<%= comment.id %>preview" style="background:white;display: none">
</div>

<div class="control-group">
<button type="submit" class="btn btn-primary"><%= translation('comments._edit.publish') %></button>
<a class="btn btn-default preview-btn" data-previewing-text="Hide Preview"
onClick="$('#c<%= comment.id %>preview').toggle();
$('#c<%= comment.id %>text').toggle();
$('#c<%= comment.id %>text').next('#imagebar').toggle();
this.previewing = !this.previewing;
$('#c<%= comment.id %>edit .preview-btn').button(this.previewing ? 'previewing' : 'reset');
$E.generate_preview('c<%= comment.id %>preview',$('#c<%= comment.id %>text').val())">
Preview
</a>
<a class="btn btn-default" onClick="$('#c<%= comment.id %>show').toggle();$('#c<%= comment.id %>edit').toggle()">
Cancel
</a>

<span class="form-grey"> &nbsp;
<br class="visible-xs" /><%= raw translation('comments._edit.logged_in', :username => current_user.username) %> |
<a target="_blank" href="/wiki/authoring-help#Formatting"><%= translation('comments._edit.formatting') %></a> |
<a onClick="$('#who-is-notified').toggle()"><%= translation('comments._edit.notifications') %></a>
</span>
</div>

<p id="who-is-notified" style="display:none;color:#888;">
<%= translation('comments._edit.email_notifications') %>
</p>
</form>
</div>
<div class="well col-md-11" id="c<%= comment.id %>preview" style="background:white;display: none">
</div>

<div class="control-group">
<button type="submit" class="btn btn-primary"><%= translation('comments._edit.publish') %></button>
<a class="btn btn-default preview-btn" data-previewing-text="Hide Preview"
onClick="$('#c<%= comment.id %>preview').toggle();
$('#c<%= comment.id %>text').toggle();
$('#c<%= comment.id %>text').next('#imagebar').toggle();
this.previewing = !this.previewing;
$('#c<%= comment.id %>edit .preview-btn').button(this.previewing ? 'previewing' : 'reset');
$E.generate_preview('c<%= comment.id %>preview',$('#c<%= comment.id %>text').val())">
Preview
</a>
<a class="btn btn-default" onClick="$('#c<%= comment.id %>show').toggle();$('#c<%= comment.id %>edit').toggle()">
Cancel
</a>

<span class="form-grey"> &nbsp;
<br class="visible-xs" /><%= raw translation('comments._edit.logged_in', :username => current_user.username) %> |
<a target="_blank" href="/wiki/authoring-help#Formatting"><%= translation('comments._edit.formatting') %></a> |
<a onClick="$('#who-is-notified').toggle()"><%= translation('comments._edit.notifications') %></a>
</span>
</div>

<p id="who-is-notified" style="display:none;color:#888;">
<%= translation('comments._edit.email_notifications') %>
</p>
</form>
</div>
</div>
56 changes: 56 additions & 0 deletions test/system/comment_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,62 @@ def setup
page.assert_selector('#preview img', count: 1)
end

# bugs can occur if we upload an image to the main comment form, and then try to upload an image into edit comment.
# the second image ends up in the main comment form, when it should end up in edit comment.
# so the two forms can get 'cross-wired.'
test "#{page_type_string}: check that edit form's select image upload isn't cross-wired with post comment form" do
node_name == :wiki_page ? (visit nodes(node_name).path + '/comments') : (visit nodes(node_name).path)

# post a fresh comment
# find the main comment form at the bottom of the page, and save for reuse
main_comment_form = page.find('h4', text: /Post comment|Post Comment/).find(:xpath, '..') # title text on wikis is 'Post comment'
# fill out the comment form
main_comment_form
.find('textarea')
.click
.fill_in with: comment_text
# publish
main_comment_form
.find('button', text: 'Publish')
.click
page.find(".noty_body", text: "Comment Added!")

# now we upload the images.
# the <inputs> that take image uploads are hidden, so reveal them for finder:
Capybara.ignore_hidden_elements = false

# we need to make the main comment form the focus by clicking on "Preview," then hiding preview.
# otherwise, image upload to main comment form will fail.
main_comment_form.find('a', text: 'Preview').click.click
# upload an image in the main comment form
main_comment_form.all('#fileinput')[1].set("#{Rails.root.to_s}/public/images/pl.png")
wait_for_ajax

# we need the selector of the EDIT comment's #fileinput
# first find the parent comment ID:
comment_id = page.find('p', text: comment_text).find(:xpath, '..')[:id]
# regex to strip the ID number out of string. ID format is comment-body-4231
comment_id_num = /comment-body-(\d+)/.match(comment_id)[1]
# this is the ID of the edit form:
edit_form_id = '#c' + comment_id_num + 'edit'
edit_image_selector = edit_form_id + ' #fileinput'

# open the edit comment form:
find("#edit-comment-btn").click
# upload an image in the edit comment form:
file_input_element = page.find(edit_image_selector)
file_input_element.set("#{Rails.root.to_s}/public/images/pl.png")
wait_for_ajax
Capybara.ignore_hidden_elements = true

# open the preview for the main comment form
main_comment_form.find('a', text: 'Preview').click
# once preview is open, the images are embedded in the page.
# there should only be 1 image in the main comment form!
preview_imgs = page.all('#preview img').size
assert_equal(1, preview_imgs)
end

test "#{page_type_string}: ctrl/cmd + enter comment publishing keyboard shortcut" do
node_name == :wiki_page ? (visit nodes(node_name).path + '/comments') : (visit nodes(node_name).path)
find("p", text: "Reply to this comment...").click()
Expand Down