Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/application/diff/DiffInline.js
/** | /** | ||||
* @provides phabricator-diff-inline | * @provides phabricator-diff-inline | ||||
* @requires javelin-dom | * @requires javelin-dom | ||||
* @javelin | * @javelin | ||||
*/ | */ | ||||
JX.install('DiffInline', { | JX.install('DiffInline', { | ||||
construct : function(row) { | construct : function() { | ||||
}, | |||||
properties: { | |||||
changeset: null | |||||
}, | |||||
members: { | |||||
_id: null, | |||||
_phid: null, | |||||
_changesetID: null, | |||||
_row: null, | |||||
_hidden: false, | |||||
_number: null, | |||||
_length: null, | |||||
_displaySide: null, | |||||
_isNewFile: null, | |||||
_undoRow: null, | |||||
_isDeleted: false, | |||||
_isInvisible: false, | |||||
_isLoading: false, | |||||
bindToRow: function(row) { | |||||
this._row = row; | this._row = row; | ||||
var row_data = JX.Stratcom.getData(row); | var row_data = JX.Stratcom.getData(row); | ||||
row_data.inline = this; | |||||
this._hidden = row_data.hidden || false; | this._hidden = row_data.hidden || false; | ||||
// TODO: Get smarter about this once we do more editing, this is pretty | // TODO: Get smarter about this once we do more editing, this is pretty | ||||
// hacky. | // hacky. | ||||
var comment = JX.DOM.find(row, 'div', 'differential-inline-comment'); | var comment = JX.DOM.find(row, 'div', 'differential-inline-comment'); | ||||
var data = JX.Stratcom.getData(comment); | var data = JX.Stratcom.getData(comment); | ||||
this._id = data.id; | this._id = data.id; | ||||
this._phid = data.phid; | |||||
// TODO: This is very, very, very, very, very, very, very hacky. | // TODO: This is very, very, very, very, very, very, very hacky. | ||||
var td = comment.parentNode; | var td = comment.parentNode; | ||||
var th = td.previousSibling; | var th = td.previousSibling; | ||||
if (th.parentNode.firstChild != th) { | if (th.parentNode.firstChild != th) { | ||||
this._displaySide = 'right'; | this._displaySide = 'right'; | ||||
} else { | } else { | ||||
this._displaySide = 'left'; | this._displaySide = 'left'; | ||||
} | } | ||||
this._number = data.number; | this._number = data.number; | ||||
this._length = data.length; | this._length = data.length; | ||||
this._isNewFile = | this._isNewFile = | ||||
(this.getDisplaySide() == 'right') || | (this.getDisplaySide() == 'right') || | ||||
(data.left != data.right); | (data.left != data.right); | ||||
this.setInvisible(false); | |||||
return this; | |||||
}, | }, | ||||
properties: { | bindToRange: function(data) { | ||||
changeset: null | this._id = null; | ||||
this._phid = null; | |||||
this._hidden = false; | |||||
this._displaySide = data.displaySide; | |||||
this._number = data.number; | |||||
this._length = data.length; | |||||
this._isNewFile = data.isNewFile; | |||||
this._changesetID = data.changesetID; | |||||
var row = this._newRow(); | |||||
JX.Stratcom.getData(row).inline = this; | |||||
this._row = row; | |||||
this.setInvisible(true); | |||||
// Insert the comment after any other comments which already appear on | |||||
// the same row. | |||||
var parent_row = JX.DOM.findAbove(data.target, 'tr'); | |||||
var target_row = parent_row.nextSibling; | |||||
while (target_row && JX.Stratcom.hasSigil(target_row, 'inline-row')) { | |||||
target_row = target_row.nextSibling; | |||||
} | |||||
parent_row.parentNode.insertBefore(row, target_row); | |||||
return this; | |||||
}, | }, | ||||
members: { | _newRow: function() { | ||||
_id: null, | var attributes = { | ||||
_row: null, | sigil: 'inline-row' | ||||
_hidden: false, | }; | ||||
_number: null, | |||||
_length: null, | |||||
_displaySide: null, | |||||
_isNewFile: null, | |||||
_undoRow: null, | |||||
_isDeleted: false, | return JX.$N('tr', attributes); | ||||
_isInvisible: false, | }, | ||||
_isLoading: false, | |||||
setHidden: function(hidden) { | setHidden: function(hidden) { | ||||
this._hidden = hidden; | this._hidden = hidden; | ||||
JX.DOM.alterClass(this._row, 'inline-hidden', this._hidden); | JX.DOM.alterClass(this._row, 'inline-hidden', this._hidden); | ||||
var op; | var op; | ||||
if (hidden) { | if (hidden) { | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | _ondone: function(response) { | ||||
// NOTE: This is marking the inline as having an unsubmitted checkmark, | // NOTE: This is marking the inline as having an unsubmitted checkmark, | ||||
// as opposed to a submitted checkmark. This is different from the | // as opposed to a submitted checkmark. This is different from the | ||||
// top-level "draft" state of unsubmitted comments. | // top-level "draft" state of unsubmitted comments. | ||||
JX.DOM.alterClass(comment, 'inline-state-is-draft', response.draftState); | JX.DOM.alterClass(comment, 'inline-state-is-draft', response.draftState); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
create: function() { | |||||
var uri = this._getInlineURI(); | |||||
var handler = JX.bind(this, this._oncreateresponse); | |||||
var data = this._newRequestData('new'); | |||||
this.setLoading(true); | |||||
new JX.Request(uri, handler) | |||||
.setData(data) | |||||
.send(); | |||||
}, | |||||
edit: function() { | edit: function() { | ||||
var uri = this._getInlineURI(); | var uri = this._getInlineURI(); | ||||
var handler = JX.bind(this, this._oneditresponse); | var handler = JX.bind(this, this._oneditresponse); | ||||
var data = this._newRequestData('edit'); | var data = this._newRequestData('edit'); | ||||
this.setLoading(true); | this.setLoading(true); | ||||
new JX.Request(uri, handler) | new JX.Request(uri, handler) | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | members: { | ||||
isNewFile: function() { | isNewFile: function() { | ||||
return this._isNewFile; | return this._isNewFile; | ||||
}, | }, | ||||
getID: function() { | getID: function() { | ||||
return this._id; | return this._id; | ||||
}, | }, | ||||
getChangesetID: function() { | |||||
return this._changesetID; | |||||
}, | |||||
setDeleted: function(deleted) { | setDeleted: function(deleted) { | ||||
this._isDeleted = deleted; | this._isDeleted = deleted; | ||||
this._redraw(); | this._redraw(); | ||||
return this; | return this; | ||||
}, | }, | ||||
setInvisible: function(invisible) { | setInvisible: function(invisible) { | ||||
this._isInvisible = invisible; | this._isInvisible = invisible; | ||||
Show All 11 Lines | _newRequestData: function(operation) { | ||||
return { | return { | ||||
op: operation, | op: operation, | ||||
id: this._id, | id: this._id, | ||||
on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), | on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), | ||||
renderer: this.getChangeset().getRenderer(), | renderer: this.getChangeset().getRenderer(), | ||||
number: this.getLineNumber(), | number: this.getLineNumber(), | ||||
length: this.getLineLength(), | length: this.getLineLength(), | ||||
is_new: this.isNewFile(), | is_new: this.isNewFile(), | ||||
changesetID: this.getChangesetID(), | |||||
replyToCommentPHID: '' | replyToCommentPHID: '' | ||||
}; | }; | ||||
}, | }, | ||||
_oneditresponse: function(response) { | _oneditresponse: function(response) { | ||||
var rows = JX.$H(response).getNode(); | var rows = JX.$H(response).getNode(); | ||||
this._drawEditRows(rows); | this._drawEditRows(rows); | ||||
this.setLoading(false); | this.setLoading(false); | ||||
this.setInvisible(true); | this.setInvisible(true); | ||||
}, | }, | ||||
_oncreateresponse: function(response) { | |||||
var rows = JX.$H(response).getNode(); | |||||
this._drawEditRows(rows); | |||||
}, | |||||
_ondeleteresponse: function() { | _ondeleteresponse: function() { | ||||
this._drawUndoRows(); | this._drawUndoRows(); | ||||
this.setLoading(false); | this.setLoading(false); | ||||
this.setDeleted(true); | this.setDeleted(true); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
Show All 23 Lines | _drawRows: function(rows, cursor, type) { | ||||
cursor = cursor || this._row.nextSibling; | cursor = cursor || this._row.nextSibling; | ||||
var next_row; | var next_row; | ||||
while (row) { | while (row) { | ||||
// Grab this first, since it's going to change once we insert the row | // Grab this first, since it's going to change once we insert the row | ||||
// into the document. | // into the document. | ||||
next_row = row.nextSibling; | next_row = row.nextSibling; | ||||
cursor.parentNode.insertBefore(row, cursor.nextSibling); | cursor.parentNode.insertBefore(row, cursor); | ||||
cursor = row; | cursor = row; | ||||
var row_meta = { | var row_meta = { | ||||
node: row, | node: row, | ||||
type: type, | type: type, | ||||
listeners: [] | listeners: [] | ||||
}; | }; | ||||
Show All 19 Lines | _drawRows: function(rows, cursor, type) { | ||||
row_meta.listeners.push( | row_meta.listeners.push( | ||||
JX.DOM.listen( | JX.DOM.listen( | ||||
row, | row, | ||||
'click', | 'click', | ||||
'differential-inline-comment-undo', | 'differential-inline-comment-undo', | ||||
JX.bind(this, this._onundo, row_meta))); | JX.bind(this, this._onundo, row_meta))); | ||||
} | } | ||||
// If the row has a textarea, focus it. This allows the user to start | |||||
// typing a comment immediately after a "new", "edit", or "reply" | |||||
// action. | |||||
var textareas = JX.DOM.scry( | |||||
row, | |||||
'textarea', | |||||
'differential-inline-comment-edit-textarea'); | |||||
if (textareas.length) { | |||||
textareas[0].focus(); | |||||
} | |||||
row = next_row; | row = next_row; | ||||
} | } | ||||
return first_meta; | return first_meta; | ||||
}, | }, | ||||
_onsubmit: function(row, e) { | _onsubmit: function(row, e) { | ||||
e.kill(); | e.kill(); | ||||
Show All 37 Lines | _oncancel: function(row, e) { | ||||
this._removeRow(row); | this._removeRow(row); | ||||
this.setInvisible(false); | this.setInvisible(false); | ||||
}, | }, | ||||
_onsubmitresponse: function(row, response) { | _onsubmitresponse: function(row, response) { | ||||
this._removeRow(row); | this._removeRow(row); | ||||
this.setLoading(false); | |||||
this.setInvisible(false); | this.setInvisible(false); | ||||
this._onupdate(response); | this._onupdate(response); | ||||
}, | }, | ||||
_onupdate: function(response) { | _onupdate: function(response) { | ||||
var new_row; | var new_row; | ||||
if (response.markup) { | if (response.markup) { | ||||
new_row = this._drawEditRows(JX.$H(response.markup).getNode()).node; | new_row = this._drawEditRows(JX.$H(response.markup).getNode()).node; | ||||
} | } | ||||
// TODO: Save the old row so the action it's undo-able if it was a | // TODO: Save the old row so the action it's undo-able if it was a | ||||
// delete. | // delete. | ||||
var remove_old = true; | var remove_old = true; | ||||
if (remove_old) { | if (remove_old) { | ||||
JX.DOM.remove(this._row); | JX.DOM.remove(this._row); | ||||
} | } | ||||
this._row = new_row; | this.bindToRow(new_row); | ||||
this._didUpdate(); | this._didUpdate(); | ||||
}, | }, | ||||
_didUpdate: function() { | _didUpdate: function() { | ||||
// After making changes to inline comments, refresh the transaction | // After making changes to inline comments, refresh the transaction | ||||
// preview at the bottom of the page. | // preview at the bottom of the page. | ||||
this.getChangeset().getChangesetList().redrawPreview(); | this.getChangeset().getChangesetList().redrawPreview(); | ||||
Show All 26 Lines |