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 2019/04/26 16:09:43 UTC

[isis] branch ISIS-1999 created (now bb04f62)

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

danhaywood pushed a change to branch ISIS-1999
in repository https://gitbox.apache.org/repos/asf/isis.git.


      at bb04f62  ISIS-1999: initial implementation for properties and collections on mixins

This branch includes the following new commits:

     new bb04f62  ISIS-1999: initial implementation for properties and collections on mixins

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[isis] 01/01: ISIS-1999: initial implementation for properties and collections on mixins

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1999
in repository https://gitbox.apache.org/repos/asf/isis.git

commit bb04f62c70c0088ee1ff5fa325701e901908072b
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Apr 26 17:09:28 2019 +0100

    ISIS-1999: initial implementation for properties and collections on mixins
---
 .../specimpl/ObjectSpecificationAbstract.java      |   2 +-
 .../model/models/ActionPromptWithExtraContent.java |  15 ++
 .../viewer/wicket/model/models/ScalarModel.java    |  10 +-
 .../actionmenu/entityactions/LinkAndLabelUtil.java |   3 +-
 .../actionpromptsb/ActionPromptSidebar.html        |   7 +-
 .../actionpromptsb/ActionPromptSidebar.java        |  29 +++-
 .../collection/AssociatedWithActionsHelper.java    |  10 +-
 .../ui/components/collection/CollectionPanel.java  |   3 +-
 .../entity/EntityComponentFactoryAbstract.java     |   3 +-
 .../assocgroup/AssociationGroup.html}              |  40 ++---
 .../entity/assocgroup/AssociationGroup.java        | 170 +++++++++++++++++++++
 .../components/entity/fieldset/PropertyGroup.java  |   5 -
 .../linkandlabel/ActionLinkFactoryAbstract.java    |  42 +++++
 .../viewer/wicket/ui/pages/bootstrap-overrides.css |   4 +
 .../wicket/ui/panels/PromptFormAbstract.java       |  18 ++-
 15 files changed, 299 insertions(+), 62 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index b270fc8..a59c9e5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -1197,7 +1197,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
      * then returns an empty list.
      */
     private List<ObjectAction> createMixedInActions() {
-        if (isService() || isValue()) {
+        if (isService() || isValue() || isMixin()) {
             return Collections.emptyList();
         }
         final Set<Class<?>> mixinTypes = AppManifest.Registry.instance().getMixinTypes();
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptWithExtraContent.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptWithExtraContent.java
new file mode 100644
index 0000000..a77f0a2
--- /dev/null
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPromptWithExtraContent.java
@@ -0,0 +1,15 @@
+package org.apache.isis.viewer.wicket.model.models;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+/**
+ * For implementations of {@link ActionPrompt} (eg sidebars) that are also able to display extra content, eg associations of a mixin.
+ */
+public interface ActionPromptWithExtraContent extends ActionPrompt {
+
+    String getExtraContentId();
+
+    void setExtraContentPanel(final Component extraContentComponent, final AjaxRequestTarget target);
+
+}
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index a59f89e..2d8149e 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -110,7 +110,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
 
             @Override
             public boolean whetherHidden(final ScalarModel scalarModel, final Where where) {
-                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().getObject();
                 final OneToOneAssociation property = scalarModel.getPropertyMemento().getProperty(scalarModel.getSpecificationLoader());
                 try {
                     final Consent visibility = property.isVisible(parentAdapter, InteractionInitiatedBy.USER, where);
@@ -122,7 +122,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
 
             @Override
             public String whetherDisabled(final ScalarModel scalarModel, final Where where) {
-                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().getObject();
                 final OneToOneAssociation property = scalarModel.getPropertyMemento().getProperty(scalarModel.getSpecificationLoader());
                 try {
                     final Consent usable = property.isUsable(parentAdapter, InteractionInitiatedBy.USER, where);
@@ -308,7 +308,7 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
             public void reset(ScalarModel scalarModel) {
                 final OneToOneAssociation property = scalarModel.propertyMemento.getProperty(scalarModel.getSpecificationLoader());
 
-                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().load();
+                final ObjectAdapter parentAdapter = scalarModel.getParentEntityModel().getObject();
 
                 setObjectFromPropertyIfVisible(scalarModel, property, parentAdapter);
             }
@@ -742,10 +742,8 @@ public class ScalarModel extends EntityModel implements LinksProvider,FormExecut
     }
 
     private void getAndStore(final EntityModel parentEntityModel) {
-        final ObjectAdapterMemento parentAdapterMemento = parentEntityModel.getObjectAdapterMemento();
         final OneToOneAssociation property = propertyMemento.getProperty(getSpecificationLoader());
-        final ObjectAdapter parentAdapter = parentAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK,
-                getPersistenceSession(), getSpecificationLoader());
+        final ObjectAdapter parentAdapter = parentEntityModel.getObject();
 
         setObjectFromPropertyIfVisible(ScalarModel.this, property, parentAdapter);
     }
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
index 441449c..121a8ad 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
@@ -26,7 +26,6 @@ import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@@ -50,7 +49,7 @@ public final class LinkAndLabelUtil {
 
         final EntityModel parentEntityModel = scalarModelForAssociation.getParentEntityModel();
 
-        final ObjectAdapter parentAdapter = parentEntityModel.load(AdapterManager.ConcurrencyChecking.NO_CHECK);
+        final ObjectAdapter parentAdapter = parentEntityModel.getObject();
 
         final OneToOneAssociation oneToOneAssociation =
                 scalarModelForAssociation.getPropertyMemento().getProperty(scalarModelForAssociation.getSpecificationLoader());
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html
index 10ec1ed..98969b3 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html
@@ -35,7 +35,12 @@
                     <h4 wicket:id="header">Action Name</h4>
                 </div>
                 <div class="sidebar-content">
-                    <div wicket:id="content"></div>
+                    <div class="action-prompt">
+                        <div wicket:id="actionPrompt">[action prompt]</div>
+                    </div>
+                    <div class="extra-content">
+                        <div wicket:id="extraContent"></div>
+                    </div>
                 </div>
             </div>
         </div>
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.java
index 7dd619c..289ad64 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.java
@@ -22,12 +22,18 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.GenericPanel;
 
-import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptWithExtraContent;
 
-public class ActionPromptSidebar extends GenericPanel<Void> implements ActionPrompt /* implements ActionPrompt */ {
+public class ActionPromptSidebar
+        extends GenericPanel<Void>
+        implements ActionPromptWithExtraContent {
 
     private static final long serialVersionUID = 1L;
 
+    private static final String ID_HEADER = "header";
+    private static final String ID_ACTION_PROMPT = "actionPrompt";
+    private static final String ID_EXTRA_CONTENT = "extraContent";
+
     private CloseHandler closeHandlerIfAny;
 
     public ActionPromptSidebar(final String id) {
@@ -39,6 +45,7 @@ public class ActionPromptSidebar extends GenericPanel<Void> implements ActionPro
         add(new Label(getTitleId(), "(no action)"));
 
         add(new WebMarkupContainer(getContentId()));
+        add(new WebMarkupContainer(getExtraContentId()));
     }
 
     public static ActionPromptSidebar newSidebar(String id) {
@@ -47,14 +54,18 @@ public class ActionPromptSidebar extends GenericPanel<Void> implements ActionPro
 
     @Override
     public String getTitleId() {
-        return "header";
+        return ID_HEADER;
     }
 
     @Override
     public String getContentId() {
-        return "content";
+        return ID_ACTION_PROMPT;
     }
 
+    @Override
+    public String getExtraContentId() {
+        return ID_EXTRA_CONTENT;
+    }
 
     @Override
     public void setTitle(final Component titleComponent, final AjaxRequestTarget target) {
@@ -69,6 +80,12 @@ public class ActionPromptSidebar extends GenericPanel<Void> implements ActionPro
     }
 
     @Override
+    public void setExtraContentPanel(final Component extraContentComponent, final AjaxRequestTarget target) {
+        extraContentComponent.setMarkupId(getExtraContentId());
+        addOrReplace(extraContentComponent);
+    }
+
+    @Override
     public void showPrompt(final AjaxRequestTarget target) {
         setVisible(true);
         show(target);
@@ -79,6 +96,10 @@ public class ActionPromptSidebar extends GenericPanel<Void> implements ActionPro
     public void closePrompt(final AjaxRequestTarget target) {
 
         setVisible(false);
+
+        addOrReplace(new WebMarkupContainer(getContentId()));
+        addOrReplace(new WebMarkupContainer(getExtraContentId()));
+
         if (target != null) {
             hide(target);
         }
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
index 7eac1a2..3767d66 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
@@ -26,8 +26,6 @@ import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.filter.Filters;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
 import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -35,7 +33,6 @@ import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
-import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsHelper;
 
@@ -70,12 +67,7 @@ public class AssociatedWithActionsHelper implements Serializable {
     }
 
     private ObjectSpecification getObjectSpecification(final IsisSessionFactory isisSessionFactory) {
-        final ObjectAdapterMemento parentOam = collectionModel.getParentObjectAdapterMemento();
-        final ObjectAdapter parentAdapter = parentOam.getObjectAdapter(
-                                                AdapterManager.ConcurrencyChecking.NO_CHECK,
-                                                isisSessionFactory.getCurrentSession().getPersistenceSession(),
-                                                isisSessionFactory.getSpecificationLoader());
-        return parentAdapter.getSpecification();
+        return collectionModel.getEntityModel().getTypeOfSpecification();
     }
 
     private static List<ActionType> inferActionTypes(final IsisSessionFactory isisSessionFactory) {
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
index e5724e4..a6d9425 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -30,7 +30,6 @@ import org.apache.wicket.feedback.ComponentFeedbackMessageFilter;
 import org.apache.wicket.markup.html.basic.Label;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.viewer.wicket.model.common.OnSelectionHandler;
@@ -76,7 +75,7 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
 
         final OneToManyAssociation otma = collectionModel.getCollectionMemento().getCollection(collectionModel.getSpecificationLoader());
         final EntityModel entityModel = collectionModel.getEntityModel();
-        final ObjectAdapter adapter = entityModel.load(AdapterManager.ConcurrencyChecking.NO_CHECK);
+        final ObjectAdapter adapter = entityModel.getObject();
 
         final List<ObjectAction> associatedActions =
                 ObjectAction.Util.findForAssociation(adapter, otma, getDeploymentCategory());
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
index 53ed51d..09c52e9 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityComponentFactoryAbstract.java
@@ -23,7 +23,6 @@ import org.apache.wicket.Component;
 import org.apache.wicket.model.IModel;
 
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -58,7 +57,7 @@ public abstract class EntityComponentFactoryAbstract extends ComponentFactoryAbs
         // is therefore not called. resulting in a concurrency exception.
         //
         // Therefore, we do the same processing here instead.
-        final ObjectAdapter adapter = entityModel.load(ConcurrencyChecking.NO_CHECK);
+        final ObjectAdapter adapter = entityModel.getObject();
         if (adapter == null) {
             // is ok;
         }
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.html
similarity index 59%
copy from core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html
copy to core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.html
index 10ec1ed..bed5dd2 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionpromptsb/ActionPromptSidebar.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.html
@@ -7,9 +7,9 @@
   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
@@ -17,30 +17,18 @@
   specific language governing permissions and limitations
   under the License.
 -->
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml"
-      xmlns:wicket="http://wicket.apache.org"
-      xml:lang="en"
-      lang="en">
-<body>
-<wicket:panel>
-<!--
-    <li class="sidebar-brand">
-    </li>
--->
-    <div class="sidebar-panel">
-        <div class="row">
-            <div class="col col-md-12">
-                <div class="sidebar-header">
-                    <h4 wicket:id="header">Action Name</h4>
-                </div>
-                <div class="sidebar-content">
-                    <div wicket:id="content"></div>
+<html xmlns:wicket="http://wicket.apache.org">
+    <body>
+        <wicket:panel>
+            <div class="associationGroup" wicket:id="associationGroup">
+                <div class="panel panel-default">
+                    <div class="associations panel-body">
+                        <div wicket:id="associations">
+                            <div wicket:id="association" class="association">[association]</div>
+                        </div>
+                    </div>
                 </div>
             </div>
-        </div>
-    </div>
-
-</wicket:panel>
-</body>
+        </wicket:panel>
+    </body>
 </html>
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.java
new file mode 100644
index 0000000..aa0e306
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/assocgroup/AssociationGroup.java
@@ -0,0 +1,170 @@
+/*
+ *  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.entity.assocgroup;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.repeater.RepeatingView;
+
+import org.apache.isis.applib.layout.component.CollectionLayoutData;
+import org.apache.isis.applib.layout.grid.Grid;
+import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.ui.ComponentType;
+import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
+import org.apache.isis.viewer.wicket.ui.panels.HasDynamicallyVisibleContent;
+import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.isis.viewer.wicket.ui.util.Components;
+
+public class AssociationGroup extends PanelAbstract<EntityModel> implements HasDynamicallyVisibleContent {
+
+    private static final String ID_ASSOCIATION_GROUP = "associationGroup";
+
+    private static final String ID_ASSOCIATIONS = "associations";
+    private static final String ID_ASSOCIATION = "association";
+
+    private final Grid grid;
+
+    private final List<ScalarPanelAbstract2> childScalarPanelAbstract2s;
+    private final List<Component> childComponents;
+
+    public AssociationGroup(final String id, final EntityModel model, final Grid grid) {
+        super(id, model);
+        this.grid = grid;
+
+        // the UI is only ever built once.
+        childComponents = buildGui();
+        childScalarPanelAbstract2s = FluentIterable.from(childComponents).filter(ScalarPanelAbstract2.class).toList();
+    }
+
+    public EntityModel getModel() {
+        return (EntityModel) getDefaultModel();
+    }
+
+
+    private List<Component> buildGui() {
+
+        final List<Component> childComponents = Lists.newArrayList();
+
+        setOutputMarkupPlaceholderTag(true);
+        setOutputMarkupId(true);
+
+        final WebMarkupContainer div = new WebMarkupContainer(ID_ASSOCIATION_GROUP);
+
+        final List<ObjectAssociation> associations = getObjectAssociations();
+
+        final RepeatingView propertyRv = new RepeatingView(ID_ASSOCIATIONS);
+        div.addOrReplace(propertyRv);
+
+        final EntityModel entityModel = getModel();
+
+        final GridFacet gridFacet = entityModel.getTypeOfSpecification().getFacet(GridFacet.class);
+        final Grid grid = gridFacet.getGrid(entityModel.getObject());
+        final Map<String, CollectionLayoutData> collectionLayoutDataById = grid.getAllCollectionsById();
+
+        for (final ObjectAssociation association : associations) {
+
+            final WebMarkupContainer associationRvContainer = new WebMarkupContainer(propertyRv.newChildId());
+            propertyRv.addOrReplace(associationRvContainer);
+
+            if(association.isOneToOneAssociation()) {
+                final OneToOneAssociation otoa = (OneToOneAssociation) association;
+
+                final PropertyMemento pm = new PropertyMemento(otoa, entityModel.getIsisSessionFactory());
+
+                final ScalarModel scalarModel =
+                        entityModel.getPropertyModel(pm, EntityModel.Mode.VIEW, EntityModel.RenderingHint.REGULAR);
+
+                final Component component = getComponentFactoryRegistry()
+                        .addOrReplaceComponent(associationRvContainer, ID_ASSOCIATION, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
+
+                childComponents.add(component);
+            } else {
+                final String associationId = association.getId();
+
+                final CollectionLayoutData collectionLayoutData = collectionLayoutDataById.get(associationId);
+
+                // successively trample all over; not a problem
+                entityModel.setCollectionLayoutData(collectionLayoutData);
+
+                final Component component = getComponentFactoryRegistry()
+                        .addOrReplaceComponent(associationRvContainer, ID_ASSOCIATION,
+                                ComponentType.ENTITY_COLLECTION, entityModel);
+
+                childComponents.add(component);
+            }
+        }
+
+
+        // either add the built content, or hide entire
+        if(associations.isEmpty()) {
+            Components.permanentlyHide(this, div.getId());
+        } else {
+            this.addOrReplace(div);
+        }
+
+        return childComponents;
+    }
+
+    private List<ObjectAssociation> getObjectAssociations() {
+        return this.getModel().getObject().getSpecification().getAssociations(Contributed.INCLUDED);
+    }
+
+    @Override
+    public void onConfigure() {
+        for (final ScalarPanelAbstract2 childComponent : childScalarPanelAbstract2s) {
+            childComponent.configure();
+        }
+        super.onConfigure();
+    }
+
+    @Override
+    public boolean isVisible() {
+
+        // HACK: there are some components that are not ScalarPanelAbstract2's, eg the pdfjsviewer.
+        // In this case, don't ever hide.
+
+        // TODO: should remove this hack.  We need some sort of SPI for ScalarPanelAbstract2's and any other component,
+        // (eg PdfJsViewer) that can implement.  It's "probably" just a matter of having PdfJsViewer do its work in the
+        // correct Wicket callback (probably onConfigure).
+        if(childComponents.size() > childScalarPanelAbstract2s.size()) {
+            return true;
+        }
+        // HACK:END
+
+        for (final ScalarPanelAbstract2 childComponent : childScalarPanelAbstract2s) {
+            if(childComponent.isVisibilityAllowed()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
index 2e7373d..4faf74a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/fieldset/PropertyGroup.java
@@ -70,7 +70,6 @@ public class PropertyGroup extends PanelAbstract<EntityModel> implements HasDyna
     private static final String ID_PROPERTY = "property";
 
     private final FieldSet fieldSet;
-    private final boolean visible;
     private final List<ScalarPanelAbstract2> childScalarPanelAbstract2s;
     private final List<Component> childComponents;
 
@@ -81,9 +80,6 @@ public class PropertyGroup extends PanelAbstract<EntityModel> implements HasDyna
         // the UI is only ever built once.
         childComponents = buildGui();
         childScalarPanelAbstract2s = FluentIterable.from(childComponents).filter(ScalarPanelAbstract2.class).toList();
-
-        final ImmutableList<ObjectAssociation> associations = getObjectAssociations();
-        this.visible = !associations.isEmpty();
     }
 
     public EntityModel getModel() {
@@ -136,7 +132,6 @@ public class PropertyGroup extends PanelAbstract<EntityModel> implements HasDyna
                     panelHeading, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN,
                     actionsPanelDropDown,
                     AdditionalLinksPanel.Style.DROPDOWN);
-
         }
 
         // either add the built content, or hide entire
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
index 4cd00b6..40ffaea 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
@@ -37,13 +37,17 @@ import org.apache.wicket.model.AbstractReadOnlyModel;
 import org.apache.wicket.request.cycle.RequestCycle;
 
 import org.apache.isis.applib.annotation.PromptStyle;
+import org.apache.isis.applib.layout.grid.Grid;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
 import org.apache.isis.applib.services.metamodel.MetaModelService2;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
 import org.apache.isis.core.metamodel.postprocessors.param.ActionParameterDefaultsFacetFromAssociatedCollection;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionMixedIn;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
@@ -54,6 +58,7 @@ import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ActionPrompt;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptWithExtraContent;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.model.models.FormExecutor;
 import org.apache.isis.viewer.wicket.model.models.InlinePromptContext;
@@ -64,6 +69,8 @@ import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionFormExecutorStrategy;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionParametersPanel;
+import org.apache.isis.viewer.wicket.ui.components.entity.assocgroup.AssociationGroup;
+import org.apache.isis.viewer.wicket.ui.components.layout.bs3.BS3GridPanel;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistryAccessor;
@@ -203,6 +210,41 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
                 actionParametersPanel.setActionPrompt(prompt);
                 prompt.showPrompt(target);
 
+                if(prompt instanceof ActionPromptWithExtraContent) {
+                    final ActionPromptWithExtraContent promptWithExtraContent =
+                            (ActionPromptWithExtraContent) prompt;
+
+                    final ObjectAction action = actionModel.getActionMemento().getAction(getSpecificationLoader());
+                    if(action instanceof ObjectActionMixedIn) {
+                        final ObjectActionMixedIn actionMixedIn = (ObjectActionMixedIn) action;
+                        final ObjectSpecification mixinType = actionMixedIn.getMixinType();
+
+                        if(mixinType.isViewModel()) {
+
+                            final ObjectAdapter targetAdapterForMixin = action.realTargetAdapter(actionModel.getTargetAdapter());
+                            final EntityModel entityModelForMixin = new EntityModel(targetAdapterForMixin);
+
+                            final GridFacet facet = mixinType.getFacet(GridFacet.class);
+                            final Grid gridForMixin = facet.getGrid(targetAdapterForMixin);
+
+                            final String extraContentId = promptWithExtraContent.getExtraContentId();
+
+                            if(gridForMixin instanceof BS3Grid) {
+                                final BS3Grid bs3Grid = (BS3Grid) gridForMixin;
+                                final BS3GridPanel gridPanel = new BS3GridPanel(extraContentId, entityModelForMixin, bs3Grid);
+                                promptWithExtraContent.setExtraContentPanel(gridPanel, target);
+                            } else {
+
+                                final AssociationGroup associationGroup = new AssociationGroup(
+                                        extraContentId, entityModelForMixin, gridForMixin);
+                                promptWithExtraContent.setExtraContentPanel(associationGroup, target);
+                            }
+                        }
+
+
+                    }
+                }
+
                 return prompt;
 
             } else {
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
index 2f4828f..1def935 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -1056,3 +1056,7 @@ ul.sidebar-nav {
     padding-bottom: 62px;
     margin-bottom: 62px;
 }
+
+div.sidebar-panel div.extra-content {
+    margin-top: 30px;
+}
\ No newline at end of file
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
index fcc531f..b89b978 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PromptFormAbstract.java
@@ -188,9 +188,14 @@ public abstract class PromptFormAbstract<T extends BookmarkableModel<ObjectAdapt
 
     protected void closePromptIfAny(final AjaxRequestTarget target) {
 
-        final ActionPromptProvider promptProvider = ActionPromptProvider.Util.getFrom(parentPanel);
-        if(promptProvider != null) {
-            promptProvider.closePrompt(target);
+        try {
+            final ActionPromptProvider promptProvider = ActionPromptProvider.Util.getFrom(parentPanel);
+            if(promptProvider != null) {
+                promptProvider.closePrompt(target);
+            }
+        } catch (org.apache.wicket.WicketRuntimeException ex) {
+            // if "No Page found for component"
+            // do nothing
         }
     }
 
@@ -207,7 +212,12 @@ public abstract class PromptFormAbstract<T extends BookmarkableModel<ObjectAdapt
     }
 
     private UiHintContainer getPageUiHintContainerIfAny() {
-        Page page = getPage();
+        final Page page;
+        try {
+            page = getPage();
+        } catch(org.apache.wicket.WicketRuntimeException ex) {
+            return null;
+        }
         if (page instanceof EntityPage) {
             EntityPage entityPage = (EntityPage) page;
             return entityPage.getUiHintContainerIfAny();