GroupsView.java
/*
** Module : GroupsView.java
** Abstract : GroupsView provides a view to manage groups.
**
** Copyright (c) 2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- ----------------Description----------------------
** 001 SBI 20170601 Created initial version.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program 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 Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.admin.client.application.home.accounts.groups;
import java.util.*;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.TextBox;
import org.gwtbootstrap3.client.ui.gwt.DataGrid;
import com.goldencode.p2j.admin.TaggedName;
import com.goldencode.p2j.admin.client.NameTokens;
import com.goldencode.p2j.admin.client.application.home.BaseViewWithUiHandlers;
import com.goldencode.p2j.admin.client.widget.*;
import com.goldencode.p2j.admin.shared.*;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.inject.Inject;
/**
* GroupsView provides a view to manage groups.
*/
public class GroupsView
extends BaseViewWithUiHandlers<GroupsUIHandlers>
implements GroupsPresenter.MyView
{
/**
* GWT UI creator
*/
interface Binder
extends UiBinder<Widget, GroupsView>
{}
/** The Refresh button */
@UiField
Button refresh;
/** The Add group button */
@UiField
Button addGroup;
/** The Delete group button */
@UiField
Button deleteGroup;
/** The clone group button */
@UiField
Button cloneGroup;
/** The edit group button */
@UiField
Button editGroup;
/** The Switch to ACLs button */
@UiField
Button switchToACLs;
/** The Delete user button */
@UiField
Button deleteUser;
/** The Add user button */
@UiField
Button addUser;
/** The text box representing the new user account name */
@UiField
TextBox newUser;
/** The Populate users button */
@UiField
Button populateUsers;
/** The Add Selected button */
@UiField
Button addSelected;
/** The filter text box selector */
@UiField
TextBox filterSelector;
/** The Filter button */
@UiField
Button filterUsers;
/** The all groups table view */
@UiField(provided = true)
DataGrid<TaggedName> groupsGrid = GridHelper.create();
/** The group users table view (all users in the given group) */
@UiField(provided = true)
DataGrid<TaggedName> groupUsersGrid = GridHelper.create();
/** The all users table view */
@UiField(provided = true)
DataGrid<TaggedName> allUsersGrid = GridHelper.create();
/** modal container */
@UiField
Widget modalFragment;
/** Column names for all groups table. */
private final String[] groupsColumnNames = { "Group ID", "Description" };
/** Column names for all users table and group users table. */
private final String[] groupUsersColumnNames = { "User ID", "Person" };
/** The all groups data provider */
private final ListDataProvider<TaggedName> groupsProvider;
/** The all groups selection model */
private final MultiSelectionModel<TaggedName> groupsSelectionModel;
/** The all groups grid handle */
private final GridHandle<TaggedName> groupsGridHandle;
/** The group users data provider */
private final ListDataProvider<TaggedName> groupUsersProvider;
/** The group users selection model */
private final MultiSelectionModel<TaggedName> groupUsersSelectionModel;
/** The group users grid handle */
private final GridHandle<TaggedName> groupUsersGridHandle;
/** The all users data provider */
private final ListDataProvider<TaggedName> allUsersProvider;
/** The all users selection model */
private final MultiSelectionModel<TaggedName> allUsersSelectionModel;
/** The all users grid handle */
private final GridHandle<TaggedName> allUsersGridHandle;
/** The Group Definition View */
private final GroupDefinitionView groupDefinitionView;
/** The Deleting Groups Alert view */
private final DeletingGroupsAlert deletingGroupsAlert;
/** The Clone Group View */
private final CloneGroupView cloneGroupView;
/** The Unassigning Users Alert view */
private final UnassigningUsersAlert unassigningUsersAlert;
/**
* Constructs this view used by by MPV gwtplatform of ArcBees Inc.
*
* @param binder
* The injected GWT UI Binder
* @param groupDefinitionView
* The injected Group Definition View
* @param deletingGroupsAlert
* The injected Deleting Groups Alert view
* @param cloneGroupView
* The injected Clone Group View
* @param unassigningUsersAlert
* The injected Unassigning Users Alert view
*/
@Inject
public GroupsView(Binder binder,
GroupDefinitionView groupDefinitionView,
DeletingGroupsAlert deletingGroupsAlert,
CloneGroupView cloneGroupView,
UnassigningUsersAlert unassigningUsersAlert)
{
initWidget(binder.createAndBindUi(this));
this.groupDefinitionView = groupDefinitionView;
this.deletingGroupsAlert = deletingGroupsAlert;
this.cloneGroupView = cloneGroupView;
this.unassigningUsersAlert = unassigningUsersAlert;
this.groupsGridHandle = initTable(groupsGrid, groupsColumnNames, true, true);
this.groupsProvider = groupsGridHandle.getDataProvider();
this.groupsSelectionModel = (MultiSelectionModel<TaggedName>) groupsGridHandle.getSelectionModel();
this.groupsSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
{
@Override
public void onSelectionChange(SelectionChangeEvent event)
{
Set<TaggedName> selected = GroupsView.this.groupsSelectionModel.getSelectedSet();
if (selected.size() != 1)
{
GroupsView.this.allUsersSelectionModel.clear();
}
GroupsView.this.getUiHandlers().onGroupSelected(selected);
}
});
this.groupUsersGridHandle = initTable(groupUsersGrid, groupUsersColumnNames, true, true);
this.groupUsersSelectionModel = (MultiSelectionModel<TaggedName>) this.groupUsersGridHandle.getSelectionModel();
this.groupUsersProvider = this.groupUsersGridHandle.getDataProvider();
this.groupUsersSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
{
@Override
public void onSelectionChange(SelectionChangeEvent event)
{
Set<TaggedName> selected = GroupsView.this.groupUsersSelectionModel.getSelectedSet();
GroupsView.this.getUiHandlers().onUserSelected(selected);
}
});
this.allUsersGridHandle = initTable(allUsersGrid, groupUsersColumnNames, true, true);
this.allUsersProvider = this.allUsersGridHandle.getDataProvider();
this.allUsersSelectionModel = (MultiSelectionModel<TaggedName>)this.allUsersGridHandle.getSelectionModel();
this.allUsersSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler()
{
@Override
public void onSelectionChange(SelectionChangeEvent event)
{
if (GroupsView.this.groupsSelectionModel.getSelectedSet().size() == 1)
{
Set<TaggedName> selected = GroupsView.this.allUsersSelectionModel.getSelectedSet();
List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));
GroupsView.this.addSelected.setEnabled(!usersInGroup.containsAll(selected));
}
else
{
GroupsView.this.allUsersSelectionModel.clear();
}
}
});
((com.google.gwt.user.cellview.client.DataGrid<TaggedName>) groupsGrid).setMinimumTableWidth(300, Unit.PX);
setupModalSlot(GroupsPresenter.MODAL_CONTENT, modalFragment);
addDialog(groupDefinitionView);
addDialog(deletingGroupsAlert);
addDialog(cloneGroupView);
addDialog(unassigningUsersAlert);
}
/**
* Setups the given table view.
*
* @param grid
* The given table view
* @param columnNames
* The given column names
* @param multiSelection
* The flag defines if the table view supports multiple rows or single row selections
* @param sortable
* The flag defines if the table columns can change its rows sort order or not.
*
* @return The grid handle
*/
private GridHandle<TaggedName> initTable(DataGrid<TaggedName> grid, String[] columnNames,
boolean multiSelection, boolean sortable)
{
GridHelper.ColumnInfo<TaggedName> col1 = new GridHelper.ColumnInfo<TaggedName>(
columnNames[0],
(tn) -> tn.getName(),
(sortable) ? (tn1, tn2) -> tn1.getName().compareTo(tn2.getName()) : null
);
GridHelper.ColumnInfo<TaggedName> col2 = new GridHelper.ColumnInfo<TaggedName>(
columnNames[1],
(tn) -> tn.getTag(),
(sortable) ? (tn1, tn2) -> tn1.getTag().compareTo(tn2.getTag()) : null
);
return GridHelper.initListGrid(grid, multiSelection, sortable, col1, col2);
}
/**
* Updates the table view data provider with new data.
*
* @param grid
* The table view
* @param dataProvider
* The data provider
* @param records
* The new data
*/
private void updateDataProvider(DataGrid<TaggedName> grid,
ListDataProvider<TaggedName> dataProvider,
TaggedName[] records)
{
GridHelper.updateDataProvider(grid, dataProvider, records);
}
/**
* Updates the table view data provider with new data.
*
* @param dataGrid
* The table view
* @param dataProvider
* The data provider
* @param records
* The new data
* @param filterExp
* The regular expression that is used to select rows that satisfy the given criteria
*/
private void updateDataProvider(DataGrid<TaggedName> dataGrid,
ListDataProvider<TaggedName> dataProvider,
TaggedName[] records,
RegExp filterExp)
{
dataProvider.getList().clear();
if (records == null)
{
return;
}
GridHelper.updateDataProvider(dataGrid, dataProvider, records, filterExp);
}
/**
* Sets the all groups table model.
*
* @param groups
* The array of groups given by tagged names
*/
@Override
public void setGroups(TaggedName[] groups)
{
logger.info("setGroups " + groups);
groupsSelectionModel.clear();
updateDataProvider(groupsGrid, groupsProvider, groups);
}
/**
* The Refresh button click handler.
*
* @param e
* Click event
*/
@UiHandler("refresh")
void onRefresh(ClickEvent e)
{
getUiHandlers().onRefresh();
}
/**
* The Add Group button click handler.
*
* @param e
* Click event
*/
@UiHandler("addGroup")
void onAddGroup(ClickEvent e)
{
logger.info("onAddGroup");
getUiHandlers().setupAddGroupDialog();
}
/**
* The Clone Group button click handler.
*
* @param e
* Click event
*/
@UiHandler("cloneGroup")
void onCloneGroup(ClickEvent e)
{
TaggedName[] groups = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
getUiHandlers().setupCloneGroupDialog(groups[0]);
}
/**
* The Edit Group button click handler.
*
* @param e
* Click event
*/
@UiHandler("editGroup")
void onEditGroup(ClickEvent e)
{
logger.info("onEditGroup");
TaggedName[] groups = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
getUiHandlers().setupEditGroupDialog(groups[0]);
}
/**
* The Populate button click handler.
*
* @param e
* Click event
*/
@UiHandler("populateUsers")
void onPopulateUsers(ClickEvent e)
{
getUiHandlers().populateAndRefreshAllUsers();
}
/**
* The Delete Group button click handler.
*
* @param e
* Click event
*/
@UiHandler("deleteGroup")
void onDeleteGroup(ClickEvent e)
{
logger.info("onDeleteGroup");
TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
getUiHandlers().setupDeletingGroupsAlert(groups);
}
/**
* The Delete User button click handler.
*
* @param e
* Click event
*/
@UiHandler("deleteUser")
void onDeleteUser(ClickEvent e)
{
logger.info("onDeleteUser");
TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
TaggedName[] users = this.groupUsersSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
getUiHandlers().setupUnassigningUsersAlert(groups[0], users);
}
/**
* The Add User button click handler.
*
* @param e
* Click event
*/
@UiHandler("addUser")
void onAddUser(ClickEvent e)
{
logger.info("onAddUser");
TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
//TODO validation
getUiHandlers().addUserToGroup(groups[0], newUser.getText());
}
/**
* The Filter Users button click handler.
*
* @param e
* Click event
*/
@UiHandler("filterUsers")
void onFilterUsers(ClickEvent e)
{
logger.info("onFilterUsers");
getUiHandlers().setUsersFilter(filterSelector.getText());
}
/**
* The Add Selected button click handler.
*
* @param e
* Click event
*/
@UiHandler("addSelected")
void onAddSelected(ClickEvent e)
{
logger.info("AddSelected");
List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
Set<TaggedName> selected = this.allUsersSelectionModel.getSelectedSet();
selected.removeAll(usersInGroup);
TaggedName[] groups = this.groupsSelectionModel.getSelectedSet().toArray(new TaggedName[0]);
getUiHandlers().addUsersToGroup(groups[0], selected);
}
/**
* Sets the group users table model.
*
* @param users
* The array of group users given by tagged names
*/
@Override
public void setUsersInGroup(TaggedName[] users)
{
this.groupUsersSelectionModel.clear();
this.allUsersSelectionModel.clear();
updateDataProvider(groupUsersGrid, groupUsersProvider, users);
List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));
GroupsView.this.addSelected.setEnabled(false);
}
/**
* Sets all users model.
*
* @param allUsers
* The array of all users accounts given by tagged names
* @param filterExp
* The search template to filter the displayed users
*/
@Override
public void setAllUsers(TaggedName[] allUsers, RegExp filterExp)
{
updateDataProvider(allUsersGrid, allUsersProvider,
allUsers, filterExp);
if (GroupsView.this.groupsSelectionModel.getSelectedSet().size() == 1)
{
List<TaggedName> usersInGroup = GroupsView.this.groupUsersProvider.getList();
usersInGroup.forEach(user -> GroupsView.this.allUsersSelectionModel.setSelected(user, true));
}
else
{
GroupsView.this.allUsersSelectionModel.clear();
}
}
/**
* Gets a reference to the Group Definition View.
*
* @return The Group Definition View
*/
@Override
public GroupDefinitionView getGroupDefinitionView()
{
return groupDefinitionView;
}
/**
* Gets a reference to the Deleting Groups Alert View.
*
* @return The Deleting Groups Alert View
*/
@Override
public DeletingGroupsAlert getDeletingGroupsAlert()
{
return deletingGroupsAlert;
}
/**
* Gets a reference to the Clone Group View.
*
* @return The Clone Group View
*/
@Override
public CloneGroupView getCloneGroupView()
{
return cloneGroupView;
}
/**
* Provides all components that must be managed by its view state machine.
*
* @return The array of components managed by its view state machine
*/
@Override
public HasEnabled[] get()
{
return new HasEnabled[] {
refresh,
addGroup,
deleteGroup,
cloneGroup,
editGroup,
switchToACLs,
newUser,
addUser,
deleteUser,
populateUsers,
addSelected,
filterSelector,
filterUsers
};
}
/**
* Gets a reference to the Unassigning Users Alert View.
*
* @return The Unassigning Users Alert View
*/
@Override
public UnassigningUsersAlert getUnassigningUsersAlert()
{
return unassigningUsersAlert;
}
/**
* Tests if this group has been selected.
*
* @param group
* The target group
*
* @return True iff the target group has een selected, otherwise false.
*/
@Override
public boolean isSelectedGroup(TaggedName group)
{
return groupsSelectionModel.isSelected(group);
}
/**
* Tests if these users have been selected.
*
* @param users
* The array of selected user accounts given by tagged names
*
* @return True if all tested users have been selected, otherwise false.
*/
@Override
public boolean isSelectedUsers(TaggedName[] users)
{
return groupUsersSelectionModel.getSelectedSet().containsAll(Arrays.asList(users));
}
/**
* Changes the Populate button's label from "Populate" to "Refresh"
*
* @param populated
* The flag which true value means to change the Populate label to Refresh one
*/
@Override
public void togglePopulateUsersButton(boolean populated)
{
if (populated)
{
populateUsers.setText("Refresh");
}
}
/**
* The Switch To ACLs button click handler.
*
* @param e
* Click event
*/
@UiHandler("switchToACLs")
void onSwitchToACLs(ClickEvent e)
{
logger.info("onSwitchToACLs");
TaggedName selected = GroupsView.this.groupsSelectionModel.getSelectedSet().toArray(
new TaggedName[0])[0];
getUiHandlers().switchToACLs(selected);
}
/**
* Returns pairs of a report parameter key and its value
*
* @return The enumeration map of report parameters keys to their values
*/
@Override
public EnumMap<ReportParameters, Object> getReportParameters()
{
EnumMap<ReportParameters, Object> parameters = new EnumMap<ReportParameters, Object>(
ReportParameters.class);
parameters.put(ReportParameters.SELECTION, groupsSelectionModel.getSelectedSet().toArray(
new TaggedName[groupsSelectionModel.getSelectedSet().size()]));
parameters.put(ReportParameters.TITLE, "Groups");
parameters.put(ReportParameters.REPORT_ID, Reports.GROUPS);
parameters.put(ReportParameters.PAPER_FORMAT, PaperFormat.A4);
parameters.put(ReportParameters.PAPER_ORIENT, PaperOrientation.PORTRAIT);
return parameters;
}
/**
* Returns the size of all data to preview or the size of selected data to preview
*
* @param range
* The target range of selected data to preview
* @return The size of the selected data
*/
@Override
public int getDataSize(Range range)
{
if (range == Range.SELECTION)
{
return groupsSelectionModel.getSelectedSet().size();
}
return groupsProvider.getList().size();
}
/**
* Returns the value of the preview dialog parameter.
*
* @param parameter
* The preview dialog parameter key
*
* @return The value of the preview dialog parameter
*/
@Override
public String getPreviewDialogParameter(PreviewDialogParameters parameter)
{
int selectedRecordsNumber = groupsSelectionModel.getSelectedSet().size();
int allRecordsNumber = groupsProvider.getList().size();
switch (parameter)
{
case HELP_TEXT:
String hlpText;
if (selectedRecordsNumber > 0)
{
hlpText = "<h4>Please refine your request.</h4>";
}
else
{
if (allRecordsNumber > 1)
{
hlpText = "<h4>" + allRecordsNumber + " group accounts being printed. Continue?</h4>";
}
else if (allRecordsNumber == 1)
{
hlpText = "<h4>1 group account being printed. Continue?</h4>";
}
else
{
hlpText = "<h4>There are no groups to print. Continue?</h4>";
}
}
return hlpText;
case TITLE:
return "Printing Groups";
case RANGE_ALL_LABEL:
if (allRecordsNumber > 2)
{
return "all " + allRecordsNumber + " group accounts";
}
else if (allRecordsNumber == 2)
{
return "both group accounts";
}
break;
case RANGE_SELECTION_LABEL:
if (selectedRecordsNumber > 1)
{
return selectedRecordsNumber + " selected group accounts";
}
else if (selectedRecordsNumber == 1)
{
return "the selected group account";
}
break;
}
return null;
}
/**
* Returns url path to this view.
*
* @return The url path.
*/
@Override
public String getPathToPrintPreviewOwner()
{
return NameTokens.GROUPS;
}
/**
* Select a group by its name.
*
* @param groupName
* The group name
*/
@Override
public void selectGroupByName(String groupName)
{
groupsSelectionModel.clear();
groupsProvider.getList().forEach(group -> {
if (group.getName().equals(groupName))
{
Scheduler.get().scheduleDeferred(new ScheduledCommand()
{
@Override
public void execute()
{
groupsSelectionModel.setSelected(group, true);
}
});
}
});
}
}