ISIS-993: renaming of components, EntityCombinedPanel now called EntityEditablePanel. Other subsidiary panels moved alongside.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/d946027a Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/d946027a Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/d946027a Branch: refs/heads/ISIS-993 Commit: d946027a36293d3e800c393f01aa145b8bc23b20 Parents: e647a95 Author: Dan Haywood <d...@haywood-associates.co.uk> Authored: Thu Jan 14 17:08:22 2016 +0000 Committer: Dan Haywood <d...@haywood-associates.co.uk> Committed: Mon Jan 25 15:06:07 2016 +0000 ---------------------------------------------------------------------- .../ComponentFactoryRegistrarDefault.java | 2 +- .../components/entity/EntityPanelFactory.java | 4 +- .../wicket/ui/components/entity/PropUtil.java | 91 +++ .../components/entity/column/EntityColumn.html | 46 ++ .../components/entity/column/EntityColumn.java | 192 +++++ .../entity/combined/EntityCombinedPanel.html | 29 - .../entity/combined/EntityCombinedPanel.java | 60 -- .../entity/editable/EntityEditablePanel.html | 29 + .../entity/editable/EntityEditablePanel.java | 60 ++ .../entity/editable/EntityPropertiesForm.java | 713 +++++++++++++++++++ .../editable/EntityPropertiesForm.properties | 22 + .../entity/editable/EntityPropertiesPanel.html | 52 ++ .../entity/editable/EntityPropertiesPanel.java | 60 ++ .../editable/EntityPropertiesPanelFactory.java | 46 ++ .../entity/properties/EntityColumn.html | 46 -- .../entity/properties/EntityColumn.java | 191 ----- .../entity/properties/EntityPropertiesForm.java | 710 ------------------ .../properties/EntityPropertiesForm.properties | 22 - .../properties/EntityPropertiesPanel.html | 52 -- .../properties/EntityPropertiesPanel.java | 60 -- .../EntityPropertiesPanelFactory.java | 46 -- .../components/entity/properties/PropUtil.java | 91 --- .../tabbed/ColumnTabGroupListColumnPanel.java | 2 +- 23 files changed, 1315 insertions(+), 1311 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/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 a7646d0..8d16642 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.properties.EntityPropertiesPanelFactory; +import org.apache.isis.viewer.wicket.ui.components.entity.editable.EntityPropertiesPanelFactory; 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; http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/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 bc5dcd0..6db00fe 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 @@ -28,7 +28,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification; 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.combined.EntityCombinedPanel; +import org.apache.isis.viewer.wicket.ui.components.entity.editable.EntityEditablePanel; import org.apache.isis.viewer.wicket.ui.components.entity.tabbed.ColumnTabGroupListColumnPanel; /** @@ -55,6 +55,6 @@ public class EntityPanelFactory extends EntityComponentFactoryAbstract { final boolean hasLayout = layoutMetadata != null; return hasLayout ? new ColumnTabGroupListColumnPanel(id, entityModel) - : new EntityCombinedPanel(id, entityModel); + : new EntityEditablePanel(id, entityModel); } } http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/PropUtil.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/PropUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/PropUtil.java new file mode 100644 index 0000000..5b4e39d --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/PropUtil.java @@ -0,0 +1,91 @@ +/* + * 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; + +import java.util.List; +import java.util.Map; + +import com.google.common.collect.FluentIterable; + +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.PropertyGroupMetadata; +import org.apache.isis.core.metamodel.adapter.ObjectAdapter; +import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.isis.core.metamodel.spec.ObjectSpecification; +import org.apache.isis.core.metamodel.spec.ObjectSpecifications; +import org.apache.isis.core.metamodel.spec.feature.Contributed; +import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; +import org.apache.isis.viewer.wicket.model.models.EntityModel; + +public final class PropUtil { + + private PropUtil() { + } + + public static List<String> propertyGroupNames( + final EntityModel entityModel, + final ColumnMetadata.Hint hint, final ColumnMetadata columnMetaDataIfAny) { + final ObjectAdapter adapter = entityModel.getObject(); + final ObjectSpecification objSpec = adapter.getSpecification(); + + final Map<String, List<ObjectAssociation>> associationsByGroup = + propertiesByMemberOrder(adapter); + + return columnMetaDataIfAny != null + ? FluentIterable + .from(columnMetaDataIfAny.getPropertyGroups()) + .transform(PropertyGroupMetadata.Util.nameOf()) + .toList() + : ObjectSpecifications.orderByMemberGroups(objSpec, associationsByGroup.keySet(), + hint); + } + + public static Map<String, List<ObjectAssociation>> propertiesByMemberOrder(final ObjectAdapter adapter) { + final List<ObjectAssociation> properties = visibleProperties(adapter); + return ObjectAssociation.Util.groupByMemberOrderName(properties); + } + + private static List<ObjectAssociation> visibleProperties(final ObjectAdapter adapter) { + return visibleProperties(adapter, Filters.<ObjectAssociation>any()); + } + + private static List<ObjectAssociation> visibleProperties( + final ObjectAdapter adapter, + final Filter<ObjectAssociation> filter) { + final ObjectSpecification objSpec = adapter.getSpecification(); + + return objSpec.getAssociations( + Contributed.INCLUDED, visiblePropertiesFilter(adapter, filter)); + } + + @SuppressWarnings("unchecked") + private static Filter<ObjectAssociation> visiblePropertiesFilter( + final ObjectAdapter adapter, + final Filter<ObjectAssociation> filter) { + return Filters.and( + ObjectAssociation.Filters.PROPERTIES, + ObjectAssociation.Filters.dynamicallyVisible( + adapter, InteractionInitiatedBy.USER, Where.OBJECT_FORMS), + filter); + } + +} http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.html ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.html new file mode 100644 index 0000000..43c76da --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.html @@ -0,0 +1,46 @@ +<?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="columnMembers"> + <div class="inputFormTable properties"> + <fieldset wicket:id="memberGroup" class="memberGroup myBlockContainer"> + <div class="panel panel-default"> + <div class="panel-heading"> + <span wicket:id="memberGroupName" class="panel-title">[group name]</span> + <div class="pull-right additionalLinks"> + <div wicket:id="associatedActionLinksPanel"></div> + <div wicket:id="associatedActionLinksPanelDropDown"></div> + </div> + </div> + <div class="properties panel-body"> + <div wicket:id="properties"> + <div wicket:id="property" class="property">[property]</div> + </div> + </div> + </div> + </fieldset> + </div> + <div wicket:id="collections"></div> + </div> + </wicket:panel> + </body> +</html> http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/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 new file mode 100644 index 0000000..43ab95b --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/column/EntityColumn.java @@ -0,0 +1,192 @@ +/* + * 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.column; + +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.MarkupContainer; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.repeater.RepeatingView; + +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.spec.ObjectSpecification; +import org.apache.isis.core.metamodel.spec.ObjectSpecifications; +import org.apache.isis.core.metamodel.spec.feature.ObjectAction; +import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; +import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; +import org.apache.isis.core.runtime.system.DeploymentType; +import org.apache.isis.core.runtime.system.context.IsisContext; +import org.apache.isis.viewer.wicket.model.links.LinkAndLabel; +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.actionmenu.entityactions.AdditionalLinksPanel; +import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil; +import org.apache.isis.viewer.wicket.ui.components.entity.PropUtil; +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.Components; + +public class EntityColumn extends PanelAbstract<EntityModel> { + + private static final long serialVersionUID = 1L; + + private static final String ID_MEMBER_GROUP = "memberGroup"; + private static final String ID_MEMBER_GROUP_NAME = "memberGroupName"; + + private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL = "associatedActionLinksPanel"; + private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN = "associatedActionLinksPanelDropDown"; + + private static final String ID_PROPERTIES = "properties"; + private static final String ID_PROPERTY = "property"; + + private final Component owningPanel; + + public EntityColumn( + final String id, + final EntityModel entityModel, + final Component owningPanel) { + + super(id, entityModel); + this.owningPanel = owningPanel; // for repainting, perhaps + + buildGui(); + } + + private void buildGui() { + addPropertiesAndCollections(this, getModel()); + } + + private void addPropertiesAndCollections( + final MarkupContainer col, + final EntityModel entityModel) { + addPropertiesInColumn(col, entityModel); + addCollectionsIfRequired(col, entityModel); + } + + private void addPropertiesInColumn( + 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(); + + final Map<String, List<ObjectAssociation>> associationsByGroup = PropUtil + .propertiesByMemberOrder(adapter); + final List<String> groupNames = columnMetaDataIfAny != null + ? FluentIterable + .from(columnMetaDataIfAny.getPropertyGroups()) + .transform(PropertyGroupMetadata.Util.nameOf()) + .toList() + : ObjectSpecifications.orderByMemberGroups(objSpec, associationsByGroup.keySet(), hint); + + final RepeatingView memberGroupRv = new RepeatingView(ID_MEMBER_GROUP); + markupContainer.add(memberGroupRv); + + for(final String groupName: groupNames) { + final List<ObjectAssociation> associationsInGroup = associationsByGroup.get(groupName); + if(associationsInGroup==null) { + continue; + } + + final WebMarkupContainer memberGroupRvContainer = new WebMarkupContainer(memberGroupRv.newChildId()); + memberGroupRv.add(memberGroupRvContainer); + memberGroupRvContainer.add(new Label(ID_MEMBER_GROUP_NAME, groupName)); + + final List<LinkAndLabel> memberGroupActions = Lists.newArrayList(); + + final RepeatingView propertyRv = new RepeatingView(ID_PROPERTIES); + memberGroupRvContainer.add(propertyRv); + + @SuppressWarnings("unused") + Component component; + for (final ObjectAssociation association : associationsInGroup) { + final WebMarkupContainer propertyRvContainer = new UiHintPathSignificantWebMarkupContainer(propertyRv.newChildId()); + propertyRv.add(propertyRvContainer); + + addPropertyToForm(entityModel, (OneToOneAssociation) association, propertyRvContainer, memberGroupActions); + } + + final List<LinkAndLabel> actionsPanel = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL); + final List<LinkAndLabel> actionsPanelDropDown = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL_DROPDOWN); + + AdditionalLinksPanel.addAdditionalLinks( + memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL, + actionsPanel, + AdditionalLinksPanel.Style.INLINE_LIST); + AdditionalLinksPanel.addAdditionalLinks( + memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN, + actionsPanelDropDown, + AdditionalLinksPanel.Style.DROPDOWN); + } + } + + private void addCollectionsIfRequired( + final MarkupContainer column, + final EntityModel entityModel) { + + final ColumnMetadata columnMetaDataIfAny = entityModel.getColumnMetadata(); + + if(columnMetaDataIfAny != null) { + getComponentFactoryRegistry() + .addOrReplaceComponent(column, "collections", ComponentType.ENTITY_COLLECTIONS, entityModel); + } else { + Components.permanentlyHide(column, "collections"); + } + } + + private void addPropertyToForm( + final EntityModel entityModel, + final OneToOneAssociation otoa, + final WebMarkupContainer container, + final List<LinkAndLabel> entityActions) { + 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); + + final List<ObjectAction> associatedActions = EntityActionUtil.getObjectActionsForAssociation(entityModel, + otoa, getDeploymentType()); + + entityActions.addAll(EntityActionUtil.asLinkAndLabelsForAdditionalLinksPanel(entityModel, associatedActions)); + } + + + + /////////////////////////////////////////////////////// + // Dependencies (from context) + /////////////////////////////////////////////////////// + + protected DeploymentType getDeploymentType() { + return IsisContext.getDeploymentType(); + } + +} http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.html ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.html deleted file mode 100644 index 540bb11..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.html +++ /dev/null @@ -1,29 +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="entityCombined"> - <div wicket:id="entitySummary"></div> - <div wicket:id="entityPropertiesAndCollections"></div> - </div> -</wicket:panel> -</body> -</html> http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.java deleted file mode 100644 index ee26581..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/combined/EntityCombinedPanel.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.combined; - -import org.apache.isis.core.metamodel.adapter.ObjectAdapter; -import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet; -import org.apache.isis.viewer.wicket.model.models.EntityModel; -import org.apache.isis.viewer.wicket.ui.ComponentType; -import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; -import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; - -/** - * {@link PanelAbstract Panel} to represent an entity on a single page made up - * of several <div> regions. - */ -public class EntityCombinedPanel extends PanelAbstract<EntityModel> { - - private static final long serialVersionUID = 1L; - - private static final String ID_ENTITY_PROPERTIES_AND_COLLECTIONS = "entityPropertiesAndCollections"; - - - public EntityCombinedPanel(final String id, final EntityModel entityModel) { - super(id, entityModel); - buildGui(); - } - - private void buildGui() { - final EntityModel model = getModel(); - final ObjectAdapter objectAdapter = model.getObject(); - final CssClassFacet facet = objectAdapter.getSpecification().getFacet(CssClassFacet.class); - if(facet != null) { - final String cssClass = facet.cssClass(objectAdapter); - CssClassAppender.appendCssClassTo(this, cssClass); - } - - addOrReplace(ComponentType.ENTITY_SUMMARY, model); - - getComponentFactoryRegistry().addOrReplaceComponent(this, ID_ENTITY_PROPERTIES_AND_COLLECTIONS, ComponentType.ENTITY_PROPERTIES, model); - } - - -} http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.html ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.html new file mode 100644 index 0000000..540bb11 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.html @@ -0,0 +1,29 @@ +<?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="entityCombined"> + <div wicket:id="entitySummary"></div> + <div wicket:id="entityPropertiesAndCollections"></div> + </div> +</wicket:panel> +</body> +</html> http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.java new file mode 100644 index 0000000..2db68d8 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityEditablePanel.java @@ -0,0 +1,60 @@ +/* + * 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.core.metamodel.facets.members.cssclass.CssClassFacet; +import org.apache.isis.viewer.wicket.model.models.EntityModel; +import org.apache.isis.viewer.wicket.ui.ComponentType; +import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract; +import org.apache.isis.viewer.wicket.ui.util.CssClassAppender; + +/** + * {@link PanelAbstract Panel} to represent an entity on a single page made up + * of several <div> regions. + */ +public class EntityEditablePanel extends PanelAbstract<EntityModel> { + + private static final long serialVersionUID = 1L; + + private static final String ID_ENTITY_PROPERTIES_AND_COLLECTIONS = "entityPropertiesAndCollections"; + + + public EntityEditablePanel(final String id, final EntityModel entityModel) { + super(id, entityModel); + buildGui(); + } + + private void buildGui() { + final EntityModel model = getModel(); + final ObjectAdapter objectAdapter = model.getObject(); + final CssClassFacet facet = objectAdapter.getSpecification().getFacet(CssClassFacet.class); + if(facet != null) { + final String cssClass = facet.cssClass(objectAdapter); + CssClassAppender.appendCssClassTo(this, cssClass); + } + + addOrReplace(ComponentType.ENTITY_SUMMARY, model); + + getComponentFactoryRegistry().addOrReplaceComponent(this, ID_ENTITY_PROPERTIES_AND_COLLECTIONS, ComponentType.ENTITY_PROPERTIES, model); + } + + +} http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/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 new file mode 100644 index 0000000..08bbc88 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.java @@ -0,0 +1,713 @@ +/* + * 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/d946027a/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 new file mode 100644 index 0000000..71edcd9 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesForm.properties @@ -0,0 +1,22 @@ +# +# 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/d946027a/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 new file mode 100644 index 0000000..e204c12 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.html @@ -0,0 +1,52 @@ +<?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/d946027a/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 new file mode 100644 index 0000000..dad0e2f --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanel.java @@ -0,0 +1,60 @@ +/* + * 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/d946027a/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 new file mode 100644 index 0000000..623ae89 --- /dev/null +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/editable/EntityPropertiesPanelFactory.java @@ -0,0 +1,46 @@ +/* + * 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); + } +} http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html deleted file mode 100644 index 43c76da..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.html +++ /dev/null @@ -1,46 +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="columnMembers"> - <div class="inputFormTable properties"> - <fieldset wicket:id="memberGroup" class="memberGroup myBlockContainer"> - <div class="panel panel-default"> - <div class="panel-heading"> - <span wicket:id="memberGroupName" class="panel-title">[group name]</span> - <div class="pull-right additionalLinks"> - <div wicket:id="associatedActionLinksPanel"></div> - <div wicket:id="associatedActionLinksPanelDropDown"></div> - </div> - </div> - <div class="properties panel-body"> - <div wicket:id="properties"> - <div wicket:id="property" class="property">[property]</div> - </div> - </div> - </div> - </fieldset> - </div> - <div wicket:id="collections"></div> - </div> - </wicket:panel> - </body> -</html> http://git-wip-us.apache.org/repos/asf/isis/blob/d946027a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java deleted file mode 100644 index 47cb002..0000000 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityColumn.java +++ /dev/null @@ -1,191 +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.properties; - -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.MarkupContainer; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.markup.repeater.RepeatingView; - -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.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.spec.ObjectSpecifications; -import org.apache.isis.core.metamodel.spec.feature.ObjectAction; -import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; -import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; -import org.apache.isis.core.runtime.system.DeploymentType; -import org.apache.isis.core.runtime.system.context.IsisContext; -import org.apache.isis.viewer.wicket.model.links.LinkAndLabel; -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.actionmenu.entityactions.AdditionalLinksPanel; -import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.EntityActionUtil; -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.Components; - -public class EntityColumn extends PanelAbstract<EntityModel> { - - private static final long serialVersionUID = 1L; - - private static final String ID_MEMBER_GROUP = "memberGroup"; - private static final String ID_MEMBER_GROUP_NAME = "memberGroupName"; - - private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL = "associatedActionLinksPanel"; - private static final String ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN = "associatedActionLinksPanelDropDown"; - - private static final String ID_PROPERTIES = "properties"; - private static final String ID_PROPERTY = "property"; - - private final Component owningPanel; - - public EntityColumn( - final String id, - final EntityModel entityModel, - final Component owningPanel) { - - super(id, entityModel); - this.owningPanel = owningPanel; // for repainting, perhaps - - buildGui(); - } - - private void buildGui() { - addPropertiesAndCollections(this, getModel()); - } - - private void addPropertiesAndCollections( - final MarkupContainer col, - final EntityModel entityModel) { - addPropertiesInColumn(col, entityModel); - addCollectionsIfRequired(col, entityModel); - } - - private void addPropertiesInColumn( - 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(); - - final Map<String, List<ObjectAssociation>> associationsByGroup = PropUtil - .propertiesByMemberOrder(adapter); - final List<String> groupNames = columnMetaDataIfAny != null - ? FluentIterable - .from(columnMetaDataIfAny.getPropertyGroups()) - .transform(PropertyGroupMetadata.Util.nameOf()) - .toList() - : ObjectSpecifications.orderByMemberGroups(objSpec, associationsByGroup.keySet(), hint); - - final RepeatingView memberGroupRv = new RepeatingView(ID_MEMBER_GROUP); - markupContainer.add(memberGroupRv); - - for(final String groupName: groupNames) { - final List<ObjectAssociation> associationsInGroup = associationsByGroup.get(groupName); - if(associationsInGroup==null) { - continue; - } - - final WebMarkupContainer memberGroupRvContainer = new WebMarkupContainer(memberGroupRv.newChildId()); - memberGroupRv.add(memberGroupRvContainer); - memberGroupRvContainer.add(new Label(ID_MEMBER_GROUP_NAME, groupName)); - - final List<LinkAndLabel> memberGroupActions = Lists.newArrayList(); - - final RepeatingView propertyRv = new RepeatingView(ID_PROPERTIES); - memberGroupRvContainer.add(propertyRv); - - @SuppressWarnings("unused") - Component component; - for (final ObjectAssociation association : associationsInGroup) { - final WebMarkupContainer propertyRvContainer = new UiHintPathSignificantWebMarkupContainer(propertyRv.newChildId()); - propertyRv.add(propertyRvContainer); - - addPropertyToForm(entityModel, (OneToOneAssociation) association, propertyRvContainer, memberGroupActions); - } - - final List<LinkAndLabel> actionsPanel = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL); - final List<LinkAndLabel> actionsPanelDropDown = LinkAndLabel.positioned(memberGroupActions, ActionLayout.Position.PANEL_DROPDOWN); - - AdditionalLinksPanel.addAdditionalLinks( - memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL, - actionsPanel, - AdditionalLinksPanel.Style.INLINE_LIST); - AdditionalLinksPanel.addAdditionalLinks( - memberGroupRvContainer, ID_ASSOCIATED_ACTION_LINKS_PANEL_DROPDOWN, - actionsPanelDropDown, - AdditionalLinksPanel.Style.DROPDOWN); - } - } - - private void addCollectionsIfRequired( - final MarkupContainer column, - final EntityModel entityModel) { - - final ColumnMetadata columnMetaDataIfAny = entityModel.getColumnMetadata(); - - if(columnMetaDataIfAny != null) { - getComponentFactoryRegistry() - .addOrReplaceComponent(column, "collections", ComponentType.ENTITY_COLLECTIONS, entityModel); - } else { - Components.permanentlyHide(column, "collections"); - } - } - - private void addPropertyToForm( - final EntityModel entityModel, - final OneToOneAssociation otoa, - final WebMarkupContainer container, - final List<LinkAndLabel> entityActions) { - 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); - - final List<ObjectAction> associatedActions = EntityActionUtil.getObjectActionsForAssociation(entityModel, - otoa, getDeploymentType()); - - entityActions.addAll(EntityActionUtil.asLinkAndLabelsForAdditionalLinksPanel(entityModel, associatedActions)); - } - - - - /////////////////////////////////////////////////////// - // Dependencies (from context) - /////////////////////////////////////////////////////// - - protected DeploymentType getDeploymentType() { - return IsisContext.getDeploymentType(); - } - -}