This is an automated email from the ASF dual-hosted git repository. ilgrosso pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/syncope.git
commit 382738527a32c01907f01982097c996dd672f14d Author: Francesco Chicchiriccò <[email protected]> AuthorDate: Thu May 26 13:22:41 2022 +0200 Further Console extendability improvements --- .../client/console/panels/RealmChoicePanel.java | 72 ++++++++---- .../client/console/widgets/NumberWidget.java | 22 ++-- .../syncope/client/console/wizards/any/Groups.java | 70 ++++++------ .../client/console/wizards/any/Relationships.java | 123 ++++++++++++--------- .../client/console/panels/RealmChoicePanel.html | 6 +- .../apache/syncope/fit/console/RealmsITCase.java | 14 ++- .../reference-guide/usage/customization.adoc | 4 +- 7 files changed, 182 insertions(+), 129 deletions(-) diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java index 9313bacd1e..07d30b2ff6 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmChoicePanel.java @@ -47,6 +47,7 @@ import org.apache.syncope.common.lib.to.RealmTO; import org.apache.syncope.common.lib.types.IdRepoEntitlement; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; import org.apache.wicket.event.Broadcast; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AbstractAutoCompleteRenderer; @@ -55,11 +56,11 @@ import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSe import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer; import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.AbstractLink; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.ResourceModel; @@ -91,9 +92,7 @@ public class RealmChoicePanel extends Panel { protected final boolean isSearchEnabled; - protected final Label realmDisplayKey; - - protected final Label realmDisplayValue; + protected final ListView<String> breadcrumb; public RealmChoicePanel(final String id, final String initialRealm, final PageReference pageRef) { super(id); @@ -169,33 +168,60 @@ public class RealmChoicePanel extends Panel { container = new WebMarkupContainerNoVeil("container", realmTree); add(container.setOutputMarkupId(true)); - realmDisplayKey = new Label("realmDisplayKey", realmDisplayKeyModel(null)); - container.addOrReplace(realmDisplayKey.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); - realmDisplayValue = new Label("realmDisplayValue", realmDisplayValueText()); - container.addOrReplace(realmDisplayValue.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); + breadcrumb = new ListView<String>("breadcrumb") { + + private static final long serialVersionUID = -8746795666847966508L; + + @Override + protected void populateItem(final ListItem<String> item) { + AjaxLink<Void> bcitem = new AjaxLink<>("bcitem") { + + private static final long serialVersionUID = -817438685948164787L; + + @Override + public void onClick(final AjaxRequestTarget target) { + RealmRestClient.list(item.getModelObject()).stream(). + filter(r -> item.getModelObject().equals(r.getFullPath())). + findFirst().ifPresent(t -> chooseRealm(t, target)); + } + }; + bcitem.setBody(Model.of(SyncopeConstants.ROOT_REALM.equals(item.getModelObject()) + ? SyncopeConstants.ROOT_REALM + : StringUtils.substringAfterLast(item.getModelObject(), "/"))); + bcitem.setEnabled(!model.getObject().getFullPath().equals(item.getModelObject())); + item.add(bcitem); + } + }; + container.addOrReplace(breadcrumb.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); + setBreadcrumb(model.getObject()); reloadRealmTree(); } - protected IModel<String> realmDisplayKeyModel(final Boolean dynamic) { - return dynamic == null - ? model.getObject().getFullPath().startsWith(SyncopeConstants.ROOT_REALM) - ? new ResourceModel("realmDisplayKey", "Realm") - : new ResourceModel("dynRealmLabel", "Dynamic Realm") - : dynamic - ? new ResourceModel("dynRealmLabel", "Dynamic Realm") - : new ResourceModel("realmDisplayKey", "Realm"); - } + protected void setBreadcrumb(final RealmTO realm) { + if (SyncopeConstants.ROOT_REALM.equals(realm.getFullPath())) { + breadcrumb.setList(List.of(realm.getFullPath())); + } else { + List<String> bcitems = new ArrayList<>(); + bcitems.add(SyncopeConstants.ROOT_REALM); + + String[] split = realm.getFullPath().split("/"); + for (int i = 1; i < split.length; i++) { + StringBuilder bcitem = new StringBuilder(); + for (int j = 1; j <= i; j++) { + bcitem.append('/').append(split[j]); + } + bcitems.add(bcitem.toString()); + } - protected String realmDisplayValueText() { - return RealmsUtils.getFullPath(model.getObject().getFullPath()); + breadcrumb.setList(bcitems); + } } protected void chooseRealm(final RealmTO realm, final AjaxRequestTarget target) { model.setObject(realm); - realmDisplayValue.setDefaultModelObject(realmDisplayValueText()); - realmDisplayKey.setDefaultModel(realmDisplayKeyModel(false)); - target.add(realmDisplayValue); + setBreadcrumb(realm); + target.add(container); send(pageRef.getPage(), Broadcast.EXACT, new ChosenRealm<>(realm, target)); } diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java index 1f720a6f32..dd6933301d 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/widgets/NumberWidget.java @@ -20,6 +20,8 @@ package org.apache.syncope.client.console.widgets; import java.util.List; import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.SyncopeWebApplication; +import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.rest.AnyTypeRestClient; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.html.WebMarkupContainer; @@ -29,7 +31,6 @@ import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.syncope.client.console.pages.Realms; import org.apache.syncope.client.console.pages.Security; import org.apache.syncope.common.lib.types.IdRepoEntitlement; -import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.mapper.parameter.PageParameters; public class NumberWidget extends BaseWidget { @@ -48,20 +49,27 @@ public class NumberWidget extends BaseWidget { WebMarkupContainer box = new WebMarkupContainer("card"); box.add(new AttributeAppender("class", ' ' + bg)); + @SuppressWarnings("unchecked") + Class<? extends BasePage> realmsPage = + (Class<? extends BasePage>) SyncopeWebApplication.get().getPageClass("realms"); + if (realmsPage == null) { + realmsPage = Realms.class; + } + boolean isAuthorized = true; PageParameters pageParameters = new PageParameters(); - Class<? extends IRequestablePage> responsePage; + Class<? extends BasePage> responsePage; List<String> anyTypes = AnyTypeRestClient.list(); switch (id) { case "totalUsers": pageParameters.add(Realms.SELECTED_INDEX, 1); - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(IdRepoEntitlement.USER_SEARCH); break; case "totalGroups": pageParameters.add(Realms.SELECTED_INDEX, 2); - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(IdRepoEntitlement.GROUP_SEARCH); break; @@ -74,7 +82,7 @@ public class NumberWidget extends BaseWidget { pageParameters.add(Realms.SELECTED_INDEX, selectedIndex); } } - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(label + "_SEARCH"); } else { responsePage = Security.class; @@ -90,13 +98,13 @@ public class NumberWidget extends BaseWidget { pageParameters.add(Realms.SELECTED_INDEX, selectedIndex); } } - responsePage = Realms.class; + responsePage = realmsPage; isAuthorized = SyncopeConsoleSession.get().owns(label + "_SEARCH"); break; default: pageParameters.add(Realms.SELECTED_INDEX, 0); - responsePage = Realms.class; + responsePage = realmsPage; } AjaxEventBehavior clickToRealms = new AjaxEventBehavior("mousedown") { diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java index e1a0c2988a..b4d88faf04 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java @@ -86,6 +86,10 @@ public class Groups extends AbstractGroups { addDynamicRealmsContainer(); } + protected List<GroupTO> searchAssignable(final String realm, final String term) { + return SyncopeRestClient.searchAssignableGroups(realm, term, 1, Constants.MAX_GROUP_LIST_SIZE); + } + @Override protected void addDynamicRealmsContainer() { dynrealmsContainer = new WebMarkupContainer("dynrealmsContainer"); @@ -123,53 +127,49 @@ public class Groups extends AbstractGroups { @Override public MembershipTO getObject( - final String id, final IModel<? extends List<? extends MembershipTO>> choices) { + final String id, final IModel<? extends List<? extends MembershipTO>> choices) { return choices.getObject().stream(). - filter(object -> id.equalsIgnoreCase(object.getGroupName())).findAny().orElse(null); + filter(object -> id.equalsIgnoreCase(object.getGroupName())).findAny().orElse(null); } }); - groupsContainer.add(builder.setAllowOrder(true).withFilter("*").build("groups", - new ListModel<>() { + groupsContainer.add(builder.setAllowOrder(true).withFilter("*").build("groups", new ListModel<>() { - private static final long serialVersionUID = -2583290457773357445L; + private static final long serialVersionUID = -2583290457773357445L; - @Override - public List<MembershipTO> getObject() { - return Groups.this.groupsModel.getMemberships(); - } - - }, new AjaxPalettePanel.Builder.Query<>() { + @Override + public List<MembershipTO> getObject() { + return Groups.this.groupsModel.getMemberships(); + } + }, new AjaxPalettePanel.Builder.Query<>() { - private static final long serialVersionUID = -7223078772249308813L; + private static final long serialVersionUID = -7223078772249308813L; - @Override - public List<MembershipTO> execute(final String filter) { - return StringUtils.isEmpty(filter) + @Override + public List<MembershipTO> execute(final String filter) { + return StringUtils.isEmpty(filter) ? List.of() : ("*".equals(filter) - ? groupsModel.getObject() - : SyncopeRestClient.searchAssignableGroups( - anyTO.getRealm(), filter, 1, Constants.MAX_GROUP_LIST_SIZE)).stream(). - map(group -> new MembershipTO.Builder(group.getKey()). - groupName(group.getName()).build()). - collect(Collectors.toList()); - } - }).hideLabel().setOutputMarkupId(true)); + ? groupsModel.getObject() + : searchAssignable(anyTO.getRealm(), filter)).stream(). + map(group -> new MembershipTO.Builder(group.getKey()). + groupName(group.getName()).build()). + collect(Collectors.toList()); + } + }).hideLabel().setOutputMarkupId(true)); dyngroupsContainer.add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build("dyngroups", - new ListModel<>() { - - private static final long serialVersionUID = -2583290457773357445L; + new ListModel<>() { - @Override - public List<String> getObject() { - return Groups.this.groupsModel.getDynMemberships(); - } + private static final long serialVersionUID = -2583290457773357445L; - }, new ListModel<>(groupsModel.getObject().stream(). - map(GroupTO::getName).collect(Collectors.toList()))). + @Override + public List<String> getObject() { + return Groups.this.groupsModel.getDynMemberships(); + } + }, new ListModel<>(groupsModel.getObject().stream(). + map(GroupTO::getName).collect(Collectors.toList()))). hideLabel().setEnabled(false).setOutputMarkupId(true)); } } @@ -214,11 +214,7 @@ public class Groups extends AbstractGroups { */ @Override protected void reloadObject() { - groupsObj = SyncopeRestClient.searchAssignableGroups( - realmObj, - null, - 1, - Constants.MAX_GROUP_LIST_SIZE); + groupsObj = searchAssignable(realmObj, null); } @Override diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java index 159d3a9296..91b84b4e38 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java @@ -82,9 +82,11 @@ public class Relationships extends WizardStep implements ICondition { private static final long serialVersionUID = 855618618337931784L; - private final PageReference pageRef; + protected final AnyTO anyTO; - private final AnyTO anyTO; + protected final Specification specification; + + protected final PageReference pageRef; public Relationships(final AnyWrapper<?> modelObject, final PageReference pageRef) { super(); @@ -101,6 +103,7 @@ public class Relationships extends WizardStep implements ICondition { } this.anyTO = modelObject.getInnerObject(); + this.specification = new Specification(); this.pageRef = pageRef; // ------------------------ @@ -115,11 +118,11 @@ public class Relationships extends WizardStep implements ICondition { return super.getHeader(id, parent, wizard).setVisible(false); } - private Fragment getViewFragment() { - final Map<String, List<RelationshipTO>> relationships = new HashMap<>(); + protected Fragment getViewFragment() { + Map<String, List<RelationshipTO>> relationships = new HashMap<>(); addRelationship(relationships, getCurrentRelationships().toArray(RelationshipTO[]::new)); - final Fragment viewFragment = new Fragment("relationships", "viewFragment", this); + Fragment viewFragment = new Fragment("relationships", "viewFragment", this); viewFragment.setOutputMarkupId(true); viewFragment.add(new Accordion("relationships", relationships.keySet().stream(). @@ -158,7 +161,7 @@ public class Relationships extends WizardStep implements ICondition { } }); - final ActionsPanel<RelationshipTO> panel = new ActionsPanel<>("actions", null); + ActionsPanel<RelationshipTO> panel = new ActionsPanel<>("actions", null); viewFragment.add(panel); panel.add(new ActionLink<>() { @@ -169,7 +172,7 @@ public class Relationships extends WizardStep implements ICondition { public void onClick(final AjaxRequestTarget target, final RelationshipTO ignore) { Fragment addFragment = new Fragment("relationships", "addFragment", Relationships.this); addOrReplace(addFragment); - addFragment.add(new Specification().setRenderBodyOnly(true)); + addFragment.add(specification.setRenderBodyOnly(true)); target.add(Relationships.this); } }, ActionType.CREATE, AnyEntitlement.UPDATE.getFor(anyTO.getType())).hideLabel(); @@ -177,18 +180,18 @@ public class Relationships extends WizardStep implements ICondition { return viewFragment; } - private List<RelationshipTO> getCurrentRelationships() { + protected List<RelationshipTO> getCurrentRelationships() { return anyTO instanceof GroupableRelatableTO ? GroupableRelatableTO.class.cast(anyTO).getRelationships() : List.of(); } - private static void addRelationship( + protected void addRelationship( final Map<String, List<RelationshipTO>> relationships, final RelationshipTO... rels) { for (RelationshipTO relationship : rels) { - final List<RelationshipTO> listrels; + List<RelationshipTO> listrels; if (relationships.containsKey(relationship.getType())) { listrels = relationships.get(relationship.getType()); } else { @@ -199,17 +202,18 @@ public class Relationships extends WizardStep implements ICondition { } } - private void addNewRelationships(final RelationshipTO... rels) { + protected void addNewRelationships(final RelationshipTO... rels) { getCurrentRelationships().addAll(List.of(rels)); } - private void removeRelationships( + protected void removeRelationships( final Map<String, List<RelationshipTO>> relationships, final RelationshipTO... rels) { - final List<RelationshipTO> currentRels = getCurrentRelationships(); + + List<RelationshipTO> currentRels = getCurrentRelationships(); for (RelationshipTO relationship : rels) { currentRels.remove(relationship); if (relationships.containsKey(relationship.getType())) { - final List<RelationshipTO> rellist = relationships.get(relationship.getType()); + List<RelationshipTO> rellist = relationships.get(relationship.getType()); rellist.remove(relationship); if (rellist.isEmpty()) { relationships.remove(relationship.getType()); @@ -228,30 +232,38 @@ public class Relationships extends WizardStep implements ICondition { private static final long serialVersionUID = 6199050589175839467L; - private final RelationshipTO rel; + protected final RelationshipTO rel; + + protected final AjaxDropDownChoicePanel<String> type; + + protected final AjaxDropDownChoicePanel<AnyTypeTO> otherType; + + protected final WebMarkupContainer container; + + protected final Fragment emptyFragment; - private AnyObjectSearchPanel anyObjectSearchPanel; + protected final Fragment fragment; - private WizardMgtPanel<AnyWrapper<AnyObjectTO>> anyObjectDirectoryPanel; + protected AnyObjectSearchPanel anyObjectSearchPanel; + + protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> anyObjectDirectoryPanel; public Specification() { super("specification"); rel = new RelationshipTO(); - final List<String> availableRels = RelationshipTypeRestClient.list().stream(). + List<String> availableRels = RelationshipTypeRestClient.list().stream(). map(EntityTO::getKey).collect(Collectors.toList()); - final AjaxDropDownChoicePanel<String> type = new AjaxDropDownChoicePanel<>( - "type", "type", new PropertyModel<>(rel, "type")); + type = new AjaxDropDownChoicePanel<>("type", "type", new PropertyModel<>(rel, "type")); type.setChoices(availableRels); - add(type.setRenderBodyOnly(true)); + add(type.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true).setRenderBodyOnly(true)); - final List<AnyTypeTO> availableTypes = AnyTypeRestClient.listAnyTypes().stream(). + List<AnyTypeTO> availableTypes = AnyTypeRestClient.listAnyTypes().stream(). filter(anyType -> anyType.getKind() != AnyTypeKind.GROUP && anyType.getKind() != AnyTypeKind.USER).collect(Collectors.toList()); - final AjaxDropDownChoicePanel<AnyTypeTO> otherType = new AjaxDropDownChoicePanel<>( - "otherType", "otherType", new PropertyModel<>(rel, "otherType") { + otherType = new AjaxDropDownChoicePanel<>("otherType", "otherType", new PropertyModel<>(rel, "otherType") { private static final long serialVersionUID = -5861057041758169508L; @@ -288,27 +300,27 @@ public class Relationships extends WizardStep implements ICondition { @Override public AnyTypeTO getObject(final String id, final IModel<? extends List<? extends AnyTypeTO>> choices) { return choices.getObject().stream(). - filter(anyTypeTO -> id.equals(anyTypeTO.getKey())).findAny().orElse(null); + filter(anyTypeTO -> id.equals(anyTypeTO.getKey())).findAny().orElse(null); } }); // enable "otherType" dropdown only if "type" option is selected - SYNCOPE-1140 otherType.setEnabled(false); - add(otherType); + add(otherType.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true)); - final WebMarkupContainer container = new WebMarkupContainer("searchPanelContainer"); - container.setOutputMarkupId(true); - add(container); + container = new WebMarkupContainer("searchPanelContainer"); + add(container.setOutputMarkupId(true)); - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", this); + emptyFragment = new Fragment("searchPanel", "emptyFragment", this); container.add(emptyFragment.setRenderBodyOnly(true)); + fragment = new Fragment("searchPanel", "searchFragment", Specification.this); + type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { private static final long serialVersionUID = -1107858522700306810L; @Override protected void onUpdate(final AjaxRequestTarget target) { - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", Specification.this); container.addOrReplace(emptyFragment.setRenderBodyOnly(true)); otherType.setModelObject(null); // enable "otherType" dropdown only if "type" option is selected - SYNCOPE-1140 @@ -324,46 +336,47 @@ public class Relationships extends WizardStep implements ICondition { @Override protected void onUpdate(final AjaxRequestTarget target) { - final AnyTypeTO anyType = otherType.getModelObject(); + AnyTypeTO anyType = otherType.getModelObject(); if (anyType == null) { - Fragment emptyFragment = new Fragment("searchPanel", "emptyFragment", Specification.this); container.addOrReplace(emptyFragment.setRenderBodyOnly(true)); } else { - final Fragment fragment = new Fragment("searchPanel", "searchFragment", Specification.this); + setupFragment(anyType); container.addOrReplace(fragment.setRenderBodyOnly(true)); - - anyObjectSearchPanel = new AnyObjectSearchPanel.Builder( - anyType.getKey(), - new ListModel<>(new ArrayList<>())). - enableSearch(Specification.this). - build("searchPanel"); - fragment.add(anyObjectSearchPanel.setRenderBodyOnly(true)); - - anyObjectDirectoryPanel = new AnyObjectSelectionDirectoryPanel.Builder( - AnyTypeClassRestClient.list(anyType.getClasses()), - anyType.getKey(), - pageRef). - setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()). - is(Constants.KEY_FIELD_NAME).notNullValue().query()). - setWizardInModal(true).build("searchResultPanel"); - fragment.add(anyObjectDirectoryPanel.setRenderBodyOnly(true)); } target.add(container); } }); } + protected void setupFragment(final AnyTypeTO anyType) { + anyObjectSearchPanel = new AnyObjectSearchPanel.Builder( + anyType.getKey(), + new ListModel<>(new ArrayList<>())). + enableSearch(Specification.this). + build("searchPanel"); + fragment.addOrReplace(anyObjectSearchPanel.setRenderBodyOnly(true)); + + anyObjectDirectoryPanel = new AnyObjectSelectionDirectoryPanel.Builder( + AnyTypeClassRestClient.list(anyType.getClasses()), + anyType.getKey(), + pageRef). + setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()). + is(Constants.KEY_FIELD_NAME).notNullValue().query()). + setWizardInModal(true).build("searchResultPanel"); + fragment.addOrReplace(anyObjectDirectoryPanel.setRenderBodyOnly(true)); + } + @Override public void onEvent(final IEvent<?> event) { if (event.getPayload() instanceof SearchClausePanel.SearchEvent) { - final AjaxRequestTarget target = SearchClausePanel.SearchEvent.class.cast(event.getPayload()). - getTarget(); - final String fiql = SearchUtils.buildFIQL(anyObjectSearchPanel.getModel().getObject(), + AjaxRequestTarget target = + SearchClausePanel.SearchEvent.class.cast(event.getPayload()).getTarget(); + String fiql = SearchUtils.buildFIQL(anyObjectSearchPanel.getModel().getObject(), SyncopeClient.getAnyObjectSearchConditionBuilder(anyObjectSearchPanel.getBackObjectType())); AnyDirectoryPanel.class.cast(Specification.this.anyObjectDirectoryPanel).search(fiql, target); } else if (event.getPayload() instanceof AnySelectionDirectoryPanel.ItemSelection) { - final AjaxRequestTarget target = AnySelectionDirectoryPanel.ItemSelection.class.cast(event. - getPayload()).getTarget(); + AjaxRequestTarget target = + AnySelectionDirectoryPanel.ItemSelection.class.cast(event.getPayload()).getTarget(); AnyTO right = AnySelectionDirectoryPanel.ItemSelection.class.cast(event.getPayload()).getSelection(); rel.setOtherEndKey(right.getKey()); diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html index 0691389902..b250636658 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/RealmChoicePanel.html @@ -20,7 +20,11 @@ under the License. <wicket:panel> <div wicket:id="container" class="realm-header"> <div class="realm-label"> - <label wicket:id="realmDisplayKey"/>: <label wicket:id="realmDisplayValue"/> + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + <li class="breadcrumb-item" wicket:id="breadcrumb"><a wicket:id="bcitem"/></li> + </ol> + </nav> </div> <span wicket:id="realmsFragment"></span> diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java index 47ee9853ab..8f2b63b0aa 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RealmsITCase.java @@ -18,7 +18,9 @@ */ package org.apache.syncope.fit.console; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; import org.apache.syncope.client.ui.commons.Constants; @@ -73,7 +75,8 @@ public class RealmsITCase extends AbstractConsoleITCase { "body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:5:button", Constants.ON_CLICK); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/testRealm"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">testRealm</a>")); TESTER.getRequest().addParameter("confirm", "true"); TESTER.clickLink( @@ -86,7 +89,8 @@ public class RealmsITCase extends AbstractConsoleITCase { "body:content:body:container:content:tabbedPanel:panel:container:policies:1:field-label", "Account Policy"); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertFalse(TESTER.getLastResponseAsString().contains(">testRealm</a>")); } @Test @@ -116,7 +120,8 @@ public class RealmsITCase extends AbstractConsoleITCase { "body:content:realmChoicePanel:container:realmsFragment:realms:dropdown-menu:buttons:4:button", Constants.ON_CLICK); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">odd</a>")); TESTER.clickLink( "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action"); @@ -136,7 +141,8 @@ public class RealmsITCase extends AbstractConsoleITCase { assertSuccessMessage(); TESTER.cleanupFeedbackMessages(); - TESTER.assertLabel("body:content:realmChoicePanel:container:realmDisplayValue", "/odd"); + assertTrue(TESTER.getLastResponseAsString().contains(">/</a>")); + assertTrue(TESTER.getLastResponseAsString().contains(">odd</a>")); TESTER.clickLink( "body:content:body:container:content:tabbedPanel:panel:actions:actions:actionRepeater:2:action:action"); diff --git a/src/main/asciidoc/reference-guide/usage/customization.adoc b/src/main/asciidoc/reference-guide/usage/customization.adoc index 4e54b98ac5..6ced0aaef9 100644 --- a/src/main/asciidoc/reference-guide/usage/customization.adoc +++ b/src/main/asciidoc/reference-guide/usage/customization.adoc @@ -120,11 +120,11 @@ At this point your favourite IDE can be attached to the port `8000`. ===== Override behavior As a rule of thumb, any file of the local project will take precedence over a file with the same name in the same -directory of the standard Apache Syncope release. +package directory of the standard Apache Syncope release. For example, if you place - core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java + core/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java in the local project, this file will be picked up instead of ifeval::["{snapshotOrRelease}" == "release"]
