From 7f1282bffa7627c341b9e52571d7412a243a07e0 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Tue, 11 Sep 2012 17:29:39 +0200 Subject: [PATCH] OO-291: in the course member emanagement: implement filter by origin,, implement the search --- .../org/olat/basesecurity/BaseSecurity.java | 7 + .../basesecurity/BaseSecurityManager.java | 103 +++++++---- .../basesecurity/SearchIdentityParams.java | 159 ++++++++++++++++ .../member/AbstractMemberListController.java | 75 ++++++-- .../course/member/CourseRoleCellRenderer.java | 20 ++- .../member/EditMembershipController.java | 2 +- .../course/member/MemberListController.java | 7 +- .../course/member/MemberListTableModel.java | 34 ++-- .../MemberListWithOriginFilterController.java | 69 +++++++ .../course/member/MemberSearchController.java | 62 +++++++ .../olat/course/member/MemberSearchForm.java | 170 ++++++++++++++++++ .../org/olat/course/member/MemberView.java | 37 ++-- .../member/MembersOverviewController.java | 52 ++++-- .../course/member/OriginFilterController.java | 93 ++++++++++ .../course/member/SearchMembersParams.java | 49 ++++- .../course/member/SearchOriginParams.java | 53 ++++++ .../member/_content/all_member_list.html | 7 + .../_content/member_list_origin_filter.html | 13 ++ .../course/member/_content/search_form.html | 14 ++ .../member/_content/search_member_list.html | 4 + .../member/_i18n/LocalStrings_de.properties | 25 ++- .../member/_i18n/LocalStrings_en.properties | 10 +- .../member/_i18n/LocalStrings_fr.properties | 10 +- .../olat/course/nodes/co/CORunController.java | 4 +- .../ui/main/_i18n/LocalStrings_de.properties | 8 +- .../_spring/userPropertiesContext.xml | 53 ++++++ .../basesecurity/BaseSecurityManagerTest.java | 93 ++++++++++ 27 files changed, 1095 insertions(+), 138 deletions(-) create mode 100644 src/main/java/org/olat/basesecurity/SearchIdentityParams.java create mode 100644 src/main/java/org/olat/course/member/MemberListWithOriginFilterController.java create mode 100644 src/main/java/org/olat/course/member/MemberSearchController.java create mode 100644 src/main/java/org/olat/course/member/MemberSearchForm.java create mode 100644 src/main/java/org/olat/course/member/OriginFilterController.java create mode 100644 src/main/java/org/olat/course/member/SearchOriginParams.java create mode 100644 src/main/java/org/olat/course/member/_content/member_list_origin_filter.html create mode 100644 src/main/java/org/olat/course/member/_content/search_form.html create mode 100644 src/main/java/org/olat/course/member/_content/search_member_list.html diff --git a/src/main/java/org/olat/basesecurity/BaseSecurity.java b/src/main/java/org/olat/basesecurity/BaseSecurity.java index efcf8f615fd..f9390bf8e66 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurity.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurity.java @@ -516,6 +516,13 @@ public interface BaseSecurity { public List<Identity> getVisibleIdentitiesByPowerSearch(String login, Map<String, String> userProperties, boolean userPropertiesAsIntersectionSearch, SecurityGroup[] groups, PermissionOnResourceable[] permissionOnResources, String[] authProviders, Date createdAfter, Date createdBefore); + /** + * Like the following method but compact + * @param params + * @return + */ + public List<Identity> getIdentitiesByPowerSearch(SearchIdentityParams params); + /** * Get a list of identities that match the following conditions. All * parameters are additive. NULL values mean "no constraints" (e.g. all diff --git a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java index 0c53ece1349..f7185b9637f 100644 --- a/src/main/java/org/olat/basesecurity/BaseSecurityManager.java +++ b/src/main/java/org/olat/basesecurity/BaseSecurityManager.java @@ -1264,15 +1264,15 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { /** * @see org.olat.basesecurity.Manager#getVisibleIdentitiesByPowerSearch(java.lang.String, java.util.Map, boolean, org.olat.basesecurity.SecurityGroup[], org.olat.basesecurity.PermissionOnResourceable[], java.lang.String[], java.util.Date, java.util.Date) */ - public List getVisibleIdentitiesByPowerSearch(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, + public List<Identity> getVisibleIdentitiesByPowerSearch(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, SecurityGroup[] groups, PermissionOnResourceable[] permissionOnResources, String[] authProviders, Date createdAfter, Date createdBefore) { - return getIdentitiesByPowerSearch(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, - authProviders, createdAfter, createdBefore, null, null, Identity.STATUS_VISIBLE_LIMIT ); + return getIdentitiesByPowerSearch(new SearchIdentityParams(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, + authProviders, createdAfter, createdBefore, null, null, Identity.STATUS_VISIBLE_LIMIT)); } public long countIdentitiesByPowerSearch(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, SecurityGroup[] groups, PermissionOnResourceable[] permissionOnResources, String[] authProviders, Date createdAfter, Date createdBefore, Date userLoginAfter, Date userLoginBefore, Integer status) { - DBQuery dbq = createIdentitiesByPowerQuery(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, authProviders, createdAfter, createdBefore, userLoginAfter, userLoginBefore, status, true); + DBQuery dbq = createIdentitiesByPowerQuery(new SearchIdentityParams(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, authProviders, createdAfter, createdBefore, userLoginAfter, userLoginBefore, status), true); Number count = (Number)dbq.uniqueResult(); return count.longValue(); } @@ -1282,16 +1282,22 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { */ public List<Identity> getIdentitiesByPowerSearch(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, SecurityGroup[] groups, PermissionOnResourceable[] permissionOnResources, String[] authProviders, Date createdAfter, Date createdBefore, Date userLoginAfter, Date userLoginBefore, Integer status) { - DBQuery dbq = createIdentitiesByPowerQuery(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, authProviders, createdAfter, createdBefore, userLoginAfter, userLoginBefore, status, false); + DBQuery dbq = createIdentitiesByPowerQuery(new SearchIdentityParams(login, userproperties, userPropertiesAsIntersectionSearch, groups, permissionOnResources, authProviders, createdAfter, createdBefore, userLoginAfter, userLoginBefore, status), false); return dbq.list(); } - private DBQuery createIdentitiesByPowerQuery(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, SecurityGroup[] groups, - PermissionOnResourceable[] permissionOnResources, String[] authProviders, Date createdAfter, Date createdBefore, Date userLoginAfter, Date userLoginBefore, Integer status, boolean count) { + @Override + public List<Identity> getIdentitiesByPowerSearch(SearchIdentityParams params) { + DBQuery dbq = createIdentitiesByPowerQuery(params, false); + @SuppressWarnings("unchecked") + List<Identity> identities = dbq.list(); + return identities; + } - boolean hasGroups = (groups != null && groups.length > 0); - boolean hasPermissionOnResources = (permissionOnResources != null && permissionOnResources.length > 0); - boolean hasAuthProviders = (authProviders != null && authProviders.length > 0); + private DBQuery createIdentitiesByPowerQuery(SearchIdentityParams params, boolean count) { + boolean hasGroups = (params.getGroups() != null && params.getGroups().length > 0); + boolean hasPermissionOnResources = (params.getPermissionOnResources() != null && params.getPermissionOnResources().length > 0); + boolean hasAuthProviders = (params.getAuthProviders() != null && params.getAuthProviders().length > 0); // select identity and inner join with user to optimize query StringBuilder sb = new StringBuilder(); @@ -1328,11 +1334,19 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { sb.append(" ,org.olat.basesecurity.SecurityGroupMembershipImpl as policyGroupMembership "); sb.append(" ,org.olat.basesecurity.PolicyImpl as policy "); sb.append(" ,org.olat.resource.OLATResourceImpl as resource "); - } + } + + String login = params.getLogin(); + Map<String,String> userproperties = params.getUserProperties(); + Date createdAfter = params.getCreatedAfter(); + Date createdBefore = params.getCreatedBefore(); + Integer status = params.getStatus(); + Collection<Long> identityKeys = params.getIdentityKeys(); // complex where clause only when values are available - if (login != null || (userproperties != null && !userproperties.isEmpty()) || createdAfter != null || createdBefore != null || - hasAuthProviders || hasGroups || hasPermissionOnResources || status != null) { + if (login != null || (userproperties != null && !userproperties.isEmpty()) + || (identityKeys != null && !identityKeys.isEmpty()) || createdAfter != null || createdBefore != null + || hasAuthProviders || hasGroups || hasPermissionOnResources || status != null) { sb.append(" where "); boolean needsAnd = false; boolean needsUserPropertiesJoin = false; @@ -1341,17 +1355,17 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { if (login != null && (userproperties != null && !userproperties.isEmpty())) { sb.append(" ( "); } - // append queries for user attributes - if (login != null) { - login = makeFuzzyQueryString(login); - if (login.contains("_") && dbVendor.equals("oracle")) { - //oracle needs special ESCAPE sequence to search for escaped strings - sb.append(" lower(ident.name) like :login ESCAPE '\\'"); - } else if (dbVendor.equals("mysql")) { - sb.append(" ident.name like :login"); - } else { - sb.append(" lower(ident.name) like :login"); - } + // append query for login + if (login != null) { + login = makeFuzzyQueryString(login); + if (login.contains("_") && dbVendor.equals("oracle")) { + //oracle needs special ESCAPE sequence to search for escaped strings + sb.append(" lower(ident.name) like :login ESCAPE '\\'"); + } else if (dbVendor.equals("mysql")) { + sb.append(" ident.name like :login"); + } else { + sb.append(" lower(ident.name) like :login"); + } // if user fields follow a join element is needed needsUserPropertiesJoin = true; // at least one user field used, after this and is required @@ -1360,8 +1374,8 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // append queries for user fields if (userproperties != null && !userproperties.isEmpty()) { - HashMap<String, String> emailProperties = new HashMap<String, String>(); - HashMap<String, String> otherProperties = new HashMap<String, String>(); + Map<String, String> emailProperties = new HashMap<String, String>(); + Map<String, String> otherProperties = new HashMap<String, String>(); // split the user fields into two groups for (String key : userproperties.keySet()) { @@ -1374,7 +1388,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // handle email fields special: search in all email fields if (!emailProperties.isEmpty()) { - needsUserPropertiesJoin = checkIntersectionInUserProperties(sb,needsUserPropertiesJoin, userPropertiesAsIntersectionSearch); + needsUserPropertiesJoin = checkIntersectionInUserProperties(sb,needsUserPropertiesJoin, params.isUserPropertiesAsIntersectionSearch()); boolean moreThanOne = emailProperties.size() > 1; if (moreThanOne) sb.append("("); boolean needsOr = false; @@ -1401,7 +1415,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // add other fields for (String key : otherProperties.keySet()) { - needsUserPropertiesJoin = checkIntersectionInUserProperties(sb,needsUserPropertiesJoin, userPropertiesAsIntersectionSearch); + needsUserPropertiesJoin = checkIntersectionInUserProperties(sb,needsUserPropertiesJoin, params.isUserPropertiesAsIntersectionSearch()); if(dbVendor.equals("mysql")) { sb.append(" user.properties['").append(key).append("'] like :").append(key).append("_value "); } else { @@ -1419,15 +1433,22 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { otherProperties.clear(); // at least one user field used, after this and is required needsAnd = true; - } + } // end of user fields and login part if (login != null && (userproperties != null && !userproperties.isEmpty())) { sb.append(" ) "); } // now continue with the other elements. They are joined with an AND connection + // append query for identity primary keys + if(identityKeys != null && !identityKeys.isEmpty()) { + needsAnd = checkAnd(sb, needsAnd); + sb.append("ident.key in (:identityKeys)"); + } + // append query for named security groups if (hasGroups) { + SecurityGroup[] groups = params.getGroups(); needsAnd = checkAnd(sb, needsAnd); sb.append(" ("); for (int i = 0; i < groups.length; i++) { @@ -1442,6 +1463,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { if (hasPermissionOnResources) { needsAnd = checkAnd(sb, needsAnd); sb.append(" ("); + PermissionOnResourceable[] permissionOnResources = params.getPermissionOnResources(); for (int i = 0; i < permissionOnResources.length; i++) { sb.append(" ("); sb.append(" policy.permission=:permission_").append(i); @@ -1460,6 +1482,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { if (hasAuthProviders) { needsAnd = checkAnd(sb, needsAnd); sb.append(" ("); + String[] authProviders = params.getAuthProviders(); for (int i = 0; i < authProviders.length; i++) { // special case for null auth provider if (authProviders[i] == null) { @@ -1481,11 +1504,11 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { needsAnd = checkAnd(sb, needsAnd); sb.append(" ident.creationDate <= :createdBefore "); } - if(userLoginAfter != null){ + if(params.getUserLoginAfter() != null){ needsAnd = checkAnd(sb, needsAnd); sb.append(" ident.lastLogin >= :lastloginAfter "); } - if(userLoginBefore != null){ + if(params.getUserLoginBefore() != null){ needsAnd = checkAnd(sb, needsAnd); sb.append(" ident.lastLogin <= :lastloginBefore "); } @@ -1509,8 +1532,13 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { DBQuery dbq = db.createQuery(query); // add user attributes - if (login != null) + if (login != null) { dbq.setString("login", login.toLowerCase()); + } + + if(identityKeys != null && !identityKeys.isEmpty()) { + dbq.setParameterList("identityKeys", identityKeys); + } // add user properties attributes if (userproperties != null && !userproperties.isEmpty()) { @@ -1523,6 +1551,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // add named security group names if (hasGroups) { + SecurityGroup[] groups = params.getGroups(); for (int i = 0; i < groups.length; i++) { SecurityGroupImpl group = (SecurityGroupImpl) groups[i]; // need to work with impls dbq.setEntity("group_" + i, group); @@ -1531,6 +1560,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // add policies if (hasPermissionOnResources) { + PermissionOnResourceable[] permissionOnResources = params.getPermissionOnResources(); for (int i = 0; i < permissionOnResources.length; i++) { PermissionOnResourceable permissionOnResource = permissionOnResources[i]; dbq.setString("permission_" + i, permissionOnResource.getPermission()); @@ -1542,6 +1572,7 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { // add authentication providers if (hasAuthProviders) { + String[] authProviders = params.getAuthProviders(); for (int i = 0; i < authProviders.length; i++) { String authProvider = authProviders[i]; if (authProvider != null) { @@ -1558,11 +1589,11 @@ public class BaseSecurityManager extends BasicManager implements BaseSecurity { if (createdBefore != null) { dbq.setDate("createdBefore", createdBefore); } - if(userLoginAfter != null){ - dbq.setDate("lastloginAfter", userLoginAfter); + if(params.getUserLoginAfter() != null){ + dbq.setDate("lastloginAfter", params.getUserLoginAfter()); } - if(userLoginBefore != null){ - dbq.setDate("lastloginBefore", userLoginBefore); + if(params.getUserLoginBefore() != null){ + dbq.setDate("lastloginBefore", params.getUserLoginBefore()); } if (status != null) { diff --git a/src/main/java/org/olat/basesecurity/SearchIdentityParams.java b/src/main/java/org/olat/basesecurity/SearchIdentityParams.java new file mode 100644 index 00000000000..b1f53ad5be6 --- /dev/null +++ b/src/main/java/org/olat/basesecurity/SearchIdentityParams.java @@ -0,0 +1,159 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.basesecurity; + +import java.util.Collection; +import java.util.Date; +import java.util.Map; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class SearchIdentityParams { + private String login; + private Map<String, String> userProperties; + private boolean userPropertiesAsIntersectionSearch; + private SecurityGroup[] groups; + private PermissionOnResourceable[] permissionOnResources; + private String[] authProviders; + private Date createdAfter; + private Date createdBefore; + private Date userLoginAfter; + private Date userLoginBefore; + private Integer status; + private Collection<Long> identityKeys; + + public SearchIdentityParams() { + // + } + + public SearchIdentityParams(String login, Map<String, String> userproperties, boolean userPropertiesAsIntersectionSearch, + SecurityGroup[] groups, PermissionOnResourceable[] permissionOnResources, String[] authProviders, + Date createdAfter, Date createdBefore, Date userLoginAfter, Date userLoginBefore, Integer status) { + this.login = login; + this.userProperties = userproperties; + this.userPropertiesAsIntersectionSearch = userPropertiesAsIntersectionSearch; + this.groups = groups; + this.permissionOnResources = permissionOnResources; + this.authProviders = authProviders; + this.createdAfter = createdAfter; + this.createdBefore = createdBefore; + this.userLoginAfter = userLoginAfter; + this.userLoginBefore = userLoginBefore; + this.status = status; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public Map<String, String> getUserProperties() { + return userProperties; + } + + public void setUserProperties(Map<String, String> userProperties) { + this.userProperties = userProperties; + } + + public boolean isUserPropertiesAsIntersectionSearch() { + return userPropertiesAsIntersectionSearch; + } + + public void setUserPropertiesAsIntersectionSearch(boolean userPropertiesAsIntersectionSearch) { + this.userPropertiesAsIntersectionSearch = userPropertiesAsIntersectionSearch; + } + + public SecurityGroup[] getGroups() { + return groups; + } + + public void setGroups(SecurityGroup[] groups) { + this.groups = groups; + } + + public PermissionOnResourceable[] getPermissionOnResources() { + return permissionOnResources; + } + + public void setPermissionOnResources(PermissionOnResourceable[] permissionOnResources) { + this.permissionOnResources = permissionOnResources; + } + + public String[] getAuthProviders() { + return authProviders; + } + + public void setAuthProviders(String[] authProviders) { + this.authProviders = authProviders; + } + + public Date getCreatedAfter() { + return createdAfter; + } + + public void setCreatedAfter(Date createdAfter) { + this.createdAfter = createdAfter; + } + + public Date getCreatedBefore() { + return createdBefore; + } + + public void setCreatedBefore(Date createdBefore) { + this.createdBefore = createdBefore; + } + + public Date getUserLoginAfter() { + return userLoginAfter; + } + + public void setUserLoginAfter(Date userLoginAfter) { + this.userLoginAfter = userLoginAfter; + } + + public Date getUserLoginBefore() { + return userLoginBefore; + } + + public void setUserLoginBefore(Date userLoginBefore) { + this.userLoginBefore = userLoginBefore; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Collection<Long> getIdentityKeys() { + return identityKeys; + } + + public void setIdentityKeys(Collection<Long> identityKeys) { + this.identityKeys = identityKeys; + } +} diff --git a/src/main/java/org/olat/course/member/AbstractMemberListController.java b/src/main/java/org/olat/course/member/AbstractMemberListController.java index 300ddc0117c..1c08954ab73 100644 --- a/src/main/java/org/olat/course/member/AbstractMemberListController.java +++ b/src/main/java/org/olat/course/member/AbstractMemberListController.java @@ -29,7 +29,7 @@ import java.util.Map; import java.util.Set; import org.olat.basesecurity.BaseSecurity; -import org.olat.basesecurity.IdentityShort; +import org.olat.basesecurity.SearchIdentityParams; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.UserRequest; @@ -53,6 +53,8 @@ import org.olat.core.gui.control.generic.closablewrapper.CloseableModalControlle import org.olat.core.gui.control.generic.modal.DialogBoxController; import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; import org.olat.core.id.Identity; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; import org.olat.course.member.MemberListTableModel.Cols; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupMembership; @@ -64,12 +66,15 @@ import org.olat.repository.RepositoryManager; import org.olat.repository.model.RepositoryEntryMembership; import org.olat.repository.model.RepositoryEntryPermissionChangeEvent; import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.UserPropertyHandler; /** * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public abstract class AbstractMemberListController extends BasicController { + + protected static final String USER_PROPS_ID = MemberListController.class.getCanonicalName(); public static final String TABLE_ACTION_EDIT = "tbl_edit"; public static final String TABLE_ACTION_MAIL = "tbl_mail"; @@ -82,6 +87,7 @@ public abstract class AbstractMemberListController extends BasicController { private DialogBoxController leaveDialogBox; protected CloseableModalController cmc; private EditMembershipController editMemberCtrl; + private final List<UserPropertyHandler> userPropertyHandlers; private final UserManager userManager; private final RepositoryEntry repoEntry; @@ -90,7 +96,7 @@ public abstract class AbstractMemberListController extends BasicController { private final BusinessGroupService businessGroupService; public AbstractMemberListController(UserRequest ureq, WindowControl wControl, RepositoryEntry repoEntry, String page) { - super(ureq, wControl); + super(ureq, wControl, Util.createPackageTranslator(UserPropertyHandler.class, ureq.getLocale())); this.repoEntry = repoEntry; userManager = CoreSpringFactory.getImpl(UserManager.class); @@ -103,12 +109,14 @@ public abstract class AbstractMemberListController extends BasicController { //table TableGuiConfiguration tableConfig = new TableGuiConfiguration(); tableConfig.setPreferencesOffered(true, this.getClass().getSimpleName()); - tableConfig.setTableEmptyMessage(translate("nomembers")); - memberListCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator(), false); + tableConfig.setTableEmptyMessage(translate("nomembers")); + + memberListCtr = new TableController(tableConfig, ureq, getWindowControl(), getTranslator(), true); listenTo(memberListCtr); - int numOfColumns = initColumns(); - memberListModel = new MemberListTableModel(numOfColumns); + userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, false); + initColumns(); + memberListModel = new MemberListTableModel(userPropertyHandlers); memberListCtr.setTableDataModel(memberListModel); memberListCtr.setMultiSelect(true); memberListCtr.addMultiSelectAction("table.header.edit", TABLE_ACTION_EDIT); @@ -125,9 +133,15 @@ public abstract class AbstractMemberListController extends BasicController { // } - protected int initColumns() { - memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastName.i18n(), Cols.lastName.ordinal(), null, getLocale())); - memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.firstName.i18n(), Cols.firstName.ordinal(), null, getLocale())); + protected void initColumns() { + int offset = Cols.values().length; + int i=0; + for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { + if (userPropertyHandler == null) continue; + boolean visible = UserManager.getInstance().isMandatoryUserProperty(USER_PROPS_ID , userPropertyHandler); + memberListCtr.addColumnDescriptor(visible, userPropertyHandler.getColumnDescriptor(i++ + offset, null, getLocale())); + } + memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.firstTime.i18n(), Cols.firstTime.ordinal(), null, getLocale())); memberListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale())); CustomCellRenderer roleRenderer = new CourseRoleCellRenderer(getLocale()); @@ -136,7 +150,6 @@ public abstract class AbstractMemberListController extends BasicController { memberListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.groups.i18n(), Cols.groups.ordinal(), null, getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, groupRenderer)); memberListCtr.addColumnDescriptor(new StaticColumnDescriptor(TABLE_ACTION_EDIT, "action", translate("table.header.edit"))); memberListCtr.addColumnDescriptor(new StaticColumnDescriptor(TABLE_ACTION_REMOVE, "action", translate("table.header.remove"))); - return 8; } @Override @@ -253,7 +266,7 @@ public abstract class AbstractMemberListController extends BasicController { protected abstract SearchMembersParams getSearchParams(); - protected void reloadModel() { + public void reloadModel() { updateTableModel(getSearchParams()); } @@ -281,13 +294,20 @@ public abstract class AbstractMemberListController extends BasicController { for(BusinessGroupMembership membership:memberships) { identityKeys.add(membership.getIdentityKey()); } - List<IdentityShort> identities = securityManager.findShortIdentitiesByKey(identityKeys); + SearchIdentityParams idParams = new SearchIdentityParams(); + idParams.setIdentityKeys(identityKeys); + if(params.getUserPropertiesSearch() != null && !params.getUserPropertiesSearch().isEmpty()) { + idParams.setUserProperties(params.getUserPropertiesSearch()); + } + if(StringHelper.containsNonWhitespace(params.getLogin())) { + idParams.setLogin(params.getLogin()); + } + List<Identity> identities = securityManager.getIdentitiesByPowerSearch(idParams); + Map<Long,MemberView> keyToMemberMap = new HashMap<Long,MemberView>(); List<MemberView> memberList = new ArrayList<MemberView>(); - for(IdentityShort identity:identities) { - MemberView member = new MemberView(identity.getKey()); - member.setFirstName(identity.getFirstName()); - member.setLastName(identity.getLastName()); + for(Identity identity:identities) { + MemberView member = new MemberView(identity); memberList.add(member); keyToMemberMap.put(identity.getKey(), member); } @@ -332,12 +352,34 @@ public abstract class AbstractMemberListController extends BasicController { } } + //the order of the filter is important filterByRoles(memberList, params); + filterByOrigin(memberList, params); memberListModel.setObjects(memberList); memberListCtr.modelChanged(); return memberList; } + private void filterByOrigin(List<MemberView> memberList, SearchMembersParams params) { + if(params.isGroupOrigin() && params.isRepoOrigin()) { + //do ntohing not very useful :-) + } else if(params.isGroupOrigin()) { + for(Iterator<MemberView> it=memberList.iterator(); it.hasNext(); ) { + CourseMembership m = it.next().getMembership(); + if(!m.isGroupTutor() && !m.isGroupParticipant() && !m.isGroupWaiting()) { + it.remove(); + } + } + } else if(params.isRepoOrigin()) { + for(Iterator<MemberView> it=memberList.iterator(); it.hasNext(); ) { + CourseMembership m = it.next().getMembership(); + if(!m.isRepoOwner() && !m.isRepoTutor() && !m.isRepoParticipant()) { + it.remove(); + } + } + } + } + /** * This filter method preserve the multiple roles of a member. If we want only the waiting list but * a member is in the waiting list and owner of the course, we want it to know. @@ -347,6 +389,7 @@ public abstract class AbstractMemberListController extends BasicController { */ private void filterByRoles(List<MemberView> memberList, SearchMembersParams params) { List<MemberView> members = new ArrayList<MemberView>(memberList); + if(params.isRepoOwners()) { for(Iterator<MemberView> it=members.iterator(); it.hasNext(); ) { if(it.next().getMembership().isRepoOwner()) { diff --git a/src/main/java/org/olat/course/member/CourseRoleCellRenderer.java b/src/main/java/org/olat/course/member/CourseRoleCellRenderer.java index 9ba236e8d42..7b80231399e 100644 --- a/src/main/java/org/olat/course/member/CourseRoleCellRenderer.java +++ b/src/main/java/org/olat/course/member/CourseRoleCellRenderer.java @@ -47,19 +47,27 @@ public class CourseRoleCellRenderer implements CustomCellRenderer { boolean and = false; if(membership.isOwner()) { and = and(sb, and); - sb.append(translator.translate("role.owner")); + sb.append(translator.translate("role.repo.owner")); } - if(membership.isTutor()) { + if(membership.isRepoTutor()) { and = and(sb, and); - sb.append(translator.translate("role.tutor")); + sb.append(translator.translate("role.repo.tutor")); } - if(membership.isParticipant()) { + if(membership.isGroupTutor()) { and = and(sb, and); - sb.append(translator.translate("role.participant")); + sb.append(translator.translate("role.group.tutor")); + } + if(membership.isRepoParticipant()) { + and = and(sb, and); + sb.append(translator.translate("role.repo.participant")); + } + if(membership.isGroupParticipant()) { + and = and(sb, and); + sb.append(translator.translate("role.group.participant")); } if(membership.isWaiting()) { and = and(sb, and); - sb.append(translator.translate("role.waiting")); + sb.append(translator.translate("role.group.waiting")); } } } diff --git a/src/main/java/org/olat/course/member/EditMembershipController.java b/src/main/java/org/olat/course/member/EditMembershipController.java index fa9eb96e8e1..d4726732abd 100644 --- a/src/main/java/org/olat/course/member/EditMembershipController.java +++ b/src/main/java/org/olat/course/member/EditMembershipController.java @@ -152,7 +152,7 @@ public class EditMembershipController extends FormBasicController { //repository entry rights String[] repoValues = new String[] { - translate("role.owner"), translate("role.tutor"), translate("role.participant") + translate("role.repo.owner"), translate("role.repo.tutor"), translate("role.repo.participant") }; repoRightsEl = uifactory.addCheckboxesVertical("repoRights", formLayout, repoRightsKeys, repoValues, null, 1); if(member != null) { diff --git a/src/main/java/org/olat/course/member/MemberListController.java b/src/main/java/org/olat/course/member/MemberListController.java index cca71c9125c..f94bca1c2ba 100644 --- a/src/main/java/org/olat/course/member/MemberListController.java +++ b/src/main/java/org/olat/course/member/MemberListController.java @@ -21,6 +21,7 @@ package org.olat.course.member; import org.olat.core.gui.UserRequest; import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; import org.olat.repository.RepositoryEntry; /** @@ -32,9 +33,13 @@ public class MemberListController extends AbstractMemberListController { private final SearchMembersParams searchParams; public MemberListController(UserRequest ureq, WindowControl wControl, - RepositoryEntry repoEntry, SearchMembersParams searchParams) { + RepositoryEntry repoEntry, SearchMembersParams searchParams, String infos) { super(ureq, wControl, repoEntry, "all_member_list"); this.searchParams = searchParams; + + if(StringHelper.containsNonWhitespace(infos)) { + mainVC.contextPut("infos", infos); + } } @Override diff --git a/src/main/java/org/olat/course/member/MemberListTableModel.java b/src/main/java/org/olat/course/member/MemberListTableModel.java index c264e3c1c2c..74fbc83936f 100644 --- a/src/main/java/org/olat/course/member/MemberListTableModel.java +++ b/src/main/java/org/olat/course/member/MemberListTableModel.java @@ -20,8 +20,10 @@ package org.olat.course.member; import java.util.Collections; +import java.util.List; import org.olat.core.gui.components.table.DefaultTableDataModel; +import org.olat.user.propertyhandlers.UserPropertyHandler; /** * @@ -29,35 +31,39 @@ import org.olat.core.gui.components.table.DefaultTableDataModel; */ public class MemberListTableModel extends DefaultTableDataModel<MemberView> { - private final int numOfColumns; + private final List<UserPropertyHandler> userPropertyHandlers; - public MemberListTableModel(int numOfColumns) { + public MemberListTableModel(List<UserPropertyHandler> userPropertyHandlers) { super(Collections.<MemberView>emptyList()); - this.numOfColumns = numOfColumns; + this.userPropertyHandlers = userPropertyHandlers; } @Override public int getColumnCount() { - return numOfColumns; + return 4 + userPropertyHandlers.size(); } @Override public Object getValueAt(int row, int col) { MemberView member = getObject(row); - switch(Cols.values()[col]) { - case firstName: return member.getFirstName(); - case lastName: return member.getLastName(); - case firstTime: return member.getFirstTime(); - case lastTime: return member.getLastTime(); - case role: return member.getMembership(); - case groups: return member; - default: return "ERROR"; + switch(col) { + case 0: return member.getFirstTime(); + case 1: return member.getLastTime(); + case 2: return member.getMembership(); + case 3: return member; + default: { + int propPos = col-4; + if(propPos < userPropertyHandlers.size()) { + UserPropertyHandler handler = userPropertyHandlers.get(propPos); + String value = handler.getUserProperty(member.getIdentity().getUser(), getLocale()); + return value; + } + return null; + } } } public enum Cols { - firstName("table.header.firstName"), - lastName("table.header.lastName"), firstTime("table.header.firstTime"), lastTime("table.header.lastTime"), role("table.header.role"), diff --git a/src/main/java/org/olat/course/member/MemberListWithOriginFilterController.java b/src/main/java/org/olat/course/member/MemberListWithOriginFilterController.java new file mode 100644 index 00000000000..321fd260a6e --- /dev/null +++ b/src/main/java/org/olat/course/member/MemberListWithOriginFilterController.java @@ -0,0 +1,69 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.member; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.repository.RepositoryEntry; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MemberListWithOriginFilterController extends AbstractMemberListController { + + private final SearchMembersParams searchParams; + private final OriginFilterController filterController; + + public MemberListWithOriginFilterController(UserRequest ureq, WindowControl wControl, + RepositoryEntry repoEntry, SearchMembersParams searchParams, String infos) { + super(ureq, wControl, repoEntry, "member_list_origin_filter"); + this.searchParams = searchParams; + + filterController = new OriginFilterController(ureq, wControl); + listenTo(filterController); + mainVC.put("originFilter", filterController.getInitialComponent()); + + if(StringHelper.containsNonWhitespace(infos)) { + mainVC.contextPut("infos", infos); + } + } + + @Override + public SearchMembersParams getSearchParams() { + return searchParams; + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == filterController) { + if(event instanceof SearchOriginParams) { + SearchOriginParams filter = (SearchOriginParams)event; + searchParams.setRepoOrigin(filter.isRepoOrigin()); + searchParams.setGroupOrigin(filter.isGroupOrigin()); + reloadModel(); + } + } + super.event(ureq, source, event); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/MemberSearchController.java b/src/main/java/org/olat/course/member/MemberSearchController.java new file mode 100644 index 00000000000..97c39fcb620 --- /dev/null +++ b/src/main/java/org/olat/course/member/MemberSearchController.java @@ -0,0 +1,62 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.member; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; +import org.olat.repository.RepositoryEntry; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MemberSearchController extends AbstractMemberListController { + + private SearchMembersParams searchParams = new SearchMembersParams(); + private final MemberSearchForm searchForm; + + public MemberSearchController(UserRequest ureq, WindowControl wControl, + RepositoryEntry repoEntry) { + super(ureq, wControl, repoEntry, "search_member_list"); + + searchForm = new MemberSearchForm(ureq, wControl); + listenTo(searchForm); + + mainVC.put("searchForm", searchForm.getInitialComponent()); + } + + @Override + public SearchMembersParams getSearchParams() { + return searchParams; + } + + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == searchForm) { + if(event instanceof SearchMembersParams) { + searchParams = (SearchMembersParams)event; + reloadModel(); + } + } + super.event(ureq, source, event); + } +} diff --git a/src/main/java/org/olat/course/member/MemberSearchForm.java b/src/main/java/org/olat/course/member/MemberSearchForm.java new file mode 100644 index 00000000000..fffbc70585a --- /dev/null +++ b/src/main/java/org/olat/course/member/MemberSearchForm.java @@ -0,0 +1,170 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.member; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.olat.core.CoreSpringFactory; +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.elements.TextElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; +import org.olat.core.util.StringHelper; +import org.olat.core.util.Util; +import org.olat.user.UserManager; +import org.olat.user.propertyhandlers.EmailProperty; +import org.olat.user.propertyhandlers.UserPropertyHandler; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class MemberSearchForm extends FormBasicController { + + private String[] roleKeys = {"owner", "tutor", "attendee", "waiting"}; + private String[] originKeys = new String[]{"all", "repo", "group"}; + + private TextElement login; + private SingleSelection originEl; + private MultipleSelectionElement rolesEl; + + private Map<String,FormItem> propFormItems; + private List<UserPropertyHandler> userPropertyHandlers; + + private final UserManager userManager; + + public MemberSearchForm(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl, "search_form", Util.createPackageTranslator(UserPropertyHandler.class, ureq.getLocale())); + + userManager = CoreSpringFactory.getImpl(UserManager.class); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + FormLayoutContainer leftContainer = FormLayoutContainer.createDefaultFormLayout("left_1", getTranslator()); + leftContainer.setRootForm(mainForm); + formLayout.add(leftContainer); + //user property + login = uifactory.addTextElement("login", "search.login", 128, "", leftContainer); + + userPropertyHandlers = userManager.getUserPropertyHandlersFor(getClass().getCanonicalName(), false); + propFormItems = new HashMap<String,FormItem>(); + for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { + if (userPropertyHandler == null) continue; + + FormItem fi = userPropertyHandler.addFormItem(getLocale(), null, getClass().getCanonicalName(), false, leftContainer); + fi.setTranslator(this.getTranslator()); + // DO NOT validate email field => see OLAT-3324, OO-155, OO-222 + if (userPropertyHandler instanceof EmailProperty && fi instanceof TextElement) { + TextElement textElement = (TextElement)fi; + textElement.setItemValidatorProvider(null); + } + propFormItems.put(userPropertyHandler.getName(), fi); + } + + //others + FormLayoutContainer rightContainer = FormLayoutContainer.createDefaultFormLayout("right_1", getTranslator()); + rightContainer.setRootForm(mainForm); + formLayout.add(rightContainer); + + //roles + String[] roleValues = new String[roleKeys.length]; + for(int i=roleKeys.length; i-->0; ) { + roleValues[i] = translate("search." + roleKeys[i]); + } + rolesEl = uifactory.addCheckboxesHorizontal("roles", "search.roles", rightContainer, roleKeys, roleValues, null); + for(String roleKey: roleKeys) { + rolesEl.select(roleKey, true); + } + + String[] openValues = new String[originKeys.length]; + for(int i=originKeys.length; i-->0; ) { + openValues[i] = translate("search." + originKeys[i]); + } + originEl = uifactory.addRadiosHorizontal("openBg", "search.origin", rightContainer, originKeys, openValues); + originEl.select("all", true); + + FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("button_layout", getTranslator()); + formLayout.add(buttonLayout); + uifactory.addFormSubmitButton("search", "search", buttonLayout); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formOK(UserRequest ureq) { + SearchMembersParams params = new SearchMembersParams(); + //roles + Set<String> selectedKeys = rolesEl.getSelectedKeys(); + params.setRepoOwners(selectedKeys.contains("owner")); + params.setRepoTutors(selectedKeys.contains("tutor")); + params.setGroupTutors(selectedKeys.contains("tutor")); + params.setRepoParticipants(selectedKeys.contains("attendee")); + params.setGroupParticipants(selectedKeys.contains("attendee")); + params.setGroupWaitingList(selectedKeys.contains("waiting")); + + //origin + if(!originEl.isOneSelected() || originEl.isSelected(0)) { + params.setRepoOrigin(true); + params.setGroupOrigin(true); + } else if(originEl.isSelected(1)) { + params.setRepoOrigin(true); + params.setGroupOrigin(false); + } else if(originEl.isSelected(2)) { + params.setRepoOrigin(false); + params.setGroupOrigin(true); + } + + String loginVal = login.getValue(); + if(StringHelper.containsNonWhitespace(loginVal)) { + params.setLogin(loginVal); + } + + //user properties + Map<String, String> userPropertiesSearch = new HashMap<String, String>(); + for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { + if (userPropertyHandler == null) continue; + FormItem ui = propFormItems.get(userPropertyHandler.getName()); + String uiValue = userPropertyHandler.getStringValue(ui); + if (StringHelper.containsNonWhitespace(uiValue)) { + userPropertiesSearch.put(userPropertyHandler.getName(), uiValue); + } + } + if(!userPropertiesSearch.isEmpty()) { + params.setUserPropertiesSearch(userPropertiesSearch); + } + + fireEvent(ureq, params); + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/MemberView.java b/src/main/java/org/olat/course/member/MemberView.java index 2669974bbe2..501fd44eb78 100644 --- a/src/main/java/org/olat/course/member/MemberView.java +++ b/src/main/java/org/olat/course/member/MemberView.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import org.olat.core.id.Identity; import org.olat.group.BusinessGroupShort; /** @@ -31,37 +32,23 @@ import org.olat.group.BusinessGroupShort; */ public class MemberView { - private final Long identityKey; - private String firstName; - private String lastName; + private final Identity identity; private Date firstTime; private Date lastTime; private final CourseMembership membership = new CourseMembership(); private List<BusinessGroupShort> groups; - public MemberView(Long identityKey) { - this.identityKey = identityKey; + public MemberView(Identity identity) { + this.identity = identity; } public Long getIdentityKey() { - return identityKey; + return identity.getKey(); } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; + + public Identity getIdentity() { + return identity; } public CourseMembership getMembership() { @@ -109,7 +96,7 @@ public class MemberView { @Override public int hashCode() { - return identityKey == null ? 2878 : identityKey.hashCode(); + return getIdentityKey() == null ? 2878 : getIdentityKey().hashCode(); } @Override @@ -119,7 +106,7 @@ public class MemberView { } if(obj instanceof MemberView) { MemberView member = (MemberView)obj; - return identityKey != null && identityKey.equals(member.getIdentityKey()); + return getIdentityKey() != null && getIdentityKey().equals(member.getIdentityKey()); } return false; } @@ -127,8 +114,8 @@ public class MemberView { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("memberView[name=").append(firstName == null ? "" : firstName) - .append(" ").append(lastName == null ? "NULL" : lastName).append("]"); + sb.append("memberView[identityKey=").append(getIdentityKey() == null ? "" : getIdentityKey()) + .append(":login=").append(identity == null ? "NULL" : identity.getName()).append("]"); return sb.toString(); } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/MembersOverviewController.java b/src/main/java/org/olat/course/member/MembersOverviewController.java index 6a92999346c..a006bf07a69 100644 --- a/src/main/java/org/olat/course/member/MembersOverviewController.java +++ b/src/main/java/org/olat/course/member/MembersOverviewController.java @@ -27,7 +27,6 @@ import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; -import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.components.segmentedview.SegmentViewComponent; import org.olat.core.gui.components.segmentedview.SegmentViewEvent; import org.olat.core.gui.components.segmentedview.SegmentViewFactory; @@ -70,12 +69,13 @@ public class MembersOverviewController extends BasicController implements Activa private final SegmentViewComponent segmentView; private final VelocityContainer mainVC; - private MemberListController allMemberListCtrl; - private MemberListController ownersCtrl; - private MemberListController tutorsCtrl; - private MemberListController participantsCtrl; - private MemberListController waitingCtrl; - private MemberListController selectedCtrl; + private AbstractMemberListController allMemberListCtrl; + private AbstractMemberListController ownersCtrl; + private AbstractMemberListController tutorsCtrl; + private AbstractMemberListController participantsCtrl; + private AbstractMemberListController waitingCtrl; + private AbstractMemberListController selectedCtrl; + private AbstractMemberListController searchCtrl; private final Link importMemberLink, addMemberLink; private StepsMainRunController importMembersWizard; @@ -232,13 +232,13 @@ public class MembersOverviewController extends BasicController implements Activa System.out.println("Send mails: " + mailTemplate); } - private MemberListController updateAllMembers(UserRequest ureq) { + private AbstractMemberListController updateAllMembers(UserRequest ureq) { if(allMemberListCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("AllMembers", 0l); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); SearchMembersParams searchParams = new SearchMembersParams(true, true, true, true, true, false); - allMemberListCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams); + allMemberListCtrl = new MemberListWithOriginFilterController(ureq, bwControl, repoEntry, searchParams, null); listenTo(allMemberListCtrl); } @@ -248,13 +248,14 @@ public class MembersOverviewController extends BasicController implements Activa return allMemberListCtrl; } - private MemberListController updateOwners(UserRequest ureq) { + private AbstractMemberListController updateOwners(UserRequest ureq) { if(ownersCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("Owners", 0l); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); SearchMembersParams searchParams = new SearchMembersParams(true, false, false, false, false, false); - ownersCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams); + String infos = translate("owners.infos"); + ownersCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams, infos); listenTo(ownersCtrl); } @@ -264,13 +265,14 @@ public class MembersOverviewController extends BasicController implements Activa return ownersCtrl; } - private MemberListController updateTutors(UserRequest ureq) { + private AbstractMemberListController updateTutors(UserRequest ureq) { if(tutorsCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("Tutors", 0l); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); SearchMembersParams searchParams = new SearchMembersParams(false, true, false, true, false, false); - tutorsCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams); + String infos = translate("tutors.infos"); + tutorsCtrl = new MemberListWithOriginFilterController(ureq, bwControl, repoEntry, searchParams, infos); listenTo(tutorsCtrl); } @@ -280,13 +282,14 @@ public class MembersOverviewController extends BasicController implements Activa return tutorsCtrl; } - private MemberListController updateParticipants(UserRequest ureq) { + private AbstractMemberListController updateParticipants(UserRequest ureq) { if(participantsCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("Tutors", 0l); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); SearchMembersParams searchParams = new SearchMembersParams(false, false, true, false, true, false); - participantsCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams); + String infos = translate("participants.infos"); + participantsCtrl = new MemberListWithOriginFilterController(ureq, bwControl, repoEntry, searchParams, infos); listenTo(participantsCtrl); } @@ -296,13 +299,14 @@ public class MembersOverviewController extends BasicController implements Activa return participantsCtrl; } - private MemberListController updateWaitingList(UserRequest ureq) { + private AbstractMemberListController updateWaitingList(UserRequest ureq) { if(waitingCtrl == null) { OLATResourceable ores = OresHelper.createOLATResourceableInstance("WaitingList", 0l); ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); SearchMembersParams searchParams = new SearchMembersParams(false, false, false, false, false, true); - waitingCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams); + String infos = translate("waiting.infos"); + waitingCtrl = new MemberListController(ureq, bwControl, repoEntry, searchParams, infos); listenTo(waitingCtrl); } @@ -312,7 +316,17 @@ public class MembersOverviewController extends BasicController implements Activa return waitingCtrl; } - private void updateSearch(UserRequest ureq) { - mainVC.put("memberList", new Panel("empty")); + private AbstractMemberListController updateSearch(UserRequest ureq) { + if(searchCtrl == null) { + OLATResourceable ores = OresHelper.createOLATResourceableInstance("Search", 0l); + ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores)); + WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl()); + searchCtrl = new MemberSearchController(ureq, bwControl, repoEntry); + listenTo(searchCtrl); + } + + mainVC.put("membersCmp", searchCtrl.getInitialComponent()); + addToHistory(ureq, searchCtrl); + return searchCtrl; } } diff --git a/src/main/java/org/olat/course/member/OriginFilterController.java b/src/main/java/org/olat/course/member/OriginFilterController.java new file mode 100644 index 00000000000..59aea79b764 --- /dev/null +++ b/src/main/java/org/olat/course/member/OriginFilterController.java @@ -0,0 +1,93 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.member; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.SingleSelection; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.WindowControl; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class OriginFilterController extends FormBasicController { + + + private String[] originKeys = new String[]{"all", "repo", "group"}; + + private SingleSelection originEl; + + public OriginFilterController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + String[] openValues = new String[originKeys.length]; + for(int i=originKeys.length; i-->0; ) { + openValues[i] = translate("search." + originKeys[i]); + } + originEl = uifactory.addRadiosHorizontal("openBg", "search.origin.alt", formLayout, originKeys, openValues); + originEl.select("all", true); + originEl.addActionListener(this, FormEvent.ONCHANGE); + } + + @Override + protected void doDispose() { + // + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(originEl == source) { + SearchOriginParams e = doSearch(); + fireEvent(ureq, e); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formOK(UserRequest ureq) { + // + } + + private SearchOriginParams doSearch() { + SearchOriginParams params = new SearchOriginParams(); + //origin + if(!originEl.isOneSelected() || originEl.isSelected(0)) { + params.setRepoOrigin(true); + params.setGroupOrigin(true); + } else if(originEl.isSelected(1)) { + params.setRepoOrigin(true); + params.setGroupOrigin(false); + } else if(originEl.isSelected(2)) { + params.setRepoOrigin(false); + params.setGroupOrigin(true); + } + return params; + } +} diff --git a/src/main/java/org/olat/course/member/SearchMembersParams.java b/src/main/java/org/olat/course/member/SearchMembersParams.java index 348fbe4079f..0367f27ea4c 100644 --- a/src/main/java/org/olat/course/member/SearchMembersParams.java +++ b/src/main/java/org/olat/course/member/SearchMembersParams.java @@ -19,11 +19,17 @@ */ package org.olat.course.member; +import java.util.Map; + +import org.olat.core.gui.control.Event; + /** * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -public class SearchMembersParams { +public class SearchMembersParams extends Event { + private static final long serialVersionUID = -8842738563007496141L; + private boolean repoOwners; private boolean repoTutors; private boolean repoParticipants; @@ -31,12 +37,19 @@ public class SearchMembersParams { private boolean groupParticipants; private boolean groupWaitingList; + private boolean repoOrigin = true; + private boolean groupOrigin = true; + + private String login; + private Map<String, String> userPropertiesSearch; + public SearchMembersParams() { - // + super("search_members"); } public SearchMembersParams(boolean repoOwners, boolean repoTutors, boolean repoParticipants, boolean groupTutors, boolean groupParticipants, boolean groupWaitingList) { + this(); this.repoOwners = repoOwners; this.repoTutors = repoTutors; this.repoParticipants = repoParticipants; @@ -92,4 +105,36 @@ public class SearchMembersParams { public void setGroupWaitingList(boolean groupWaitingList) { this.groupWaitingList = groupWaitingList; } + + public boolean isRepoOrigin() { + return repoOrigin; + } + + public void setRepoOrigin(boolean repoOrigin) { + this.repoOrigin = repoOrigin; + } + + public boolean isGroupOrigin() { + return groupOrigin; + } + + public void setGroupOrigin(boolean groupOrigin) { + this.groupOrigin = groupOrigin; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public Map<String, String> getUserPropertiesSearch() { + return userPropertiesSearch; + } + + public void setUserPropertiesSearch(Map<String, String> userPropertiesSearch) { + this.userPropertiesSearch = userPropertiesSearch; + } } \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/SearchOriginParams.java b/src/main/java/org/olat/course/member/SearchOriginParams.java new file mode 100644 index 00000000000..0ad01020f88 --- /dev/null +++ b/src/main/java/org/olat/course/member/SearchOriginParams.java @@ -0,0 +1,53 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.member; + +import org.olat.core.gui.control.Event; + +/** + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +public class SearchOriginParams extends Event { + + private static final long serialVersionUID = -8878568908411612699L; + private boolean repoOrigin = true; + private boolean groupOrigin = true; + + public SearchOriginParams() { + super("search_origin"); + } + + public boolean isRepoOrigin() { + return repoOrigin; + } + + public void setRepoOrigin(boolean repoOrigin) { + this.repoOrigin = repoOrigin; + } + + public boolean isGroupOrigin() { + return groupOrigin; + } + + public void setGroupOrigin(boolean groupOrigin) { + this.groupOrigin = groupOrigin; + } +} \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/_content/all_member_list.html b/src/main/java/org/olat/course/member/_content/all_member_list.html index 963f2f3490a..df7e6fe736b 100644 --- a/src/main/java/org/olat/course/member/_content/all_member_list.html +++ b/src/main/java/org/olat/course/member/_content/all_member_list.html @@ -1,3 +1,10 @@ +#if($infos) + <br/> + <div class="b_clearfix"> + <p class="b_info">$infos</p> + </div> +#end + <div class="b_clearfix"> $r.render("memberList") </div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/_content/member_list_origin_filter.html b/src/main/java/org/olat/course/member/_content/member_list_origin_filter.html new file mode 100644 index 00000000000..b37db7384fb --- /dev/null +++ b/src/main/java/org/olat/course/member/_content/member_list_origin_filter.html @@ -0,0 +1,13 @@ +#if($infos) + <br/> + <div class="b_clearfix"> + <p class="b_info">$infos</p> + </div> +#end +<br/> +<div class="b_clearfix" style="position:relative;"> + <div class="o_buttons_box_right"> + $r.render("originFilter") + </div> + $r.render("memberList") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/_content/search_form.html b/src/main/java/org/olat/course/member/_content/search_form.html new file mode 100644 index 00000000000..90eb3abd9de --- /dev/null +++ b/src/main/java/org/olat/course/member/_content/search_form.html @@ -0,0 +1,14 @@ +<br/> +<div class="b_clearfix"> + <div class="b_c33l"> + <div class="b_subcl"> + $r.render("left_1") + $r.render("button_layout") + </div> + </div> + <div class="b_c66r"> + <div class="b_subcr"> + $r.render("right_1") + </div> + </div> +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/_content/search_member_list.html b/src/main/java/org/olat/course/member/_content/search_member_list.html new file mode 100644 index 00000000000..02a204d385d --- /dev/null +++ b/src/main/java/org/olat/course/member/_content/search_member_list.html @@ -0,0 +1,4 @@ +$r.render("searchForm") +<div class="b_clearfix"> + $r.render("memberList") +</div> \ No newline at end of file diff --git a/src/main/java/org/olat/course/member/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/member/_i18n/LocalStrings_de.properties index 639ce202ca2..8887f47b5d2 100644 --- a/src/main/java/org/olat/course/member/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/member/_i18n/LocalStrings_de.properties @@ -9,9 +9,13 @@ menu.rights=Rechte menu.rights.alt=Rechte members.all=Alle owners=Besitzer +owners.infos=Besitzer haben volle Autoren- und Administrationsrechte für diesen Kurs. tutors=Betreuer +tutors.infos=Betreuer haben Zugang zum Coaching- und Bewertswerkzeug für Kursteilnehmer.<br/>Gruppenbetreuer haben Zugang zum Coaching- und bewertswerkzeug ihrer Gruppenteilnehmer. participants=Teilnehmer +participants.infos=Teilnehmer haben Zugang zum Kurs.<br/>Gruppenteilnehmer haben Zugang zum Kurs und zu ihrer Gruppe. waitinglist=Warteliste +waiting.infos=Personen auf der Gruppenwarteliste haben weder Zugang zum Kurs noch zu der Gruppe. Der Zugang wird erst freigegeben wenn genügend Platz vorhanden ist oder die Person von Hand umgeteilt wurde. search=Suche action=Aktion add.member=Mitglieder hinzufügen @@ -24,10 +28,23 @@ assessment=Bewertungswerkzeug dialog.modal.bg.leave.text=Wollen Sie wirklich dieser Person {0} von dem Kurs und alle Gruppe entfernen? group.create=Gruppe erstellen group.add=Gruppe hinzufügen -role.owner=Besitzer -role.tutor=Betreuer -role.participant=Teilnehmer -role.waiting=Warteliste +role.repo.owner=Besitzer +role.repo.tutor=Betreuer +role.group.tutor=Gruppenbetreuer +role.repo.participant=Teilnehmer +role.group.participant=Gruppenteilnehmer +role.group.waiting=Warteliste +search.roles=Rolle +search.origin=Herkunft +search.origin.alt=Anzeige +search.owner=$\:role.repo.owner +search.tutor=$\:role.repo.tutor +search.attendee=$\:role.repo.participant +search.waiting=$\:role.group.waiting +search.all=alle Mitglieder +search.repo=nur Kursmitglieder +search.group=nur Gruppenmitglieder +search.login=Benutzername table.header.edit=Bearbeiten table.header.remove=Entfernen table.header.firstName=Vorname diff --git a/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties index e3d51733d83..73db4840164 100644 --- a/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/member/_i18n/LocalStrings_en.properties @@ -16,10 +16,12 @@ search=Search action=Action group.create=Create group group.add=Add group -role.owner=Propriétaire -role.tutor=Coach -role.participant=Participant -role.waiting=En attente +role.repo.owner=Owner +role.repo.tutor=Coach +role.group.tutor=Coach +role.repo.participant=Participant +role.group.participant=Participant +role.group.waiting=Waiting table.header.edit=Edit table.header.remove=Remove table.header.firstName=First name diff --git a/src/main/java/org/olat/course/member/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/member/_i18n/LocalStrings_fr.properties index 22778694452..c257bfe1bb4 100644 --- a/src/main/java/org/olat/course/member/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/member/_i18n/LocalStrings_fr.properties @@ -16,10 +16,12 @@ search=Recherche action=Action group.create=Cr\u00E9er un groupe group.add=Ajouter un groupe -role.owner=Propri\u00E9taire -role.tutor=Coach -role.participant=Participant -role.waiting=En attente +role.repo.owner=Propri\u00E9taire +role.repo.tutor=Coach +role.group.tutor=Coach +role.repo.participant=Participant +role.group.participant=Participant +role.group.waiting=En attente table.header.edit=Editer table.header.remove=Enlever table.header.firstName=Pr\u00E9nom diff --git a/src/main/java/org/olat/course/nodes/co/CORunController.java b/src/main/java/org/olat/course/nodes/co/CORunController.java index 68c7837cb76..cd6f46ba8bc 100644 --- a/src/main/java/org/olat/course/nodes/co/CORunController.java +++ b/src/main/java/org/olat/course/nodes/co/CORunController.java @@ -121,11 +121,11 @@ public class CORunController extends BasicController { if(groupKeys != null && StringHelper.containsNonWhitespace(grpNames)) { groupKeys = businessGroupService.toGroupKeys(grpNames, cgm.getCourseResource()); } - if (coachesConfigured) { + if (coachesConfigured != null && coachesConfigured.booleanValue()) { ContactList cl = retrieveCoachesFromGroups(groupKeys); contactLists.push(cl); } - if (partipsConfigured) { + if (partipsConfigured != null && partipsConfigured.booleanValue()) { ContactList cl = retrieveParticipantsFromGroups(groupKeys); contactLists.push(cl); } diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties index b5698a54865..fc2e5cf76df 100644 --- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties @@ -1,7 +1,7 @@ #Mon Mar 02 09:54:04 CET 2009 create.form.title=Neue Arbeitsgruppe erstellen create.group=Gruppe erstellen -create.group.description=Erzeugen Sie eine neue Gruppe mit der unten stehenden Schaltfläche. Als Besitzer dieser Gruppe können Sie danach die Gruppenwerkzeuge freischalten, Benutzer hinzufügen oder die Gruppe veröffentlichen. +create.group.description=Erzeugen Sie eine neue Gruppe mit der unten stehenden Schaltfläche. Als Betreuer dieser Gruppe können Sie danach die Gruppenwerkzeuge freischalten, Benutzer hinzufügen oder die Gruppe veröffentlichen. copy.group=Kopieren dialog.modal.bg.delete.title=Gruppe l\u00F6schen? dialog.modal.bg.delete.text=Wollen Sie die Gruppe "{0}" wirklich l\u00F6schen? @@ -27,7 +27,7 @@ menu.groups=Meine Gruppen menu.groups.alt=Arbeiten Sie mit Ihren Gruppen menu.opengroups=Ver\u00F6ffentlichte Gruppen menu.opengroups.alt=Arbeitsgruppen in die \u00F6ffentlich sind und an denen ich teilnehmen kann. -msg.atleastone=Es muss mindestens ein Besitzer in der Arbeitsgruppe eingetragen sein. +msg.atleastone=Es muss mindestens ein Betreuer in der Arbeitsgruppe eingetragen sein. msg.alleastone.editable.group=Sie m\u00FCssen mindestens eine Gruppe wählen, die Sie besitzen. right.header=Rechtegruppen right.intro=In dieser Liste finden Sie alle Rechtegruppen, an denen Sie teilnehmen. @@ -44,7 +44,7 @@ search.header=Gruppe search.intro=In Gruppe suchen search.generic=Suche search.attendee=Teilnehmer -search.owner=Besitzer / Betreuer +search.owner=Betreuer search.waiting=Warteliste search.public=Public group search.all=alle @@ -57,7 +57,7 @@ search.headless=Orphans search.headless.check=Gruppe ohne Mitglieder und Ressourcen cif.displayname=Name cif.description=Beschreibung -cif.owner=Besitzer +cif.owner=Betreuer cif.id=ID cif.coursetitle=Kurstitel cif.error.allempty=Bitte f\u00FCllen Sie mindestens ein Formularfeld aus. diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml index dc766058a2e..6717f3cbc75 100644 --- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml +++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml @@ -182,6 +182,59 @@ </bean> </entry> + <entry key="org.olat.course.member.MemberSearchForm"> + <bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext"> + <property name="propertyHandlers"> + <list> + <ref bean="userPropertyFirstName" /> + <ref bean="userPropertyLastName" /> + <ref bean="userPropertyEmail" /> + <ref bean="userPropertyInstitutionalName" /> + <ref bean="userPropertyInstitutionalUserIdentifier" /> + <ref bean="userPropertyInstitutionalEmail" /> + </list> + </property> + <property name="adminViewOnlyProperties"> + <set> + <ref bean="userPropertyEmail" /> + <ref bean="userPropertyInstitutionalName" /> + <ref bean="userPropertyInstitutionalUserIdentifier" /> + <ref bean="userPropertyInstitutionalEmail" /> + </set> + </property> + </bean> + </entry> + + <entry key="org.olat.course.member.MemberListController"> + <bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext"> + <property name="propertyHandlers"> + <list> + <ref bean="userPropertyFirstName" /> + <ref bean="userPropertyLastName" /> + <ref bean="userPropertyEmail" /> + <ref bean="userPropertyInstitutionalName" /> + <ref bean="userPropertyInstitutionalUserIdentifier" /> + <ref bean="userPropertyInstitutionalEmail" /> + </list> + </property> + <property name="adminViewOnlyProperties"> + <set> + <ref bean="userPropertyEmail" /> + <ref bean="userPropertyInstitutionalName" /> + <ref bean="userPropertyInstitutionalUserIdentifier" /> + <ref bean="userPropertyInstitutionalEmail" /> + </set> + </property> + <property name="mandatoryProperties"> + <set> + <ref bean="userPropertyFirstName" /> + <ref bean="userPropertyLastName" /> + <ref bean="userPropertyEmail" /> + </set> + </property> + </bean> + </entry> + <entry key="org.olat.admin.user.UsermanagerUserSearchForm"> <bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext"> <property name="propertyHandlers"> diff --git a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java index 7ecaa1d8de4..d682ea1c4bf 100644 --- a/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java +++ b/src/test/java/org/olat/basesecurity/BaseSecurityManagerTest.java @@ -20,15 +20,20 @@ package org.olat.basesecurity; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.Assert; import org.junit.Test; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; +import org.olat.core.id.UserConstants; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; +import org.olat.user.UserManager; import org.springframework.beans.factory.annotation.Autowired; /** @@ -41,6 +46,8 @@ public class BaseSecurityManagerTest extends OlatTestCase { @Autowired private DB dbInstance; @Autowired + private UserManager userManager; + @Autowired private BaseSecurity securityManager; @Test @@ -145,4 +152,90 @@ public class BaseSecurityManagerTest extends OlatTestCase { Assert.assertTrue(identities.contains(id2)); } + @Test + public void testGetIdentityByPowerSearch_IdentityKeys() { + String login = "pow-1-" + UUID.randomUUID().toString(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser(login); + dbInstance.commitAndCloseSession(); + + SearchIdentityParams params = new SearchIdentityParams(); + params.setIdentityKeys(Collections.singletonList(id.getKey())); + + List<Identity> ids = securityManager.getIdentitiesByPowerSearch(params); + Assert.assertNotNull(ids); + Assert.assertEquals(1, ids.size()); + Assert.assertEquals(id, ids.get(0)); + } + + @Test + public void testGetIdentityByPowerSearch_Login() { + String login = "pow-2-" + UUID.randomUUID().toString(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser(login); + dbInstance.commitAndCloseSession(); + + SearchIdentityParams params = new SearchIdentityParams(); + params.setLogin(login); + + List<Identity> ids = securityManager.getIdentitiesByPowerSearch(params); + Assert.assertNotNull(ids); + Assert.assertEquals(1, ids.size()); + Assert.assertEquals(id, ids.get(0)); + } + + @Test + public void testGetIdentityByPowerSearch_UserProperty() { + //create a user with a first name + String login = "pow-3-" + UUID.randomUUID().toString(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser(login); + String firstName = id.getUser().getProperty(UserConstants.FIRSTNAME, null); + dbInstance.commitAndCloseSession(); + + SearchIdentityParams params = new SearchIdentityParams(); + Map<String,String> props = new HashMap<String,String>(); + props.put(UserConstants.FIRSTNAME, firstName); + params.setUserProperties(props); + + List<Identity> ids = securityManager.getIdentitiesByPowerSearch(params); + Assert.assertNotNull(ids); + Assert.assertEquals(1, ids.size()); + Assert.assertEquals(id, ids.get(0)); + } + + @Test + public void testGetIdentityByPowerSearch_LoginIdentityKeys() { + String login = "pow-4-" + UUID.randomUUID().toString(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser(login); + dbInstance.commitAndCloseSession(); + + SearchIdentityParams params = new SearchIdentityParams(); + params.setLogin(login); + params.setIdentityKeys(Collections.singletonList(id.getKey())); + + List<Identity> ids = securityManager.getIdentitiesByPowerSearch(params); + Assert.assertNotNull(ids); + Assert.assertEquals(1, ids.size()); + Assert.assertEquals(id, ids.get(0)); + } + + @Test + public void testGetIdentityByPowerSearch_LoginIdentityKeysProperty() { + String login = "pow-5-" + UUID.randomUUID().toString(); + Identity id = JunitTestHelper.createAndPersistIdentityAsUser(login); + dbInstance.commitAndCloseSession(); + + SearchIdentityParams params = new SearchIdentityParams(); + params.setLogin(login); + Map<String,String> props = new HashMap<String,String>(); + props.put(UserConstants.FIRSTNAME, id.getUser().getProperty(UserConstants.FIRSTNAME, null)); + props.put(UserConstants.LASTNAME, id.getUser().getProperty(UserConstants.LASTNAME, null)); + params.setUserProperties(props); + params.setIdentityKeys(Collections.singletonList(id.getKey())); + + List<Identity> ids = securityManager.getIdentitiesByPowerSearch(params); + Assert.assertNotNull(ids); + Assert.assertEquals(1, ids.size()); + Assert.assertEquals(id, ids.get(0)); + } + + } -- GitLab