You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2017/04/27 12:32:52 UTC
[06/35] isis git commit: ISIS-1603: working on validation,
not there yet
ISIS-1603: working on validation, not there yet
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/6bd683d0
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/6bd683d0
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/6bd683d0
Branch: refs/heads/ISIS-1603
Commit: 6bd683d01155e79a25c6e74168025dd2be3f49fe
Parents: 4d79170
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 21 19:15:51 2017 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Apr 27 13:25:36 2017 +0100
----------------------------------------------------------------------
.../scalars/ScalarPanelTextFieldAbstract.html | 42 ++++-
.../scalars/ScalarPanelTextFieldAbstract.java | 173 +++++++++++++++++--
.../components/scalars/XEditableBehavior2.java | 84 +++++++++
3 files changed, 285 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/6bd683d0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.html
index 7bbfcf0..a05f536 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.html
@@ -27,16 +27,52 @@
<wicket:container wicket:id="scalarValueContainer"/>
<wicket:fragment wicket:id="text">
- <input type="text" name="scalarValue" class="form-control input-sm scalarValue" wicket:id="scalarValue" />
+ <input
+ type="text"
+ name="scalarValue"
+ class="form-control input-sm scalarValue"
+ wicket:id="scalarValue" />
+ <a
+ href="#"
+ data-type="text"
+ name="scalarValueEditInline"
+ class="form-control input-sm scalarValueEditInline"
+ wicket:id="scalarValueEditInline">
+ <span wicket:id="scalarValueEditInlineLabel"></span>
+ </a>
</wicket:fragment>
<wicket:fragment wicket:id="textarea">
- <textarea name="scalarValue" class="form-control scalarValue" wicket:id="scalarValue"></textarea>
+ <textarea
+ name="scalarValue"
+ class="form-control scalarValue"
+ wicket:id="scalarValue">
+ </textarea>
+ <a
+ href="#"
+ data-type="textarea"
+ name="scalarValueEditInline"
+ class="form-control input-sm scalarValueEditInline"
+ wicket:id="scalarValueEditInline"
+ style="height: auto"
+ ><span wicket:id="scalarValueEditInlineLabel"></span></a>
</wicket:fragment>
<wicket:fragment wicket:id="date">
<div class="date">
- <input type="text" name="scalarValue" wicket:id="scalarValue" class="form-control input-sm scalarValue"/>
+ <input
+ type="text"
+ name="scalarValue"
+ class="form-control input-sm scalarValue"
+ wicket:id="scalarValue"/>
+ <a
+ data-type="combodate"
+ href="#"
+ name="scalarValueEditInline"
+ class="form-control input-sm scalarValueEditInline"
+ wicket:id="scalarValueEditInline">
+ <span wicket:id="scalarValueEditInlineLabel"></span>
+ </a>
</div>
</wicket:fragment>
http://git-wip-us.apache.org/repos/asf/isis/blob/6bd683d0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
index fd371d6..7dea2c3 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelTextFieldAbstract.java
@@ -27,6 +27,10 @@ import com.google.common.base.Strings;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxCallListener;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -36,17 +40,19 @@ import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.string.StringValue;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
-import org.apache.wicket.validation.validator.StringValidator;
+import org.apache.isis.applib.annotation.PropertyEditStyle;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.facets.SingleIntValueFacet;
import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
import org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
@@ -54,6 +60,11 @@ import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.Enti
import org.apache.isis.viewer.wicket.ui.components.widgets.bootstrap.FormGroup;
import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.xeditable.XEditableBehavior;
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.xeditable.XEditableOptions;
+import de.agilecoders.wicket.jquery.Key;
+import de.agilecoders.wicket.jquery.util.Json;
+
/**
* Adapter for {@link ScalarPanelAbstract scalar panel}s that are implemented
* using a simple {@link TextField}.
@@ -79,6 +90,7 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
protected WebMarkupContainer scalarTypeContainer;
private AbstractTextComponent<T> textField;
+ private WebMarkupContainer editInlineLink;
public ScalarPanelTextFieldAbstract(final String id, final ScalarModel scalarModel, final Class<T> cls) {
super(id, scalarModel);
@@ -95,6 +107,13 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
}
+ private Component getEditComponent() {
+ return textField.isVisibilityAllowed()
+ ? textField
+ : editInlineLink;
+ }
+
+
AbstractTextComponent<T> getTextField() {
return textField;
}
@@ -113,8 +132,132 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
@Override
protected MarkupContainer addComponentForRegular() {
+
+ // even though only one of textField and editInlineLink will ever be visible,
+ // am instantiating both to avoid NPEs
+ // elsewhere can use Component#isVisibilityAllowed or ScalarModel.getEditStyle() to check whichis visible.
+
textField = createTextFieldForRegular(ID_SCALAR_VALUE);
textField.setOutputMarkupId(true);
+ editInlineLink = new WebMarkupContainer(ID_SCALAR_VALUE_EDIT_INLINE);
+ editInlineLink.setOutputMarkupId(true);
+
+ final IModel<T> textFieldModel = textField.getModel();
+
+ final Label editInlineLinkLabel = new Label(ID_SCALAR_VALUE_EDIT_INLINE_LABEL, textFieldModel);
+ editInlineLink.add(editInlineLinkLabel);
+
+ if(scalarModel.getEditStyle() == PropertyEditStyle.INLINE) {
+ textField.setVisibilityAllowed(false);
+
+ final XEditableOptions options = new XEditableOptions() {
+ {
+ put(new Key<String>("toggle"), "click");
+ if(scalarModel.isRequired()) {
+ put(new Key<Json.RawValue>("validate"), new Json.RawValue(
+ "function (value) { if (value == '') { return 'Required field'; } }"));
+ }
+// put(new Key<Json.RawValue>("error"), new Json.RawValue(
+// "function(response, newValue) {\n"
+// + " if(response.status === 500) {\n"
+// + " return 'Service unavailable. Please try later.';\n"
+// + " } else {\n"
+// + " return response.responseText;\n"
+// + " }\n"
+// + "}"));
+
+ }
+ }.withMode("inline");
+
+ options.withDefaultValue(asString(textFieldModel));
+
+ XEditableBehavior xEditable = new XEditableBehavior(options) {
+ @Override
+ protected void onSave(final AjaxRequestTarget target, final String value) {
+
+ scalarModel.setObjectAsString(value);
+
+ ObjectAdapter adapter = scalarModel.getParentObjectAdapterMemento()
+ .getObjectAdapter(AdapterManager.ConcurrencyChecking.NO_CHECK, getPersistenceSession(),
+ getSpecificationLoader());
+
+ scalarModel.applyValue(adapter);
+
+ target.add(editInlineLink);
+
+ options.withDefaultValue(asString(textFieldModel));
+ }
+
+ protected AjaxEventBehavior newSaveListener() {
+ return new AjaxEventBehavior("save") {
+ @Override
+ protected void onEvent(AjaxRequestTarget target) {
+
+ final ObjectAdapter currentValue = scalarModel.getObject();
+ StringValue newValue = RequestCycle.get().getRequest().getRequestParameters().getParameterValue("newValue");
+
+ try {
+ onSave(target, newValue.toString());
+ } catch (Exception ex) {
+ scalarModel.setObject(currentValue);
+
+ final String value = asString(textFieldModel);
+ options.withDefaultValue(value);
+
+ //
+ // hmmm... thought had this working, but turns out that can't rely on the .control-group to exist
+ //
+ // also: even if get going, still need to reset the value of the inline edit, and also
+ // to handle updates to the title (eg Wicket event bus, I think)
+ //
+ final String message = ex.getMessage();
+ target.appendJavaScript(
+ "( function() { "
+ + "var component = $(\"#" + editInlineLink.getMarkupId() + "\"); "
+ + "var parent = $(component).parent(); "
+
+ + "var controlGroup = $(parent).find(\".control-group\"); "
+ + "var errorBlock = $(parent).find(\".editable-error-block\"); "
+
+ + "$(component).editable(\"show\"); "
+ + "$(controlGroup).addClass(\"has-error\"); "
+ + "$(errorBlock).css(\"display\", \"block\"); "
+ + "$(errorBlock).text(\"" + message + "\"); "
+
+ + "} )();");
+ }
+
+ }
+
+ @Override
+ protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+ super.updateAjaxAttributes(attributes);
+ attributes.getDynamicExtraParameters().add("return [{'name':'newValue', 'value': attrs.event.extraData.newValue}]");
+
+ AjaxCallListener myAjaxCallListener = new AjaxCallListener() {
+
+ @Override
+ public CharSequence getBeforeHandler(Component component) {
+ return ""; // "var myEl = $(\"#" + component.getMarkupId() + "\"); console.log(myEl);";
+ }
+
+ @Override public CharSequence getFailureHandler(final Component component) {
+ return "alert(\"failure!!!\")";
+ }
+ };
+ attributes.getAjaxCallListeners().add(myAjaxCallListener);
+
+ }
+ };
+ }
+
+ };
+
+
+ editInlineLink.add(xEditable);
+ } else {
+ editInlineLink.setVisibilityAllowed(false);
+ }
addStandardSemantics();
@@ -147,7 +290,8 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
labelIfRegular.add(new AttributeModifier("title", Model.of(describedAs)));
}
- addFeedbackOnlyTo(labelIfRegular, textField);
+ addFeedbackOnlyTo(labelIfRegular, getEditComponent());
+
addEditPropertyTo(labelIfRegular);
// ... add entity links to panel (below and to right)
@@ -156,6 +300,10 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
return labelIfRegular;
}
+ private String asString(final IModel<T> textFieldModel) {
+ return textFieldModel != null && textFieldModel.getObject() != null ? textFieldModel.getObject().toString() : null;
+ }
+
protected abstract IModel<String> getScalarPanelType();
private void addReplaceDisabledTagWithReadonlyTagBehaviourIfRequired(final Component component) {
@@ -181,6 +329,8 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
textFieldFragment.add(this.textField);
scalarNameAndValue.add(textFieldFragment);
+ textFieldFragment.add(this.editInlineLink);
+
return scalarNameAndValue;
}
@@ -265,12 +415,6 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
textField.setEnabled(false);
addReplaceDisabledTagWithReadonlyTagBehaviourIfRequired(textField);
- final String disableReasonIfAny = scalarModel.disable(getRendering().getWhere());
- if(disableReasonIfAny == null) {
- CssClassAppender.appendCssClassTo(this, "editable");
- }
-
-
setTitleAttribute("");
}
@@ -278,6 +422,7 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
protected void onBeforeRenderWhenDisabled(final String disableReason) {
super.onBeforeRenderWhenDisabled(disableReason);
textField.setEnabled(false);
+ editInlineLink.setEnabled(false);
addReplaceDisabledTagWithReadonlyTagBehaviourIfRequired(textField);
setTitleAttribute(disableReason);
}
@@ -286,16 +431,22 @@ public abstract class ScalarPanelTextFieldAbstract<T extends Serializable> exten
protected void onBeforeRenderWhenEnabled() {
super.onBeforeRenderWhenEnabled();
textField.setEnabled(true);
+ editInlineLink.setEnabled(true);
setTitleAttribute("");
}
private void setTitleAttribute(final String titleAttribute) {
- textField.add(new AttributeModifier("title", Model.of(titleAttribute)));
+ AttributeModifier title = new AttributeModifier("title", Model.of(titleAttribute));
+ textField.add(title);
+ editInlineLink.add(title);
}
@Override
protected void addFormComponentBehavior(Behavior behavior) {
- textField.add(behavior);
+
+ // some behaviours can only be attached to one component
+ // so we check as to which will actually be visible.
+ getEditComponent().add(behavior);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/6bd683d0/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/XEditableBehavior2.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/XEditableBehavior2.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/XEditableBehavior2.java
new file mode 100644
index 0000000..d8bf40b
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/XEditableBehavior2.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.viewer.wicket.ui.components.scalars;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.string.StringValue;
+
+import de.agilecoders.wicket.extensions.markup.html.bootstrap.xeditable.XEditableBehavior;
+
+public class XEditableBehavior2 extends XEditableBehavior {
+
+ private AjaxEventBehavior validateListener;
+
+ /**
+ * Fired when new value for validation.
+ */
+ protected void onValidate(AjaxRequestTarget target, String value) {
+
+ }
+
+
+ @Override
+ public void bind(Component component) {
+ super.bind(component);
+ validateListener = newSaveListener();
+ component.add(validateListener);
+ }
+
+ @Override
+ public void unbind(Component component) {
+ component.remove(validateListener);
+ validateListener = null;
+
+ super.unbind(component);
+ }
+
+ protected AjaxEventBehavior newValidateListener() {
+ return new AjaxEventBehavior("validate") {
+
+ /**
+ * what's bound to "validate" event in Javascript, and sent to the server
+ */
+ @Override
+ protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+ super.updateAjaxAttributes(attributes);
+ attributes.getDynamicExtraParameters().add("return [{'name':'newValue', 'value': attrs.event.extraData.newValue}]");
+ }
+
+ /**
+ * What's received at the server
+ */
+ @Override
+ protected void onEvent(AjaxRequestTarget target) {
+ StringValue newValue = RequestCycle.get().getRequest().getRequestParameters().getParameterValue("newValue");
+ onValidate(target, newValue.toString());
+ }
+
+ };
+ }
+
+
+
+}