You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/09/20 07:57:53 UTC

[isis] branch master updated: ISIS-3215: update negotiation models on select2 events

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new fe7ed87171 ISIS-3215: update negotiation models on select2 events
fe7ed87171 is described below

commit fe7ed871714e80f0f9b6d85ceeed2f137c8d34c9
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Sep 20 09:57:47 2022 +0200

    ISIS-3215: update negotiation models on select2 events
---
 .../ui/components/widgets/select2/Select2.java     |  60 +------
 .../widgets/select2/Select2OnSelect.java           | 191 +++++++++++++++++++++
 2 files changed, 194 insertions(+), 57 deletions(-)

diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2.java
index aab59cdf9e..c864260ecb 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2.java
@@ -20,20 +20,13 @@ package org.apache.isis.viewer.wicket.ui.components.widgets.select2;
 
 import java.io.Serializable;
 import java.util.List;
-import java.util.Optional;
 
-import org.apache.wicket.Component;
-import org.apache.wicket.behavior.AbstractAjaxBehavior;
 import org.apache.wicket.behavior.Behavior;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.LambdaModel;
 import org.apache.wicket.model.Model;
-import org.apache.wicket.request.mapper.parameter.INamedParameters.NamedPair;
 import org.apache.wicket.validation.IValidator;
 import org.wicketstuff.select2.AbstractSelect2Choice;
-import org.wicketstuff.select2.JQuery;
 import org.wicketstuff.select2.Select2Choice;
 import org.wicketstuff.select2.Select2MultiChoice;
 
@@ -45,7 +38,6 @@ import org.apache.isis.viewer.wicket.model.models.HasCommonContext;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModelWithMultiChoice;
 import org.apache.isis.viewer.wicket.model.models.ScalarModelWithSingleChoice;
-import org.apache.isis.viewer.wicket.model.util.PageParameterUtils;
 import org.apache.isis.viewer.wicket.model.util.WktContext;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstract;
 import org.apache.isis.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderAbstractForScalarModel;
@@ -85,8 +77,8 @@ implements
         select2.setLabel(Model.of(scalarModel.getFriendlyName()));
         select2.getSettings().setWidth("100%");
 
-        // listen on select2:select events (client-side)
-        select2.add(new Select2OnSelect());
+        // listen on select2:select/unselect events (client-side)
+        select2.add(new Select2OnSelect(scalarModel));
 
         return select2;
     }
@@ -191,53 +183,7 @@ implements
         });
     }
 
-    /**
-     * Listen on select2:select events so that we then can send an AJAX request with all selected object(.id)s,
-     * while still doing parameter negotiation; that is, not submitting the form yet.
-     * @see "https://select2.org/programmatic-control/events#listening-for-events"
-     * @since 2.0
-     */
-    static class Select2OnSelect extends AbstractAjaxBehavior {
-        private static final long serialVersionUID = 1L;
-        private static enum Event {
-            SELECT, UNSELECT, CLEAR;
-            String key() { return name().toLowerCase(); }
-            static Optional<Event> valueOf(final NamedPair pair) {
-                for(val event : Event.values()) {
-                    if(event.name().equalsIgnoreCase(pair.getKey())) {
-                        return Optional.of(event);
-                    }
-                }
-                return Optional.empty();
-            }
-        };
-        @Override public void renderHead(final Component component, final IHeaderResponse response) {
-            for(val event : Event.values()) {
-                response.render(OnDomReadyHeaderItem.forScript(JQuery.execute("$('#%s')"
-                        + ".on('select2:%s', function (e) {"
-                        + "var data = e.params.data;"
-                        //debug + "console.log(e);"
-                        + "Wicket.Ajax.get({'u': '%s&%s=' + data.id});"
-                        + "});",
-                        component.getMarkupId(),
-                        event.key(),
-                        getCallbackUrl(),
-                        event.key()
-                        )));
-            }
-        }
-
-        @Override public void onRequest() {
-            PageParameterUtils.streamCurrentRequestParameters()
-            .forEach(pair->
-                Event.valueOf(pair).ifPresent(event->{
-                    val itemId = ObjectMemento.destringFromUrlBase64(pair.getValue());
-                    //TODO update the param negotiation model
-                    //System.err.printf("onRequest %s->%s%n", event, itemId.getTitle());
-                })
-            );
-        }
-    }
+    
 
     // -- HELPER
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2OnSelect.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2OnSelect.java
new file mode 100644
index 0000000000..59f103ea62
--- /dev/null
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/Select2OnSelect.java
@@ -0,0 +1,191 @@
+/*
+ *  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.widgets.select2;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.behavior.AbstractAjaxBehavior;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.request.mapper.parameter.INamedParameters.NamedPair;
+import org.wicketstuff.select2.JQuery;
+
+import org.apache.isis.commons.binding.Bindable;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.core.metamodel.object.ManagedObject;
+import org.apache.isis.core.metamodel.object.PackedManagedObject;
+import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.util.PageParameterUtils;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+/**
+ * Listen on select2:select, select2:unselect and select2:clear events
+ * so that we then can send an AJAX request including the event type and
+ * the selected or un-selected object(.id),
+ * while still doing parameter negotiation; that is, not submitting the form yet.
+ * @see "https://select2.org/programmatic-control/events#listening-for-events"
+ * @since 2.0
+ */
+@RequiredArgsConstructor
+class Select2OnSelect extends AbstractAjaxBehavior {
+    private static final long serialVersionUID = 1L;
+    private final ScalarModel scalarModel;
+
+    private static enum Event {
+        SELECT, UNSELECT, CLEAR;
+        String key() { return name().toLowerCase(); }
+        static Optional<Select2OnSelect.Event> valueOf(final NamedPair pair) {
+            for(var event : Event.values()) {
+                if(event.name().equalsIgnoreCase(pair.getKey())) {
+                    return Optional.of(event);
+                }
+            }
+            return Optional.empty();
+        }
+    };
+
+    @Override
+    public void renderHead(final Component component, final IHeaderResponse response) {
+        for(var event : Event.values()) {
+            response.render(OnDomReadyHeaderItem.forScript(JQuery.execute("$('#%s')"
+                    + ".on('select2:%s', function (e) {"
+                    + "var data = e.params.data;"
+                    //debug + "console.log(e);"
+                    + "Wicket.Ajax.get({'u': '%s&%s=' + data.id});"
+                    + "});",
+                    component.getMarkupId(),
+                    event.key(),
+                    getCallbackUrl(),
+                    event.key()
+                    )));
+        }
+    }
+
+    /**
+     * update the param negotiation model
+     */
+    @Override
+    public void onRequest() {
+        PageParameterUtils.streamCurrentRequestParameters()
+        .forEach(pair->
+            Event.valueOf(pair).ifPresent(event->{
+                val objectMementoFromEvent = ObjectMemento.destringFromUrlBase64(pair.getValue());
+                if(getComponent() instanceof Select2MultiChoiceExt) {
+                    val component = (Select2MultiChoiceExt)getComponent();
+                    switch(event) {
+                    case SELECT:{
+                        val selection = component.getModelObject();
+                        val newSelection = selection!=null
+                                ? new ArrayList<ObjectMemento>(selection)
+                                : new ArrayList<ObjectMemento>();
+                        newSelection.add(objectMementoFromEvent);
+                        component.setModelObject(newSelection);
+                        updateReceiver().setValue(demementify(newSelection));
+                        break;
+                    }
+                    case UNSELECT:{
+                        val selection = component.getModelObject();
+                        val newSelection = selection!=null
+                                ? new ArrayList<ObjectMemento>(selection)
+                                : new ArrayList<ObjectMemento>();
+                        newSelection.remove(objectMementoFromEvent);
+                        component.setModelObject(newSelection);
+                        updateReceiver().setValue(demementify(newSelection));
+                        break;
+                    }
+                    case CLEAR:
+                        component.setModelObject(null);
+                        clearUpdateReceiver();
+                        break;
+                    }
+//                    System.err.printf("value updated %s%n",
+//                            scalarModel.getObjectManager().demementify(objectMementoFromEvent));
+                }
+                else
+                if(getComponent() instanceof Select2ChoiceExt) {
+                    val component = (Select2ChoiceExt)getComponent();
+                    switch(event) {
+                    case SELECT:
+                        component.setModelObject(objectMementoFromEvent);
+                        updateReceiver().setValue(demementify(objectMementoFromEvent));
+                        break;
+                    case UNSELECT:
+                    case CLEAR:
+                        component.clearInput();
+                        clearUpdateReceiver();
+                        break;
+                    }
+
+                } else return;
+
+                //TODO schedule form update (AJAX)
+
+            })
+        );
+    }
+
+    // -- HELPER
+
+    private ManagedObject demementify(final ObjectMemento memento) {
+        return scalarModel.getObjectManager().demementify(memento);
+    }
+
+    private PackedManagedObject demementify(
+            final @NonNull List<ObjectMemento> mementos) {
+        return ManagedObject.packed(
+                elementSpec(),
+                mementos.stream().map(this::demementify).collect(Can.toCan()));
+    }
+
+    private @NonNull Bindable<ManagedObject> updateReceiver() {
+        val updateReceiver = scalarModel.getSpecialization().fold(
+                param->
+                    param.getParameterNegotiationModel().getBindableParamValue(param.getParameterIndex()),
+                prop->
+                    prop.getPendingPropertyModel().getValue());
+        return updateReceiver;
+    }
+
+    private @NonNull ObjectSpecification elementSpec() {
+        val updateReceiver = scalarModel.getSpecialization().fold(
+                param->param.getScalarTypeSpec(),
+                prop->prop.getScalarTypeSpec());
+        return updateReceiver;
+    }
+
+    private void clearUpdateReceiver() {
+        scalarModel.getSpecialization().accept(
+            param->
+                param.getParameterNegotiationModel().getParamModels()
+                .getElseFail(param.getParameterIndex())
+                .clear(),
+            prop->
+                prop.getPendingPropertyModel().clear());
+    }
+
+
+}
\ No newline at end of file