Add admin screen to edit the plugin configuration
Change-Id: I6830a863a42d6630d63b6e14db901f698f41bb0c
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagareMenu.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagareMenu.java
index 63f4689..b968b77 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagareMenu.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/ImagareMenu.java
@@ -30,6 +30,8 @@
menuEntries = new ArrayList<TopMenu.MenuEntry>();
menuEntries.add(new MenuEntry("Tools", Collections
.singletonList(new MenuItem("Image Upload", "#/x/" + pluginName + "/upload", ""))));
+ menuEntries.add(new MenuEntry("Plugins", Collections
+ .singletonList(new MenuItem("Imagare Admin", "#/x/" + pluginName + "/admin", ""))));
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ConfigInfo.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ConfigInfo.java
index 332ef3d..dcea642 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ConfigInfo.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ConfigInfo.java
@@ -18,6 +18,7 @@
public class ConfigInfo extends JavaScriptObject {
final native String getDefaultProject() /*-{ return this.default_project }-*/;
+ final native void setDefaultProject(String p) /*-{ this.default_project = p; }-*/;
static ConfigInfo create() {
ConfigInfo g = (ConfigInfo) createObject();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagareAdminScreen.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagareAdminScreen.java
new file mode 100644
index 0000000..cab716d
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagareAdminScreen.java
@@ -0,0 +1,104 @@
+// Copyright (C) 2014 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.
+
+package com.googlesource.gerrit.plugins.imagare.client;
+
+import com.google.gerrit.plugin.client.Plugin;
+import com.google.gerrit.plugin.client.rpc.RestApi;
+import com.google.gerrit.plugin.client.screen.Screen;
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+public class ImagareAdminScreen extends VerticalPanel {
+
+ static class Factory implements Screen.EntryPoint {
+ @Override
+ public void onLoad(Screen screen) {
+ screen.setPageTitle("Imagare Admin");
+ screen.show(new ImagareAdminScreen());
+ }
+ }
+
+ private TextBox projectBox;
+ private Button saveButton;
+
+ ImagareAdminScreen() {
+ setStyleName("imagare-admin-screen");
+
+ new RestApi("config").id("server").view(Plugin.get().getPluginName(), "config")
+ .get(new AsyncCallback<ConfigInfo>() {
+ @Override
+ public void onSuccess(ConfigInfo info) {
+ display(info);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ // never invoked
+ }
+ });
+ }
+
+ private void display(ConfigInfo info) {
+ HorizontalPanel p = new HorizontalPanel();
+ p.setStyleName("imagare-project-panel");
+ p.add(new Label("Project:"));
+ projectBox = new TextBox();
+ projectBox.setValue(info.getDefaultProject());
+ p.add(projectBox);
+ add(p);
+
+ HorizontalPanel buttons = new HorizontalPanel();
+ add(buttons);
+
+ saveButton = new Button("Save");
+ saveButton.addClickHandler(new ClickHandler() {
+ @Override
+ public void onClick(final ClickEvent event) {
+ doSave();
+ }
+ });
+ buttons.add(saveButton);
+ saveButton.setEnabled(false);
+ new OnEditEnabler(saveButton, projectBox);
+
+ projectBox.setFocus(true);
+ saveButton.setEnabled(false);
+ }
+
+ private void doSave() {
+ ConfigInfo in = ConfigInfo.create();
+ in.setDefaultProject(projectBox.getValue());
+ new RestApi("config").id("server").view(Plugin.get().getPluginName(), "config")
+ .put(in, new AsyncCallback<JavaScriptObject>() {
+
+ @Override
+ public void onSuccess(JavaScriptObject result) {
+ saveButton.setEnabled(false);
+ }
+
+ @Override
+ public void onFailure(Throwable caught) {
+ // never invoked
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagarePlugin.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagarePlugin.java
index 221238a..68fca51 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagarePlugin.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/ImagarePlugin.java
@@ -24,5 +24,6 @@
@Override
public void onPluginLoad() {
Plugin.get().screen("upload", new ImageUploadScreen.Factory());
+ Plugin.get().screen("admin", new ImagareAdminScreen.Factory());
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/client/OnEditEnabler.java b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/OnEditEnabler.java
new file mode 100644
index 0000000..c0de2ee
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/client/OnEditEnabler.java
@@ -0,0 +1,184 @@
+// Copyright (C) 2010 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.
+
+package com.googlesource.gerrit.plugins.imagare.client;
+
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.logical.shared.ValueChangeEvent;
+import com.google.gwt.event.logical.shared.ValueChangeHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FocusWidget;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.TextBoxBase;
+import com.google.gwt.user.client.ui.ValueBoxBase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/** Enables a FocusWidget (e.g. a Button) if an edit is detected from any
+ * registered input widget.
+ */
+public class OnEditEnabler implements KeyPressHandler, KeyDownHandler,
+ MouseUpHandler, ChangeHandler, ValueChangeHandler<Object> {
+
+ private final FocusWidget widget;
+ private Map<TextBoxBase, String> strings = new HashMap<TextBoxBase, String>();
+ private String originalValue;
+
+
+ // The first parameter to the contructors must be the FocusWidget to enable,
+ // subsequent parameters are widgets to listenTo.
+
+ public OnEditEnabler(final FocusWidget w, final TextBoxBase tb) {
+ this(w);
+ originalValue = tb.getValue().trim();
+ listenTo(tb);
+ }
+
+ public OnEditEnabler(final FocusWidget w, final ListBox lb) {
+ this(w);
+ listenTo(lb);
+ }
+
+ public OnEditEnabler(final FocusWidget w, final CheckBox cb) {
+ this(w);
+ listenTo(cb);
+ }
+
+ public OnEditEnabler(final FocusWidget w) {
+ widget = w;
+ }
+
+
+ // Register input widgets to be listened to
+
+ public void listenTo(final TextBoxBase tb) {
+ strings.put(tb, tb.getText().trim());
+ tb.addKeyPressHandler(this);
+
+ // Is there another way to capture middle button X11 pastes in browsers
+ // which do not yet support ONPASTE events (Firefox)?
+ tb.addMouseUpHandler(this);
+
+ // Resetting the "original text" on focus ensures that we are
+ // up to date with non-user updates of the text (calls to
+ // setText()...) and also up to date with user changes which
+ // occured after enabling "widget".
+ tb.addFocusHandler(new FocusHandler() {
+ @Override
+ public void onFocus(FocusEvent event) {
+ strings.put(tb, tb.getText().trim());
+ }
+ });
+
+ // CTRL-V Pastes in Chrome seem only detectable via BrowserEvents or
+ // KeyDownEvents, the latter is better.
+ tb.addKeyDownHandler(this);
+ }
+
+ public void listenTo(final ListBox lb) {
+ lb.addChangeHandler(this);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public void listenTo(final CheckBox cb) {
+ cb.addValueChangeHandler((ValueChangeHandler) this);
+ }
+
+
+ // Handlers
+
+ @Override
+ public void onKeyPress(final KeyPressEvent e) {
+ on(e);
+ }
+
+ @Override
+ public void onKeyDown(final KeyDownEvent e) {
+ on(e);
+ }
+
+ @Override
+ public void onMouseUp(final MouseUpEvent e) {
+ on(e);
+ }
+
+ @Override
+ public void onChange(final ChangeEvent e) {
+ on(e);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void onValueChange(final ValueChangeEvent e) {
+ on(e);
+ }
+
+ private void on(final GwtEvent<?> e) {
+ if (widget.isEnabled() ||
+ ! (e.getSource() instanceof FocusWidget) ||
+ ! ((FocusWidget) e.getSource()).isEnabled() ) {
+ if (e.getSource() instanceof ValueBoxBase) {
+ final TextBoxBase box = ((TextBoxBase) e.getSource());
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ if (box.getValue().trim().equals(originalValue)) {
+ widget.setEnabled(false);
+ }
+ }
+ });
+ }
+ return;
+ }
+
+ if (e.getSource() instanceof TextBoxBase) {
+ onTextBoxBase((TextBoxBase) e.getSource());
+ } else {
+ // For many widgets, we can assume that a change is an edit. If
+ // a widget does not work that way, it should be special cased
+ // above.
+ widget.setEnabled(true);
+ }
+ }
+
+ private void onTextBoxBase(final TextBoxBase tb) {
+ // The text appears to not get updated until the handlers complete.
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ String orig = strings.get(tb);
+ if (orig == null) {
+ orig = "";
+ }
+ if (! orig.equals(tb.getText().trim())) {
+ widget.setEnabled(true);
+ }
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/imagare/public/imagare.css b/src/main/java/com/googlesource/gerrit/plugins/imagare/public/imagare.css
index b227fc2..b30fdff 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/imagare/public/imagare.css
+++ b/src/main/java/com/googlesource/gerrit/plugins/imagare/public/imagare.css
@@ -1,4 +1,5 @@
-.imagare-image-upload-screen, .imagare-uploaded-images-panel {
+.imagare-image-upload-screen, .imagare-uploaded-images-panel,
+.imagare-admin-screen {
width: 100%;
border-spacing: 0px 5px;
}