Author: ilgrosso Date: Wed Jan 30 11:36:08 2013 New Revision: 1440351 URL: http://svn.apache.org/viewvc?rev=1440351&view=rev Log: [SYNCOPE-122] Console extension completed featuring on-the-fly selection for resources added (directly or via role selection) but not yet submitted
Added: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java (with props) Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractAttributableTO.java syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleTreeBuilder.java syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/SelectChoiceRenderer.java syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/StatusUtils.java syncope/trunk/console/src/main/java/org/apache/syncope/console/markup/html/CrontabContainer.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/DerivedAttributesPanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/MembershipsPanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourcesPanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AbstractFieldPanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxPalettePanel.java syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/tree/TreeRoleProvider.java syncope/trunk/console/src/test/java/org/apache/syncope/console/EditProfileTestITCase.java Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractAttributableTO.java URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractAttributableTO.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractAttributableTO.java (original) +++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/AbstractAttributableTO.java Wed Jan 30 11:36:08 2013 @@ -25,11 +25,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlType; - import org.codehaus.jackson.annotate.JsonIgnore; @XmlType Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java (original) +++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/UserTO.java Wed Jan 30 11:36:08 2013 @@ -25,12 +25,10 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; - import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; - import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; import org.codehaus.jackson.annotate.JsonIgnore; Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleTreeBuilder.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleTreeBuilder.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleTreeBuilder.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleTreeBuilder.java Wed Jan 30 11:36:08 2013 @@ -23,11 +23,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; - import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeModel; - import org.apache.syncope.common.to.RoleTO; import org.apache.syncope.console.rest.RoleRestClient; import org.springframework.beans.factory.annotation.Autowired; @@ -39,6 +37,8 @@ public class RoleTreeBuilder { private final RoleTOComparator comparator = new RoleTOComparator(); + private List<RoleTO> allRoles; + private List<RoleTO> getChildRoles(final long parentRoleId, final List<RoleTO> roles) { List<RoleTO> result = new ArrayList<RoleTO>(); for (RoleTO role : roles) { @@ -62,8 +62,13 @@ public class RoleTreeBuilder { } } + public List<RoleTO> getAllRoles() { + return this.allRoles; + } + public TreeModel build() { - return build(restClient.list()); + this.allRoles = this.restClient.list(); + return build(this.allRoles); } public TreeModel build(final List<RoleTO> roles) { Added: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java?rev=1440351&view=auto ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java (added) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java Wed Jan 30 11:36:08 2013 @@ -0,0 +1,36 @@ +/* + * 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.syncope.console.commons; + +import org.apache.syncope.common.to.RoleTO; + +public class RoleUtils { + + public static RoleTO findRole(final RoleTreeBuilder roleTreeBuilder, final long roleId) { + RoleTO found = null; + if (roleTreeBuilder.getAllRoles() != null) { + for (RoleTO roleTO : roleTreeBuilder.getAllRoles()) { + if (roleTO.getId() == roleId) { + found = roleTO; + } + } + } + return found; + } +} Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/RoleUtils.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/SelectChoiceRenderer.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/SelectChoiceRenderer.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/SelectChoiceRenderer.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/SelectChoiceRenderer.java Wed Jan 30 11:36:08 2013 @@ -20,12 +20,12 @@ package org.apache.syncope.console.commo import org.apache.wicket.markup.html.form.IChoiceRenderer; -public class SelectChoiceRenderer implements IChoiceRenderer { +public class SelectChoiceRenderer<T> implements IChoiceRenderer<T> { private static final long serialVersionUID = -3242441544405909243L; @Override - public Object getDisplayValue(Object obj) { + public Object getDisplayValue(T obj) { if (obj instanceof SelectOption) { return ((SelectOption) obj).getDisplayValue(); } else { @@ -34,7 +34,7 @@ public class SelectChoiceRenderer implem } @Override - public String getIdValue(Object obj, int i) { + public String getIdValue(T obj, int i) { return obj.toString(); } } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/StatusUtils.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/StatusUtils.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/StatusUtils.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/commons/StatusUtils.java Wed Jan 30 11:36:08 2013 @@ -23,6 +23,7 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.syncope.common.to.AbstractAttributableTO; @@ -35,8 +36,10 @@ import org.apache.syncope.common.to.Reso import org.apache.syncope.common.to.RoleTO; import org.apache.syncope.common.to.UserTO; import org.apache.syncope.common.types.IntMappingType; +import org.apache.syncope.console.pages.panels.StatusPanel; import org.apache.syncope.console.rest.AbstractAttributableRestClient; import org.apache.syncope.console.rest.ResourceRestClient; +import org.apache.wicket.ajax.AjaxRequestTarget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,6 +49,7 @@ public class StatusUtils implements Seri public enum Status { + NOT_YET_SUBMITTED, CREATED, ACTIVE, SUSPENDED, @@ -182,14 +186,14 @@ public class StatusUtils implements Seri private String getAccountLink(final ConnObjectTO objectTO) { final String NAME = "__NAME__"; - final Map<String, AttributeTO> attributeTOs = objectTO != null - ? objectTO.getAttributeMap() - : Collections.EMPTY_MAP; + final Map<String, AttributeTO> attributeTOs = objectTO == null + ? Collections.<String, AttributeTO>emptyMap() + : objectTO.getAttributeMap(); final AttributeTO name = attributeTOs.get(NAME); return name != null && name.getValues() != null && !name.getValues().isEmpty() - ? (String) name.getValues().get(0) + ? name.getValues().get(0) : null; } @@ -240,4 +244,37 @@ public class StatusUtils implements Seri return propagationRequestTO; } + + public static void update(final StatusPanel statusPanel, final AjaxRequestTarget target, + final Collection<String> resourcesToAdd, final Collection<String> resourcesToRemove) { + + if (statusPanel != null) { + Map<String, StatusBean> statusMap = new LinkedHashMap<String, StatusBean>(); + for (StatusBean statusBean : statusPanel.getStatusBeans()) { + statusMap.put(statusBean.getResourceName(), statusBean); + } + + for (String resource : resourcesToAdd) { + if (!statusMap.keySet().contains(resource)) { + StatusBean statusBean; + if (statusPanel.getInitialStatusBeanMap().containsKey(resource)) { + statusBean = statusPanel.getInitialStatusBeanMap().get(resource); + } else { + statusBean = new StatusBean(); + statusBean.setResourceName(resource); + statusBean.setStatus(StatusUtils.Status.NOT_YET_SUBMITTED); + } + + statusMap.put(statusBean.getResourceName(), statusBean); + } + } + + for (String resource : resourcesToRemove) { + statusMap.remove(resource); + } + + statusPanel.updateStatusBeans(new ArrayList<StatusBean>(statusMap.values())); + target.add(statusPanel); + } + } } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/markup/html/CrontabContainer.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/markup/html/CrontabContainer.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/markup/html/CrontabContainer.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/markup/html/CrontabContainer.java Wed Jan 30 11:36:08 2013 @@ -19,7 +19,6 @@ package org.apache.syncope.console.markup.html; import java.util.Arrays; - import org.apache.syncope.console.commons.SelectChoiceRenderer; import org.apache.syncope.console.commons.SelectOption; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -41,12 +40,13 @@ public class CrontabContainer extends We */ protected static final Logger LOG = LoggerFactory.getLogger(CrontabContainer.class); - private static final SelectOption[] CRON_TEMPLATES = new SelectOption[] { - new SelectOption("Unschedule", "UNSCHEDULE"), new SelectOption("Every 5 minutes", "0 0/5 * * * ?"), - new SelectOption("Fire at 12pm (noon) every day", "0 0 12 * * ?"), - new SelectOption("Fire at 12am (midnight) every first day of the month", "0 0 0 1 * ?"), - new SelectOption("Fire at 12am (midnight) every last day of the month", "0 0 0 L * ?"), - new SelectOption("Fire at 12am (midnight) every Monday", "0 0 0 ? * 2") }; + private static final SelectOption[] CRON_TEMPLATES = { + new SelectOption("Unschedule", "UNSCHEDULE"), new SelectOption("Every 5 minutes", "0 0/5 * * * ?"), + new SelectOption("Fire at 12pm (noon) every day", "0 0 12 * * ?"), + new SelectOption("Fire at 12am (midnight) every first day of the month", "0 0 0 1 * ?"), + new SelectOption("Fire at 12am (midnight) every last day of the month", "0 0 0 L * ?"), + new SelectOption("Fire at 12am (midnight) every Monday", "0 0 0 ? * 2") + }; private static final long serialVersionUID = 7879593326085337650L; @@ -68,16 +68,16 @@ public class CrontabContainer extends We super(id); setOutputMarkupId(true); - final DropDownChoice<SelectOption> cronTemplateChooser = new DropDownChoice<SelectOption>("cronTemplateChooser") { - - private static final long serialVersionUID = -5843424545478691442L; + final DropDownChoice<SelectOption> cronTemplateChooser = + new DropDownChoice<SelectOption>("cronTemplateChooser") { - @Override - protected CharSequence getDefaultChoice(final String selected) { + private static final long serialVersionUID = -5843424545478691442L; - return "<option value=\"\">" + getString("chooseForTemplate") + "</option>"; - } - }; + @Override + protected CharSequence getDefaultChoice(final String selected) { + return "<option value=\"\">" + getString("chooseForTemplate") + "</option>"; + } + }; cronTemplateChooser.setModel(new IModel<SelectOption>() { private static final long serialVersionUID = 6762568283146531315L; @@ -146,7 +146,6 @@ public class CrontabContainer extends We } private String getCronField(final FormComponent formComponent, final int field) { - String cronField = null; if (formComponent != null) { @@ -173,10 +172,13 @@ public class CrontabContainer extends We && hours != null && hours.getInput() != null && daysOfMonth != null && daysOfMonth.getInput() != null && months != null && months.getInput() != null && daysOfWeek != null && daysOfWeek.getInput() != null) { - cronExpression = new StringBuilder().append(seconds.getInput().trim()).append(" ").append( - minutes.getInput().trim()).append(" ").append(hours.getInput().trim()).append(" ").append( - daysOfMonth.getInput().trim()).append(" ").append(months.getInput().trim()).append(" ").append( - daysOfWeek.getInput().trim()).toString(); + cronExpression = new StringBuilder(). + append(seconds.getInput().trim()).append(" "). + append(minutes.getInput().trim()).append(" "). + append(hours.getInput().trim()).append(" "). + append(daysOfMonth.getInput().trim()).append(" "). + append(months.getInput().trim()).append(" "). + append(daysOfWeek.getInput().trim()).toString(); } return cronExpression; Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/EditUserModalPage.java Wed Jan 30 11:36:08 2013 @@ -19,12 +19,13 @@ package org.apache.syncope.console.pages; import java.util.ArrayList; -import java.util.List; import org.apache.syncope.common.mod.UserMod; import org.apache.syncope.common.to.UserTO; import org.apache.syncope.common.util.AttributableOperations; import org.apache.syncope.console.commons.StatusBean; import org.apache.syncope.console.pages.panels.AccountInformationPanel; +import org.apache.syncope.console.pages.panels.MembershipsPanel; +import org.apache.syncope.console.pages.panels.ResourcesPanel; import org.apache.syncope.console.pages.panels.StatusPanel; import org.apache.syncope.console.rest.UserRestClient; import org.apache.wicket.PageReference; @@ -58,14 +59,17 @@ public class EditUserModalPage extends U // add resource assignment details in case of update if (userTO.getId() != 0) { - final List<StatusBean> statuses = new ArrayList<StatusBean>(); - form.addOrReplace(new Label("pwdChangeInfo", new ResourceModel("pwdChangeInfo"))); - statusPanel = new StatusPanel("statuspanel", userTO, statuses); + statusPanel = new StatusPanel("statuspanel", userTO, new ArrayList<StatusBean>()); + statusPanel.setOutputMarkupId(true); form.addOrReplace(statusPanel); form.addOrReplace(new AccountInformationPanel("accountinformation", userTO)); + + form.addOrReplace(new ResourcesPanel("resources", userTO, statusPanel)); + + form.addOrReplace(new MembershipsPanel("memberships", userTO, false, statusPanel)); } } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/MembershipModalPage.java Wed Jan 30 11:36:08 2013 @@ -53,7 +53,6 @@ public class MembershipModalPage extends @Override protected void onSubmit(final AjaxRequestTarget target, final Form form) { - userTO.removeMembership(membershipTO); userTO.addMembership(membershipTO); Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/UserModalPage.java Wed Jan 30 11:36:08 2013 @@ -107,7 +107,7 @@ public abstract class UserModalPage exte form.add(new UserDetailsPanel("details", userTO, form, resetPassword, mode == Mode.TEMPLATE)); form.add(new Label("statuspanel", "")); - + form.add(new Label("pwdChangeInfo", "")); form.add(new Label("accountinformation", "")); @@ -134,13 +134,13 @@ public abstract class UserModalPage exte //-------------------------------- // Resources panel //-------------------------------- - form.add(new ResourcesPanel("resources", userTO)); + form.add(new ResourcesPanel("resources", userTO, null)); //-------------------------------- //-------------------------------- // Roles panel //-------------------------------- - form.add(new MembershipsPanel("memberships", userTO, mode == Mode.TEMPLATE)); + form.add(new MembershipsPanel("memberships", userTO, mode == Mode.TEMPLATE, null)); //-------------------------------- final AjaxButton submit = getOnSubmit(); Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/DerivedAttributesPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/DerivedAttributesPanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/DerivedAttributesPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/DerivedAttributesPanel.java Wed Jan 30 11:36:08 2013 @@ -19,7 +19,6 @@ package org.apache.syncope.console.pages.panels; import java.util.List; - import org.apache.syncope.common.to.AbstractAttributableTO; import org.apache.syncope.common.to.AttributeTO; import org.apache.syncope.common.to.RoleTO; Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/MembershipsPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/MembershipsPanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/MembershipsPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/MembershipsPanel.java Wed Jan 30 11:36:08 2013 @@ -18,14 +18,17 @@ */ package org.apache.syncope.console.pages.panels; +import java.util.Collections; +import java.util.HashSet; import java.util.List; - +import java.util.Set; import javax.swing.tree.DefaultMutableTreeNode; - import org.apache.syncope.common.to.MembershipTO; import org.apache.syncope.common.to.RoleTO; import org.apache.syncope.common.to.UserTO; import org.apache.syncope.console.commons.RoleTreeBuilder; +import org.apache.syncope.console.commons.RoleUtils; +import org.apache.syncope.console.commons.StatusUtils; import org.apache.syncope.console.pages.MembershipModalPage; import org.apache.syncope.console.pages.UserModalPage; import org.apache.syncope.console.wicket.ajax.markup.html.IndicatingDeleteOnConfirmAjaxLink; @@ -34,6 +37,7 @@ import org.apache.syncope.console.wicket import org.apache.syncope.console.wicket.markup.html.tree.TreeRoleProvider; import org.apache.wicket.Component; import org.apache.wicket.Page; +import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink; @@ -60,24 +64,29 @@ public class MembershipsPanel extends Pa @SpringBean private RoleTreeBuilder roleTreeBuilder; - private ListView<MembershipTO> membershipsView; + private final ListView<MembershipTO> membView; private final UserTO userTO; + private final StatusPanel statusPanel; + private final NestedTree<DefaultMutableTreeNode> tree; - public MembershipsPanel(final String id, final UserTO userTO, final boolean templateMode) { + public MembershipsPanel(final String id, final UserTO userTO, final boolean templateMode, + final StatusPanel statusPanel) { + super(id); this.userTO = userTO; + this.statusPanel = statusPanel; final WebMarkupContainer membershipsContainer = new WebMarkupContainer("membershipsContainer"); membershipsContainer.setOutputMarkupId(true); add(membershipsContainer); - final ModalWindow membershipWin = new ModalWindow("membershipWin"); - membershipWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); - membershipWin.setCookieName("create-membership-modal"); - add(membershipWin); + final ModalWindow membWin = new ModalWindow("membershipWin"); + membWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + membWin.setCookieName("create-membership-modal"); + add(membWin); final ITreeProvider<DefaultMutableTreeNode> treeProvider = new TreeRoleProvider(roleTreeBuilder, true); final DefaultMutableTreeNodeExpansionModel treeModel = new DefaultMutableTreeNodeExpansionModel(); @@ -107,32 +116,27 @@ public class MembershipsPanel extends Pa @Override protected void onClick(final AjaxRequestTarget target) { - super.onClick(target); - - membershipWin.setPageCreator(new ModalWindow.PageCreator() { + membWin.setPageCreator(new ModalWindow.PageCreator() { private static final long serialVersionUID = 7661763358801821185L; - private MembershipTO membershipTO; - @Override public Page createPage() { + PageReference pageRef = getPage().getPageReference(); - for (MembershipTO memberTO : membershipsView.getList()) { - if (memberTO.getRoleId() == roleTO.getId()) { - return new MembershipModalPage(getPage().getPageReference(), - membershipWin, memberTO, templateMode); + for (MembershipTO membTO : membView.getList()) { + if (membTO.getRoleId() == roleTO.getId()) { + return new MembershipModalPage(pageRef, membWin, membTO, templateMode); } } - membershipTO = new MembershipTO(); - membershipTO.setRoleId(roleTO.getId()); - membershipTO.setRoleName(roleTO.getName()); + MembershipTO membTO = new MembershipTO(); + membTO.setRoleId(roleTO.getId()); + membTO.setRoleName(roleTO.getName()); - return new MembershipModalPage(getPage().getPageReference(), membershipWin, - membershipTO, templateMode); + return new MembershipModalPage(pageRef, membWin, membTO, templateMode); } }); - membershipWin.show(target); + membWin.show(target); } }; } @@ -144,7 +148,7 @@ public class MembershipsPanel extends Pa this.add(tree); - membershipsView = new ListView<MembershipTO>("memberships", + membView = new ListView<MembershipTO>("memberships", new PropertyModel<List<? extends MembershipTO>>(userTO, "memberships")) { private static final long serialVersionUID = 9101744072914090143L; @@ -153,8 +157,8 @@ public class MembershipsPanel extends Pa protected void populateItem(final ListItem<MembershipTO> item) { final MembershipTO membershipTO = (MembershipTO) item.getDefaultModelObject(); - item.add(new Label("roleId", new Model(membershipTO.getRoleId()))); - item.add(new Label("roleName", new Model(membershipTO.getRoleName()))); + item.add(new Label("roleId", new Model<Long>(membershipTO.getRoleId()))); + item.add(new Label("roleName", new Model<String>(membershipTO.getRoleName()))); AjaxLink editLink = new IndicatingAjaxLink("editLink") { @@ -162,18 +166,18 @@ public class MembershipsPanel extends Pa @Override public void onClick(final AjaxRequestTarget target) { - membershipWin.setPageCreator(new ModalWindow.PageCreator() { + membWin.setPageCreator(new ModalWindow.PageCreator() { private static final long serialVersionUID = -7834632442532690940L; @Override public Page createPage() { - return new MembershipModalPage(getPage().getPageReference(), membershipWin, + return new MembershipModalPage(getPage().getPageReference(), membWin, membershipTO, templateMode); } }); - membershipWin.show(target); + membWin.show(target); } }; item.add(editLink); @@ -186,19 +190,35 @@ public class MembershipsPanel extends Pa public void onClick(final AjaxRequestTarget target) { userTO.removeMembership(membershipTO); target.add(membershipsContainer); + + RoleTO roleTO = RoleUtils.findRole(roleTreeBuilder, membershipTO.getRoleId()); + Set<String> resourcesToRemove = roleTO == null + ? Collections.<String>emptySet() : roleTO.getResources(); + if (!resourcesToRemove.isEmpty()) { + Set<String> resourcesAssignedViaMembership = new HashSet<String>(); + for (MembershipTO membTO : userTO.getMemberships()) { + roleTO = RoleUtils.findRole(roleTreeBuilder, membTO.getRoleId()); + if (roleTO != null) { + resourcesAssignedViaMembership.addAll(roleTO.getResources()); + } + } + resourcesToRemove.removeAll(resourcesAssignedViaMembership); + resourcesToRemove.removeAll(userTO.getResources()); + } + + StatusUtils.update(statusPanel, target, Collections.<String>emptySet(), resourcesToRemove); } }; item.add(deleteLink); } }; - membershipsContainer.add(membershipsView); + membershipsContainer.add(membView); - setWindowClosedCallback(membershipWin, membershipsContainer); + setWindowClosedCallback(membWin, membershipsContainer); } private void setWindowClosedCallback(final ModalWindow window, final WebMarkupContainer container) { - window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() { private static final long serialVersionUID = 8804221891699487139L; @@ -207,6 +227,19 @@ public class MembershipsPanel extends Pa public void onClose(final AjaxRequestTarget target) { final UserTO updatedUserTO = ((UserModalPage) getPage()).getUserTO(); + if (updatedUserTO.getMemberships().size() > userTO.getMemberships().size()) { + Set<Long> diff = new HashSet<Long>(updatedUserTO.getMembershipMap().keySet()); + diff.removeAll(userTO.getMembershipMap().keySet()); + + Set<String> resourcesToAdd = new HashSet<String>(); + for (Long diffMembId : diff) { + long roleId = updatedUserTO.getMembershipMap().get(diffMembId).getRoleId(); + RoleTO roleTO = RoleUtils.findRole(roleTreeBuilder, roleId); + resourcesToAdd.addAll(roleTO.getResources()); + StatusUtils.update(statusPanel, target, resourcesToAdd, Collections.<String>emptySet()); + } + } + MembershipsPanel.this.userTO.setMemberships(updatedUserTO.getMemberships()); target.add(container); } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourcesPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourcesPanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourcesPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/ResourcesPanel.java Wed Jan 30 11:36:08 2013 @@ -19,15 +19,27 @@ package org.apache.syncope.console.pages.panels; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; - +import java.util.Set; import org.apache.syncope.common.to.AbstractAttributableTO; +import org.apache.syncope.common.to.MembershipTO; import org.apache.syncope.common.to.ResourceTO; +import org.apache.syncope.common.to.RoleTO; +import org.apache.syncope.common.to.UserTO; +import org.apache.syncope.console.commons.RoleTreeBuilder; +import org.apache.syncope.console.commons.RoleUtils; +import org.apache.syncope.console.commons.SelectChoiceRenderer; +import org.apache.syncope.console.commons.StatusUtils; import org.apache.syncope.console.rest.ResourceRestClient; import org.apache.syncope.console.wicket.markup.html.form.AjaxPalettePanel; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.extensions.markup.html.form.palette.Palette; +import org.apache.wicket.extensions.markup.html.form.palette.component.Recorder; +import org.apache.wicket.markup.html.form.IChoiceRenderer; 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.PropertyModel; import org.apache.wicket.model.util.ListModel; import org.apache.wicket.spring.injection.annot.SpringBean; @@ -39,34 +51,99 @@ public class ResourcesPanel extends Pane @SpringBean private ResourceRestClient resourceRestClient; - public <T extends AbstractAttributableTO> ResourcesPanel(final String id, final T entityTO) { + @SpringBean + private RoleTreeBuilder roleTreeBuilder; + + private final AbstractAttributableTO attributableTO; + + private final Set<String> previousResources; + + private final List<String> allResources; + + private ResourcesPanel(final String id, final AbstractAttributableTO attributableTO) { super(id); - final IModel<List<String>> allResources = new allResourcesModel(resourceRestClient); + this.attributableTO = attributableTO; + previousResources = new HashSet<String>(attributableTO.getResources()); + allResources = new ArrayList<String>(); + for (ResourceTO resourceTO : resourceRestClient.getAllResources()) { + allResources.add(resourceTO.getName()); + } + } - final AjaxPalettePanel<String> resourcesPalette = new AjaxPalettePanel<String>("resourcesPalette", - new PropertyModel<List<String>>(entityTO, "resources"), - new ListModel<String>(allResources.getObject())); + public ResourcesPanel(final String id, final UserTO userTO, final StatusPanel statusPanel) { + this(id, userTO); + final AjaxPalettePanel<String> resourcesPalette = new AjaxRecordingPalettePanel<String>("resourcesPalette", + new PropertyModel<List<String>>(userTO, "resources"), + new ListModel<String>(allResources), statusPanel); add(resourcesPalette); } - - private static class allResourcesModel extends LoadableDetachableModel<List<String>> { - private static final long serialVersionUID = 5275935387613157437L; - - private ResourceRestClient client; - - public allResourcesModel(ResourceRestClient resourceRestClient) { - this.client = resourceRestClient; + + public ResourcesPanel(final String id, final RoleTO roleTO) { + this(id, (AbstractAttributableTO) roleTO); + + final AjaxPalettePanel<String> resourcesPalette = new AjaxPalettePanel<String>("resourcesPalette", + new PropertyModel<List<String>>(roleTO, "resources"), + new ListModel<String>(allResources)); + add(resourcesPalette); + } + + private class AjaxRecordingPalettePanel<T> extends AjaxPalettePanel<T> { + + private static final long serialVersionUID = -4215625881756021988L; + + private final StatusPanel statusPanel; + + public AjaxRecordingPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices, + final StatusPanel statusPanel) { + + super(id, model, choices, new SelectChoiceRenderer<T>(), false); + this.statusPanel = statusPanel; } @Override - protected List<String> load() { - final List<String> resourceNames = new ArrayList<String>(); + protected Palette<T> createPalette(final IModel<List<T>> model, final ListModel<T> choices, + final IChoiceRenderer<T> renderer, final boolean allowOrder) { + + return new Palette("paletteField", model, choices, renderer, 8, allowOrder) { + + private static final long serialVersionUID = -3415146226879212841L; - for (ResourceTO resourceTO : client.getAllResources()) { - resourceNames.add(resourceTO.getName()); - } - return resourceNames; + @Override + protected Recorder newRecorderComponent() { + Recorder recorder = super.newRecorderComponent(); + recorder.add(new AjaxFormComponentUpdatingBehavior("change") { + + private static final long serialVersionUID = 5538299138211283825L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + if (attributableTO instanceof UserTO) { + UserTO userTO = (UserTO) attributableTO; + + Set<String> resourcesToRemove = new HashSet<String>(previousResources); + resourcesToRemove.removeAll(userTO.getResources()); + if (!resourcesToRemove.isEmpty()) { + Set<String> resourcesAssignedViaMembership = new HashSet<String>(); + for (MembershipTO membTO : userTO.getMemberships()) { + RoleTO roleTO = RoleUtils.findRole(roleTreeBuilder, membTO.getRoleId()); + if (roleTO != null) { + resourcesAssignedViaMembership.addAll(roleTO.getResources()); + } + } + resourcesToRemove.removeAll(resourcesAssignedViaMembership); + } + + previousResources.clear(); + previousResources.addAll(userTO.getResources()); + + StatusUtils.update(statusPanel, target, userTO.getResources(), resourcesToRemove); + } + } + }); + return recorder; + } + }; } } } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/StatusPanel.java Wed Jan 30 11:36:08 2013 @@ -20,7 +20,9 @@ package org.apache.syncope.console.pages import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.syncope.common.to.AbstractAttributableTO; import org.apache.syncope.common.to.PropagationRequestTO; @@ -59,8 +61,12 @@ public class StatusPanel extends Panel { private final StatusUtils statusUtils; + private final Map<String, StatusBean> initialStatusBeanMap; + private final CheckGroup<StatusBean> checkGroup; + private final ListView<StatusBean> statusBeansListView; + public <T extends AbstractAttributableTO> StatusPanel(final String id, final AbstractAttributableTO attributable, final List<StatusBean> selectedResources) { @@ -68,7 +74,7 @@ public class StatusPanel extends Panel { statusUtils = new StatusUtils(resourceRestClient, (attributable instanceof UserTO ? userRestClient : roleRestClient)); - final List<StatusBean> statuses = new ArrayList<StatusBean>(); + final List<StatusBean> statusBeans = new ArrayList<StatusBean>(); final StatusBean syncope = new StatusBean(); syncope.setResourceName("Syncope"); @@ -84,16 +90,30 @@ public class StatusPanel extends Panel { syncope.setAccountLink(roleTO.getDisplayName()); syncope.setStatus(Status.ACTIVE); } - statuses.add(syncope); - statuses.addAll(statusUtils.getRemoteStatuses(attributable)); + statusBeans.add(syncope); + statusBeans.addAll(statusUtils.getRemoteStatuses(attributable)); + + initialStatusBeanMap = new HashMap<String, StatusBean>(statusBeans.size()); + for (StatusBean statusBean : statusBeans) { + initialStatusBeanMap.put(statusBean.getResourceName(), statusBean); + } + + checkGroup = new CheckGroup<StatusBean>("group", selectedResources) { + + private static final long serialVersionUID = 4085912362037539780L; - checkGroup = new CheckGroup<StatusBean>("group", selectedResources); + @Override + protected boolean wantOnSelectionChangedNotifications() { + return true; + } + }; + checkGroup.setOutputMarkupId(true); add(checkGroup); add(new CheckGroupSelector("groupselector", checkGroup)); - final ListView<StatusBean> resources = new ListView<StatusBean>("resources", statuses) { + statusBeansListView = new ListView<StatusBean>("resources", statusBeans) { private static final long serialVersionUID = 4949588177564901031L; @@ -105,6 +125,12 @@ public class StatusPanel extends Panel { switch (item.getModelObject().getStatus()) { + case NOT_YET_SUBMITTED: + image = new Image("icon", "../statuses/undefined.png"); + alt = "undefined icon"; + title = "Not yet submitted"; + break; + case ACTIVE: image = new Image("icon", "../statuses/active.png"); alt = "active icon"; @@ -142,7 +168,7 @@ public class StatusPanel extends Panel { } }); - final Check check = new Check("check", item.getModel(), checkGroup); + final Check<StatusBean> check = new Check<StatusBean>("check", item.getModel(), checkGroup); check.setEnabled(checkVisibility); check.setVisible(checkVisibility); item.add(check); @@ -160,10 +186,8 @@ public class StatusPanel extends Panel { item.add(image); } }; - - resources.setReuseItems(true); - - checkGroup.add(resources); + statusBeansListView.setReuseItems(true); + checkGroup.add(statusBeansListView); } public PropagationRequestTO getPropagationRequestTO() { @@ -177,4 +201,26 @@ public class StatusPanel extends Panel { return result; } + + public List<StatusBean> getStatusBeans() { + return statusBeansListView.getModelObject(); + } + + public Map<String, StatusBean> getInitialStatusBeanMap() { + return initialStatusBeanMap; + } + + public void updateStatusBeans(final List<StatusBean> statusBeans) { + statusBeansListView.removeAll(); + statusBeansListView.getModelObject().clear(); + statusBeansListView.getModelObject().addAll(statusBeans); + + for (StatusBean statusBean : statusBeans) { + if (!checkGroup.getModelObject().contains(statusBean) + && statusBean.getStatus() == StatusUtils.Status.NOT_YET_SUBMITTED) { + + checkGroup.getModelObject().add(statusBean); + } + } + } } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AbstractFieldPanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AbstractFieldPanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AbstractFieldPanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AbstractFieldPanel.java Wed Jan 30 11:36:08 2013 @@ -19,7 +19,6 @@ package org.apache.syncope.console.wicket.markup.html.form; import java.io.Serializable; - import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.slf4j.Logger; @@ -35,7 +34,6 @@ public abstract class AbstractFieldPanel private static final long serialVersionUID = 5958017546318855690L; public AbstractFieldPanel(final String id, final IModel<T> model) { - super(id, model); } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxPalettePanel.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxPalettePanel.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxPalettePanel.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxPalettePanel.java Wed Jan 30 11:36:08 2013 @@ -20,7 +20,6 @@ package org.apache.syncope.console.wicke import java.io.Serializable; import java.util.List; - import org.apache.syncope.console.commons.SelectChoiceRenderer; import org.apache.wicket.extensions.markup.html.form.palette.Palette; import org.apache.wicket.markup.html.form.IChoiceRenderer; @@ -34,14 +33,13 @@ public class AjaxPalettePanel<T> extends final Palette<T> palette; public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices) { - this(id, model, choices, false); } public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices, final boolean allowOrder) { - this(id, model, choices, new SelectChoiceRenderer(), allowOrder); + this(id, model, choices, new SelectChoiceRenderer<T>(), allowOrder); } public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices, @@ -54,14 +52,14 @@ public class AjaxPalettePanel<T> extends setOutputMarkupId(true); } - private Palette<T> createPalette(final IModel<List<T>> model, final ListModel<T> choices, + protected Palette<T> createPalette(final IModel<List<T>> model, final ListModel<T> choices, final IChoiceRenderer<T> renderer, final boolean allowOrder) { return new Palette("paletteField", model, choices, renderer, 8, allowOrder); } @Override - public AbstractFieldPanel setModelObject(Serializable object) { + public AbstractFieldPanel setModelObject(final Serializable object) { palette.setDefaultModelObject(object); return this; } Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/tree/TreeRoleProvider.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/tree/TreeRoleProvider.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/tree/TreeRoleProvider.java (original) +++ syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/tree/TreeRoleProvider.java Wed Jan 30 11:36:08 2013 @@ -19,7 +19,6 @@ package org.apache.syncope.console.wicket.markup.html.tree; import javax.swing.tree.DefaultMutableTreeNode; - import org.apache.syncope.console.commons.RoleTreeBuilder; import org.apache.wicket.extensions.markup.html.repeater.util.TreeModelProvider; import org.apache.wicket.model.IModel; Modified: syncope/trunk/console/src/test/java/org/apache/syncope/console/EditProfileTestITCase.java URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/test/java/org/apache/syncope/console/EditProfileTestITCase.java?rev=1440351&r1=1440350&r2=1440351&view=diff ============================================================================== --- syncope/trunk/console/src/test/java/org/apache/syncope/console/EditProfileTestITCase.java (original) +++ syncope/trunk/console/src/test/java/org/apache/syncope/console/EditProfileTestITCase.java Wed Jan 30 11:36:08 2013 @@ -26,14 +26,11 @@ public class EditProfileTestITCase exten @Override @Before public void setUp() throws Exception { - super.setUp(BASE_URL, "*firefox"); } @Test public void selfRegistration() { - selenium.setSpeed("1000"); - selenium.open("/syncope-console/"); selenium.click("//div/span/span/a"); @@ -52,8 +49,6 @@ public class EditProfileTestITCase exten @Test public void editUserProfile() { - selenium.setSpeed("1000"); - selenium.open("/syncope-console/"); selenium.type("name=userId", "user1"); selenium.type("name=password", "password"); @@ -63,12 +58,10 @@ public class EditProfileTestITCase exten selenium.click("css=img[alt=\"Schema\"]"); selenium.waitForPageToLoad("30000"); - selenium.click("id=username"); - selenium.click("//span[@id='editProfile']/a"); + selenium.click("//div/ul/li[10]/div/div/a/span"); selenium.waitForCondition("selenium.isElementPresent(\"//span[contains(text(),'Attributes')]\");", "30000"); - - assertTrue(selenium.isElementPresent("//input[@value='user1']")); + selenium.waitForCondition("selenium.isElementPresent(\"//input[@value='user1']\");", "30000"); selenium.click("css=a.w_close"); }