ISIS-993: SessionScopedAttribute factored out, now used for the selectedItem drop-down so that the system remembers which view to use for rendering a collection (for a particular object).
Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/35201392 Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/35201392 Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/35201392 Branch: refs/heads/ISIS-993 Commit: 35201392b424e507e6fc54d6fe8e7381e37b04c8 Parents: d946027 Author: Dan Haywood <d...@haywood-associates.co.uk> Authored: Thu Jan 14 20:16:36 2016 +0000 Committer: Dan Haywood <d...@haywood-associates.co.uk> Committed: Mon Jan 25 15:06:07 2016 +0000 ---------------------------------------------------------------------- .../isis/applib/layout/v1_0/ColumnMetadata.java | 2 +- .../ComponentFactoryRegistrarDefault.java | 4 +- .../model/models/EntityCollectionModel.java | 19 +- .../model/util/ScopedSessionAttribute.java | 118 +++ .../selector/CollectionSelectorHelper.java | 25 + .../selector/CollectionSelectorPanel.java | 25 +- .../CollectionContentsMultipleViewsPanel.java | 3 +- .../components/entity/EntityPanelFactory.java | 8 +- .../collections/EntityCollectionsPanel.java | 14 +- .../components/entity/column/EntityColumn.java | 29 +- .../entity/editable/EntityPropertiesForm.java | 713 ------------------- .../editable/EntityPropertiesForm.properties | 22 - .../entity/editable/EntityPropertiesPanel.html | 52 -- .../entity/editable/EntityPropertiesPanel.java | 60 -- .../editable/EntityPropertiesPanelFactory.java | 46 -- .../propsandcolls/EntityPropsAndCollsForm.java | 713 +++++++++++++++++++ .../EntityPropsAndCollsForm.properties | 22 + .../propsandcolls/EntityPropsAndCollsPanel.html | 52 ++ .../propsandcolls/EntityPropsAndCollsPanel.java | 67 ++ .../EntityPropsAndCollsPanelFactory.java | 53 ++ .../links/EntityLinksSelectorPanel.java | 16 +- .../tabbed/ColumnTabGroupListColumnPanel.html | 34 - .../tabbed/ColumnTabGroupListColumnPanel.java | 113 --- .../entity/tabbed/EntityTabbedPanel.html | 34 + .../entity/tabbed/EntityTabbedPanel.java | 113 +++ .../entity/tabgroup/TabGroupPanel.java | 60 +- 26 files changed, 1315 insertions(+), 1102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnMetadata.java ---------------------------------------------------------------------- diff --git a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnMetadata.java b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnMetadata.java index 3663600..49c681f 100644 --- a/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnMetadata.java +++ b/core/applib/src/main/java/org/apache/isis/applib/layout/v1_0/ColumnMetadata.java @@ -37,7 +37,7 @@ import org.apache.isis.applib.annotation.Programmatic; , "collections" } ) -public class ColumnMetadata implements Serializable, Owner, Owned<ColumnOwner> { +public class ColumnMetadata implements Serializable, Owner, Owned<ColumnOwner>, HasPath { private static final long serialVersionUID = 1L; http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java index 8d16642..c150cf0 100644 --- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java +++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/registries/components/ComponentFactoryRegistrarDefault.java @@ -43,7 +43,7 @@ import org.apache.isis.viewer.wicket.ui.components.entity.collections.EntityColl import org.apache.isis.viewer.wicket.ui.components.entity.header.EntityHeaderPanelFactory; import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconAndTitlePanelFactory; import org.apache.isis.viewer.wicket.ui.components.entity.icontitle.EntityIconTitleAndCopyLinkPanelFactory; -import org.apache.isis.viewer.wicket.ui.components.entity.editable.EntityPropertiesPanelFactory; +import org.apache.isis.viewer.wicket.ui.components.entity.propsandcolls.EntityPropsAndCollsPanelFactory; import org.apache.isis.viewer.wicket.ui.components.entity.selector.links.EntityLinksSelectorPanelFactory; import org.apache.isis.viewer.wicket.ui.components.entity.EntityPanelFactory; import org.apache.isis.viewer.wicket.ui.components.footer.FooterPanelFactory; @@ -172,7 +172,7 @@ public class ComponentFactoryRegistrarDefault implements ComponentFactoryRegistr componentFactories.add(new EntityIconAndTitlePanelFactory()); componentFactories.add(new EntityIconTitleAndCopyLinkPanelFactory()); componentFactories.add(new EntityHeaderPanelFactory()); - componentFactories.add(new EntityPropertiesPanelFactory()); + componentFactories.add(new EntityPropsAndCollsPanelFactory()); componentFactories.add(new EntityCollectionsPanelFactory()); } http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java index f456afc..26f3128 100644 --- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java +++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java @@ -51,6 +51,7 @@ import org.apache.isis.viewer.wicket.model.links.LinkAndLabel; import org.apache.isis.viewer.wicket.model.links.LinksProvider; import org.apache.isis.viewer.wicket.model.mementos.CollectionMemento; import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento; +import org.apache.isis.viewer.wicket.model.util.ScopedSessionAttribute; /** * Model representing a collection of entities, either {@link Type#STANDALONE @@ -432,7 +433,23 @@ public class EntityCollectionModel extends ModelAbstract<List<ObjectAdapter>> im public EntityCollectionModel asDummy() { return new EntityCollectionModel(typeOf, Collections.<ObjectAdapterMemento>emptyList(), pageSize); } - + + // ////////////////////////////////////// + + private ScopedSessionAttribute<Integer> selectedItemSessionAttribute; + + /** + * provides a mechanism to retrieve the selected item (view selector) from the session. + */ + public ScopedSessionAttribute<Integer> getSelectedItemSessionAttribute() { + return selectedItemSessionAttribute; + } + + public void setSelectedItemSessionAttribute(final ScopedSessionAttribute<Integer> selectedItemSessionAttribute) { + this.selectedItemSessionAttribute = selectedItemSessionAttribute; + } + + // ////////////////////////////////////// private static AdapterManager getAdapterManagerStatic() { http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/util/ScopedSessionAttribute.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/util/ScopedSessionAttribute.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/util/ScopedSessionAttribute.java new file mode 100644 index 0000000..d038167 --- /dev/null +++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/util/ScopedSessionAttribute.java @@ -0,0 +1,118 @@ +/* + * 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.model.util; + +import java.io.Serializable; + +import org.apache.wicket.Session; + +import org.apache.isis.applib.layout.v1_0.HasPath; +import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; +import org.apache.isis.core.metamodel.adapter.oid.RootOid; +import org.apache.isis.core.runtime.system.context.IsisContext; +import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento; +import org.apache.isis.viewer.wicket.model.models.EntityModel; + +/** + * Scoped by both {@link EntityModel object} and either {@link HasPath path} (if view metadata is in use) + * or simply a string constructed by some other mechanism ("legacy"). + */ +public class ScopedSessionAttribute<T extends Serializable> implements Serializable { + + private static final long serialVersionUID = 1L; + + public static <T extends Serializable> ScopedSessionAttribute<T> create( + final EntityModel entityModel, + final HasPath hasPath, + final String attributeName) { + final ObjectAdapterMemento objectAdapterMemento = entityModel.getObjectAdapterMemento(); + return create(objectAdapterMemento, hasPath, attributeName); + } + + public static <T extends Serializable> ScopedSessionAttribute<T> create( + final ObjectAdapterMemento objectAdapterMemento, + final HasPath hasPath, + final String attributeName) { + if (hasPath == null) { + return noop(); + } + final String path = hasPath.getPath(); + return create(objectAdapterMemento, path, attributeName); + } + + public static <T extends Serializable> ScopedSessionAttribute<T> create( + final EntityModel entityModel, + final String scopeKey, + final String attributeName) { + final ObjectAdapterMemento objectAdapterMemento = entityModel.getObjectAdapterMemento(); + return create(objectAdapterMemento, scopeKey, attributeName); + } + + public static <T extends Serializable> ScopedSessionAttribute<T> create( + final ObjectAdapterMemento objectAdapterMemento, + final String scopeKey, + final String attributeName) { + if (objectAdapterMemento == null) { + return noop(); + } + final String oidStr = asStr(objectAdapterMemento); + final String key = oidStr + ":" + scopeKey + "#" + attributeName; + return new ScopedSessionAttribute<T>(key); + } + + private static String asStr(final ObjectAdapterMemento objectAdapterMemento) { + final RootOid oid = + (RootOid) objectAdapterMemento.getObjectAdapter(AdapterManager.ConcurrencyChecking.NO_CHECK).getOid(); + return IsisContext.getOidMarshaller().marshalNoVersion(oid); + } + + private final String key; + + private ScopedSessionAttribute(final String key) { + this.key = key; + } + + public void set(T t) { + Session.get().setAttribute(key, t); + } + + public T get() { + return (T) Session.get().getAttribute(key); + } + + public void remove() { + Session.get().removeAttribute(key); + } + + public static <T extends Serializable> ScopedSessionAttribute<T> noop() { + return new ScopedSessionAttribute<T>(null) { + @Override public void set(final T serializable) { + } + + @Override public T get() { + return null; + } + + @Override public void remove() { + } + }; + } + + +} http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java index 9267389..34d58da 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java @@ -42,6 +42,7 @@ import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry; import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory; import org.apache.isis.viewer.wicket.ui.components.collectioncontents.multiple.CollectionContentsMultipleViewsPanelFactory; import org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsAsUnresolvedPanelFactory; +import org.apache.isis.viewer.wicket.model.util.ScopedSessionAttribute; public class CollectionSelectorHelper implements Serializable { @@ -50,13 +51,27 @@ public class CollectionSelectorHelper implements Serializable { static final String UIHINT_EVENT_VIEW_KEY = "view"; private final EntityCollectionModel model; + private final List<ComponentFactory> componentFactories; + private final ScopedSessionAttribute<Integer> selectedItemSessionAttribute; public CollectionSelectorHelper( final EntityCollectionModel model, final ComponentFactoryRegistry componentFactoryRegistry) { + this(model, componentFactoryRegistry, ScopedSessionAttribute.<Integer>noop()); + } + + public CollectionSelectorHelper( + final EntityCollectionModel model, + final ComponentFactoryRegistry componentFactoryRegistry, + final ScopedSessionAttribute<Integer> selectedItemSessionAttribute) { this.model = model; this.componentFactories = locateComponentFactories(componentFactoryRegistry); + this.selectedItemSessionAttribute = + selectedItemSessionAttribute != null + ? selectedItemSessionAttribute + : ScopedSessionAttribute.<Integer>noop(); + model.setSelectedItemSessionAttribute(selectedItemSessionAttribute); } private List<ComponentFactory> locateComponentFactories(ComponentFactoryRegistry componentFactoryRegistry) { @@ -108,6 +123,14 @@ public class CollectionSelectorHelper implements Serializable { * otherwise first factory. */ private int determineInitialFactory() { + + // try to load from session, if can + final Integer sessionAttribute = selectedItemSessionAttribute.get(); + if(sessionAttribute != null) { + return sessionAttribute; + } + + // else @CollectionLayout#defaultView attribute if (hasDefaultViewFacet(model)) { DefaultViewFacet defaultViewFacet = model.getCollectionMemento().getCollection().getFacet(DefaultViewFacet.class); for (int i = 0; i < componentFactories.size(); i++) { @@ -118,6 +141,8 @@ public class CollectionSelectorHelper implements Serializable { } } } + + // else @CollectionLayout#renderEagerly if (!hasRenderEagerlyFacet(model)) { for (int i = 0; i < componentFactories.size(); i++) { if (componentFactories.get(i) instanceof CollectionContentsAsUnresolvedPanelFactory) { http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java index 02aa720..0fa075b 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java @@ -19,9 +19,8 @@ package org.apache.isis.viewer.wicket.ui.components.collection.selector; -import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons; - import java.util.List; + import org.apache.wicket.AttributeModifier; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; @@ -34,6 +33,7 @@ import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; + import org.apache.isis.core.commons.lang.StringExtensions; import org.apache.isis.viewer.wicket.model.hints.IsisUiHintEvent; import org.apache.isis.viewer.wicket.model.hints.UiHintContainer; @@ -42,9 +42,12 @@ import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel; import org.apache.isis.viewer.wicket.model.models.EntityModel; import org.apache.isis.viewer.wicket.ui.CollectionContentsAsFactory; import org.apache.isis.viewer.wicket.ui.ComponentFactory; +import org.apache.isis.viewer.wicket.model.util.ScopedSessionAttribute; import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; +import de.agilecoders.wicket.core.markup.html.bootstrap.button.Buttons; + /** * Provides a list of links for selecting other views that support * {@link org.apache.isis.viewer.wicket.ui.ComponentType#COLLECTION_CONTENTS} with a backing @@ -66,12 +69,25 @@ public class CollectionSelectorPanel private static final String ID_VIEW_BUTTON_ICON = "viewButtonIcon"; private final CollectionSelectorHelper selectorHelper; + private final ScopedSessionAttribute<Integer> selectedItemSessionAttribute; private ComponentFactory selectedComponentFactory; - public CollectionSelectorPanel(final String id, final EntityCollectionModel model) { + public CollectionSelectorPanel( + final String id, + final EntityCollectionModel model) { + this(id, model, ScopedSessionAttribute.<Integer>noop()); + } + + public CollectionSelectorPanel( + final String id, + final EntityCollectionModel model, + final ScopedSessionAttribute<Integer> selectedItemSessionAttribute) { super(id, model); - selectorHelper = new CollectionSelectorHelper(model, getComponentFactoryRegistry()); + this.selectedItemSessionAttribute = selectedItemSessionAttribute; + + selectorHelper = new CollectionSelectorHelper( + model, getComponentFactoryRegistry(), selectedItemSessionAttribute); } /** @@ -130,6 +146,7 @@ public class CollectionSelectorPanel linksSelectorPanel.setViewHintAndBroadcast(underlyingViewNum, target); linksSelectorPanel.selectedComponentFactory = componentFactory; + selectedItemSessionAttribute.set(underlyingViewNum); target.add(linksSelectorPanel, views); } http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java index 8c3a1e6..eec4e99 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java @@ -73,8 +73,7 @@ public class CollectionContentsMultipleViewsPanel this.ignoreFactory = ignoreFactory; this.underlyingIdPrefix = ComponentType.COLLECTION_CONTENTS.toString(); this.componentType = ignoreFactory.getComponentType(); - selectorHelper = new CollectionSelectorHelper(model, getComponentFactoryRegistry()); - + selectorHelper = new CollectionSelectorHelper(model, getComponentFactoryRegistry(), model.getSelectedItemSessionAttribute()); } /** http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityPanelFactory.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityPanelFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityPanelFactory.java index 6db00fe..4020bd2 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityPanelFactory.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityPanelFactory.java @@ -29,10 +29,10 @@ import org.apache.isis.viewer.wicket.model.models.EntityModel; import org.apache.isis.viewer.wicket.ui.ComponentFactory; import org.apache.isis.viewer.wicket.ui.ComponentType; import org.apache.isis.viewer.wicket.ui.components.entity.editable.EntityEditablePanel; -import org.apache.isis.viewer.wicket.ui.components.entity.tabbed.ColumnTabGroupListColumnPanel; +import org.apache.isis.viewer.wicket.ui.components.entity.tabbed.EntityTabbedPanel; /** - * {@link ComponentFactory} for {@link ColumnTabGroupListColumnPanel}. + * {@link ComponentFactory} for {@link EntityTabbedPanel}. */ public class EntityPanelFactory extends EntityComponentFactoryAbstract { @@ -41,7 +41,7 @@ public class EntityPanelFactory extends EntityComponentFactoryAbstract { private static final String NAME = "tabbed"; public EntityPanelFactory() { - super(ComponentType.ENTITY, NAME, ColumnTabGroupListColumnPanel.class); + super(ComponentType.ENTITY, NAME, EntityTabbedPanel.class); } @Override @@ -54,7 +54,7 @@ public class EntityPanelFactory extends EntityComponentFactoryAbstract { final ObjectLayoutMetadata layoutMetadata = facet.getMetadata(); final boolean hasLayout = layoutMetadata != null; return hasLayout - ? new ColumnTabGroupListColumnPanel(id, entityModel) + ? new EntityTabbedPanel(id, entityModel) : new EntityEditablePanel(id, entityModel); } } http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java index 9cbe7e4..a3c4979 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java @@ -53,6 +53,7 @@ import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.Addi import org.apache.isis.viewer.wicket.ui.components.collection.CollectionPanel; import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorHelper; import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorPanel; +import org.apache.isis.viewer.wicket.model.util.ScopedSessionAttribute; import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPathSignificantWebMarkupContainer; import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; @@ -74,9 +75,16 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> { private static final String ID_ADDITIONAL_LINKS = "additionalLinks"; private static final String ID_SELECTOR_DROPDOWN = "selectorDropdown"; + // view metadata (if any available) + private final ColumnMetadata columnMetadataIfAny; + private final ScopedSessionAttribute<Integer> selectedItemSessionAttribute; + public EntityCollectionsPanel(final String id, final EntityModel entityModel) { super(id, entityModel); + columnMetadataIfAny = entityModel.getColumnMetadata(); + selectedItemSessionAttribute = ScopedSessionAttribute.create(entityModel, columnMetadataIfAny, "selectedItem"); + buildGui(); } @@ -99,7 +107,6 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> { final EntityModel entityModel = getModel(); final ObjectAdapter adapter = entityModel.getObject(); - final ColumnMetadata columnMetadataIfAny = entityModel.getColumnMetadata(); final Filter<ObjectAssociation> filter; if (columnMetadataIfAny != null) { final ImmutableList<String> collectionIds = FluentIterable @@ -176,7 +183,8 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> { AdditionalLinksPanel.addAdditionalLinks (fieldset,ID_ADDITIONAL_LINKS, links, AdditionalLinksPanel.Style.INLINE_LIST); - final CollectionSelectorHelper selectorHelper = new CollectionSelectorHelper(entityCollectionModel, getComponentFactoryRegistry()); + final CollectionSelectorHelper selectorHelper = new CollectionSelectorHelper(entityCollectionModel, getComponentFactoryRegistry(), selectedItemSessionAttribute + ); final List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories(); @@ -184,7 +192,7 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> { permanentlyHide(ID_SELECTOR_DROPDOWN); } else { CollectionSelectorPanel selectorDropdownPanel; - selectorDropdownPanel = new CollectionSelectorPanel(ID_SELECTOR_DROPDOWN, entityCollectionModel); + selectorDropdownPanel = new CollectionSelectorPanel(ID_SELECTOR_DROPDOWN, entityCollectionModel, selectedItemSessionAttribute); final Model<ComponentFactory> componentFactoryModel = new Model<>(); http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java index 43ab95b..ea71425 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java @@ -34,6 +34,7 @@ import org.apache.isis.applib.annotation.ActionLayout; import org.apache.isis.applib.layout.v1_0.ColumnMetadata; import org.apache.isis.applib.layout.v1_0.PropertyGroupMetadata; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; +import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.ObjectSpecifications; import org.apache.isis.core.metamodel.spec.feature.ObjectAction; @@ -53,6 +54,16 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.containers.UiHintPath import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; import org.apache.isis.viewer.wicket.ui.util.Components; +/** + * Adds properties (in property groups) and collections to a column. + * + * <p> + * If {@link ColumnMetadata} is present, then only those properties and collections for that + * column metadata are rendered. Otherwise the {@link MemberGroupLayoutFacet} on the + * {@link ObjectSpecification} in conjunction with the provided {@link ColumnMetadata.Hint} is + * used to filter down to just those properties/collections in the column. + * </p> + */ public class EntityColumn extends PanelAbstract<EntityModel> { private static final long serialVersionUID = 1L; @@ -66,15 +77,19 @@ public class EntityColumn extends PanelAbstract<EntityModel> { private static final String ID_PROPERTIES = "properties"; private static final String ID_PROPERTY = "property"; - private final Component owningPanel; + // view metadata (populated for EntityTabbedPanel, absent for EntityEditablePanel) + private final ColumnMetadata columnMetaDataIfAny; + // which column to render (populated for EntityEditablePanel, not required and so absent for EntityTabbedPanel) + final ColumnMetadata.Hint hint; public EntityColumn( final String id, - final EntityModel entityModel, - final Component owningPanel) { + final EntityModel entityModel) { super(id, entityModel); - this.owningPanel = owningPanel; // for repainting, perhaps + + columnMetaDataIfAny = entityModel.getColumnMetadata(); + hint = entityModel.getColumnHint(); buildGui(); } @@ -94,8 +109,6 @@ public class EntityColumn extends PanelAbstract<EntityModel> { final MarkupContainer markupContainer, final EntityModel entityModel) { - final ColumnMetadata columnMetaDataIfAny = entityModel.getColumnMetadata(); - final ColumnMetadata.Hint hint = entityModel.getColumnHint(); final ObjectAdapter adapter = entityModel.getObject(); final ObjectSpecification objSpec = adapter.getSpecification(); @@ -153,8 +166,6 @@ public class EntityColumn extends PanelAbstract<EntityModel> { final MarkupContainer column, final EntityModel entityModel) { - final ColumnMetadata columnMetaDataIfAny = entityModel.getColumnMetadata(); - if(columnMetaDataIfAny != null) { getComponentFactoryRegistry() .addOrReplaceComponent(column, "collections", ComponentType.ENTITY_COLLECTIONS, entityModel); @@ -171,7 +182,7 @@ public class EntityColumn extends PanelAbstract<EntityModel> { final PropertyMemento pm = new PropertyMemento(otoa); final ScalarModel scalarModel = entityModel.getPropertyModel(pm); - final Component component = getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel); + getComponentFactoryRegistry().addOrReplaceComponent(container, ID_PROPERTY, ComponentType.SCALAR_NAME_AND_VALUE, scalarModel); final List<ObjectAction> associatedActions = EntityActionUtil.getObjectActionsForAssociation(entityModel, otoa, getDeploymentType()); http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.java deleted file mode 100644 index 08bbc88..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.java +++ /dev/null @@ -1,713 +0,0 @@ -/* - * 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.editable; - -import java.util.List; - -import org.apache.wicket.Component; -import org.apache.wicket.MarkupContainer; -import org.apache.wicket.Session; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; -import org.apache.wicket.ajax.markup.html.form.AjaxButton; -import org.apache.wicket.feedback.ComponentFeedbackMessageFilter; -import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.html.form.Button; -import org.apache.wicket.markup.html.form.Form; -import org.apache.wicket.markup.html.form.FormComponent; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.ResourceModel; -import org.apache.wicket.request.Response; -import org.apache.wicket.util.string.Strings; -import org.apache.wicket.util.visit.IVisit; -import org.apache.wicket.util.visit.IVisitor; - -import org.apache.isis.applib.annotation.MemberGroupLayout.ColumnSpans; -import org.apache.isis.applib.annotation.Where; -import org.apache.isis.applib.filter.Filter; -import org.apache.isis.applib.filter.Filters; -import org.apache.isis.applib.layout.v1_0.ColumnMetadata; -import org.apache.isis.applib.layout.v1_0.ColumnMetadata.Hint; -import org.apache.isis.applib.layout.v1_0.TabMetadata; -import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer; -import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite; -import org.apache.isis.core.commons.authentication.MessageBroker; -import org.apache.isis.core.metamodel.adapter.ObjectAdapter; -import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking; -import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException; -import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; -import org.apache.isis.core.metamodel.facets.object.membergroups.MemberGroupLayoutFacet; -import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.spec.feature.Contributed; -import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; -import org.apache.isis.core.runtime.memento.Memento; -import org.apache.isis.core.runtime.system.context.IsisContext; -import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; -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.EntityModel; -import org.apache.isis.viewer.wicket.ui.ComponentType; -import org.apache.isis.viewer.wicket.ui.components.entity.PropUtil; -import org.apache.isis.viewer.wicket.ui.components.entity.column.EntityColumn; -import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired; -import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour; -import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage; -import org.apache.isis.viewer.wicket.ui.panels.FormAbstract; -import org.apache.isis.viewer.wicket.ui.panels.IFormSubmitterWithPreValidateHook; -import org.apache.isis.viewer.wicket.ui.util.Components; -import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; - -import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel; -import de.agilecoders.wicket.core.util.Attributes; - -public class EntityPropertiesForm extends FormAbstract<ObjectAdapter> implements ActionPromptProvider { - - private static final long serialVersionUID = 1L; - - private static final String ID_LEFT_COLUMN = "leftColumn"; - private static final String ID_MIDDLE_COLUMN = "middleColumn"; - private static final String ID_RIGHT_COLUMN = "rightColumn"; - - private static final String ID_ENTITY_COLLECTIONS = "entityCollections"; - private static final String ID_ENTITY_COLLECTIONS_OVERFLOW = "entityCollectionsOverflow"; - - private static final String ID_EDIT_BUTTON = "edit"; - private static final String ID_OK_BUTTON = "ok"; - private static final String ID_CANCEL_BUTTON = "cancel"; - - private static final String ID_FEEDBACK = "feedback"; - - private final Component owningPanel; - - private Button editButton; - private Button okButton; - private Button cancelButton; - - private NotificationPanel feedback; - - - public EntityPropertiesForm( - final String id, - final EntityModel entityModel, - final Component owningPanel) { - - super(id, entityModel); - this.owningPanel = owningPanel; // for repainting - - buildGui(); - - // add any concurrency exception that might have been propagated into the entity model - // as a result of a previous action invocation - final String concurrencyExceptionIfAny = entityModel.getAndClearConcurrencyExceptionIfAny(); - if(concurrencyExceptionIfAny != null) { - error(concurrencyExceptionIfAny); - } - } - - private void buildGui() { - - final EntityModel entityModel = (EntityModel) getModel(); - final TabMetadata tabMetaDataIfAny = entityModel.getTabMetadata(); - - final ColumnSpans columnSpans; - if(tabMetaDataIfAny != null) { - final ColumnMetadata middle = tabMetaDataIfAny.getMiddle(); - final ColumnMetadata right = tabMetaDataIfAny.getRight(); - columnSpans = ColumnSpans.asSpans( - tabMetaDataIfAny.getLeft().getSpan(), - middle != null? middle.getSpan(): 0, - right != null? right.getSpan(): 0); - } else { - final MemberGroupLayoutFacet memberGroupLayoutFacet = - entityModel.getObject().getSpecification().getFacet(MemberGroupLayoutFacet.class); - columnSpans = memberGroupLayoutFacet.getColumnSpans(); - } - - // left column - // (unlike middle and right columns, the left column is always added to hold the edit buttons and feedback) - MarkupContainer leftColumn = new WebMarkupContainer(ID_LEFT_COLUMN); - add(leftColumn); - - if(columnSpans.getLeft() > 0) { - - addPropertiesAndCollections(leftColumn, entityModel, tabMetaDataIfAny, Hint.LEFT); - - } else { - Components.permanentlyHide(this, ID_LEFT_COLUMN); - } - - // middle column - MarkupContainer middleColumn; - if(columnSpans.getMiddle() > 0) { - middleColumn = new WebMarkupContainer(ID_MIDDLE_COLUMN); - add(middleColumn); - - addPropertiesAndCollections(middleColumn, entityModel, tabMetaDataIfAny, Hint.MIDDLE); - } else { - middleColumn = null; - Components.permanentlyHide(this, ID_MIDDLE_COLUMN); - } - - // right column - MarkupContainer rightColumn; - if(columnSpans.getRight() > 0) { - rightColumn = new WebMarkupContainer(ID_RIGHT_COLUMN); - add(rightColumn); - - addPropertiesAndCollections(rightColumn, entityModel, tabMetaDataIfAny, Hint.RIGHT); - } else { - rightColumn = null; - Components.permanentlyHide(this, ID_RIGHT_COLUMN); - } - - // column spans - if(columnSpans.getLeft() > 0) { - addClassForSpan(leftColumn, Hint.LEFT.from(columnSpans)); - } - if(columnSpans.getMiddle() > 0) { - addClassForSpan(middleColumn, Hint.MIDDLE.from(columnSpans)); - } - if(columnSpans.getRight() > 0) { - addClassForSpan(rightColumn, Hint.RIGHT.from(columnSpans)); - } - - // edit buttons and feedback (not supported on tabbed view) - final Hint leftHint = Hint.LEFT; - final ColumnMetadata leftColumnMetaDataIfAny = leftHint.from(tabMetaDataIfAny); - final boolean hasProperties = leftColumnMetaDataIfAny == null && !PropUtil - .propertyGroupNames(entityModel, leftHint, leftColumnMetaDataIfAny).isEmpty(); - if (hasProperties) { - addButtons(leftColumn); - addFeedbackGui(leftColumn); - - } else { - Components.permanentlyHide(leftColumn, - ID_EDIT_BUTTON, ID_OK_BUTTON, ID_CANCEL_BUTTON, - ID_FEEDBACK); - } - - - // collections (only if not being added to a tab) - if(tabMetaDataIfAny == null && columnSpans.getCollections() > 0) { - final String idCollectionsToShow; - final String idCollectionsToHide; - int collectionSpan; - if (columnSpans.exceedsRow()) { - idCollectionsToShow = ID_ENTITY_COLLECTIONS_OVERFLOW; - idCollectionsToHide = ID_ENTITY_COLLECTIONS; - collectionSpan = 12; - } else { - idCollectionsToShow = ID_ENTITY_COLLECTIONS; - idCollectionsToHide = ID_ENTITY_COLLECTIONS_OVERFLOW; - collectionSpan = columnSpans.getCollections(); - } - - final Component collectionsColumn = - getComponentFactoryRegistry().addOrReplaceComponent( - this, idCollectionsToShow, ComponentType.ENTITY_COLLECTIONS, entityModel); - addClassForSpan(collectionsColumn, collectionSpan); - - Components.permanentlyHide(this, idCollectionsToHide); - } else { - Components.permanentlyHide(this, ID_ENTITY_COLLECTIONS); - Components.permanentlyHide(this, ID_ENTITY_COLLECTIONS_OVERFLOW); - } - } - - private void addPropertiesAndCollections( - final MarkupContainer markupContainer, - final EntityModel entityModel, - final TabMetadata tabMetaDataIfAny, - final Hint hint) { - final ColumnMetadata columnMetaDataIfAny = hint.from(tabMetaDataIfAny); - - final EntityModel entityModelWithHints = entityModel.cloneWithColumnMetadata(columnMetaDataIfAny, hint); - - final EntityColumn columnMembers = - new EntityColumn("entityMembers", entityModelWithHints, markupContainer); - markupContainer.add(columnMembers); - } - - - @Override - protected void onComponentTag(ComponentTag tag) { - super.onComponentTag(tag); - - Attributes.addClass(tag, "form-horizontal"); - } - - @Override - public ActionPrompt getActionPrompt() { - return ActionPromptProvider.Util.getFrom(this).getActionPrompt(); - } - - abstract class AjaxButtonWithOnError extends AjaxButton { - - public AjaxButtonWithOnError(String id, IModel<String> model) { - super(id, model); - } - - @Override - protected void onError(AjaxRequestTarget target, Form<?> form) { - super.onError(target, form); - toEditMode(target); - } - - /** - * Render the 'type' attribute even for invisible buttons to avoid - * <a href="https://github.com/twbs/bootlint/wiki/W007">Bootlint W007</a> - * - * @param tag The component tag to render - * @param response The response to write to - */ - // TODO mgrigorov Move this to Wicket Bootstrap project - @Override - protected void renderPlaceholderTag(ComponentTag tag, Response response) { - String ns = Strings.isEmpty(tag.getNamespace()) ? null : tag.getNamespace() + ':'; - - response.write("<"); - if (ns != null) - { - response.write(ns); - } - response.write(tag.getName()); - response.write(" id=\""); - response.write(getAjaxRegionMarkupId()); - - String type = tag.getAttribute("type"); - if (!Strings.isEmpty(type)) { - response.write("\" type=\""+type); - } - - response.write("\" style=\"display:none\"></"); - if (ns != null) - { - response.write(ns); - } - response.write(tag.getName()); - response.write(">"); - } - } - - public class AjaxButtonForValidate extends AjaxButtonWithOnError implements IFormSubmitterWithPreValidateHook { - private static final long serialVersionUID = 1L; - public AjaxButtonForValidate(String id, IModel<String> model) { - super(id, model); - } - - @Override - public String preValidate() { - // attempt to load with concurrency checking, catching recognized exceptions - try { - getEntityModel().load(ConcurrencyChecking.CHECK); // could have also just called #getObject(), since CHECK is the default - - } catch(ConcurrencyException ex){ - String recognizedErrorMessage = recognizeException(ex); - if(recognizedErrorMessage == null) { - throw ex; - } - - // reload - getEntityModel().load(ConcurrencyChecking.NO_CHECK); - - getForm().clearInput(); - getEntityModel().resetPropertyModels(); - - toViewMode(null); - toEditMode(null); - - return recognizedErrorMessage; - } - - return null; - } - - @Override - public void validate() { - // add in any error message that we might have recognized from above - EntityPropertiesForm form = EntityPropertiesForm.this; - String preValidationErrorIfAny = form.getPreValidationErrorIfAny(); - - if(preValidationErrorIfAny != null) { - feedbackOrNotifyAnyRecognizedError(preValidationErrorIfAny, form); - // skip validation, because would relate to old values - - final EntityPage entityPage = new EntityPage(EntityPropertiesForm.this.getModelObject(), null); - EntityPropertiesForm.this.setResponsePage(entityPage); - } else { - // run Wicket's validation - super.validate(); - } - } - - @Override - protected void onSubmit(AjaxRequestTarget target, Form<?> form) { - - if (getForm().hasError()) { - // stay in edit mode - return; - } - - doPreApply(); - if (applyFormChangesElse(target)) return; - final Object redirectIfAny = doPostApply(); - - if (flushChangesElse(target)) return; - - - getEntityModel().resetPropertyModels(); - - toViewMode(null); - - // "redirect-after-post" - // - // RequestCycle.get().getActiveRequestHandler() indicates this is handled by the ListenerInterfaceRequestHandler - // which renders page at end. - // - // it's necessary to zap the page parameters (so mapping is to just wicket/page?nn) - // otherwise (what I think happens) is that the httpServletResponse.sendRedirect ends up being to the same URL, - // and this is rejected as invalid either by the browser or by the servlet container (perhaps only if running remotely). - // - - final ObjectAdapter objectAdapter; - if(redirectIfAny != null) { - objectAdapter = getPersistenceSession().adapterFor(redirectIfAny); - } else { - // we obtain the adapter from the entity model because (if a view model) then the entity model may contain - // a different adapter (the cloned view model) to the one with which we started with. - objectAdapter = getEntityModel().getObjectAdapterMemento().getObjectAdapter(ConcurrencyChecking.NO_CHECK); - } - - final EntityPage entityPage = new EntityPage(objectAdapter, null); - EntityPropertiesForm.this.setResponsePage(entityPage); - } - - /** - * Optional hook to override. - * - * <p> - * If a non-null value is returned, then transition to it (ie eg the finish() transition for a wizard). - * </p> - */ - protected void doPreApply() { - } - - /** - * Optional hook to override. - * - * <p> - * If a non-null value is returned, then transition to it (ie eg the finish() transition for a wizard). - * </p> - */ - protected Object doPostApply() { - return null; - } - - } - - abstract class AjaxButtonForCancel extends AjaxButtonWithOnError { - - public AjaxButtonForCancel(String id, IModel<String> model) { - super(id, model); - setDefaultFormProcessing(false); - } - } - - - private void addButtons(MarkupContainer markupContainer) { - - // edit button - editButton = new AjaxButtonWithOnError(ID_EDIT_BUTTON, new ResourceModel("editLabel")) { - private static final long serialVersionUID = 1L; - - @Override - public void validate() { - - // same logic as in cancelButton; should this be factored out? - try { - getEntityModel().load(ConcurrencyChecking.CHECK); - } catch(ConcurrencyException ex) { - getMessageBroker().addMessage("Object changed by " + ex.getOid().getVersion().getUser() + ", automatically reloading"); - getEntityModel().load(ConcurrencyChecking.NO_CHECK); - } - - super.validate(); - } - - @Override - public void onSubmit(final AjaxRequestTarget target, final Form<?> form) { - getEntityModel().resetPropertyModels(); - toEditMode(target); - } - - @Override - protected void updateAjaxAttributes(AjaxRequestAttributes attributes) { - super.updateAjaxAttributes(attributes); - attributes.getAjaxCallListeners().add(new org.apache.wicket.ajax.attributes.AjaxCallListener(){ - - private static final long serialVersionUID = 1L; - - @Override - public CharSequence getSuccessHandler(Component component) { - // scroll to the top of the entity panel - return "$('html, body').animate({" - + " scrollTop: $('.entityIconAndTitlePanel').offset().top" - + " }, 1000);"; - } - }); - } - }; - editButton.add(new Label("editLabel", editButton.getModel())); - markupContainer.add(editButton); - - - // ok button - okButton = new AjaxButtonForValidate(ID_OK_BUTTON, new ResourceModel("okLabel")); - markupContainer.add(okButton); - - - // cancel button - cancelButton = new AjaxButtonForCancel(ID_CANCEL_BUTTON, new ResourceModel("cancelLabel")) { - private static final long serialVersionUID = 1L; - - @Override - public void validate() { - - // same logic as in editButton; should this be factored out? - try { - getEntityModel().load(ConcurrencyChecking.CHECK); - } catch(ConcurrencyException ex) { - getMessageBroker().addMessage("Object changed by " + ex.getOid().getVersion().getUser() + ", automatically reloading"); - getEntityModel().load(ConcurrencyChecking.NO_CHECK); - } - super.validate(); - } - - @Override - protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { - Session.get().getFeedbackMessages().clear(); - getForm().clearInput(); - getForm().visitFormComponentsPostOrder(new IVisitor<FormComponent<?>, Void>() { - - @Override - public void component(FormComponent<?> formComponent, IVisit<Void> visit) { - if (formComponent instanceof CancelHintRequired) { - final CancelHintRequired cancelHintRequired = (CancelHintRequired) formComponent; - cancelHintRequired.onCancel(); - } - } - }); - - try { - getEntityModel().resetPropertyModels(); - } catch(RuntimeException ex) { - throw ex; - } - toViewMode(target); - } - }; - - markupContainer.add(cancelButton); - - okButton.setOutputMarkupPlaceholderTag(true); - editButton.setOutputMarkupPlaceholderTag(true); - cancelButton.setOutputMarkupPlaceholderTag(true); - - // flush any JGrowl messages (typically concurrency exceptions) if they are added. - okButton.add(new JGrowlBehaviour()); - editButton.add(new JGrowlBehaviour()); - cancelButton.add(new JGrowlBehaviour()); - } - - // to perform object-level validation, we must apply the changes first - // contrast this with ActionPanel (for validating actionarguments) where - // we do the validation prior to the execution of the action - private boolean applyFormChangesElse(AjaxRequestTarget target) { - final ObjectAdapter adapter = getEntityModel().getObject(); - final Memento snapshotToRollbackToIfInvalid = new Memento(adapter); - - getEntityModel().apply(); - final String invalidReasonIfAny = getEntityModel().getReasonInvalidIfAny(); - if (invalidReasonIfAny != null) { - error(invalidReasonIfAny); - snapshotToRollbackToIfInvalid.recreateObject(); - toEditMode(target); - - // abort otherwise the object will have been dirtied and JDO will end up committing, - // possibly bumping the version and resulting in a subsequent concurrency exception. - IsisContext.getTransactionManager().abortTransaction(); - return true; - } - return false; - } - - private boolean flushChangesElse(AjaxRequestTarget target) { - try { - this.getTransactionManager().flushTransaction(); - } catch(RuntimeException ex) { - - // There's no need to abort the transaction here, as it will have already been done - // (in IsisTransactionManager#executeWithinTransaction(...)). - - String message = recognizeExceptionAndNotify(ex, this); - if(message == null) { - throw ex; - } - - toEditMode(target); - return true; - } - return false; - } - - - private String recognizeExceptionAndNotify(RuntimeException ex, Component feedbackComponentIfAny) { - - // see if the exception is recognized as being a non-serious error - - String recognizedErrorMessageIfAny = recognizeException(ex); - feedbackOrNotifyAnyRecognizedError(recognizedErrorMessageIfAny, feedbackComponentIfAny); - - return recognizedErrorMessageIfAny; - } - - private void feedbackOrNotifyAnyRecognizedError(String recognizedErrorMessageIfAny, Component feedbackComponentIfAny) { - if(recognizedErrorMessageIfAny == null) { - return; - } - - if(feedbackComponentIfAny != null) { - feedbackComponentIfAny.error(recognizedErrorMessageIfAny); - } - getMessageBroker().addWarning(recognizedErrorMessageIfAny); - - // we clear the abort cause because we've handled rendering the exception - getTransactionManager().getTransaction().clearAbortCause(); - } - - private String recognizeException(RuntimeException ex) { - - // REVIEW: this code is similar to stuff in EntityPropertiesForm, perhaps move up to superclass? - // REVIEW: similar code also in WebRequestCycleForIsis; combine? - - final List<ExceptionRecognizer> exceptionRecognizers = getServicesInjector().lookupServices(ExceptionRecognizer.class); - final String message = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex); - return message; - } - - private void requestRepaintPanel(final AjaxRequestTarget target) { - if (target != null) { - target.add(owningPanel); - // TODO: is it necessary to add these too? - target.add(editButton, okButton, cancelButton, feedback); - } - } - - private EntityModel getEntityModel() { - return (EntityModel) getModel(); - } - - void toViewMode(final AjaxRequestTarget target) { - - getEntityModel().toViewMode(); - - setVisible(editButton, isAnythingEditable()); - setVisible(okButton, false); - setVisible(cancelButton, false); - - requestRepaintPanel(target); - } - - private void setVisible(Button b, boolean editable) { - if(b != null) { - b.setVisible(editable); - } - } - - private boolean isAnythingEditable() { - final EntityModel entityModel = (EntityModel) getModel(); - final ObjectAdapter adapter = entityModel.getObject(); - - return !enabledAssociations(adapter, adapter.getSpecification()).isEmpty(); - } - - private List<ObjectAssociation> enabledAssociations(final ObjectAdapter adapter, final ObjectSpecification objSpec) { - return objSpec.getAssociations(Contributed.EXCLUDED, enabledAssociationFilter(adapter)); - } - - @SuppressWarnings("unchecked") - private Filter<ObjectAssociation> enabledAssociationFilter(final ObjectAdapter adapter) { - return Filters.and(ObjectAssociation.Filters.PROPERTIES, ObjectAssociation.Filters.enabled(adapter, - InteractionInitiatedBy.USER, Where.OBJECT_FORMS - )); - } - - private void toEditMode(final AjaxRequestTarget target) { - getEntityModel().toEditMode(); - - editButton.setVisible(false); - okButton.setVisible(true); - cancelButton.setVisible(true); - - requestRepaintPanel(target); - } - - private void addFeedbackGui(final MarkupContainer markupContainer) { - feedback = new NotificationPanel(ID_FEEDBACK, this, new ComponentFeedbackMessageFilter(this)); - feedback.setOutputMarkupPlaceholderTag(true); - markupContainer.addOrReplace(feedback); - - // to avoid potential XSS attacks, no longer escape model strings - // (risk is low but could just happen: error message being rendered might accidentally or deliberately contain rogue Javascript) - // feedback.setEscapeModelStrings(false); - - final ObjectAdapter adapter = getEntityModel().getObject(); - if (adapter == null) { - feedback.error("cannot locate object:" + getEntityModel().getObjectAdapterMemento().toString()); - } - } - - - static void addClassForSpan(final Component component, final int numGridCols) { - component.add(new CssClassAppender("col-xs-"+numGridCols)); - } - - - - /////////////////////////////////////////////////////// - // Dependencies (from context) - /////////////////////////////////////////////////////// - - protected IsisTransactionManager getTransactionManager() { - return IsisContext.getTransactionManager(); - } - - protected ServicesInjector getServicesInjector() { - return IsisContext.getPersistenceSession().getServicesInjector(); - } - - protected MessageBroker getMessageBroker() { - return getAuthenticationSession().getMessageBroker(); - } - - -} http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.properties ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.properties b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.properties deleted file mode 100644 index 71edcd9..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.properties +++ /dev/null @@ -1,22 +0,0 @@ -# -# 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. -# - -okLabel=OK -cancelLabel=Cancel -editLabel=Edit http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.html ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.html deleted file mode 100644 index e204c12..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.html +++ /dev/null @@ -1,52 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - 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. ---> -<html xmlns:wicket="http://wicket.apache.org"> - <body> - <wicket:panel> - <div class="entityPropertiesPanel entityPropertiesComponentType"> - <form wicket:id="entityProperties" class="inputForm" role="form"> - <div class="row"> - <div wicket:id="leftColumn"> - <div wicket:id="entityMembers"/> - <div class="feedbackPanel"> - <span wicket:id="feedback"></span> - </div> - <div class="buttons"> - <button type="submit" class="edit btn btn-primary btn-md" wicket:id="edit"><span class="fa fa-edit"></span> <wicket:container wicket:id="editLabel"></wicket:container></button> - <input type="submit" class="ok btn btn-primary btn-md" wicket:id="ok"/> - <input type="submit" class="cancel btn btn-default btn-md" wicket:id="cancel"/> - </div> - </div> - <div wicket:id="middleColumn"> - <div wicket:id="entityMembers"/> - </div> - <div wicket:id="rightColumn"> - <div wicket:id="entityMembers"/> - </div> - <div wicket:id="entityCollections"></div> - </div> - <div class="row"> - <div wicket:id="entityCollectionsOverflow"></div> - </div> - </form> - </div> - </wicket:panel> - </body> -</html> http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.java deleted file mode 100644 index dad0e2f..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.editable; - -import org.apache.isis.core.metamodel.adapter.ObjectAdapter; -import org.apache.isis.viewer.wicket.model.models.EntityModel; -import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; - -/** - * {@link PanelAbstract Panel} representing the properties of an entity, as per - * the provided {@link EntityModel}. - */ -public class EntityPropertiesPanel extends PanelAbstract<EntityModel> { - - private static final long serialVersionUID = 1L; - - private static final String ID_ENTITY_PROPERTIES = "entityProperties"; - - private EntityPropertiesForm form; - - public EntityPropertiesPanel(final String id, final EntityModel entityModel) { - super(id, entityModel); - buildGui(); - form.toViewMode(null); - } - - - private void buildGui() { - buildEntityPropertiesAndOrCollectionsGui(); - setOutputMarkupId(true); - } - - private void buildEntityPropertiesAndOrCollectionsGui() { - final EntityModel model = getModel(); - final ObjectAdapter adapter = model.getObject(); - if (adapter != null) { - form = new EntityPropertiesForm(ID_ENTITY_PROPERTIES, model, this); - addOrReplace(form); - } else { - permanentlyHide(ID_ENTITY_PROPERTIES); - } - } -} http://git-wip-us.apache.org/repos/asf/isis/blob/35201392/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanelFactory.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanelFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanelFactory.java deleted file mode 100644 index 623ae89..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanelFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.editable; - -import org.apache.wicket.Component; -import org.apache.wicket.model.IModel; - -import org.apache.isis.viewer.wicket.model.models.EntityModel; -import org.apache.isis.viewer.wicket.ui.ComponentFactory; -import org.apache.isis.viewer.wicket.ui.ComponentType; -import org.apache.isis.viewer.wicket.ui.components.entity.EntityComponentFactoryAbstract; - -/** - * {@link ComponentFactory} for {@link EntityPropertiesPanel}. - */ -public class EntityPropertiesPanelFactory extends EntityComponentFactoryAbstract { - - private static final long serialVersionUID = 1L; - - public EntityPropertiesPanelFactory() { - super(ComponentType.ENTITY_PROPERTIES, EntityPropertiesPanel.class); - } - - @Override - public Component createComponent(final String id, final IModel<?> model) { - final EntityModel entityModel = (EntityModel) model; - return new EntityPropertiesPanel(id, entityModel); - } -}