launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27114
Re: [Merge] ~pappacena/launchpad:comment-editing-ui into launchpad:master
Pushed the requested changes. This should be good to go now.
Diff comments:
> diff --git a/lib/lp/answers/templates/questionmessage-display.pt b/lib/lp/answers/templates/questionmessage-display.pt
> index b69b4b6..e41a0a7 100644
> --- a/lib/lp/answers/templates/questionmessage-display.pt
> +++ b/lib/lp/answers/templates/questionmessage-display.pt
> @@ -5,9 +5,10 @@
> <div
> itemscope=""
> itemtype="http://schema.org/UserComments"
> - tal:define="css_classes view/getBoardCommentCSSClass"
> + tal:define="css_classes python: view.getBoardCommentCSSClass()"
Yep. I was concatenating something here, but ended up moving it into the method. Let me revert this piece.
> tal:attributes="class string:${css_classes};
> - id string:comment-${context/index}">
> + id string:comment-${context/index};
> + data-baseurl context/fmt:url">
> <div class="boardCommentDetails">
> <table>
> <tbody>
> @@ -25,8 +26,20 @@
> itemprop="commentTime"
> tal:attributes="title context/datecreated/fmt:datetime;
> datetime context/datecreated/fmt:isodate"
> - tal:content="context/datecreated/fmt:displaydate">Thursday
> - 13:21</time>:
> + tal:content="context/datecreated/fmt:displaydate">Thursday 13:21
> + </time><span class="editable-message-last-edit-date"><span tal:condition="not:context/date_last_edited">:</span>
Taking care of the white spaces makes it a bit hard, but I think I've found a reasonable way. Changing it.
> + <tal:last-edit condition="context/date_last_edited">
> + (last edit <time
> + itemprop="editTime"
> + tal:attributes="title context/date_last_edited/fmt:datetime;
> + datetime context/date_last_edited/fmt:isodate"
> + tal:content="context/date_last_edited/fmt:displaydate" />):
> + </tal:last-edit>
> + </span>
> + </td>
> + <td>
> + <img class="sprite edit action-icon editable-message-edit-btn"
> + tal:condition="view/can_edit"/>
> </td>
> <td class="bug-comment-index">
> <a
> diff --git a/lib/lp/services/messages/javascript/messages.edit.js b/lib/lp/services/messages/javascript/messages.edit.js
> new file mode 100644
> index 0000000..5cb6156
> --- /dev/null
> +++ b/lib/lp/services/messages/javascript/messages.edit.js
> @@ -0,0 +1,208 @@
> +/* Copyright 2015-2021 Canonical Ltd. This software is licensed under the
> + * GNU Affero General Public License version 3 (see the file LICENSE).
> + *
> + * This modules controls HTML comments in order to make them editable. To do
> + * so, it requires:
> + * - A div container with the class .editable-message containing everything
> + * else related to the message
> + * - A data-baseurl="/path/to/msg" on the .editable-message container
> + * - A .editable-message-body container with the original msg content
> + * - A .editable-message-edit-btn element inside the main container, that will
> + * switch the view to edit form when clicked.
> + * - A .editable-message-form, with a textarea and 2 buttons:
> + * .editable-message-update-btn and .editable-message-cancel-btn.
> + * - A .editable-message-last-edit-date span, where we update the date of the
> + * last message editing.
> + *
> + * Once those HTML elements are available in the page, this module should be
> + * initialized with `lp.services.messages.edit.setup()`.
> + *
> + * @module Y.lp.services.messages.edit
> + * @requires node, DOM, lp.client
> + */
> +YUI.add('lp.services.messages.edit', function(Y) {
> + var module = Y.namespace('lp.services.messages.edit');
> +
> + module.msg_edit_success_notification = (
> + "Message edited, but the original content may still be publicly " +
> + "visible using the API.<br />Please, " +
Ok!
> + "<a href='https://launchpad.net/+apidoc/devel.html#message'>" +
> + "check the API documentation</a> in case " +
Sure!
> + "need to remove old message revisions."
> + );
> + module.msg_edit_error_notification = (
> + "There was an error updating the comment. " +
> + "Please, try again in some minutes."
Ok!
> + );
> +
> + module.htmlify_msg = function(text) {
Right!
> + text = text.replace(/</g, "<");
> + text = text.replace(/>/g, ">");
> + text = text.replace(/\n/g, "<br/>");
> + return "<p>" + text + "</p>";
> + };
> +
> + module.showEditMessageField = function(msg_body, msg_form) {
> + msg_body.setStyle('display', 'none');
> + msg_form.setStyle('display', 'block');
> + };
> +
> + module.hideEditMessageField = function(msg_body, msg_form) {
> + msg_body.setStyle('display', 'block');
> + msg_form.setStyle('display', 'none');
> + };
> +
> + module.saveMessageContent = function(
> + msg_path, new_content, on_success, on_failure) {
> + var msg_url = "/api/devel" + msg_path;
> + var config = {
> + on: {
> + success: on_success,
> + failure: on_failure
> + },
> + parameters: {"new_content": new_content}
> + };
> + this.lp_client.named_post(msg_url, 'editContent', config);
> + };
> +
> + module.showNotification = function(container, msg, can_dismiss) {
> + can_dismiss = can_dismiss || false;
> + // Clean up previous notification.
> + module.hideNotification(container);
> + container.setStyle('position', 'relative');
> + var node = Y.Node.create(
> + "<div class='editable-message-notification'>" +
> + " <p class='block-sprite large-warning'>" +
> + msg +
> + " </p>" +
> + "</div>");
> + container.append(node);
> + if (can_dismiss) {
> + var dismiss = Y.Node.create(
> + "<div class='editable-message-notification-dismiss'>" +
> + " <input type='button' value=' Ok ' />" +
Ok ! :)
> + "</div>");
> + dismiss.on('click', function() {
> + module.hideNotification(container);
> + });
> + node.append(dismiss);
> + }
> + };
> +
> + module.hideNotification = function(container) {
> + var notification = container.one(".editable-message-notification");
> + if(notification) {
> + notification.remove();
> + }
> + };
> +
> + module.showLoading = function(container) {
> + module.showNotification(
> + container,
> + '<img class="spinner" src="/@@/spinner" alt="Loading..." />');
> + };
> +
> + module.hideLoading = function(container) {
> + module.hideNotification(container);
> + };
> +
> + // What to do when a user clicks a message's "edit" button.
> + module.onEditClick = function(elements) {
> + // When clicking edit icon, show the edit form and focus on the
> + // text area.
> + module.showEditMessageField(elements.msg_body, elements.msg_form);
> + elements.msg_form.one('textarea').getDOMNode().focus();
> + }
> +
> + // What to do when a user clicks "cancel edit" button.
> + module.onEditCancelClick = function(elements) {
> + module.hideEditMessageField(elements.msg_body, elements.msg_form);
> + };
> +
> + // What to do when a user clicks the update button after editing a msg.
> + module.onUpdateClick = function(elements, baseurl) {
> + // When clicking on "update" button, disable UI elements and send a
> + // request to update the message at the backend.
> + module.showLoading(elements.container);
> + var textarea = elements.textarea.getDOMNode();
> + var new_content = textarea.value;
> + textarea.disabled = true;
> + elements.update_btn.getDOMNode().disabled = true;
> +
> + module.saveMessageContent(
> + baseurl, new_content,
> + function(err) { module.onMessageSaved(elements, new_content); },
> + function(err) { module.onMessageSaveError(elements, err); }
> + );
> + };
> +
> + // What to do when a message is saved in the backend.
> + module.onMessageSaved = function(elements, new_content) {
> + // When finished updating at the backend, re-enable UI
> + // elements and display the new message.
> + var html_msg = module.htmlify_msg(new_content);
> + elements.msg_body_text.getDOMNode().innerHTML = html_msg;
> + module.hideEditMessageField(
> + elements.msg_body, elements.msg_form);
> + elements.textarea.getDOMNode().disabled = false;
> + elements.update_btn.getDOMNode().disabled = false;
> + module.hideLoading(elements.container);
> + module.showNotification(
> + elements.container,
> + module.msg_edit_success_notification, true);
> + elements.last_edit.getDOMNode().innerHTML = (
> + ' (last edit a moment ago): ');
> + };
> +
> + // What to do when a message fails to update on the backend.
> + module.onMessageSaveError = function(elements, err) {
> + // When something goes wrong at the backend, re-enable
> + // UI elements and display an error.
> + module.showNotification(
> + elements.container,
> + module.msg_edit_error_notification, true);
> + elements.textarea.getDOMNode().disabled = false;
> + elements.update_btn.getDOMNode().disabled = false;
> + };
> +
> + module.wireEventHandlers = function(container) {
> + var node = container.getDOMNode();
> + var baseurl = node.dataset.baseurl;
> + var elements = {
> + "container": container,
> + "msg_body": container.one('.editable-message-body'),
> + "msg_body_text": container.one('.editable-message-text'),
> + "msg_form": container.one('.editable-message-form'),
> + "edit_btn": container.one('.editable-message-edit-btn'),
> + "update_btn": container.one('.editable-message-update-btn'),
> + "cancel_btn": container.one('.editable-message-cancel-btn'),
> + "last_edit": container.one('.editable-message-last-edit-date')
> + };
> + elements.textarea = elements.msg_form.one('textarea');
> +
> + module.hideEditMessageField(elements.msg_body, elements.msg_form);
> +
> + // If the edit button is not present, do not try to bind the
> + // handlers.
> + if (!elements.edit_btn || !baseurl) {
> + return;
> + }
> +
> + elements.edit_btn.on('click', function(e) {
> + module.onEditClick(elements);
> + });
> +
> + elements.update_btn.on('click', function(e) {
> + module.onUpdateClick(elements, baseurl);
> + });
> +
> + elements.cancel_btn.on('click', function(e) {
> + module.onEditCancelClick(elements);
> + });
> + };
> +
> + module.setup = function() {
> + this.lp_client = new Y.lp.client.Launchpad();
> + Y.all('.editable-message').each(module.wireEventHandlers);
> + };
> +}, '0.1', {'requires': ['lp.client', 'node', 'DOM']});
--
https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/402522
Your team Launchpad code reviewers is subscribed to branch ~pappacena/launchpad:comment-editing-revisions-api.
References