From 668eb0193dae160686d8a51650eff07aa679e22d Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 15 Apr 2016 09:58:26 +0000 Subject: [PATCH] CCM NG: Group Administration git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3998 8810af33-2d31-482b-a856-94f89814c4df --- .../groups/GroupAddMemberForm.java | 283 ++++++++++++++++++ .../usersgroupsroles/groups/GroupAdmin.java | 60 +++- .../usersgroupsroles/groups/GroupDetails.java | 43 +++ .../usersgroupsroles/groups/GroupForm.java | 2 +- .../groups/GroupMembersTable.java | 241 +++++++++++++++ .../groups/GroupPropertySheetModel.java | 26 +- .../usersgroupsroles/groups/GroupsTable.java | 2 + .../main/java/org/libreccm/security/User.java | 124 ++++---- .../ui/admin/AdminResources.properties | 23 ++ .../ui/admin/AdminResources_de.properties | 26 +- .../ui/admin/AdminResources_en.properties | 24 ++ .../ui/admin/AdminResources_fr.properties | 24 ++ .../themes/foundry/foundry/styles/admin.css | 35 ++- 13 files changed, 835 insertions(+), 78 deletions(-) create mode 100644 ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAddMemberForm.java create mode 100644 ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupMembersTable.java diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAddMemberForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAddMemberForm.java new file mode 100644 index 000000000..75842b1ee --- /dev/null +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAddMemberForm.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.arsdigita.ui.admin.usersgroupsroles.groups; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.util.LockableImpl; + +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.Group; +import org.libreccm.security.GroupManager; +import org.libreccm.security.GroupRepository; +import org.libreccm.security.User; +import org.libreccm.security.UserRepository; + +import java.util.ArrayList; +import java.util.List; + +import static com.arsdigita.ui.admin.AdminUiConstants.*; + +/** + * + * @author Jens Pelzetter + */ +public class GroupAddMemberForm extends Form { + + private static final String MEMBER_NAME = "membername"; + + private static final int COL_MEMBER_NAME = 0; + private static final int COL_MEMBER_FAMILY_NAME = 1; + private static final int COL_MEMBER_GIVEN_NAME = 2; + private static final int COL_MEMBER_EMAIL = 3; + private static final int COL_MEMBER_ADD = 4; + + private final TextField memberName; + + public GroupAddMemberForm( + final GroupAdmin groupAdmin, + final ParameterSingleSelectionModel selectedGroupId) { + super("groupAddMemberForm"); + + final ActionLink backToGroup = new ActionLink(new GlobalizedMessage( + "ui.admin.group_details.add_member.back", ADMIN_BUNDLE)); + backToGroup.addActionListener(e -> { + groupAdmin.hideGroupMemberAddForm(e.getPageState()); + }); + add(backToGroup); + + final Label header = new Label(); + header.setClassAttr("heading"); + header.addPrintListener(e -> { + final PageState state = e.getPageState(); + final Label target = (Label) e.getTarget(); + + final GroupRepository groupRepository = CdiUtil.createCdiUtil() + .findBean(GroupRepository.class); + final Group group = groupRepository.findById(Long.parseLong( + selectedGroupId.getSelectedKey(state))); + + target.setLabel(new GlobalizedMessage( + "ui.admin.group_details.add_member.header", + ADMIN_BUNDLE, + new String[]{group.getName()})); + + }); + add(header); + + memberName = new TextField(MEMBER_NAME); + memberName.setLabel(new GlobalizedMessage( + "ui.admin.group_details.add_member.find", ADMIN_BUNDLE)); + add(memberName); + + final Submit submit = new Submit(new GlobalizedMessage( + "ui.admin.group_details.add_member.search", ADMIN_BUNDLE)); + add(submit); + +// addProcessListener(e -> { +// final PageState state = e.getPageState(); +// final FormData data = e.getFormData(); +// }); + add(new UsersToAddTable(groupAdmin, selectedGroupId)); + } + + private class UsersToAddTable extends Table { + + public UsersToAddTable( + final GroupAdmin groupAdmin, + final ParameterSingleSelectionModel selectedGroupId) { + + super(); + + setEmptyView(new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.empty", ADMIN_BUNDLE))); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn( + COL_MEMBER_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_FAMILY_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.family_name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_GIVEN_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.given_name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_EMAIL, + new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.email", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_ADD, + new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.add", + ADMIN_BUNDLE)))); + + columnModel.get(COL_MEMBER_ADD).setCellRenderer( + new TableCellRenderer() { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final ControlLink link = new ControlLink((Component) value); + return link; + } + + }); + + addTableActionListener(new TableActionListener() { + + @Override + public void cellSelected(final TableActionEvent event) { + final PageState state = event.getPageState(); + final String key = (String) event.getRowKey(); + + switch (event.getColumn()) { + case COL_MEMBER_ADD: + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final UserRepository userRepository = cdiUtil + .findBean(UserRepository.class); + final GroupRepository groupRepository = cdiUtil + .findBean(GroupRepository.class); + final GroupManager groupManager = cdiUtil.findBean( + GroupManager.class); + final User user = userRepository.findById(Long + .parseLong(key)); + final Group group = groupRepository.findById( + Long + .parseLong(selectedGroupId.getSelectedKey(state))); + groupManager.addMemberToGroup(user, group); + groupAdmin.hideGroupMemberAddForm(state); + break; + default: + throw new IllegalArgumentException( + "Invalid value for column"); + } + + } + + @Override + public void headSelected(final TableActionEvent event) { + // Nothing + } + + }); + + setModelBuilder(new UsersToAddTableModelBuilder()); + } + + } + + private class UsersToAddTableModelBuilder extends LockableImpl + implements TableModelBuilder { + + @Override + public TableModel makeModel(final Table table, + final PageState state) { + return new UsersToAddTableModel(state); + } + + } + + private class UsersToAddTableModel implements TableModel { + + private final List users; + private int index = -1; + + public UsersToAddTableModel(final PageState state) { + + final String term = (String) memberName.getValue(state); + if (term == null || term.isEmpty()) { + users = new ArrayList<>(); + } else { + final UserRepository userRepository = CdiUtil.createCdiUtil() + .findBean(UserRepository.class); + users = userRepository.filtered(term); + } + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public boolean nextRow() { + index++; + return index < users.size(); + } + + @Override + public Object getElementAt(final int columnIndex) { + final User user = users.get(index); + switch (columnIndex) { + case COL_MEMBER_NAME: + return user.getName(); + case COL_MEMBER_FAMILY_NAME: + return user.getFamilyName(); + case COL_MEMBER_GIVEN_NAME: + return user.getGivenName(); + case COL_MEMBER_EMAIL: + return user.getPrimaryEmailAddress().getAddress(); + case COL_MEMBER_ADD: + return new Label(new GlobalizedMessage( + "ui.admin.group_details.add_member.table.add", + ADMIN_BUNDLE)); + default: + throw new IllegalArgumentException( + "Not a valid column index"); + } + } + + @Override + public Object getKeyAt(final int columnIndex) { + return users.get(index).getPartyId(); + } + + } + +} diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAdmin.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAdmin.java index 53a40555f..67a7357de 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAdmin.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupAdmin.java @@ -21,6 +21,7 @@ package com.arsdigita.ui.admin.usersgroupsroles.groups; import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Page; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.ParameterSingleSelectionModel; @@ -40,8 +41,6 @@ import static com.arsdigita.ui.admin.AdminUiConstants.*; */ public class GroupAdmin extends BoxPanel { - private final static Logger LOGGER = LogManager.getLogger(GroupAdmin.class); - private final StringParameter groupIdParameter; private final ParameterSingleSelectionModel selectedGroupId; private final TextField groupsTableFilter; @@ -49,24 +48,30 @@ public class GroupAdmin extends BoxPanel { private final GroupsTable groupsTable; private final GroupForm groupForm; private final GroupDetails groupDetails; + private final GroupAddMemberForm groupAddMemberForm; public GroupAdmin() { super(); setBasicProperties(); + final Label heading = new Label(new GlobalizedMessage( + "ui.admin.groups.heading", ADMIN_BUNDLE)); + heading.setClassAttr("heading"); + add(heading); + groupsTablePanel = new BoxPanel(); groupsTablePanel.setIdAttr("groupsTablePanel"); final Form filterForm = new Form("groupsTableFilterForm"); groupsTableFilter = new TextField("groupsTableFilter"); groupsTableFilter.setLabel(new GlobalizedMessage( - "ui.admin.groups.table.filter.term", ADMIN_BUNDLE)); + "ui.admin.groups.table.filter.term", ADMIN_BUNDLE)); filterForm.add(groupsTableFilter); filterForm.add(new Submit(new GlobalizedMessage( - "ui.admin.groups.filter.submit", ADMIN_BUNDLE))); + "ui.admin.groups.filter.submit", ADMIN_BUNDLE))); final ActionLink clearLink = new ActionLink(new GlobalizedMessage( - "ui.admin.groups.table.filter.clear", ADMIN_BUNDLE)); + "ui.admin.groups.table.filter.clear", ADMIN_BUNDLE)); clearLink.addActionListener(e -> { final PageState state = e.getPageState(); groupsTableFilter.setValue(state, null); @@ -76,26 +81,29 @@ public class GroupAdmin extends BoxPanel { groupIdParameter = new StringParameter("selected_group_id"); selectedGroupId = new ParameterSingleSelectionModel<>( - groupIdParameter); + groupIdParameter); groupsTable = new GroupsTable(this, groupsTableFilter, selectedGroupId); groupsTablePanel.add(groupsTable); final ActionLink addNewGroupLink = new ActionLink(new GlobalizedMessage( - "ui.admin.new_group_link", ADMIN_BUNDLE)); + "ui.admin.new_group_link", ADMIN_BUNDLE)); addNewGroupLink.addActionListener(e -> { showGroupForm(e.getPageState()); }); groupsTablePanel.add(addNewGroupLink); add(groupsTablePanel); - + groupForm = new GroupForm(this, selectedGroupId); add(groupForm); - + groupDetails = new GroupDetails(this, selectedGroupId); add(groupDetails); + groupAddMemberForm = new GroupAddMemberForm(this, selectedGroupId); + add(groupAddMemberForm); + } @Override @@ -107,6 +115,7 @@ public class GroupAdmin extends BoxPanel { page.setVisibleDefault(groupsTablePanel, true); page.setVisibleDefault(groupForm, false); page.setVisibleDefault(groupDetails, false); + page.setVisibleDefault(groupAddMemberForm, false); } private void setBasicProperties() { @@ -118,24 +127,47 @@ public class GroupAdmin extends BoxPanel { groupsTablePanel.setVisible(state, false); groupForm.setVisible(state, false); groupDetails.setVisible(state, true); + groupAddMemberForm.setVisible(state, false); } - + protected void hideGroupDetails(final PageState state) { selectedGroupId.clearSelection(state); groupsTablePanel.setVisible(state, true); groupForm.setVisible(state, false); groupDetails.setVisible(state, false); + groupAddMemberForm.setVisible(state, false); } - + protected void showGroupForm(final PageState state) { groupsTablePanel.setVisible(state, false); groupForm.setVisible(state, true); + groupDetails.setVisible(state, false); + groupAddMemberForm.setVisible(state, false); } - + protected void hideGroupForm(final PageState state) { - groupsTablePanel.setVisible(state, true); + //If we want to show the groups table or the group details depends + //if a group is selected or not. + boolean groupSelected = selectedGroupId.isSelected(state); + + groupsTablePanel.setVisible(state, !groupSelected); groupForm.setVisible(state, false); + groupDetails.setVisible(state, groupSelected); + groupAddMemberForm.setVisible(state, false); + } + + protected void showGroupMemberAddForm(final PageState state) { + groupsTablePanel.setVisible(state, false); + groupForm.setVisible(state, false); + groupDetails.setVisible(state, false); + groupAddMemberForm.setVisible(state, true); + } + + protected void hideGroupMemberAddForm(final PageState state) { + groupsTablePanel.setVisible(state, false); + groupForm.setVisible(state, false); + groupDetails.setVisible(state, true); + groupAddMemberForm.setVisible(state, false); } - } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupDetails.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupDetails.java index 26547f01a..65f927edc 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupDetails.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupDetails.java @@ -20,10 +20,16 @@ package com.arsdigita.ui.admin.usersgroupsroles.groups; import com.arsdigita.bebop.ActionLink; import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.ParameterSingleSelectionModel; import com.arsdigita.bebop.PropertySheet; import com.arsdigita.globalization.GlobalizedMessage; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.Group; +import org.libreccm.security.GroupRepository; + import static com.arsdigita.ui.admin.AdminUiConstants.*; /** @@ -37,18 +43,55 @@ public class GroupDetails extends BoxPanel { final ParameterSingleSelectionModel selectedGroupId) { super(BoxPanel.VERTICAL); + final ActionLink backLink = new ActionLink(new GlobalizedMessage( "ui.admin.group_details.back", ADMIN_BUNDLE)); + backLink.setClassAttr("back-link"); backLink.addActionListener(e -> { groupAdmin.hideGroupDetails(e.getPageState()); }); add(backLink); + final Label header = new Label(); + header.setClassAttr("heading"); + header.addPrintListener(e -> { + final PageState state = e.getPageState(); + final Label target = (Label) e.getTarget(); + final GroupRepository groupRepository = CdiUtil.createCdiUtil() + .findBean(GroupRepository.class); + final Group group = groupRepository.findById(Long.parseLong( + selectedGroupId.getSelectedKey(state))); + target.setLabel(new GlobalizedMessage( + "ui.admin.group_details.header", + ADMIN_BUNDLE, new String[]{group.getName()})); + }); + add(header); + final PropertySheet propertySheet = new PropertySheet( new GroupPropertySheetModelBuilder(selectedGroupId)); add(propertySheet); + final BoxPanel links = new BoxPanel(BoxPanel.HORIZONTAL); + final ActionLink editProperties = new ActionLink(new GlobalizedMessage( + "ui.admin.group_details.edit_properties", ADMIN_BUNDLE)); + editProperties.addActionListener(e -> { + groupAdmin.showGroupForm(e.getPageState()); + }); + links.add(editProperties); + + add(links); + + final GroupMembersTable membersTable = new GroupMembersTable( + selectedGroupId); + add(membersTable); + + final ActionLink addMember = new ActionLink(new GlobalizedMessage( + "ui.admin.group_details.add_member", ADMIN_BUNDLE)); + addMember.addActionListener(e -> { + groupAdmin.showGroupMemberAddForm(e.getPageState()); + }); + add(addMember); } } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupForm.java index 9907af45b..c73b8149c 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupForm.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupForm.java @@ -159,7 +159,7 @@ public class GroupForm extends Form { } } - groupAdmin.hideGroupDetails(state); + groupAdmin.hideGroupForm(state); }); } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupMembersTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupMembersTable.java new file mode 100644 index 000000000..c3948f7cd --- /dev/null +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupMembersTable.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package com.arsdigita.ui.admin.usersgroupsroles.groups; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.util.LockableImpl; + +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.Group; +import org.libreccm.security.GroupManager; +import org.libreccm.security.GroupRepository; +import org.libreccm.security.User; +import org.libreccm.security.UserRepository; + +import java.util.ArrayList; +import java.util.List; + +import static com.arsdigita.ui.admin.AdminUiConstants.*; + +/** + * + * @author Jens Pelzetter + */ +public class GroupMembersTable extends Table { + + private static final int COL_MEMBER_NAME = 0; + private static final int COL_MEMBER_FAMILY_NAME = 1; + private static final int COL_MEMBER_GIVEN_NAME = 2; + private static final int COL_MEMBER_EMAIL = 3; + private static final int COL_MEMBER_REMOVE = 4; + + public GroupMembersTable( + final ParameterSingleSelectionModel selectedGroupId) { + + super(); + setIdAttr("groupMembersTable"); + + setEmptyView(new Label(new GlobalizedMessage( + "ui.admin.group_details.members.none", ADMIN_BUNDLE))); + + final TableColumnModel columnModel = getColumnModel(); + columnModel.add(new TableColumn( + COL_MEMBER_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.cols.name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_FAMILY_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.cols.family_name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_GIVEN_NAME, + new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.cols.given_name", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_EMAIL, + new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.cols.email", + ADMIN_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MEMBER_REMOVE, + new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.cols.remove", + ADMIN_BUNDLE)))); + + columnModel.get(COL_MEMBER_REMOVE).setCellRenderer( + new TableCellRenderer() { + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final ControlLink link = new ControlLink((Component) value); + link.setConfirmation(new GlobalizedMessage( + "ui.admin.group_details.members_table.member.remove", + ADMIN_BUNDLE)); + return link; + } + + }); + + addTableActionListener(new TableActionListener() { + + @Override + public void cellSelected(final TableActionEvent event) { + final PageState state = event.getPageState(); + final String key = (String) event.getRowKey(); + + switch (event.getColumn()) { + case COL_MEMBER_REMOVE: + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final UserRepository userRepository = cdiUtil + .findBean(UserRepository.class); + final GroupRepository groupRepository = cdiUtil + .findBean(GroupRepository.class); + final GroupManager groupManager = cdiUtil.findBean( + GroupManager.class); + final User user = userRepository.findById(Long + .parseLong(key)); + final Group group = groupRepository.findById( + Long + .parseLong(selectedGroupId.getSelectedKey(state))); + groupManager.removeMemberFromGroup(user, group); + break; + default: + throw new IllegalArgumentException( + "Invalid value for column"); + } + } + + @Override + public void headSelected(final TableActionEvent event) { + //Nothing + } + + }); + + setModelBuilder(new GroupMembersTableModelBuilder(selectedGroupId)); + } + + private class GroupMembersTableModelBuilder extends LockableImpl + implements TableModelBuilder { + + private final ParameterSingleSelectionModel selectedGroupId; + + public GroupMembersTableModelBuilder( + final ParameterSingleSelectionModel selectedGroupId) { + + this.selectedGroupId = selectedGroupId; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + table.getRowSelectionModel().clearSelection(state); + + return new GroupMembersTableModel(selectedGroupId, state); + } + + } + + private class GroupMembersTableModel implements TableModel { + + private final List members; + private int index = -1; + + public GroupMembersTableModel( + final ParameterSingleSelectionModel selectedGroupId, + final PageState state) { + + final GroupRepository groupRepository = CdiUtil.createCdiUtil() + .findBean(GroupRepository.class); + final Group group = groupRepository.findById(Long.parseLong( + selectedGroupId.getSelectedKey(state))); + + members = new ArrayList<>(); + + group.getMemberships().forEach(m -> { + members.add(m.getMember()); + }); + + members.sort((User m1, User m2) -> { + return m1.getName().compareTo(m2.getName()); + }); + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public boolean nextRow() { + index++; + return index < members.size(); + } + + @Override + public Object getElementAt(final int columnIndex) { + final User member = members.get(index); + switch (columnIndex) { + case COL_MEMBER_NAME: + return member.getName(); + case COL_MEMBER_FAMILY_NAME: + return member.getFamilyName(); + case COL_MEMBER_GIVEN_NAME: + return member.getGivenName(); + case COL_MEMBER_EMAIL: + return member.getPrimaryEmailAddress().getAddress(); + case COL_MEMBER_REMOVE: + return new Label(new GlobalizedMessage( + "ui.admin.group_details.members_table.remove", + ADMIN_BUNDLE)); + default: + throw new IllegalArgumentException( + "Not a valid column index"); + } + } + + @Override + public Object getKeyAt(final int columnIndex) { + return members.get(index).getPartyId(); + } + + } + +} diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupPropertySheetModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupPropertySheetModel.java index c97d3ba68..98e15a878 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupPropertySheetModel.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupPropertySheetModel.java @@ -22,9 +22,15 @@ import com.arsdigita.bebop.PropertySheetModel; import com.arsdigita.globalization.GlobalizedMessage; import org.libreccm.security.Group; +import org.libreccm.security.Role; +import org.libreccm.security.RoleMembership; import java.util.Arrays; import java.util.Iterator; +import java.util.Set; +import java.util.SortedSet; +import java.util.StringJoiner; +import java.util.TreeSet; import static com.arsdigita.ui.admin.AdminUiConstants.*; @@ -35,7 +41,8 @@ import static com.arsdigita.ui.admin.AdminUiConstants.*; class GroupPropertySheetModel implements PropertySheetModel { private static enum GroupProperty { - GROUP_NAME; + GROUP_NAME, + ROLES } private final Group selectedGroup; @@ -84,9 +91,26 @@ class GroupPropertySheetModel implements PropertySheetModel { switch (currentProperty) { case GROUP_NAME: return selectedGroup.getName(); + case ROLES: + return retrieveRoles(); default: return ""; } } + private String retrieveRoles() { + final Set roleMemberships = selectedGroup + .getRoleMemberships(); + + final SortedSet roles = new TreeSet<>((r1, r2) -> { + return r1.compareTo(r2); + }); + + roleMemberships.forEach(m -> { + roles.add(m.getRole().getName()); + }); + + return String.join(", ", roles.toArray(new String[roles.size()])); + } + } diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupsTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupsTable.java index cd2b66bb7..1b043dcdb 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupsTable.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/usersgroupsroles/groups/GroupsTable.java @@ -61,9 +61,11 @@ public class GroupsTable extends Table { final GroupAdmin parent, final TextField groupsTableFilter, final ParameterSingleSelectionModel selectedGroupId) { + super(); setIdAttr("groupsTable"); + setStyleAttr("width: 30em"); this.groupsTableFilter = groupsTableFilter; this.selectedGroupId = selectedGroupId; diff --git a/ccm-core/src/main/java/org/libreccm/security/User.java b/ccm-core/src/main/java/org/libreccm/security/User.java index ad390d882..0a377cf55 100644 --- a/ccm-core/src/main/java/org/libreccm/security/User.java +++ b/ccm-core/src/main/java/org/libreccm/security/User.java @@ -65,53 +65,57 @@ import javax.xml.bind.annotation.XmlTransient; @NamedQueries({ @NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = :name " - + "ORDER BY u.name, " - + " u.familyName, " - + " u.givenName, " - + " u.primaryEmailAddress.address"), + + "ORDER BY u.name, " + + " u.familyName, " + + " u.givenName, " + + " u.primaryEmailAddress.address"), @NamedQuery(name = "User.findByEmailAddress", query = "SELECT u FROM User u WHERE " - + "u.primaryEmailAddress.address = :emailAddress " - + "ORDER BY u.name, " - + " u.familyName, " - + " u.givenName, " - + " u.primaryEmailAddress.address"), + + "u.primaryEmailAddress.address = :emailAddress " + + "ORDER BY u.name, " + + " u.familyName, " + + " u.givenName, " + + " u.primaryEmailAddress.address"), @NamedQuery( - name = "User.filterByNameAndEmail", - query = "SELECT u FROM User u WHERE " - + "LOWER(u.name) LIKE CONCAT(LOWER(:term), '%') " - + "OR LOWER(u.givenName) LIKE CONCAT(LOWER(:term), '%') " + name = "User.filterByNameAndEmail", + query = "SELECT u FROM User u WHERE " + + "LOWER(u.name) LIKE CONCAT(LOWER(:term), '%') " + + "OR LOWER(u.givenName) LIKE CONCAT(LOWER(:term), '%') " + "OR LOWER(u.familyName) LIKE CONCAT(LOWER(:term), '%') " - + "OR LOWER(u.primaryEmailAddress.address) LIKE CONCAT('%', LOWER(:term), '%')"), + + "OR LOWER(u.primaryEmailAddress.address) LIKE CONCAT('%', LOWER(:term), '%') " + + "ORDER BY u.name," + + "u.familyName, " + + "u.givenName, " + + "u.primaryEmailAddress.address"), @NamedQuery( - name = "User.findAllOrderedByUsername", - query = "SELECT u FROM User u ORDER BY u.name, " - + " u.familyName, " - + " u.givenName, " - + " u.primaryEmailAddress.address") + name = "User.findAllOrderedByUsername", + query = "SELECT u FROM User u ORDER BY u.name, " + + " u.familyName, " + + " u.givenName, " + + " u.primaryEmailAddress.address") }) @NamedEntityGraphs({ @NamedEntityGraph( - name = "User.withGroupAndRoleMemberships", - attributeNodes = { - @NamedAttributeNode( - value = "groupMemberships"), - @NamedAttributeNode( - value = "roleMemberships", - subgraph = "role")}, - subgraphs = { - @NamedSubgraph( - name = "role", - attributeNodes = { - @NamedAttributeNode(value = "role", - subgraph = "permissions") - }), - @NamedSubgraph( - name = "permissions", - attributeNodes = { - @NamedAttributeNode(value = "permissions")} - ) - }) + name = "User.withGroupAndRoleMemberships", + attributeNodes = { + @NamedAttributeNode( + value = "groupMemberships"), + @NamedAttributeNode( + value = "roleMemberships", + subgraph = "role")}, + subgraphs = { + @NamedSubgraph( + name = "role", + attributeNodes = { + @NamedAttributeNode(value = "role", + subgraph = "permissions") + }), + @NamedSubgraph( + name = "permissions", + attributeNodes = { + @NamedAttributeNode(value = "permissions")} + ) + }) }) @DefaultEntityGraph("User.withGroupAndRoleMemberships") @XmlRootElement(name = "user", namespace = CORE_XML_NS) @@ -141,12 +145,12 @@ public class User extends Party implements Serializable { */ @Embedded @AssociationOverride( - name = "USER_PRIMARY_EMAIL_ADDRESSES", - joinTable = @JoinTable(name = "USER_PRIMARY_EMAIL_ADDRESSES", - schema = DB_SCHEMA, - joinColumns = { - @JoinColumn(name = "USER_ID") - })) + name = "USER_PRIMARY_EMAIL_ADDRESSES", + joinTable = @JoinTable(name = "USER_PRIMARY_EMAIL_ADDRESSES", + schema = DB_SCHEMA, + joinColumns = { + @JoinColumn(name = "USER_ID") + })) @NotNull @XmlElement(name = "primary-email-address", namespace = CORE_XML_NS) private EmailAddress primaryEmailAddress; @@ -275,7 +279,7 @@ public class User extends Party implements Serializable { } protected void setGroupMemberships( - final Set groupMemberships) { + final Set groupMemberships) { this.groupMemberships = groupMemberships; } @@ -284,7 +288,7 @@ public class User extends Party implements Serializable { } protected void removeGroupMembership( - final GroupMembership groupMembership) { + final GroupMembership groupMembership) { groupMemberships.remove(groupMembership); } @@ -332,19 +336,19 @@ public class User extends Party implements Serializable { @Override public String toString(final String data) { return super.toString(String.format( - ", givenName = \"%s\", " - + "familyName = \"%s\", " - + "primaryEmailAddress = { %s }, " - + "emailAddresses = { %s }, " - + "banned = %b, " - + "passwordResetRequired = %b%s", - givenName, - familyName, - Objects.toString(primaryEmailAddress), - Objects.toString(emailAddresses), - banned, - passwordResetRequired, - data + ", givenName = \"%s\", " + + "familyName = \"%s\", " + + "primaryEmailAddress = { %s }, " + + "emailAddresses = { %s }, " + + "banned = %b, " + + "passwordResetRequired = %b%s", + givenName, + familyName, + Objects.toString(primaryEmailAddress), + Objects.toString(emailAddresses), + banned, + passwordResetRequired, + data )); } diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties index 7f2c7f435..06c70ffc9 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties @@ -255,3 +255,26 @@ ui.admin.group.name=Name of group ui.admin.group.delete.confirm=Are you sure to delete this group? ui.admin.group.property_sheet.group_name=Name of Group ui.admin.group_details.back=Back to groups table +ui.admin.group.property_sheet.roles=Assigned roles +ui.admin.group_details.edit_properties=Rename group +ui.admin.group_details.members.none=This group has no members +ui.admin.group_details.members_table.cols.name=User name +ui.admin.group_details.members_table.cols.family_name=Family name +ui.admin.group_details.members_table.cols.given_name=Given name +ui.admin.group_details.members_table.cols.email=Email +ui.admin.group_details.members_table.cols.remove=Remove +ui.admin.group_details.members_table.member.remove=Are you sure to remove this member from this group? +ui.admin.group_details.members_table.remove=Remove +ui.admin.group_details.add_member.search=Search +ui.admin.group_details.add_member.find=Find user to add +ui.admin.group_details.add_member.table.empty=No matching users +ui.admin.group_details.add_member.table.name=User name +ui.admin.group_details.add_member.table.family_name=Family name +ui.admin.group_details.add_member.table.given_name=Given name +ui.admin.group_details.add_member.table.email=Email +ui.admin.group_details.add_member.table.add=Add member +ui.admin.group_details.add_member=Add member +ui.admin.group_details.add_member.back=Back to group details +ui.admin.group_details.add_member.header=Add member to group {0} +ui.admin.group_details.header=Details for group {0} +ui.admin.groups.heading=Groups diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties index b973581c3..6fcc76f91 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties @@ -244,7 +244,7 @@ ui.admin.groups.filter.submit=Anwenden ui.admin.groups.table.filter.clear=Filter zur\u00fccksetzen ui.admin.groups.table.no_groups=Keine Gruppen gefunden ui.admin.groups.table.name=Name -ui.admin.groups.table.delete=Delete +ui.admin.groups.table.delete=L\u00f6schen ui.admin.new_group_link=Neue Gruppe anlegen ui.admin.group.name.error.notempty=Der Name einer Gruppe kann nicht leer sein. ui.admin.group.name.error.length=Der Name einer Gruppe darf maximal 256 Zeichen lang sein. @@ -255,3 +255,27 @@ ui.admin.group.name=Name der Gruppe ui.admin.group.delete.confirm=Sind Sie sicher das Sie diese Gruppe l\u00f6schen wollen? ui.admin.group.property_sheet.group_name=Name der Gruppe ui.admin.group_details.back=Zur\u00fcck zur Gruppen\u00fcbersicht +ui.admin.group.property_sheet.roles=Zugewiesene Rollen +ui.admin.group_details.edit_properties=Gruppe umbenennen +ui.admin.group_details.members.none=Diese Gruppe hat keine Mitglieder +ui.admin.group_details.members_table.cols.name=Benutzername +ui.admin.group_details.members_table.cols.family_name=Familienname +ui.admin.group_details.members_table.cols.given_name=Vorname +ui.admin.group_details.members_table.cols.email=E-Mail +ui.admin.group_details.members_table.cols.remove=Remove +ui.admin.group_details.members_table.member.remove=Sind Sie sicher, dass sie dieses Mitglied aus der Gruppe entfernen wollen? +ui.admin.group_details.members_table.remove=Entfernen +ui.admin.group_details.add_member.search=Suchen +ui.admin.group_details.add_member.find=Benutzer suchen +ui.admin.group_details.add_member.table.empty=Keine passenden Benutzer +ui.admin.group_details.add_member.table.name=Benutzername +ui.admin.group_details.add_member.table.family_name=Familienname +ui.admin.group_details.add_member.table.given_name=Vorname +#Email +ui.admin.group_details.add_member.table.email=E-Mail +ui.admin.group_details.add_member.table.add=Hinzuf\u00fcgen +ui.admin.group_details.add_member=Mitglied hinzuf\u00fcgen +ui.admin.group_details.add_member.back=Zur\u00fcck zur Detailansicht der Gruppe +ui.admin.group_details.add_member.header=Mitglieder zur Gruppe {0} hinzuf\u00fcgen +ui.admin.group_details.header=Details Gruppe {0} +ui.admin.groups.heading=Gruppen diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties index 52084b1f4..afa5273a7 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties @@ -228,3 +228,27 @@ ui.admin.group.name=Name of group ui.admin.group.delete.confirm=Are you sure to delete this group? ui.admin.group.property_sheet.group_name=Name of Group ui.admin.group_details.back=Back to groups table +ui.admin.group.property_sheet.roles=Assigned roles +ui.admin.group_details.edit_properties=Rename group +ui.admin.group_details.members.none=This group has no members +ui.admin.group_details.members_table.cols.name=User name +ui.admin.group_details.members_table.cols.family_name=Family name +ui.admin.group_details.members_table.cols.given_name=Given name +ui.admin.group_details.members_table.cols.email=Email +ui.admin.group_details.members_table.cols.remove=Remove +ui.admin.group_details.members_table.member.remove=Are you sure to remove this member from this group? +ui.admin.group_details.members_table.remove=Remove +ui.admin.group_details.add_member.search=Search +ui.admin.group_details.add_member.find=Find user to add +ui.admin.group_details.add_member.table.empty=No matching users +ui.admin.group_details.add_member.table.name=User name +ui.admin.group_details.add_member.table.family_name=Family name +ui.admin.group_details.add_member.table.given_name=Given name +#Email +ui.admin.group_details.add_member.table.email=Email +ui.admin.group_details.add_member.table.add=Add member +ui.admin.group_details.add_member=Add member +ui.admin.group_details.add_member.back=Back to group details +ui.admin.group_details.add_member.header=Add member to group {0} +ui.admin.group_details.header=Details for group {0} +ui.admin.groups.heading=Groups diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties index 6761655fe..5208152c6 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties @@ -219,3 +219,27 @@ ui.admin.group.name=Name of group ui.admin.group.delete.confirm=Are you sure to delete this group? ui.admin.group.property_sheet.group_name=Name of Group ui.admin.group_details.back=Back to groups table +ui.admin.group.property_sheet.roles=Assigned roles +ui.admin.group_details.edit_properties=Rename group +ui.admin.group_details.members.none=This group has no members +ui.admin.group_details.members_table.cols.name=User name +ui.admin.group_details.members_table.cols.family_name=Family name +ui.admin.group_details.members_table.cols.given_name=Given name +ui.admin.group_details.members_table.cols.email=Email +ui.admin.group_details.members_table.cols.remove=Remove +ui.admin.group_details.members_table.member.remove=Are you sure to remove this member from this group? +ui.admin.group_details.members_table.remove=Remove +ui.admin.group_details.add_member.search=Search +ui.admin.group_details.add_member.find=Find user to add +ui.admin.group_details.add_member.table.empty=No matching users +ui.admin.group_details.add_member.table.name=User name +ui.admin.group_details.add_member.table.family_name=Family name +ui.admin.group_details.add_member.table.given_name=Given name +#Email +ui.admin.group_details.add_member.table.email=Email +ui.admin.group_details.add_member.table.add=Add member +ui.admin.group_details.add_member=Add member +ui.admin.group_details.add_member.back=Back to group details +ui.admin.group_details.add_member.header=Add member to group {0} +ui.admin.group_details.header=Details for group {0} +ui.admin.groups.heading=Groups diff --git a/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/styles/admin.css b/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/styles/admin.css index 8f824f6b8..8ada0da67 100644 --- a/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/styles/admin.css +++ b/ccm-theme-foundry/src/main/resources/themes/foundry/foundry/styles/admin.css @@ -660,7 +660,7 @@ table.dataTable{ table * table ,form table { border-style: none; - /*width: auto;*/ + width: auto; margin: 0; } @@ -1807,3 +1807,36 @@ span#quickLinksCascade { .wysiwyg ul { list-style: disc inside; } + +.wysiwyg div.image { + border: 1px solid #999; + + margin-bottom: 0.5em; +} + +.wysiwyg div.image span.caption { + display: block; +} + +.wysiwyg div.image.left { + float: left; + + margin-right: 1em; +} + +.wysiwyg div.image.right { + float: right; + + margin-left: 1em; +} + +.wysiwg div.image.center { + text-align: center; +} + +.wysiwg div.image.center span.caption { + margin-left: auto; + margin-right: auto; + + text-align: left; +}