1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-25 16:22:43 +01:00

Make inline content "state-oriented", not "string-oriented"

Summary:
Ref T13513. Currently, all the inline code passes around strings to describe content. I plan to add background music, animation effects, etc., soon. To prepare for this change, make content a state object.

This does not change any user-visible behavior, it just prepares for content to become more complicated than a single string.

Test Plan: Created, edited, submitted, cancelled, etc., comments.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21273
This commit is contained in:
epriestley 2020-05-19 13:46:58 -07:00
parent 9d5b8bd14a
commit 87bc30526b
8 changed files with 176 additions and 149 deletions

View file

@ -13,7 +13,7 @@ return array(
'core.pkg.js' => '845355f4', 'core.pkg.js' => '845355f4',
'dark-console.pkg.js' => '187792c2', 'dark-console.pkg.js' => '187792c2',
'differential.pkg.css' => '42a2334f', 'differential.pkg.css' => '42a2334f',
'differential.pkg.js' => '8f59bce2', 'differential.pkg.js' => 'ff8ca085',
'diffusion.pkg.css' => '42c75c37', 'diffusion.pkg.css' => '42c75c37',
'diffusion.pkg.js' => 'a98c0bf7', 'diffusion.pkg.js' => 'a98c0bf7',
'maniphest.pkg.css' => '35995d6d', 'maniphest.pkg.css' => '35995d6d',
@ -379,9 +379,9 @@ return array(
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be', 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be',
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8', 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
'rsrc/js/application/diff/DiffChangeset.js' => '0c083409', 'rsrc/js/application/diff/DiffChangeset.js' => '6e5e03d2',
'rsrc/js/application/diff/DiffChangesetList.js' => 'db615898', 'rsrc/js/application/diff/DiffChangesetList.js' => 'b51ba93a',
'rsrc/js/application/diff/DiffInline.js' => 'b00168c1', 'rsrc/js/application/diff/DiffInline.js' => '28e53a2c',
'rsrc/js/application/diff/DiffPathView.js' => '8207abf9', 'rsrc/js/application/diff/DiffPathView.js' => '8207abf9',
'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b', 'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b',
'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
@ -774,9 +774,9 @@ return array(
'phabricator-darklog' => '3b869402', 'phabricator-darklog' => '3b869402',
'phabricator-darkmessage' => '26cd4b73', 'phabricator-darkmessage' => '26cd4b73',
'phabricator-dashboard-css' => '5a205b9d', 'phabricator-dashboard-css' => '5a205b9d',
'phabricator-diff-changeset' => '0c083409', 'phabricator-diff-changeset' => '6e5e03d2',
'phabricator-diff-changeset-list' => 'db615898', 'phabricator-diff-changeset-list' => 'b51ba93a',
'phabricator-diff-inline' => 'b00168c1', 'phabricator-diff-inline' => '28e53a2c',
'phabricator-diff-path-view' => '8207abf9', 'phabricator-diff-path-view' => '8207abf9',
'phabricator-diff-tree-view' => '5d83623b', 'phabricator-diff-tree-view' => '5d83623b',
'phabricator-drag-and-drop-file-upload' => '4370900d', 'phabricator-drag-and-drop-file-upload' => '4370900d',
@ -1000,19 +1000,6 @@ return array(
'javelin-dom', 'javelin-dom',
'phabricator-draggable-list', 'phabricator-draggable-list',
), ),
'0c083409' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
'phabricator-diff-inline',
'phabricator-diff-path-view',
'phuix-button-view',
),
'0cf79f45' => array( '0cf79f45' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',
@ -1150,6 +1137,9 @@ return array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
), ),
'28e53a2c' => array(
'javelin-dom',
),
'29819b75' => array( '29819b75' => array(
'phabricator-notification', 'phabricator-notification',
'javelin-stratcom', 'javelin-stratcom',
@ -1561,6 +1551,19 @@ return array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
), ),
'6e5e03d2' => array(
'javelin-dom',
'javelin-util',
'javelin-stratcom',
'javelin-install',
'javelin-workflow',
'javelin-router',
'javelin-behavior-device',
'javelin-vector',
'phabricator-diff-inline',
'phabricator-diff-path-view',
'phuix-button-view',
),
70245195 => array( 70245195 => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',
@ -1935,9 +1938,6 @@ return array(
'javelin-behavior-device', 'javelin-behavior-device',
'javelin-vector', 'javelin-vector',
), ),
'b00168c1' => array(
'javelin-dom',
),
'b105a3a6' => array( 'b105a3a6' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',
@ -1970,6 +1970,11 @@ return array(
'b517bfa0' => array( 'b517bfa0' => array(
'phui-oi-list-view-css', 'phui-oi-list-view-css',
), ),
'b51ba93a' => array(
'javelin-install',
'phuix-button-view',
'phabricator-diff-tree-view',
),
'b557770a' => array( 'b557770a' => array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
@ -2119,11 +2124,6 @@ return array(
'javelin-uri', 'javelin-uri',
'phabricator-notification', 'phabricator-notification',
), ),
'db615898' => array(
'javelin-install',
'phuix-button-view',
'phabricator-diff-tree-view',
),
'e150bd50' => array( 'e150bd50' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',

View file

@ -39,7 +39,6 @@ abstract class PhabricatorInlineCommentController
private $isOnRight; private $isOnRight;
private $lineNumber; private $lineNumber;
private $lineLength; private $lineLength;
private $commentText;
private $operation; private $operation;
private $commentID; private $commentID;
private $renderer; private $renderer;
@ -99,16 +98,16 @@ abstract class PhabricatorInlineCommentController
$request = $this->getRequest(); $request = $this->getRequest();
$viewer = $this->getViewer(); $viewer = $this->getViewer();
if (!$request->validateCSRF()) {
return new Aphront404Response();
}
$this->readRequestParameters(); $this->readRequestParameters();
$op = $this->getOperation(); $op = $this->getOperation();
switch ($op) { switch ($op) {
case 'hide': case 'hide':
case 'show': case 'show':
if (!$request->validateCSRF()) {
return new Aphront404Response();
}
$ids = $request->getStrList('ids'); $ids = $request->getStrList('ids');
if ($ids) { if ($ids) {
if ($op == 'hide') { if ($op == 'hide') {
@ -120,9 +119,6 @@ abstract class PhabricatorInlineCommentController
return id(new AphrontAjaxResponse())->setContent(array()); return id(new AphrontAjaxResponse())->setContent(array());
case 'done': case 'done':
if (!$request->validateCSRF()) {
return new Aphront404Response();
}
$inline = $this->loadCommentForDone($this->getCommentID()); $inline = $this->loadCommentForDone($this->getCommentID());
$is_draft_state = false; $is_draft_state = false;
@ -158,10 +154,6 @@ abstract class PhabricatorInlineCommentController
case 'delete': case 'delete':
case 'undelete': case 'undelete':
case 'refdelete': case 'refdelete':
if (!$request->validateCSRF()) {
return new Aphront404Response();
}
// NOTE: For normal deletes, we just process the delete immediately // NOTE: For normal deletes, we just process the delete immediately
// and show an "Undo" action. For deletes by reference from the // and show an "Undo" action. For deletes by reference from the
// preview ("refdelete"), we prompt first (because the "Undo" may // preview ("refdelete"), we prompt first (because the "Undo" may
@ -193,15 +185,14 @@ abstract class PhabricatorInlineCommentController
return $this->buildEmptyResponse(); return $this->buildEmptyResponse();
case 'edit': case 'edit':
case 'save':
$inline = $this->loadCommentByIDForEdit($this->getCommentID()); $inline = $this->loadCommentByIDForEdit($this->getCommentID());
$text = $this->getCommentText(); if ($op === 'save') {
$this->updateCommentContentState($inline);
if ($request->isFormPost()) { $inline->setIsEditing(false);
if (strlen($text)) {
$inline
->setContent($text)
->setIsEditing(false);
if (!$inline->isVoidComment($viewer)) {
$this->saveComment($inline); $this->saveComment($inline);
return $this->buildRenderedCommentResponse( return $this->buildRenderedCommentResponse(
@ -216,7 +207,7 @@ abstract class PhabricatorInlineCommentController
} }
} else { } else {
// NOTE: At time of writing, the "editing" state of inlines is // NOTE: At time of writing, the "editing" state of inlines is
// preserved by simluating a click on "Edit" when the inline loads. // preserved by simulating a click on "Edit" when the inline loads.
// In this case, we don't want to "saveComment()", because it // In this case, we don't want to "saveComment()", because it
// recalculates object drafts and purges versioned drafts. // recalculates object drafts and purges versioned drafts.
@ -234,8 +225,8 @@ abstract class PhabricatorInlineCommentController
$is_dirty = true; $is_dirty = true;
} }
if (strlen($text)) { if ($this->hasContentState()) {
$inline->setContent($text); $this->updateCommentContentState($inline);
$is_dirty = true; $is_dirty = true;
} else { } else {
PhabricatorInlineComment::loadAndAttachVersionedDrafts( PhabricatorInlineComment::loadAndAttachVersionedDrafts(
@ -262,13 +253,9 @@ abstract class PhabricatorInlineCommentController
// If the user uses "Undo" to get into an edited state ("AB"), then // If the user uses "Undo" to get into an edited state ("AB"), then
// clicks cancel to return to the previous state ("A"), we also want // clicks cancel to return to the previous state ("A"), we also want
// to set the stored state back to "A". // to set the stored state back to "A".
$text = $this->getCommentText(); $this->updateCommentContentState($inline);
if (strlen($text)) {
$inline->setContent($text);
}
$content = $inline->getContent(); if ($inline->isVoidComment($viewer)) {
if (!strlen($content)) {
$inline->setIsDeleted(1); $inline->setIsDeleted(1);
} }
@ -283,11 +270,11 @@ abstract class PhabricatorInlineCommentController
$viewer->getPHID(), $viewer->getPHID(),
$inline->getID()); $inline->getID());
$text = $this->getCommentText(); $map = $this->getContentState();
foreach ($map as $key => $value) {
$versioned_draft $versioned_draft->setProperty($key, $value);
->setProperty('inline.text', $text) }
->save(); $versioned_draft->save();
// We have to synchronize the draft engine after saving a versioned // We have to synchronize the draft engine after saving a versioned
// draft, because taking an inline comment from "no text, no draft" // draft, because taking an inline comment from "no text, no draft"
@ -318,11 +305,11 @@ abstract class PhabricatorInlineCommentController
->setIsNewFile($is_new) ->setIsNewFile($is_new)
->setLineNumber($number) ->setLineNumber($number)
->setLineLength($length) ->setLineLength($length)
->setContent((string)$this->getCommentText())
->setReplyToCommentPHID($this->getReplyToCommentPHID()) ->setReplyToCommentPHID($this->getReplyToCommentPHID())
->setIsEditing(true) ->setIsEditing(true)
->setStartOffset($request->getInt('startOffset')) ->setStartOffset($request->getInt('startOffset'))
->setEndOffset($request->getInt('endOffset')); ->setEndOffset($request->getInt('endOffset'))
->setContent('');
$document_engine_key = $request->getStr('documentEngineKey'); $document_engine_key = $request->getStr('documentEngineKey');
if ($document_engine_key !== null) { if ($document_engine_key !== null) {
@ -338,6 +325,10 @@ abstract class PhabricatorInlineCommentController
} }
} }
if ($this->hasContentState()) {
$this->updateCommentContentState($inline);
}
$this->saveComment($inline); $this->saveComment($inline);
$edit_dialog = $this->buildEditDialog($inline); $edit_dialog = $this->buildEditDialog($inline);
@ -365,7 +356,6 @@ abstract class PhabricatorInlineCommentController
$this->isOnRight = $request->getBool('on_right'); $this->isOnRight = $request->getBool('on_right');
$this->lineNumber = $request->getInt('number'); $this->lineNumber = $request->getInt('number');
$this->lineLength = $request->getInt('length'); $this->lineLength = $request->getInt('length');
$this->commentText = $request->getStr('text');
$this->commentID = $request->getInt('id'); $this->commentID = $request->getInt('id');
$this->operation = $request->getStr('op'); $this->operation = $request->getStr('op');
$this->renderer = $request->getStr('renderer'); $this->renderer = $request->getStr('renderer');
@ -529,6 +519,36 @@ abstract class PhabricatorInlineCommentController
return $inline; return $inline;
} }
private function hasContentState() {
$request = $this->getRequest();
return (bool)$request->getBool('hasContentState');
}
private function getContentState() {
$request = $this->getRequest();
$comment_text = $request->getStr('text');
return array(
'inline.text' => (string)$comment_text,
);
}
private function updateCommentContentState(PhabricatorInlineComment $inline) {
if (!$this->hasContentState()) {
throw new Exception(
pht(
'Attempting to update comment content state, but request has no '.
'content state.'));
}
$state = $this->getContentState();
$text = $state['inline.text'];
$inline->setContent($text);
}
private function saveComment(PhabricatorInlineComment $inline) { private function saveComment(PhabricatorInlineComment $inline) {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$draft_engine = $this->newDraftEngine(); $draft_engine = $this->newDraftEngine();

View file

@ -322,6 +322,11 @@ abstract class PhabricatorInlineComment
return $draft_text; return $draft_text;
} }
public function getContentState() {
return array(
'text' => $this->getContent(),
);
}
/* -( PhabricatorMarkupInterface Implementation )-------------------------- */ /* -( PhabricatorMarkupInterface Implementation )-------------------------- */

View file

@ -22,39 +22,12 @@ final class PHUIDiffInlineCommentEditView
'sigil' => 'inline-edit-form', 'sigil' => 'inline-edit-form',
), ),
array( array(
$this->renderInputs(),
$this->renderBody(), $this->renderBody(),
)); ));
return $content; return $content;
} }
private function renderInputs() {
$inputs = array();
$inline = $this->getInlineComment();
$inputs[] = array('op', 'edit');
$inputs[] = array('id', $inline->getID());
$inputs[] = array('on_right', $this->getIsOnRight());
$inputs[] = array('renderer', $this->getRenderer());
$out = array();
foreach ($inputs as $input) {
list($name, $value) = $input;
$out[] = phutil_tag(
'input',
array(
'type' => 'hidden',
'name' => $name,
'value' => $value,
));
}
return $out;
}
private function renderBody() { private function renderBody() {
$buttons = array(); $buttons = array();

View file

@ -82,7 +82,6 @@ abstract class PHUIDiffInlineCommentView extends AphrontView {
'number' => $inline->getLineNumber(), 'number' => $inline->getLineNumber(),
'length' => $inline->getLineLength(), 'length' => $inline->getLineLength(),
'isNewFile' => (bool)$inline->getIsNewFile(), 'isNewFile' => (bool)$inline->getIsNewFile(),
'original' => $inline->getContent(),
'replyToCommentPHID' => $inline->getReplyToCommentPHID(), 'replyToCommentPHID' => $inline->getReplyToCommentPHID(),
'isDraft' => $inline->isDraft(), 'isDraft' => $inline->isDraft(),
'isFixed' => $is_fixed, 'isFixed' => $is_fixed,
@ -93,8 +92,8 @@ abstract class PHUIDiffInlineCommentView extends AphrontView {
'documentEngineKey' => $inline->getDocumentEngineKey(), 'documentEngineKey' => $inline->getDocumentEngineKey(),
'startOffset' => $inline->getStartOffset(), 'startOffset' => $inline->getStartOffset(),
'endOffset' => $inline->getEndOffset(), 'endOffset' => $inline->getEndOffset(),
'on_right' => $this->getIsOnRight(), 'on_right' => $this->getIsOnRight(),
'contentState' => $inline->getContentState(),
); );
} }

View file

@ -761,14 +761,14 @@ JX.install('DiffChangeset', {
return inline; return inline;
}, },
newInlineReply: function(original, text) { newInlineReply: function(original, state) {
var inline = new JX.DiffInline() var inline = new JX.DiffInline()
.setChangeset(this) .setChangeset(this)
.bindToReply(original); .bindToReply(original);
this._inlines.push(inline); this._inlines.push(inline);
inline.create(text); inline.create(state);
return inline; return inline;
}, },

View file

@ -2410,7 +2410,7 @@ JX.install('DiffChangesetList', {
switch (action) { switch (action) {
case 'save': case 'save':
inline.save(e.getTarget()); inline.save();
break; break;
case 'cancel': case 'cancel':
inline.cancel(); inline.cancel();

View file

@ -19,7 +19,7 @@ JX.install('DiffInline', {
_displaySide: null, _displaySide: null,
_isNewFile: null, _isNewFile: null,
_replyToCommentPHID: null, _replyToCommentPHID: null,
_originalText: null, _originalState: null,
_snippet: null, _snippet: null,
_menuItems: null, _menuItems: null,
_documentEngineKey: null, _documentEngineKey: null,
@ -42,7 +42,7 @@ JX.install('DiffInline', {
_editRow: null, _editRow: null,
_undoRow: null, _undoRow: null,
_undoType: null, _undoType: null,
_undoText: null, _undoState: null,
_draftRequest: null, _draftRequest: null,
_skipFocus: false, _skipFocus: false,
@ -76,12 +76,7 @@ JX.install('DiffInline', {
this._number = parseInt(data.number, 10); this._number = parseInt(data.number, 10);
this._length = parseInt(data.length, 10); this._length = parseInt(data.length, 10);
var original = '' + data.original; this._originalState = data.contentState;
if (original.length) {
this._originalText = original;
} else {
this._originalText = null;
}
this._isNewFile = data.isNewFile; this._isNewFile = data.isNewFile;
this._replyToCommentPHID = data.replyToCommentPHID; this._replyToCommentPHID = data.replyToCommentPHID;
@ -314,10 +309,6 @@ JX.install('DiffInline', {
return this._hasMenuAction('collapse'); return this._hasMenuAction('collapse');
}, },
getRawText: function() {
return this._originalText;
},
_newRow: function() { _newRow: function() {
var attributes = { var attributes = {
sigil: 'inline-row' sigil: 'inline-row'
@ -332,7 +323,7 @@ JX.install('DiffInline', {
this._phid = null; this._phid = null;
this._isCollapsed = false; this._isCollapsed = false;
this._originalText = null; this._originalState = null;
return row; return row;
}, },
@ -404,7 +395,7 @@ JX.install('DiffInline', {
this._didUpdate(); this._didUpdate();
}, },
create: function(text) { create: function(content_state) {
var changeset = this.getChangeset(); var changeset = this.getChangeset();
if (!this._documentEngineKey) { if (!this._documentEngineKey) {
this._documentEngineKey = changeset.getResponseDocumentEngineKey(); this._documentEngineKey = changeset.getResponseDocumentEngineKey();
@ -412,7 +403,7 @@ JX.install('DiffInline', {
var uri = this._getInlineURI(); var uri = this._getInlineURI();
var handler = JX.bind(this, this._oncreateresponse); var handler = JX.bind(this, this._oncreateresponse);
var data = this._newRequestData('new', text); var data = this._newRequestData('new', content_state);
this.setLoading(true); this.setLoading(true);
@ -421,22 +412,33 @@ JX.install('DiffInline', {
.send(); .send();
}, },
_getContentState: function() {
var state;
if (this._editRow) {
state = this._readFormState(this._editRow);
} else {
state = this._originalState;
}
return state;
},
reply: function(with_quote) { reply: function(with_quote) {
this._closeMenu(); this._closeMenu();
var text; var content_state = this._newContentState();
if (with_quote) { if (with_quote) {
text = this.getRawText(); var text = this._getContentState().text;
text = '> ' + text.replace(/\n/g, '\n> ') + '\n\n'; text = '> ' + text.replace(/\n/g, '\n> ') + '\n\n';
} else { content_state.text = text;
text = '';
} }
var changeset = this.getChangeset(); var changeset = this.getChangeset();
return changeset.newInlineReply(this, text); return changeset.newInlineReply(this, content_state);
}, },
edit: function(text, skip_focus) { edit: function(content_state, skip_focus) {
this._closeMenu(); this._closeMenu();
this._skipFocus = !!skip_focus; this._skipFocus = !!skip_focus;
@ -456,7 +458,7 @@ JX.install('DiffInline', {
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', text || null); var data = this._newRequestData('edit', content_state);
this.setLoading(true); this.setLoading(true);
@ -545,13 +547,12 @@ JX.install('DiffInline', {
return this; return this;
}, },
_newRequestData: function(operation, text) { _newRequestData: function(operation, content_state) {
var data = { var data = {
op: operation, op: operation,
is_new: this.isNewFile(), is_new: this.isNewFile(),
on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), on_right: ((this.getDisplaySide() == 'right') ? 1 : 0),
renderer: this.getChangeset().getRendererKey(), renderer: this.getChangeset().getRendererKey()
text: text || null
}; };
if (operation === 'new') { if (operation === 'new') {
@ -574,6 +575,11 @@ JX.install('DiffInline', {
JX.copy(data, edit_data); JX.copy(data, edit_data);
} }
if (content_state) {
data.hasContentState = 1;
JX.copy(data, content_state);
}
return data; return data;
}, },
@ -608,14 +614,14 @@ JX.install('DiffInline', {
// If there's an existing editor, remove it. This happens when you // If there's an existing editor, remove it. This happens when you
// delete a comment from the comment preview area. In this case, we // delete a comment from the comment preview area. In this case, we
// read and preserve the text so "Undo" restores it. // read and preserve the text so "Undo" restores it.
var text; var state = null;
if (this._editRow) { if (this._editRow) {
text = this._readText(this._editRow); state = this._readFormState(this._editRow);
JX.DOM.remove(this._editRow); JX.DOM.remove(this._editRow);
this._editRow = null; this._editRow = null;
} }
this._drawUndeleteRows(text); this._drawUndeleteRows(state);
this.setLoading(false); this.setLoading(false);
this.setDeleted(true); this.setDeleted(true);
@ -623,21 +629,21 @@ JX.install('DiffInline', {
this._didUpdate(); this._didUpdate();
}, },
_drawUndeleteRows: function(text) { _drawUndeleteRows: function(content_state) {
this._undoType = 'undelete'; this._undoType = 'undelete';
this._undoText = text || null; this._undoState = content_state || null;
return this._drawUndoRows('undelete', this._row); return this._drawUndoRows('undelete', this._row);
}, },
_drawUneditRows: function(text) { _drawUneditRows: function(content_state) {
this._undoType = 'unedit'; this._undoType = 'unedit';
this._undoText = text; this._undoState = content_state;
return this._drawUndoRows('unedit', null, text); return this._drawUndoRows('unedit', null);
}, },
_drawUndoRows: function(mode, cursor, text) { _drawUndoRows: function(mode, cursor) {
var templates = this.getChangeset().getUndoTemplates(); var templates = this.getChangeset().getUndoTemplates();
var template; var template;
@ -648,7 +654,7 @@ JX.install('DiffInline', {
} }
template = JX.$H(template).getNode(); template = JX.$H(template).getNode();
this._undoRow = this._drawRows(template, cursor, mode, text); this._undoRow = this._drawRows(template, cursor, mode);
}, },
_drawContentRows: function(rows) { _drawContentRows: function(rows) {
@ -660,7 +666,7 @@ JX.install('DiffInline', {
this._editRow = this._drawRows(rows, null, 'edit'); this._editRow = this._drawRows(rows, null, 'edit');
}, },
_drawRows: function(rows, cursor, type, text) { _drawRows: function(rows, cursor, type) {
var first_row = JX.DOM.scry(rows, 'tr')[0]; var first_row = JX.DOM.scry(rows, 'tr')[0];
var row = first_row; var row = first_row;
var anchor = cursor || this._row; var anchor = cursor || this._row;
@ -713,14 +719,17 @@ JX.install('DiffInline', {
return result_row; return result_row;
}, },
save: function(form) { save: function() {
var handler = JX.bind(this, this._onsubmitresponse); var handler = JX.bind(this, this._onsubmitresponse);
this.setLoading(true); this.setLoading(true);
JX.Workflow.newFromForm(form) var uri = this._getInlineURI();
.setHandler(handler) var data = this._newRequestData('save', this._getContentState());
.start();
new JX.Request(uri, handler)
.setData(data)
.send();
}, },
undo: function() { undo: function() {
@ -740,8 +749,8 @@ JX.install('DiffInline', {
.send(); .send();
} }
if (this._undoText !== null) { if (this._undoState !== null) {
this.edit(this._undoText); this.edit(this._undoState);
} }
}, },
@ -751,18 +760,20 @@ JX.install('DiffInline', {
}, },
cancel: function() { cancel: function() {
var text = this._readText(this._editRow); var state = this._readFormState(this._editRow);
JX.DOM.remove(this._editRow); JX.DOM.remove(this._editRow);
this._editRow = null; this._editRow = null;
if (text && text.length && (text != this._originalText)) { var is_empty = this._isVoidContentState(state);
this._drawUneditRows(text); var is_same = this._isSameContentState(state, this._originalState);
if (!is_empty && !is_same) {
this._drawUneditRows(state);
} }
// If this was an empty box and we typed some text and then hit cancel, // If this was an empty box and we typed some text and then hit cancel,
// don't show the empty concrete inline. // don't show the empty concrete inline.
if (!this._originalText) { if (!this._isVoidContentState(this._originalState)) {
this.setInvisible(true); this.setInvisible(true);
} else { } else {
this.setInvisible(false); this.setInvisible(false);
@ -773,7 +784,7 @@ JX.install('DiffInline', {
// text ("A") to the server as the current persistent state. // text ("A") to the server as the current persistent state.
var uri = this._getInlineURI(); var uri = this._getInlineURI();
var data = this._newRequestData('cancel', this._originalText); var data = this._newRequestData('cancel', this._originalState);
var handler = JX.bind(this, this._onCancelResponse); var handler = JX.bind(this, this._onCancelResponse);
this.setLoading(true); this.setLoading(true);
@ -792,7 +803,7 @@ JX.install('DiffInline', {
// If the comment was empty when we started editing it (there's no // If the comment was empty when we started editing it (there's no
// original text) and empty when we finished editing it (there's no // original text) and empty when we finished editing it (there's no
// undo row), just delete the comment. // undo row), just delete the comment.
if (!this._originalText && !this.isUndo()) { if (this._isVoidContentState(this._originalState) && !this.isUndo()) {
this.setDeleted(true); this.setDeleted(true);
JX.DOM.remove(this._row); JX.DOM.remove(this._row);
@ -802,7 +813,7 @@ JX.install('DiffInline', {
} }
}, },
_readText: function(row) { _readFormState: function(row) {
var textarea; var textarea;
try { try {
textarea = JX.DOM.find( textarea = JX.DOM.find(
@ -813,7 +824,9 @@ JX.install('DiffInline', {
return null; return null;
} }
return textarea.value; return {
text: textarea.value
};
}, },
_onsubmitresponse: function(response) { _onsubmitresponse: function(response) {
@ -920,16 +933,19 @@ JX.install('DiffInline', {
return null; return null;
} }
var text = this._readText(this._editRow); var state = this._readFormState(this._editRow);
if (text === null) { if (this._isVoidContentState(state)) {
return null; return null;
} }
return { var draft_data = {
op: 'draft', op: 'draft',
id: this.getID(), id: this.getID(),
text: text
}; };
JX.copy(draft_data, state);
return draft_data;
}, },
triggerDraft: function() { triggerDraft: function() {
@ -1035,6 +1051,20 @@ JX.install('DiffInline', {
if (this._menu) { if (this._menu) {
this._menu.close(); this._menu.close();
} }
},
_isVoidContentState: function(state) {
return !state.text.length;
},
_isSameContentState: function(u, v) {
return (u.text === v.text);
},
_newContentState: function() {
return {
text: ''
};
} }
} }