CCM NG: Improvments for permissions management including an authoring step for managing the permissions for a single item
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5322 8810af33-2d31-482b-a856-94f89814c4dfccm-docs
parent
0deb4a2ab4
commit
3046dc9490
|
|
@ -143,6 +143,26 @@ public class CMSPermissionsPane extends SimpleContainer implements Resettable,
|
|||
this.selectionModel = selectionModel;
|
||||
this.privilegeNameMap = privilegeNameMap;
|
||||
}
|
||||
|
||||
public CMSPermissionsPane(
|
||||
final Class<?> privilegesClass,
|
||||
final CcmObjectSelectionModel<CcmObject> selectionModel) {
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final PermissionManager permissionManager = cdiUtil.findBean(
|
||||
PermissionManager.class);
|
||||
final List<String> privilegesFromClass = permissionManager
|
||||
.listDefiniedPrivileges(privilegesClass);
|
||||
|
||||
final Map<String, String> nameMap = new HashMap<>();
|
||||
for(final String privilege: privilegesFromClass) {
|
||||
nameMap.put(privilege, privilege);
|
||||
}
|
||||
|
||||
this.privileges = privilegesFromClass.toArray(new String[]{});
|
||||
this.selectionModel = selectionModel;
|
||||
this.privilegeNameMap = nameMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite this method to construct your default Permissions Pane with the
|
||||
|
|
@ -253,9 +273,10 @@ public class CMSPermissionsPane extends SimpleContainer implements Resettable,
|
|||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final PermissionManager permissionManager = cdiUtil.findBean(
|
||||
PermissionManager.class);
|
||||
final List<String> privileges = permissionManager
|
||||
.listDefiniedPrivileges(ItemPrivileges.class);
|
||||
final List<Label> headerLabels = privileges.stream()
|
||||
// final List<String> privileges = permissionManager
|
||||
// .listDefiniedPrivileges(ItemPrivileges.class);
|
||||
// final List<Label> headerLabels = privileges.stream()
|
||||
final List<Label> headerLabels = Arrays.stream(privileges)
|
||||
.map(privilege -> generatePrivilegeColumnHeader(privilege))
|
||||
.collect(Collectors.toList());
|
||||
headerLabels.add(0,
|
||||
|
|
@ -269,7 +290,8 @@ public class CMSPermissionsPane extends SimpleContainer implements Resettable,
|
|||
headerLabels.toArray());
|
||||
table.setClassAttr("dataTable");
|
||||
for (int j = 1; j < table.getColumnModel().size() - 1; j++) {
|
||||
table.getColumn(j).setKey(privileges.get(j - 1));
|
||||
// table.getColumn(j).setKey(privileges.get(j - 1));
|
||||
// table.getColumn(j).setKey(privileges[j - 1]);
|
||||
table.getColumn(j).setCellRenderer(new TableCellRenderer() {
|
||||
|
||||
@Override
|
||||
|
|
@ -349,8 +371,10 @@ public class CMSPermissionsPane extends SimpleContainer implements Resettable,
|
|||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
if (columnIndex > 0 && columnIndex < lastColumnIndex) {
|
||||
final String privilege = table.getColumn(columnIndex)
|
||||
.getKey();
|
||||
// final String privilege = table
|
||||
// .getColumn(columnIndex)
|
||||
// .getKey();
|
||||
final String privilege = privileges[columnIndex - 1];
|
||||
|
||||
if (permissionChecker.isPermitted(privilege,
|
||||
object,
|
||||
|
|
|
|||
|
|
@ -79,22 +79,23 @@ class CMSPermissionsTableModel implements TableModel {
|
|||
@Override
|
||||
public Object getKeyAt(final int columnIndex) {
|
||||
|
||||
if (columnIndex == 0) {
|
||||
return String.format("%s-%s-role",
|
||||
currentRow.getObject().getUuid(),
|
||||
currentRow.getRoleName());
|
||||
} else if (columnIndex >= currentRow.getColumns().size() - 1) {
|
||||
return String.format("%s-%s-remove-all",
|
||||
currentRow.getObject().getUuid(),
|
||||
currentRow.getRoleName());
|
||||
} else {
|
||||
return String.format(
|
||||
"%s-%s-%s",
|
||||
currentRow.getObject().getUuid(),
|
||||
currentRow.getRoleName(),
|
||||
currentRow.getColumns().get(columnIndex - 1).getPrivilege()
|
||||
);
|
||||
}
|
||||
return currentRow.getRoleName();
|
||||
|
||||
// if (columnIndex == 0) {
|
||||
// return String.format("%s-%s-role",
|
||||
// currentRow.getObject().getUuid(),
|
||||
// currentRow.getRoleName());
|
||||
// } else if (columnIndex >= currentRow.getColumns().size() - 1) {
|
||||
// return String.format("%s-%s-remove-all",
|
||||
// currentRow.getObject().getUuid(),
|
||||
// currentRow.getRoleName());
|
||||
// } else {
|
||||
// return String.format(
|
||||
// "%s-%s-%s",
|
||||
// currentRow.getObject().getUuid(),
|
||||
// currentRow.getRoleName(),
|
||||
// currentRow.getColumns().get(columnIndex - 1).getPrivilege()
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,18 +19,10 @@
|
|||
package com.arsdigita.cms.ui.permissions;
|
||||
|
||||
import com.arsdigita.bebop.BoxPanel;
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.ControlLink;
|
||||
import com.arsdigita.bebop.FormProcessException;
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Resettable;
|
||||
import com.arsdigita.bebop.SimpleContainer;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.bebop.event.TableActionEvent;
|
||||
import com.arsdigita.bebop.event.TableActionListener;
|
||||
import com.arsdigita.bebop.parameters.StringParameter;
|
||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||
import com.arsdigita.cms.CMS;
|
||||
|
|
@ -38,22 +30,19 @@ import com.arsdigita.cms.ItemSelectionModel;
|
|||
import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
|
||||
import com.arsdigita.cms.ui.authoring.ResettableContainer;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.ui.CcmObjectSelectionModel;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.core.CcmObject;
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.security.PermissionChecker;
|
||||
import org.libreccm.security.PermissionManager;
|
||||
import org.libreccm.security.Role;
|
||||
import org.libreccm.security.RoleRepository;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
||||
import org.librecms.ui.authoring.ContentItemAuthoringStep;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -73,15 +62,11 @@ public class ItemPermissionsStep extends ResettableContainer {
|
|||
final AuthoringKitWizard authoringKitWizard,
|
||||
final StringParameter selectedLanguage) {
|
||||
|
||||
super("cms:permissionsStep", CMS.CMS_XML_NS);
|
||||
super("cms:permissionsStep", CMS.CMS_XML_NS);
|
||||
|
||||
this.itemSelectionModel = itemSelectionModel;
|
||||
|
||||
final BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL);
|
||||
final Label header = new Label(new GlobalizedMessage(
|
||||
"cms.ui.permissions.table.header",
|
||||
CmsConstants.CMS_BUNDLE));
|
||||
panel.add(header);
|
||||
super.add(panel);
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
|
|
@ -89,134 +74,166 @@ public class ItemPermissionsStep extends ResettableContainer {
|
|||
PermissionManager.class);
|
||||
final List<String> privileges = permissionManager
|
||||
.listDefiniedPrivileges(ItemPrivileges.class);
|
||||
final List<Label> headerLabels = privileges.stream()
|
||||
.map(privilege -> generatePrivilegeColumnHeader(privilege))
|
||||
.collect(Collectors.toList());
|
||||
headerLabels.add(0,
|
||||
new Label(new GlobalizedMessage(
|
||||
"cms.ui.permissions.table.role_header",
|
||||
CmsConstants.CMS_BUNDLE)));
|
||||
headerLabels.add(new Label(new GlobalizedMessage(
|
||||
"cms.ui.permissions.table.remove_all.header",
|
||||
CmsConstants.CMS_BUNDLE)));
|
||||
final Table table = new Table(
|
||||
new PermissionsTableModelBuilder(),
|
||||
headerLabels.toArray());
|
||||
table.setClassAttr("dataTable");
|
||||
for (int j = 1; j < table.getColumnModel().size() - 1; j++) {
|
||||
table.getColumn(j).setKey(privileges.get(j - 1));
|
||||
table.getColumn(j).setCellRenderer(new TableCellRenderer() {
|
||||
final Map<String, String> privNameMap = new HashMap<>();
|
||||
privileges.forEach(privilege -> privNameMap.put(privilege, privilege));
|
||||
|
||||
@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 CcmObjectSelectionModel<CcmObject> objSelectionModel
|
||||
= new CcmObjectSelectionModel<>(
|
||||
itemSelectionModel.getStateParameter().getName());
|
||||
|
||||
final ControlLink link = new ControlLink("");
|
||||
|
||||
final CMSPermissionsTableColumn col
|
||||
= (CMSPermissionsTableColumn) value;
|
||||
if (col.isPermitted()) {
|
||||
link.setClassAttr("checkBoxChecked");
|
||||
} else {
|
||||
link.setClassAttr("checkBoxUnchecked");
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
table.getColumn(table.getColumnModel().size() - 1).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(new Label(
|
||||
new GlobalizedMessage(
|
||||
"cms.ui.permissions.table.actions.remove_all",
|
||||
CmsConstants.CMS_BUNDLE)));
|
||||
link.setConfirmation(new GlobalizedMessage(
|
||||
"cms.ui.permissions.table.actions.remove_all.confirm",
|
||||
CmsConstants.CMS_BUNDLE));
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
});
|
||||
table.addTableActionListener(new TableActionListener() {
|
||||
|
||||
@Override
|
||||
public void cellSelected(final TableActionEvent event)
|
||||
throws FormProcessException {
|
||||
|
||||
final PageState state = event.getPageState();
|
||||
final int columnIndex = event.getColumn();
|
||||
if (event.getRowKey() == null) {
|
||||
return;
|
||||
}
|
||||
final String roleName = (String) event.getRowKey();
|
||||
|
||||
final Table table = (Table) event.getSource();
|
||||
final int columnCount = table.getColumnModel().size();
|
||||
final int lastColumnIndex = columnCount - 1;
|
||||
|
||||
final CcmObject object = itemSelectionModel
|
||||
.getSelectedItem(state);
|
||||
final RoleRepository roleRepo = cdiUtil.findBean(
|
||||
RoleRepository.class);
|
||||
final Optional<Role> role = roleRepo.findByName(roleName);
|
||||
if (!role.isPresent()) {
|
||||
throw new UnexpectedErrorException(String.format(
|
||||
"Role \"%s\" was not found inthe database, but was in "
|
||||
+ "the permissions table.",
|
||||
roleName));
|
||||
}
|
||||
final PermissionChecker permissionChecker = cdiUtil.findBean(
|
||||
PermissionChecker.class);
|
||||
if (columnIndex > 0 && columnIndex < lastColumnIndex) {
|
||||
final String privilege = table.getColumn(columnIndex)
|
||||
.getKey();
|
||||
|
||||
if (permissionChecker.isPermitted(privilege,
|
||||
object,
|
||||
role.get())) {
|
||||
permissionManager.revokePrivilege(privilege,
|
||||
role.get(),
|
||||
object);
|
||||
} else {
|
||||
permissionManager.grantPrivilege(privilege,
|
||||
role.get(),
|
||||
object);
|
||||
}
|
||||
} else if (columnIndex == lastColumnIndex) {
|
||||
final List<String> privileges = permissionManager
|
||||
.listDefiniedPrivileges(ItemPrivileges.class);
|
||||
privileges.forEach(privilege -> permissionManager
|
||||
.revokePrivilege(privilege, role.get(), object));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void headSelected(final TableActionEvent event) {
|
||||
//Nothing
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
panel.add(table);
|
||||
final CMSPermissionsPane permissionsPane = new CMSPermissionsPane(
|
||||
privileges.toArray(new String[]{}),
|
||||
privNameMap,
|
||||
objSelectionModel);
|
||||
panel.add(permissionsPane);
|
||||
}
|
||||
|
||||
// public ItemPermissionsStep(final ItemSelectionModel itemSelectionModel,
|
||||
// final AuthoringKitWizard authoringKitWizard,
|
||||
// final StringParameter selectedLanguage) {
|
||||
// super("cms:permissionsStep", CMS.CMS_XML_NS);
|
||||
//
|
||||
// this.itemSelectionModel = itemSelectionModel;
|
||||
//
|
||||
// final BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL);
|
||||
// final Label header = new Label(new GlobalizedMessage(
|
||||
// "cms.ui.permissions.table.header",
|
||||
// CmsConstants.CMS_BUNDLE));
|
||||
// panel.add(header);
|
||||
// super.add(panel);
|
||||
//
|
||||
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
// final PermissionManager permissionManager = cdiUtil.findBean(
|
||||
// PermissionManager.class);
|
||||
// final List<String> privileges = permissionManager
|
||||
// .listDefiniedPrivileges(ItemPrivileges.class);
|
||||
// final List<Label> headerLabels = privileges.stream()
|
||||
// .map(privilege -> generatePrivilegeColumnHeader(privilege))
|
||||
// .collect(Collectors.toList());
|
||||
// headerLabels.add(0,
|
||||
// new Label(new GlobalizedMessage(
|
||||
// "cms.ui.permissions.table.role_header",
|
||||
// CmsConstants.CMS_BUNDLE)));
|
||||
// headerLabels.add(new Label(new GlobalizedMessage(
|
||||
// "cms.ui.permissions.table.remove_all.header",
|
||||
// CmsConstants.CMS_BUNDLE)));
|
||||
// final Table table = new Table(
|
||||
// new PermissionsTableModelBuilder(),
|
||||
// headerLabels.toArray());
|
||||
// table.setClassAttr("dataTable");
|
||||
// for (int j = 1; j < table.getColumnModel().size() - 1; j++) {
|
||||
// table.getColumn(j).setKey(privileges.get(j - 1));
|
||||
// table.getColumn(j).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("");
|
||||
//
|
||||
// final CMSPermissionsTableColumn col
|
||||
// = (CMSPermissionsTableColumn) value;
|
||||
// if (col.isPermitted()) {
|
||||
// link.setClassAttr("checkBoxChecked");
|
||||
// } else {
|
||||
// link.setClassAttr("checkBoxUnchecked");
|
||||
// }
|
||||
//
|
||||
// return link;
|
||||
// }
|
||||
//
|
||||
// });
|
||||
// }
|
||||
// table.getColumn(table.getColumnModel().size() - 1).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(new Label(
|
||||
// new GlobalizedMessage(
|
||||
// "cms.ui.permissions.table.actions.remove_all",
|
||||
// CmsConstants.CMS_BUNDLE)));
|
||||
// link.setConfirmation(new GlobalizedMessage(
|
||||
// "cms.ui.permissions.table.actions.remove_all.confirm",
|
||||
// CmsConstants.CMS_BUNDLE));
|
||||
//
|
||||
// return link;
|
||||
// }
|
||||
//
|
||||
// });
|
||||
// table.addTableActionListener(new TableActionListener() {
|
||||
//
|
||||
// @Override
|
||||
// public void cellSelected(final TableActionEvent event)
|
||||
// throws FormProcessException {
|
||||
//
|
||||
// final PageState state = event.getPageState();
|
||||
// final int columnIndex = event.getColumn();
|
||||
// if (event.getRowKey() == null) {
|
||||
// return;
|
||||
// }
|
||||
// final String roleName = (String) event.getRowKey();
|
||||
//
|
||||
// final Table table = (Table) event.getSource();
|
||||
// final int columnCount = table.getColumnModel().size();
|
||||
// final int lastColumnIndex = columnCount - 1;
|
||||
//
|
||||
// final CcmObject object = itemSelectionModel
|
||||
// .getSelectedItem(state);
|
||||
// final RoleRepository roleRepo = cdiUtil.findBean(
|
||||
// RoleRepository.class);
|
||||
// final Optional<Role> role = roleRepo.findByName(roleName);
|
||||
// if (!role.isPresent()) {
|
||||
// throw new UnexpectedErrorException(String.format(
|
||||
// "Role \"%s\" was not found inthe database, but was in "
|
||||
// + "the permissions table.",
|
||||
// roleName));
|
||||
// }
|
||||
// final PermissionChecker permissionChecker = cdiUtil.findBean(
|
||||
// PermissionChecker.class);
|
||||
// if (columnIndex > 0 && columnIndex < lastColumnIndex) {
|
||||
// final String privilege = table.getColumn(columnIndex)
|
||||
// .getKey();
|
||||
//
|
||||
// if (permissionChecker.isPermitted(privilege,
|
||||
// object,
|
||||
// role.get())) {
|
||||
// permissionManager.revokePrivilege(privilege,
|
||||
// role.get(),
|
||||
// object);
|
||||
// } else {
|
||||
// permissionManager.grantPrivilege(privilege,
|
||||
// role.get(),
|
||||
// object);
|
||||
// }
|
||||
// } else if (columnIndex == lastColumnIndex) {
|
||||
// final List<String> privileges = permissionManager
|
||||
// .listDefiniedPrivileges(ItemPrivileges.class);
|
||||
// privileges.forEach(privilege -> permissionManager
|
||||
// .revokePrivilege(privilege, role.get(), object));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void headSelected(final TableActionEvent event) {
|
||||
// //Nothing
|
||||
// }
|
||||
//
|
||||
// });
|
||||
//
|
||||
// panel.add(table);
|
||||
// }
|
||||
private Label generatePrivilegeColumnHeader(final String privilege) {
|
||||
return new Label(new GlobalizedMessage(
|
||||
String.format("cms.ui.permissions.table.privilege.headers.%s",
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ public class ContentSectionConfig {
|
|||
ItemCategoryStep.class.getName(),
|
||||
ImageStep.class.getName(),
|
||||
RelatedInfoStep.class.getName(),
|
||||
// ItemPermissionsStep.class.getName()
|
||||
ItemPermissionsStep.class.getName()
|
||||
});
|
||||
|
||||
public static ContentSectionConfig getConfig() {
|
||||
|
|
|
|||
|
|
@ -146,10 +146,10 @@ public class AdminServlet extends BaseApplicationServlet {
|
|||
ADMIN_BUNDLE)),
|
||||
new ConfigurationTab());
|
||||
|
||||
tabbedPane.addTab(
|
||||
new Label(new GlobalizedMessage("ui.admin.tab.workflows.title",
|
||||
ADMIN_BUNDLE)),
|
||||
new WorkflowAdminTab());
|
||||
// tabbedPane.addTab(
|
||||
// new Label(new GlobalizedMessage("ui.admin.tab.workflows.title",
|
||||
// ADMIN_BUNDLE)),
|
||||
// new WorkflowAdminTab());
|
||||
|
||||
tabbedPane.addTab(
|
||||
new Label(new GlobalizedMessage("ui.admin.tab.importexport.title",
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public class WorkflowAdminTab extends LayoutPanel {
|
||||
|
||||
public WorkflowAdminTab() {
|
||||
super();
|
||||
|
||||
setLeft(new Label("Workflow Admin Tab Left"));
|
||||
|
||||
setBody(new Label("Workflow Admin Tab Body"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -65,8 +65,8 @@ class GroupsTable extends Table {
|
|||
|
||||
super();
|
||||
|
||||
setIdAttr("groupsTable");
|
||||
setStyleAttr("width: 30em");
|
||||
super.setIdAttr("groupsTable");
|
||||
super.setStyleAttr("width: 30em");
|
||||
|
||||
this.groupsTableFilter = groupsTableFilter;
|
||||
this.selectedGroupId = selectedGroupId;
|
||||
|
|
|
|||
Loading…
Reference in New Issue