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

Refactor Comment Editor Save & Recover #9132

Merged
merged 15 commits into from
Feb 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 19 additions & 11 deletions app/assets/javascripts/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class Editor {
constructor(defaultForm = "main", elementIDPrefixes = {}) {
this.commentFormID = defaultForm;
this.elementIDPrefixes = elementIDPrefixes;
this.textarea = $("#text-input-" + this.commentFormID);
// this will get deleted in the next few PRs, so collapsing into one line to pass codeclimate
this.templates = { 'blog': "## The beginning\n\n## What we did\n\n## Why it matters\n\n## How can you help", 'default': "## What I want to do\n\n## My attempt and results\n\n## Questions and next steps\n\n## Why I'm interested", 'support': "## Details about the problem\n\n## A photo or screenshot of the setup", 'event': "## Event details\n\nWhen, where, what\n\n## Background\n\nWho, why", 'question': "## What I want to do or know\n\n## Background story" };

Expand All @@ -31,8 +30,7 @@ class Editor {
}
setState(commentFormID) {
this.commentFormID = commentFormID;
this.textarea = $("#text-input-" + commentFormID);
$E.textarea.bind('input propertychange', $E.save);
this.attachSaveListener();
}
get textAreaElement() {
const textAreaID = "#text-input-" + this.commentFormID;
Expand All @@ -50,13 +48,13 @@ class Editor {
const previewID = previewIDPrefix + this.commentFormID;
return $(previewID);
}
// wraps currently selected text in textarea with strings a and b
wrap(a, b, newlineDesired = false, fallback) {
// wraps currently selected text in textarea with strings startString & endString
wrap(startString, endString, newlineDesired = false, fallback) {
const selectionStart = this.textAreaElement[0].selectionStart;
const selectionEnd = this.textAreaElement[0].selectionEnd;
const selection = fallback || this.textAreaValue.substring(selectionStart, selectionEnd); // fallback if nothing has been selected, and we're simply dealing with an insertion point

let newText = newlineDesired ? a + selection + b + "\n\n" : a + selection + b; // ie. ** + selection + ** (wrapping selection in bold)
let newText = newlineDesired ? startString + selection + endString + "\n\n" : startString + selection + endString; // ie. ** + selection + ** (wrapping selection in bold)
const selectionStartsMidText = this.textAreaElement[0].selectionStart > 0;
if (newlineDesired && selectionStartsMidText) { newText = "\n" + newText; }

Expand Down Expand Up @@ -109,11 +107,21 @@ class Editor {
// this.wrap('#######','')
// }
// this function is dedicated to Don Blair https://github.com/donblair
save() {
localStorage.setItem('plots:lastpost', this.textAreaValue);
attachSaveListener() {
// remove any other existing eventHandler
$("textarea").off("input.save"); // input.save is a custom jQuery eventHandler
const thisEditor = this; // save a reference to this editor, because inside the eventListener, "this" points to e.target
this.textAreaElement.on("input.save", function() {
thisEditor.save(thisEditor)
});
}
save(thisEditor) {
const storageKey = "plots:" + window.location.pathname + ":" + thisEditor.commentFormID;
localStorage.setItem(storageKey, thisEditor.textAreaValue);
}
recover() {
this.textAreaElement.val(localStorage.getItem('plots:lastpost'));
const storageKey = "plots:" + window.location.pathname + ":" + this.commentFormID;
this.textAreaElement.val(localStorage.getItem(storageKey));
}
apply_template(template) {
if(this.textAreaValue == ""){
Expand All @@ -131,11 +139,11 @@ class Editor {
// if the element is part of a multi-comment page,
// ensure to grab the current element and not the other comment element.
const previewBtn = $("#toggle-preview-button-" + this.commentFormID);
const dropzone = $("#dropzone-large-" + this.commentFormID);
const commentFormBody = $("#comment-form-body-" + this.commentFormID);

this.previewElement[0].innerHTML = marked(this.textAreaValue);
this.previewElement.toggle();
dropzone.toggle();
commentFormBody.toggle();

this.toggleButtonPreviewMode(previewBtn);
}
Expand Down
43 changes: 32 additions & 11 deletions app/assets/javascripts/editorToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
// /app/views/map/edit.html.erb
// and wherever /app/views/editor/editor.html.erb is still used in production

const progressAll = (elem, data) => {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(elem).css(
'width',
progress + '%'
);
}
// * * * * * * * * * * *

// attach eventListeners on document.load for toolbar rich-text buttons & image upload .dropzones
// attach eventListeners on document.load:
// 1. rich-text buttons
// 2. save & recover buttons
// 3. textareas
// 4. image upload .dropzones & buttons
$(function() {
// for rich-text buttons (bold, italic, header, and link):
$('.rich-text-button').on('click', function(e) {
Expand All @@ -22,6 +20,22 @@ $(function() {
$E[action](); // call the appropriate editor function
});

// for save & recover buttons
$('.save-button').on('click', function(e) {
$E.setState(e.currentTarget.dataset.formId); // string that is: "main", "reply-123", "edit-123" etc.
$E.save($E);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

$E.setState in three new places: save buttons, recover buttons, clicking on textareas.

});

$('.recover-button').on('click', function(e) {
$E.setState(e.currentTarget.dataset.formId); // string that is: "main", "reply-123", "edit-123" etc.
$E.recover();
});

// textAreas
$('.text-input').on('click', function(e) {
$E.setState(e.currentTarget.dataset.formId);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

});

// image upload event listeners for both:
// 1. click-to-upload
// 2. drag & drop
Expand Down Expand Up @@ -66,15 +80,14 @@ $(function() {
start: function(e) {
$E.setState(e.target.dataset.formId); // string that is: "main", "reply-123", "edit-123" etc.
$(e.target).removeClass('hover');
console.log($("#image-upload-progress-container-" + $E.commentFormID));
$("#image-upload-progress-container-" + $E.commentFormID).show();
$("#image-upload-text-" + $E.commentFormID).show();
$("#dropzone-choose-one-" + $E.commentFormID).hide();
$("#choose-one-" + $E.commentFormID).hide();
},
done: function (e, data) {
$("#image-upload-progress-container-" + $E.commentFormID).hide();
$("#image-upload-text-" + $E.commentFormID).hide();
$("#dropzone-choose-one-" + $E.commentFormID).show();
$("#choose-one-" + $E.commentFormID).show();
$("#image-upload-progress-bar-" + $E.commentFormID).css('width', 0);
var extension = data.result['filename'].split('.')[data.result['filename'].split('.').length - 1]; var file_url = data.result.url.split('?')[0]; var file_type;
if (['gif', 'GIF', 'jpeg', 'JPEG', 'jpg', 'JPG', 'png', 'PNG'].includes(extension))
Expand Down Expand Up @@ -106,6 +119,14 @@ $(function() {
});
});

const progressAll = (elem, data) => {
var progress = parseInt(data.loaded / data.total * 100, 10);
$(elem).css(
'width',
progress + '%'
);
}

// #side-dropzone, is for the main image of research notes, in /app/views/editor/post.html.erb
$('#side-dropzone').on('dragover',function(e) {
e.preventDefault();
Expand Down
13 changes: 7 additions & 6 deletions app/views/comments/_edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
</style>
<!-- toolbar needs location & comment_id to make unique element IDs -->
<%= render :partial => "editor/toolbar", :locals => { :comment_id => comment.id.to_s, :location => :edit } %>
<div id="c<%= comment.id%>div" class="form-group dropzone" data-form-id="edit-<%= comment.id %>">
<div id="comment-form-body-edit-<%= comment.id%>" class="form-group dropzone dropzone-large" data-form-id="edit-<%= comment.id %>">
<textarea
aria-label="Edit Comment"
onFocus="editing=true"
name="body"
class="form-control"
id="text-input-edit-<%= comment.id%>"
class="form-control text-input"
name="body"
data-form-id="edit-<%= comment.id %>"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The editor needs this data-form-id attribute to setState.

onFocus="editing=true"
aria-label="Edit Comment"
rows="6"
cols="40"
placeholder="<%= placeholder %>"
Expand All @@ -47,7 +48,7 @@
>
<%= translation('comments._edit.uploading') %>
</span>
<span id="dropzone-choose-one-edit-<%= comment.id%>" class="prompt choose-one-prompt-text">
<span id="choose-one-edit-<%= comment.id%>" class="prompt choose-one-prompt-text">
<span style="padding-right:4px;float:left;" class="hidden-xs">
<%= raw translation('comments._edit.drag_and_drop') %>
</span>
Expand Down
13 changes: 7 additions & 6 deletions app/views/comments/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

<!-- most comment forms have two dropzones: 1) small button, 2) large form that covers textarea -->
<!-- this is the large dropzone -->
<div id="dropzone-large-<%= comment_form_id %>" class="form-group dropzone dropzone-large" data-form-id="<%= comment_form_id %>">
<div id="comment-form-body-<%= comment_form_id %>" class="comment-face form-group dropzone dropzone-large" data-form-id="<%= comment_form_id %>">
<%
body = body || params[:body]
# Look for comment templates
Expand All @@ -50,12 +50,13 @@
</div>
<% end %>
<textarea
id="text-input-<%= comment_form_id %>"
class="form-control text-input"
name="body"
data-form-id="<%= comment_form_id %>"
onFocus="editing=true"
aria-label="Comment Text"
style="border: 1px solid #bbb;border-bottom-left-radius: 0;border-bottom-right-radius: 0;border-bottom: 0;padding: 10px;"
onFocus="editing=true"
name="body"
class="form-control text-input"
id="text-input-<%= comment_form_id %>"
rows="6"
cols="40"
placeholder="<%= placeholder %>"><%= body %>
Expand All @@ -80,7 +81,7 @@
>
<%= translation('comments._form.uploading') %>
</span>
<span id="dropzone-choose-one-<%= comment_form_id %>" class="prompt choose-one-prompt-text">
<span id="choose-one-<%= comment_form_id %>" class="prompt choose-one-prompt-text">
<span style="padding-right:4px;float:left;" class="d-none d-md-inline">
<%= raw translation('comments._form.drag_and_drop') %>
</span>
Expand Down
11 changes: 10 additions & 1 deletion app/views/editor/_editor.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
<%= render :partial => "editor/toolbar", :locals => { :location => :main } %>

<div class="form-group dropzone dropzone-large" data-form-id="main">
<textarea aria-label="Wiki Text" name="body" tabindex="2" class="form-control" id="text-input-main" rows="20" cols="60"><% if @node && @node.latest && @node.latest.body %><%= @node.latest.body %><% else %><%= params[:body] %><% end %></textarea>
<textarea
id="text-input-main"
class="form-control text-input"
name="body"
data-form-id="main"
aria-label="Wiki Text"
tabindex="2"
rows="20"
cols="60"
><% if @node && @node.latest && @node.latest.body %><%= @node.latest.body %><% else %><%= params[:body] %><% end %></textarea>
<div class="imagebar">
<div
id="image-upload-progress-container-main" style="display:none;"
Expand Down
22 changes: 11 additions & 11 deletions app/views/editor/_toolbar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
</a>
<a
id="link-button-<%= toolbar_element_id %>"
aria-label="Make a link"
title="Make a link"
aria-label="Link"
title="Link"
data-action="link"
<%# to setState on editor.js %>
data-form-id="<%= toolbar_element_id %>"
Expand All @@ -70,9 +70,9 @@
</a>
<a
id="image-upload-button-<%= toolbar_element_id %>"
aria-label="Upload an image"
aria-label="Upload Image"
data-toggle="tooltip"
title="Upload an image"
title="Upload Image"
data-placement="bottom"
class="upload-button btn btn-outline-secondary btn-sm"
>
Expand All @@ -94,23 +94,23 @@
<div class="btn-group mr-2 ">
<a
id="save-button-<%= toolbar_element_id %>"
data-toggle="tooltip"
class="save-button btn btn-outline-secondary btn-sm"
title="Save"
data-form-id="<%= toolbar_element_id %>"
data-placement="bottom"
onClick="$E.save()"
class="save-button btn btn-outline-secondary btn-sm"
data-toggle="tooltip"
>
<i class="fa fa-save"></i>
</a>
<a
id="recover-button-<%= toolbar_element_id %>"
data-toggle="tooltip"
class="recover-button btn btn-outline-secondary btn-sm"
title="Recover"
data-form-id="<%= toolbar_element_id %>"
data-placement="bottom"
onClick="$E.recover()"
class="recover-button btn btn-outline-secondary btn-sm"
data-toggle="tooltip"
>
Recover
<i class="fas fa-undo"></i>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New icon for the Recover Button!

Now it looks like this:
Screen Shot 2021-02-04 at 8 13 18 PM

Before (bleh):
Screen Shot 2021-02-04 at 8 14 24 PM

</a>
</div>

Expand Down
4 changes: 3 additions & 1 deletion app/views/notes/_comment.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@
<% end %>
<% if current_user && comment.uid == current_user.uid %>
<a
aria-label="Edit comment"
aria-label="Edit Comment"
class="btn btn-outline-secondary btn-sm edit-comment-btn"
rel="tooltip"
title="Edit Comment"
href="javascript:void(0)" onClick="
$('#edit-comment-form-wrapper-<%= comment.cid %>').toggle();
$('#<%= comment.cid %>-like-emojis').toggle();
Expand Down
68 changes: 56 additions & 12 deletions test/system/comment_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,16 +80,60 @@ def get_path(page_type, path)
find("p", text: comment_response_text)
end

test "#{page_type_string}: comment preview button works" do
test "#{page_type_string}: toggle preview buttons work" do
nodes(node_name).add_comment({
uid: 2,
# **bold**
body: "**" + comment_text + "**"
})
visit get_path(page_type, nodes(node_name).path)
find("p", text: "Reply to this comment...").click()
reply_preview_button = page.all('.preview-btn')[0]
comment_preview_button = page.all('.preview-btn')[1]
# Toggle preview
reply_preview_button.click()
# Make sure that buttons are not binded with each other
assert_equal( reply_preview_button.text, "Hide Preview" )
assert_equal( comment_preview_button.text, "Preview" )

# open up reply comment form
page.all('p', text: 'Reply to this comment...')[0].click
# get the ID of reply form
reply_form = page.find('[id^=comment-form-reply-]')
reply_form_id = reply_form[:id]
reply_id_num = /comment-form-reply-(\d+)/.match(reply_form_id)[1]
page.find('#text-input-reply-' + reply_id_num)
.click
.fill_in with: "**" + comment_text + "**"

# open up edit comment form
page.find(".edit-comment-btn").click
# get the ID of edit form
edit_form = page.find('[id^=comment-form-edit-]')
edit_form_id = edit_form[:id]
edit_id_num = /comment-form-edit-(\d+)/.match(edit_form_id)[1]
page.find('#text-input-edit-' + edit_id_num)
.click
.fill_in with: "**" + comment_text + "**"

# fill out main comment form
main_form = page.find('#text-input-main')
main_form
.click
.fill_in with: "**" + comment_text + "**"

# click on toggle preview buttons for main, edit, and reply
replyPreviewButton = page.find('#toggle-preview-button-reply-' + reply_id_num)
editPreviewButton = page.find('#toggle-preview-button-edit-' + edit_id_num)
mainPreviewButton = page.find('#toggle-preview-button-main')
replyPreviewButton.click
editPreviewButton.click
mainPreviewButton.click

# assert preview element appears
assert_selector('#comment-preview-edit-' + edit_id_num)
assert_selector('#comment-preview-reply-' + reply_id_num)
assert_selector('#comment-preview-main')
# assert that button text says Hide Preview
assert_equal(replyPreviewButton.text, 'Hide Preview')
assert_equal(editPreviewButton.text, 'Hide Preview')
assert_equal(mainPreviewButton.text, 'Hide Preview')
# assert text is woot woot, not **woot woot**
reply_form.has_no_text? '**' + comment_text + '**'
edit_form.has_no_text? '**' + comment_text + '**'
main_form.has_no_text? '**' + comment_text + '**'
end

test "#{page_type_string}: ctrl/cmd + enter comment publishing keyboard shortcut" do
Expand Down Expand Up @@ -164,8 +208,8 @@ def get_path(page_type, path)
assert_selector('.btn[data-original-title="Bold"]', count: 1)
assert_selector('.btn[data-original-title="Italic"]', count: 1)
assert_selector('.btn[data-original-title="Header"]', count: 1)
assert_selector('.btn[data-original-title="Make a link"]', count: 1)
assert_selector('.btn[data-original-title="Upload an image"]', count: 1)
assert_selector('.btn[data-original-title="Link"]', count: 1)
assert_selector('.btn[data-original-title="Upload Image"]', count: 1)
assert_selector('.btn[data-original-title="Save"]', count: 1)
assert_selector('.btn[data-original-title="Recover"]', count: 1)
assert_selector('.btn[data-original-title="Help"]', count: 1)
Expand Down Expand Up @@ -443,7 +487,7 @@ def get_path(page_type, path)
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]
comment_dropzone_selector = '#c' + comment_id_num + 'div'
comment_dropzone_selector = '#comment-form-body-edit-' + comment_id_num
# open the edit comment form
page.find(".edit-comment-btn").click
# drop into the edit comment form
Expand Down