Merge changes I4ada8109,I483822f8
* changes:
Add action to edit the project configuration in the browser
EditScreen: Wait until CodeMirror Library is initialized
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index 371a472..b18e219 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -82,7 +82,8 @@
private final static String FILE_NAME3 = "foo3";
private final static byte[] CONTENT_OLD = "bar".getBytes(UTF_8);
private final static byte[] CONTENT_NEW = "baz".getBytes(UTF_8);
- private final static byte[] CONTENT_NEW2 = "quxÄÜÖßµ".getBytes(UTF_8);
+ private final static String CONTENT_NEW2_STR = "quxÄÜÖßµ";
+ private final static byte[] CONTENT_NEW2 = CONTENT_NEW2_STR.getBytes(UTF_8);
@Inject
private SchemaFactory<ReviewDb> reviewDbProvider;
@@ -302,7 +303,7 @@
.isEqualTo(SC_NOT_FOUND);
EditMessage.Input in = new EditMessage.Input();
in.message = String.format("New commit message\n\n" +
- CONTENT_NEW2 + "\n\nChange-Id: %s",
+ CONTENT_NEW2_STR + "\n\nChange-Id: %s",
change.getKey());
assertThat(adminSession.put(urlEditMessage(), in).getStatusCode())
.isEqualTo(SC_NO_CONTENT);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java
index e85633f..ab3ff5d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ConfirmationDialog.java
@@ -25,8 +25,8 @@
public class ConfirmationDialog extends AutoCenterDialogBox {
-
private Button cancelButton;
+ private Button okButton;
public ConfirmationDialog(final String dialogTitle, final SafeHtml message,
final ConfirmationCallback callback) {
@@ -36,7 +36,7 @@
final FlowPanel buttons = new FlowPanel();
- final Button okButton = new Button();
+ okButton = new Button();
okButton.setText(Gerrit.C.confirmationDialogOk());
okButton.addClickHandler(new ClickHandler() {
@Override
@@ -76,4 +76,11 @@
GlobalKey.dialog(this);
cancelButton.setFocus(true);
}
+
+ public void setCancelVisible(boolean visible) {
+ cancelButton.setVisible(visible);
+ if (!visible) {
+ okButton.setFocus(true);
+ }
+ }
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
index d7bd00d8..6d94f1d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java
@@ -846,6 +846,11 @@
return new NotFoundScreen();
}
+ int q = rest.lastIndexOf('?');
+ if (q > 0 && rest.lastIndexOf(',', q) > 0) {
+ c = rest.substring(0, q - 1).lastIndexOf(',');
+ }
+
Project.NameKey k = Project.NameKey.parse(rest.substring(0, c));
String panel = rest.substring(c + 1);
@@ -853,7 +858,8 @@
return new ProjectInfoScreen(k);
}
- if (ProjectScreen.BRANCH.equals(panel)) {
+ if (ProjectScreen.BRANCH.equals(panel)
+ || matchPrefix(ProjectScreen.BRANCH, panel)) {
return new ProjectBranchesScreen(k);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
index 64025db..6bbc8f1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java
@@ -36,6 +36,9 @@
String confirmationDialogOk();
String confirmationDialogCancel();
+ String branchCreationDialogTitle();
+ String branchCreationConfirmationMessage();
+
String branchDeletionDialogTitle();
String branchDeletionConfirmationMessage();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
index a335d6b..05de983 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties
@@ -17,6 +17,9 @@
confirmationDialogOk = OK
confirmationDialogCancel = Cancel
+branchCreationDialogTitle = Branch Creation
+branchCreationConfirmationMessage = The following branch was successfully created:
+
branchDeletionDialogTitle = Branch Deletion
branchDeletionConfirmationMessage = Do you really want to delete the following branches?
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index cbf906e..c919c6b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -31,6 +31,7 @@
String addWatchPanel();
String avatarInfoPanel();
String bottomheader();
+ String branchTablePrevNextLinks();
String cAPPROVAL();
String cLastUpdate();
String cOWNER();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
index 66d9d67..9ec8c6c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
@@ -31,10 +31,12 @@
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
-import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.HintTextBox;
+import com.google.gerrit.client.ui.Hyperlink;
+import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.common.PageLinks;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -48,12 +50,14 @@
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.TextBox;
@@ -67,15 +71,62 @@
import java.util.Set;
public class ProjectBranchesScreen extends ProjectScreen {
+ private Hyperlink prev;
+ private Hyperlink next;
private BranchesTable branchTable;
private Button delBranch;
private Button addBranch;
private HintTextBox nameTxtBox;
private HintTextBox irevTxtBox;
private FlowPanel addPanel;
+ private int pageSize;
+ private int start;
+ private Query query;
public ProjectBranchesScreen(final Project.NameKey toShow) {
super(toShow);
+ configurePageSize();
+ }
+
+ private void configurePageSize() {
+ if (Gerrit.isSignedIn()) {
+ AccountGeneralPreferences p =
+ Gerrit.getUserAccount().getGeneralPreferences();
+ short m = p.getMaximumPageSize();
+ pageSize = 0 < m ? m : AccountGeneralPreferences.DEFAULT_PAGESIZE;
+ } else {
+ pageSize = AccountGeneralPreferences.DEFAULT_PAGESIZE;
+ }
+ }
+
+ private void parseToken() {
+ String token = getToken();
+
+ for (String kvPair : token.split("[,;&/?]")) {
+ String[] kv = kvPair.split("=", 2);
+ if (kv.length != 2 || kv[0].isEmpty()) {
+ continue;
+ }
+
+ if ("skip".equals(kv[0])
+ && URL.decodeQueryString(kv[1]).matches("^[\\d]+")) {
+ start = Integer.parseInt(URL.decodeQueryString(kv[1]));
+ }
+ }
+ }
+
+ private void setupNavigationLink(Hyperlink link, int skip) {
+ link.setTargetHistoryToken(getTokenForScreen(skip));
+ link.setVisible(true);
+ }
+
+ private String getTokenForScreen(int skip) {
+ String token = PageLinks.toProjectBranches(getProjectKey());
+
+ if (skip > 0) {
+ token += "?skip=" + skip;
+ }
+ return token;
}
@Override
@@ -89,28 +140,10 @@
addPanel.setVisible(result.canAddRefs());
}
});
- refreshBranches();
+ query = new Query().start(start).run();
savedPanel = BRANCH;
}
- private void refreshBranches() {
- ProjectApi.getBranches(getProjectKey(),
- new ScreenLoadCallback<JsArray<BranchInfo>>(this) {
- @Override
- public void preDisplay(final JsArray<BranchInfo> result) {
- Set<String> checkedRefs = branchTable.getCheckedRefs();
- display(Natives.asList(result));
- branchTable.setChecked(checkedRefs);
- updateForm();
- }
- });
- }
-
- private void display(final List<BranchInfo> branches) {
- branchTable.display(branches);
- delBranch.setVisible(branchTable.hasBranchCanDelete());
- }
-
private void updateForm() {
branchTable.updateDeleteButton();
addBranch.setEnabled(true);
@@ -121,6 +154,13 @@
@Override
protected void onInitUI() {
super.onInitUI();
+ parseToken();
+
+ prev = new Hyperlink(Util.C.pagedListPrev(), true, "");
+ prev.setVisible(false);
+
+ next = new Hyperlink(Util.C.pagedListNext(), true, "");
+ next.setVisible(false);
addPanel = new FlowPanel();
@@ -175,9 +215,13 @@
branchTable.deleteChecked();
}
});
-
+ HorizontalPanel buttons = new HorizontalPanel();
+ buttons.setStyleName(Gerrit.RESOURCES.css().branchTablePrevNextLinks());
+ buttons.add(delBranch);
+ buttons.add(prev);
+ buttons.add(next);
add(branchTable);
- add(delBranch);
+ add(buttons);
add(addPanel);
}
@@ -206,6 +250,7 @@
new GerritCallback<BranchInfo>() {
@Override
public void onSuccess(BranchInfo branch) {
+ showAddedBranch(branch);
addBranch.setEnabled(true);
nameTxtBox.setText("");
irevTxtBox.setText("");
@@ -213,21 +258,43 @@
delBranch.setVisible(branchTable.hasBranchCanDelete());
}
- @Override
- public void onFailure(Throwable caught) {
- addBranch.setEnabled(true);
- selectAllAndFocus(nameTxtBox);
- new ErrorDialog(caught.getMessage()).center();
- }
- });
+ @Override
+ public void onFailure(Throwable caught) {
+ addBranch.setEnabled(true);
+ selectAllAndFocus(nameTxtBox);
+ new ErrorDialog(caught.getMessage()).center();
+ }
+ });
}
- private static void selectAllAndFocus(final TextBox textBox) {
+ void showAddedBranch(BranchInfo branch) {
+ SafeHtmlBuilder b = new SafeHtmlBuilder();
+ b.openElement("b");
+ b.append(Gerrit.C.branchCreationConfirmationMessage());
+ b.closeElement("b");
+
+ b.openElement("p");
+ b.append(branch.ref());
+ b.closeElement("p");
+
+ ConfirmationDialog confirmationDialog =
+ new ConfirmationDialog(Gerrit.C.branchCreationDialogTitle(),
+ b.toSafeHtml(), new ConfirmationCallback() {
+ @Override
+ public void onOk() {
+ //do nothing
+ }
+ });
+ confirmationDialog.center();
+ confirmationDialog.setCancelVisible(false);
+ }
+
+ private static void selectAllAndFocus(TextBox textBox) {
textBox.selectAll();
textBox.setFocus(true);
}
- private class BranchesTable extends FancyFlexTable<BranchInfo> {
+ private class BranchesTable extends NavigationTable<BranchInfo> {
private ValueChangeHandler<Boolean> updateDeleteHandler;
boolean canDelete;
@@ -332,19 +399,23 @@
@Override
public void onFailure(Throwable caught) {
- refreshBranches();
+ query = new Query().start(start).run();
super.onFailure(caught);
}
});
}
void display(List<BranchInfo> branches) {
+ displaySubset(branches, 0, branches.size());
+ }
+
+ void displaySubset(List<BranchInfo> branches, int fromIndex, int toIndex) {
canDelete = false;
while (1 < table.getRowCount())
table.removeRow(table.getRowCount() - 1);
- for (final BranchInfo k : branches) {
+ for (BranchInfo k : branches.subList(fromIndex, toIndex)) {
final int row = table.getRowCount();
table.insertRow(row);
applyDataRowStyle(row);
@@ -353,17 +424,21 @@
}
void insert(BranchInfo info) {
- Comparator<BranchInfo> c = new Comparator<BranchInfo>() {
- @Override
- public int compare(BranchInfo a, BranchInfo b) {
- return a.ref().compareTo(b.ref());
+ if (table.getRowCount() <= pageSize || pageSize == 0) {
+ Comparator<BranchInfo> c = new Comparator<BranchInfo>() {
+ @Override
+ public int compare(BranchInfo a, BranchInfo b) {
+ return a.ref().compareTo(b.ref());
+ }
+ };
+ int insertPos = getInsertRow(c, info);
+ if (insertPos >= 0) {
+ table.insertRow(insertPos);
+ applyDataRowStyle(insertPos);
+ populate(insertPos, info);
}
- };
- int insertPos = getInsertRow(c, info);
- if (insertPos >= 0) {
- table.insertRow(insertPos);
- applyDataRowStyle(insertPos);
- populate(insertPos, info);
+ } else {
+ setupNavigationLink(next, ProjectBranchesScreen.this.start + pageSize);
}
}
@@ -530,5 +605,74 @@
}
delBranch.setEnabled(on);
}
+
+ @Override
+ protected void onOpenRow(int row) {
+ if (row > 0) {
+ movePointerTo(row);
+ }
+ }
+
+ @Override
+ protected Object getRowItemKey(BranchInfo item) {
+ return item.ref();
+ }
+ }
+
+ private class Query {
+ private int qStart;
+
+ Query start(int start) {
+ this.qStart = start;
+ return this;
+ }
+
+ Query run() {
+ // Retrieve one more branch than page size to determine if there are more
+ // branches to display
+ ProjectApi.getBranches(getProjectKey(), pageSize + 1, qStart,
+ new ScreenLoadCallback<JsArray<BranchInfo>>(ProjectBranchesScreen.this) {
+ @Override
+ public void preDisplay(JsArray<BranchInfo> result) {
+ if (!isAttached()) {
+ // View has been disposed.
+ } else if (query == Query.this) {
+ query = null;
+ showList(result);
+ } else {
+ query.run();
+ }
+ }
+ });
+ return this;
+ }
+
+ void showList(JsArray<BranchInfo> result) {
+ setToken(getTokenForScreen(qStart));
+ ProjectBranchesScreen.this.start = qStart;
+
+ if (result.length() <= pageSize) {
+ branchTable.display(Natives.asList(result));
+ next.setVisible(false);
+ } else {
+ branchTable.displaySubset(Natives.asList(result), 0,
+ result.length() - 1);
+ setupNavigationLink(next, qStart + pageSize);
+ }
+ if (qStart > 0) {
+ setupNavigationLink(prev, qStart - pageSize);
+ } else {
+ prev.setVisible(false);
+ }
+
+ delBranch.setVisible(branchTable.hasBranchCanDelete());
+ Set<String> checkedRefs = branchTable.getCheckedRefs();
+ branchTable.setChecked(checkedRefs);
+ updateForm();
+
+ if (!isCurrentView()) {
+ display();
+ }
+ }
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
index fd9f4bc..f9054fe 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/change/ReplyBox.java
@@ -351,7 +351,6 @@
final String id = lv.info.name();
final CheckBox b = new CheckBox();
b.setText(id);
- b.setTitle(lv.info.value_text("+1"));
b.setEnabled(lv.permitted.contains((short) 1));
if (self != null && self.value() == 1) {
b.setValue(true);
@@ -364,6 +363,10 @@
});
b.setStyleName(style.label_name());
labelsTable.setWidget(row, 0, b);
+
+ CellFormatter fmt = labelsTable.getCellFormatter();
+ fmt.setStyleName(row, labelHelpColumn, style.label_help());
+ labelsTable.setText(row, labelHelpColumn, lv.info.value_text("+1"));
}
private static boolean isCheckBox(Set<Short> values) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
index bd25d60..5cf7d62 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/editor/EditScreen.java
@@ -403,7 +403,7 @@
InlineHyperlink unified = new InlineHyperlink();
unified.setHTML(new ImageResourceRenderer()
.render(Gerrit.RESOURCES.unifiedDiff()));
- sbs.setTargetHistoryToken(
+ unified.setTargetHistoryToken(
Dispatcher.toPatch("unified", base, new Patch.Key(revision, path)));
unified.setTitle(PatchUtil.C.unifiedDiff());
linkPanel.add(unified);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 38b2f69..0d0f793 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -1232,6 +1232,20 @@
cursor: pointer;
}
+.branchTablePrevNextLinks {
+ position: relative;
+}
+.branchTablePrevNextLinks td {
+ float: left;
+ width: 5em;
+ text-align: left;
+ padding-right: 10px;
+}
+.branchTablePrevNextLinks .gwt-Hyperlink {
+ font-size: 9pt;
+ color: #2a5db0;
+}
+
/** PluginListScreen **/
.pluginsTable {
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
index f4f7087..b657f23 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
@@ -58,6 +58,14 @@
project(name).view("branches").get(cb);
}
+ public static void getBranches(Project.NameKey name, int limit, int start,
+ AsyncCallback<JsArray<BranchInfo>> cb) {
+ RestApi call = project(name).view("branches");
+ call.addParameter("n", limit);
+ call.addParameter("s", start);
+ call.get(cb);
+ }
+
/**
* Delete branches. One call is fired to the server to delete all the
* branches.
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java
index f5ab20a..b02c591 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StreamEvents.java
@@ -22,6 +22,7 @@
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.events.Event;
+import com.google.gerrit.server.events.EventTypes;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.WorkQueue.CancelableRunnable;
import com.google.gerrit.sshd.BaseCommand;
@@ -64,10 +65,17 @@
private final Gson gson = new Gson();
/** Special event to notify clients they missed other events. */
- private final Object droppedOutputEvent = new Object() {
- @SuppressWarnings("unused")
- final String type = "dropped-output";
- };
+ private static final class DroppedOutputEvent extends Event {
+ public DroppedOutputEvent() {
+ super("dropped-output");
+ }
+ }
+
+ private static final DroppedOutputEvent droppedOutputEvent = new DroppedOutputEvent();
+
+ static {
+ EventTypes.registerClass(droppedOutputEvent);
+ }
private final EventListener listener = new EventListener() {
@Override