Add canned per-line comment reply of 'Done'
The inline comment panels now have a canned reply button labeled "Reply 'Done'" to automatically write the comment and save it as a draft message. This change covers only the original feature request in issue 405, for just this button, to save a lot of keystrokes when typing out a very common reply for some Google engineers. An additional comment requested configurable per-user and per-project canned replies, in a lot more contexts than just the per-line case. This is a bit more to implement because we need to have a way to store the canned reply list, and to edit it. Bug: issue 405 Change-Id: If67ab6f71eaf30cd23a9cd67b5914ec63dbecdfc Signed-off-by: Shawn O. Pearce <sop@google.com> Reviewed-by: Nico Sallembien <nsallembien@google.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.PatchTable;
|
||||
import com.google.gerrit.client.changes.PublishCommentScreen;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.CommentPanel;
|
||||
import com.google.gerrit.client.ui.NavigationTable;
|
||||
import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
|
||||
@@ -319,76 +320,8 @@ public abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
||||
*/
|
||||
protected void createCommentEditor(final int suggestRow, final int column,
|
||||
final int line, final short file) {
|
||||
createCommentEditor(suggestRow, column, line, file, null /* no parent */);
|
||||
}
|
||||
|
||||
protected void createReplyEditor(final PublishedCommentPanel currentPanel) {
|
||||
final int row = rowOf(currentPanel.getElement());
|
||||
if (row >= 0) {
|
||||
final int column = columnOf(currentPanel.getElement());
|
||||
final PatchLineComment c = currentPanel.comment;
|
||||
final String uuid = c.getKey().get();
|
||||
final PatchSet.Id psId = c.getKey().getParentKey().getParentKey();
|
||||
final short file;
|
||||
if (idSideA == null) {
|
||||
file = c.getSide();
|
||||
} else if (idSideB.equals(psId)) {
|
||||
file = 1;
|
||||
} else {
|
||||
file = 0;
|
||||
}
|
||||
createCommentEditor(row, column, c.getLine(), file, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCommentEditor(final int suggestRow, final int column,
|
||||
final int line, final short file, final String parentUuid) {
|
||||
if (line < 1) {
|
||||
// Refuse to create an editor before the start of the file.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
int row = suggestRow;
|
||||
if (parentUuid != null) {
|
||||
row++;
|
||||
} else {
|
||||
int spans[] = new int[column + 1];
|
||||
OUTER: while (row < table.getRowCount()) {
|
||||
int col = 0;
|
||||
for (int cell = 0; row < table.getRowCount()
|
||||
&& cell < table.getCellCount(row); cell++) {
|
||||
while (col < column && 0 < spans[col]) {
|
||||
spans[col++]--;
|
||||
}
|
||||
spans[col] = table.getFlexCellFormatter().getRowSpan(row, cell);
|
||||
if (col == column) {
|
||||
final Widget w = table.getWidget(row, cell);
|
||||
if (w instanceof CommentEditorPanel) {
|
||||
break OUTER;
|
||||
} else if (w instanceof CommentPanel) {
|
||||
row++;
|
||||
} else {
|
||||
break OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row < table.getRowCount() && column < table.getCellCount(row)
|
||||
&& table.getWidget(row, column) instanceof CommentEditorPanel) {
|
||||
// Don't insert two editors on the same position, it doesn't make
|
||||
// any sense to the user.
|
||||
//
|
||||
((CommentEditorPanel) table.getWidget(row, column)).setFocus(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Gerrit.isSignedIn()) {
|
||||
Gerrit.doSignIn(History.getToken());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Gerrit.isSignedIn()) {
|
||||
if (1 <= line) {
|
||||
final Patch.Key parentKey;
|
||||
final short side;
|
||||
switch (file) {
|
||||
@@ -410,11 +343,57 @@ public abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
||||
}
|
||||
|
||||
final PatchLineComment newComment =
|
||||
new PatchLineComment(new PatchLineComment.Key(parentKey, null), line,
|
||||
Gerrit.getUserAccount().getId(), parentUuid);
|
||||
new PatchLineComment(new PatchLineComment.Key(parentKey, null),
|
||||
line, Gerrit.getUserAccount().getId(), null);
|
||||
newComment.setSide(side);
|
||||
newComment.setMessage("");
|
||||
|
||||
createCommentEditor(suggestRow, column, newComment).setFocus(true);
|
||||
}
|
||||
} else {
|
||||
Gerrit.doSignIn(History.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
private CommentEditorPanel createCommentEditor(final int suggestRow,
|
||||
final int column, final PatchLineComment newComment) {
|
||||
int row = suggestRow;
|
||||
int spans[] = new int[column + 1];
|
||||
FIND_ROW: while (row < table.getRowCount()) {
|
||||
int col = 0;
|
||||
for (int cell = 0; row < table.getRowCount()
|
||||
&& cell < table.getCellCount(row); cell++) {
|
||||
while (col < column && 0 < spans[col]) {
|
||||
spans[col++]--;
|
||||
}
|
||||
spans[col] = table.getFlexCellFormatter().getRowSpan(row, cell);
|
||||
if (col == column) {
|
||||
final Widget w = table.getWidget(row, cell);
|
||||
if (w instanceof CommentEditorPanel) {
|
||||
// Don't insert two editors on the same position, it doesn't make
|
||||
// any sense to the user.
|
||||
//
|
||||
return ((CommentEditorPanel) w);
|
||||
|
||||
} else if (w instanceof CommentPanel) {
|
||||
if (newComment != null && newComment.getParentUuid() != null) {
|
||||
// If we are a reply, we were given the exact row to insert
|
||||
// ourselves at. We should be before this panel so break.
|
||||
//
|
||||
break FIND_ROW;
|
||||
}
|
||||
row++;
|
||||
} else {
|
||||
break FIND_ROW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newComment == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CommentEditorPanel ed = new CommentEditorPanel(newComment);
|
||||
boolean isCommentRow = false;
|
||||
boolean needInsert = false;
|
||||
@@ -467,7 +446,7 @@ public abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
||||
}
|
||||
}
|
||||
|
||||
ed.setFocus(true);
|
||||
return ed;
|
||||
}
|
||||
|
||||
protected void insertRow(final int row) {
|
||||
@@ -691,19 +670,92 @@ public abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
||||
private class PublishedCommentPanel extends CommentPanel implements
|
||||
ClickHandler {
|
||||
final PatchLineComment comment;
|
||||
final Button reply;
|
||||
final Button replyDone;
|
||||
|
||||
PublishedCommentPanel(final AccountInfo author, final PatchLineComment c) {
|
||||
super(author, c.getWrittenOn(), c.getMessage());
|
||||
this.comment = c;
|
||||
|
||||
final Button reply = new Button(PatchUtil.C.buttonReply());
|
||||
reply = new Button(PatchUtil.C.buttonReply());
|
||||
reply.addClickHandler(this);
|
||||
getButtonPanel().add(reply);
|
||||
|
||||
replyDone = new Button(PatchUtil.C.buttonReplyDone());
|
||||
replyDone.addClickHandler(this);
|
||||
getButtonPanel().add(replyDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
createReplyEditor(this);
|
||||
if (Gerrit.isSignedIn()) {
|
||||
if (reply == event.getSource()) {
|
||||
createReplyEditor();
|
||||
} else if (replyDone == event.getSource()) {
|
||||
cannedReply(PatchUtil.C.cannedReplyDone());
|
||||
}
|
||||
|
||||
} else {
|
||||
Gerrit.doSignIn(History.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
private void createReplyEditor() {
|
||||
final PatchLineComment newComment = newComment();
|
||||
newComment.setMessage("");
|
||||
createEditor(newComment).setFocus(true);
|
||||
}
|
||||
|
||||
private void cannedReply(String message) {
|
||||
CommentEditorPanel p = createEditor(null);
|
||||
if (p == null) {
|
||||
final PatchLineComment newComment = newComment();
|
||||
newComment.setMessage(message);
|
||||
|
||||
enable(false);
|
||||
PatchUtil.DETAIL_SVC.saveDraft(newComment,
|
||||
new GerritCallback<PatchLineComment>() {
|
||||
public void onSuccess(final PatchLineComment result) {
|
||||
enable(true);
|
||||
notifyDraftDelta(1);
|
||||
createEditor(result).setOpen(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
enable(true);
|
||||
super.onFailure(caught);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!p.isOpen()) {
|
||||
p.setOpen(true);
|
||||
}
|
||||
p.setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
private CommentEditorPanel createEditor(final PatchLineComment newComment) {
|
||||
int row = rowOf(getElement());
|
||||
int column = columnOf(getElement());
|
||||
return createCommentEditor(row + 1, column, newComment);
|
||||
}
|
||||
|
||||
private PatchLineComment newComment() {
|
||||
PatchLineComment newComment =
|
||||
new PatchLineComment(new PatchLineComment.Key(comment.getKey()
|
||||
.getParentKey(), null), comment.getLine(), Gerrit
|
||||
.getUserAccount().getId(), comment.getKey().get());
|
||||
newComment.setSide(comment.getSide());
|
||||
return newComment;
|
||||
}
|
||||
|
||||
private void enable(boolean on) {
|
||||
for (Widget w : getButtonPanel()) {
|
||||
if (w instanceof Button) {
|
||||
((Button) w).setEnabled(on);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,4 +61,7 @@ public interface PatchConstants extends Constants {
|
||||
|
||||
String reviewed();
|
||||
String download();
|
||||
|
||||
String buttonReplyDone();
|
||||
String cannedReplyDone();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
draft = (Draft)
|
||||
|
||||
buttonReply = Reply
|
||||
buttonReply = Reply ...
|
||||
buttonReplyDone = Reply 'Done'
|
||||
cannedReplyDone = Done
|
||||
buttonEdit = Edit
|
||||
buttonSave = Save
|
||||
buttonCancel = Cancel
|
||||
|
||||
Reference in New Issue
Block a user