// Copyright (C) 2016 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. (function() { 'use strict'; Polymer({ is: 'gr-diff-comment', /** * Fired when the Reply action is triggered. * * @event reply */ /** * Fired when the Done action is triggered. * * @event done */ /** * Fired when this comment is discarded. * * @event comment-discard */ properties: { changeNum: String, comment: { type: Object, notify: true, }, disabled: { type: Boolean, value: false, reflectToAttribute: true, }, draft: { type: Boolean, value: false, observer: '_draftChanged', }, editing: { type: Boolean, value: false, observer: '_editingChanged', }, patchNum: String, showActions: Boolean, projectConfig: Object, _xhrPromise: Object, // Used for testing. _editDraft: String, }, ready: function() { this._editDraft = (this.comment && this.comment.message) || ''; this.editing = this._editDraft.length == 0; }, save: function() { this.comment.message = this._editDraft; this.disabled = true; var endpoint = this._restEndpoint(this.comment.id); this._send('PUT', endpoint).then(function(req) { this.disabled = false; var comment = req.response; comment.__draft = true; // Maintain the ephemeral draft ID for identification by other // elements. if (this.comment.__draftID) { comment.__draftID = this.comment.__draftID; } this.comment = comment; this.editing = false; }.bind(this)).catch(function(err) { alert('Your draft couldn’t be saved. Check the console and contact ' + 'the PolyGerrit team for assistance.'); this.disabled = false; }.bind(this)); }, _draftChanged: function(draft) { this.$.container.classList.toggle('draft', draft); }, _editingChanged: function(editing) { this.$.container.classList.toggle('editing', editing); if (editing) { var textarea = this.$.editTextarea.textarea; // Put the cursor at the end always. textarea.selectionStart = textarea.value.length; textarea.selectionEnd = textarea.selectionStart; this.async(function() { textarea.focus(); }.bind(this)); } if (this.comment && this.comment.id) { this.$$('.cancel').hidden = !editing; } }, _computeLinkToComment: function(comment) { return '#' + comment.line; }, _computeSaveDisabled: function(draft) { return draft == null || draft.trim() == ''; }, _handleTextareaKeydown: function(e) { if (e.keyCode == 27) { // 'esc' this._handleCancel(e); } }, _handleLinkTap: function(e) { e.preventDefault(); var hash = this._computeLinkToComment(this.comment); // Don't add the hash to the window history if it's already there. // Otherwise you mess up expected back button behavior. if (window.location.hash == hash) { return; } // Change the URL but don’t trigger a nav event. Otherwise it will // reload the page. page.show(window.location.pathname + hash, null, false); }, _handleReply: function(e) { this._preventDefaultAndBlur(e); this.fire('reply', {comment: this.comment}, {bubbles: false}); }, _handleQuote: function(e) { this._preventDefaultAndBlur(e); this.fire('reply', {comment: this.comment, quote: true}, {bubbles: false}); }, _handleDone: function(e) { this._preventDefaultAndBlur(e); this.fire('done', {comment: this.comment}, {bubbles: false}); }, _handleEdit: function(e) { this._preventDefaultAndBlur(e); this._editDraft = this.comment.message; this.editing = true; }, _handleSave: function(e) { this._preventDefaultAndBlur(e); this.save(); }, _handleCancel: function(e) { this._preventDefaultAndBlur(e); if (this.comment.message == null || this.comment.message.length == 0) { this.fire('comment-discard'); return; } this._editDraft = this.comment.message; this.editing = false; }, _handleDiscard: function(e) { this._preventDefaultAndBlur(e); if (!this.comment.__draft) { throw Error('Cannot discard a non-draft comment.'); } this.disabled = true; var commentID = this.comment.id; if (!commentID) { this.fire('comment-discard'); return; } this._send('DELETE', this._restEndpoint(commentID)).then(function(req) { this.fire('comment-discard'); }.bind(this)).catch(function(err) { alert('Your draft couldn’t be deleted. Check the console and ' + 'contact the PolyGerrit team for assistance.'); this.disabled = false; }.bind(this)); }, _preventDefaultAndBlur: function(e) { e.preventDefault(); Polymer.dom(e).rootTarget.blur(); }, _send: function(method, url) { var xhr = document.createElement('gr-request'); var opts = { method: method, url: url, }; if (method == 'PUT' || method == 'POST') { opts.body = this.comment; } this._xhrPromise = xhr.send(opts); return this._xhrPromise; }, _restEndpoint: function(id) { var path = '/changes/' + this.changeNum + '/revisions/' + this.patchNum + '/drafts'; if (id) { path += '/' + id; } return path; }, }); })();