modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedEvent.java | 20 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedHandler.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ReorderableList.java | 177 ++++++++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TimestampCellFormatter.java | 3 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/operation/schedule/GroupOperationScheduleDetailsView.java | 93 +++++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java | 12 6 files changed, 312 insertions(+), 3 deletions(-)
New commits: commit 1ef99fb331b3754bec5c6114948997c02b7421f9 Author: Ian Springer ian.springer@redhat.com Date: Tue Jan 25 15:55:49 2011 -0500
more work on group ops
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedEvent.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedEvent.java new file mode 100644 index 0000000..aeb8e66 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedEvent.java @@ -0,0 +1,20 @@ +package org.rhq.enterprise.gui.coregui.client.components.sorter; + +import com.smartgwt.client.widgets.grid.ListGridRecord; + +/** + * + */ +public class ListOrderChangedEvent { + + private ListGridRecord[] items; + + public ListOrderChangedEvent(ListGridRecord[] items) { + this.items = items; + } + + public ListGridRecord[] getItems() { + return this.items; + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedHandler.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedHandler.java new file mode 100644 index 0000000..cad63cf --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ListOrderChangedHandler.java @@ -0,0 +1,10 @@ +package org.rhq.enterprise.gui.coregui.client.components.sorter; + +/** + * + */ +public interface ListOrderChangedHandler { + + void onListOrderChanged(ListOrderChangedEvent event); + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ReorderableList.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ReorderableList.java new file mode 100644 index 0000000..b0b1214 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/sorter/ReorderableList.java @@ -0,0 +1,177 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.components.sorter; + +import com.google.gwt.event.shared.HandlerRegistration; +import com.smartgwt.client.types.ListGridFieldType; +import com.smartgwt.client.types.SelectionStyle; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.events.RecordDropEvent; +import com.smartgwt.client.widgets.grid.events.RecordDropHandler; +import com.smartgwt.client.widgets.layout.HLayout; +import com.smartgwt.client.widgets.layout.SectionStack; +import com.smartgwt.client.widgets.layout.SectionStackSection; +import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableListGrid; +import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Ian Springer + */ +public class ReorderableList extends LocatableVLayout { + + protected ListGridRecord[] initialSelection; + protected HLayout hlayout; + protected LocatableListGrid listGrid; + /** an icon displayed next to each item in the list grids, or null if no icon should be displayed */ + private String itemIcon; + /** the item title (i.e. display name), which should be plural and capitalized, e.g. "Resource Groups", "Roles". */ + private String itemTitle; + + private Set<ListOrderChangedHandler> listOrderChangedHandlers = new HashSet<ListOrderChangedHandler>(); + + private boolean isReadOnly; + + public ReorderableList(String locatorId, ListGridRecord[] records, String itemTitle, String itemIcon) { + this(locatorId, false, records, itemTitle, itemIcon); + } + + public ReorderableList(String locatorId, boolean isReadOnly, ListGridRecord[] records, String itemTitle, String itemIcon) { + super(locatorId); + + this.isReadOnly = isReadOnly; + + setWidth100(); + setMargin(7); + + this.hlayout = new HLayout(); + this.listGrid = new LocatableListGrid(extendLocatorId("listGrid")); + this.initialSelection = records; + this.listGrid.setRecords(records); + + if (this.isReadOnly) { + this.listGrid.setSelectionType(SelectionStyle.NONE); + } + + this.itemTitle = itemTitle; + this.itemIcon = itemIcon; + } + + /** + * Returns the {@link com.smartgwt.client.data.Record record}s in the order currently specified by the user. + * + * @return the {@link com.smartgwt.client.data.Record record}s in the order currently specified by the user + */ + public ListGridRecord[] getRecords() { + return this.listGrid.getRecords(); + } + + @Override + protected void onInit() { + super.onInit(); + + SectionStack itemsStack = buildItemsSectionStack(); + hlayout.addMember(itemsStack); + + addMember(this.hlayout); + } + + private SectionStack buildItemsSectionStack() { + SectionStack itemsSectionStack = new SectionStack(); + itemsSectionStack.setWidth(300); + itemsSectionStack.setHeight(250); + + SectionStackSection itemsSection = new SectionStackSection(getItemTitle()); + itemsSection.setCanCollapse(false); + itemsSection.setExpanded(true); + + this.listGrid.setCanReorderRecords(true); + this.listGrid.setLoadingMessage(MSG.common_msg_loading()); + this.listGrid.setEmptyMessage(MSG.common_msg_noItemsToShow()); + this.listGrid.addRecordDropHandler(new RecordDropHandler() { + @Override + public void onRecordDrop(RecordDropEvent event) { + notifyListOrderChangedHandlers(); + } + }); + + List<ListGridField> fields = new ArrayList<ListGridField>(); + String itemIcon = getItemIcon(); + if (itemIcon != null) { + ListGridField iconField = new ListGridField("icon", 25); + iconField.setType(ListGridFieldType.ICON); + iconField.setCellIcon(itemIcon); + iconField.setShowDefaultContextMenu(false); + fields.add(iconField); + } + ListGridField nameField = new ListGridField(getNameField(), MSG.common_title_name()); + fields.add(nameField); + this.listGrid.setFields(fields.toArray(new ListGridField[fields.size()])); + + itemsSection.setItems(this.listGrid); + itemsSectionStack.addSection(itemsSection); + + return itemsSectionStack; + } + + private void notifyListOrderChangedHandlers() { + for (ListOrderChangedHandler handler : this.listOrderChangedHandlers) { + handler.onListOrderChanged(new ListOrderChangedEvent(this.listGrid.getSelection())); + } + } + + public void reset() { + this.listGrid.setData(this.initialSelection); + } + + public HandlerRegistration addListOrderChangedHandler(final ListOrderChangedHandler handler) { + this.listOrderChangedHandlers.add(handler); + return new HandlerRegistration() { + @Override + public void removeHandler() { + listOrderChangedHandlers.remove(handler); + } + }; + } + + protected String getNameField() { + return "name"; + } + + public String getItemTitle() { + return itemTitle; + } + + protected String getItemIcon() { + return itemIcon; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + + this.listGrid.destroy(); + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TimestampCellFormatter.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TimestampCellFormatter.java index 086d7be..b08c0ee 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TimestampCellFormatter.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TimestampCellFormatter.java @@ -23,7 +23,8 @@ public class TimestampCellFormatter implements CellFormatter { * even if the caller doesn't have data from a cell or list grid. This can keep date formatting * consistent across the app, whether the data is in a cell or not. * - * @param date the date to format as a Date, Long, Integer or a String + * @param value the date to format as a Date, Long, Integer or a String + * * @return the formatted date string */ public static String format(Object value) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/operation/schedule/GroupOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/operation/schedule/GroupOperationScheduleDetailsView.java index b6a37bf..59cb90c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/operation/schedule/GroupOperationScheduleDetailsView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/operation/schedule/GroupOperationScheduleDetailsView.java @@ -1,16 +1,107 @@ package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.operation.schedule;
+import com.smartgwt.client.data.Criteria; +import com.smartgwt.client.data.DSCallback; +import com.smartgwt.client.data.DSRequest; +import com.smartgwt.client.data.DSResponse; +import com.smartgwt.client.data.Record; +import com.smartgwt.client.widgets.HTMLFlow; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.CheckboxItem; +import com.smartgwt.client.widgets.form.fields.RadioGroupItem; +import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; +import org.rhq.enterprise.gui.coregui.client.ImageManager; +import org.rhq.enterprise.gui.coregui.client.components.sorter.ReorderableList; import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule.AbstractOperationScheduleDetailsView; +import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceDatasource; +import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout; + +import java.util.LinkedHashMap;
/** - * + * @author Ian Springer */ public class GroupOperationScheduleDetailsView extends AbstractOperationScheduleDetailsView {
+ private ResourceGroupComposite groupComposite; + private ListGridRecord[] memberResourceRecords; + public GroupOperationScheduleDetailsView(String locatorId, ResourceGroupComposite groupComposite, int scheduleId) { super(locatorId, new GroupOperationScheduleDataSource(groupComposite), groupComposite.getResourceGroup().getResourceType(), scheduleId); + this.groupComposite = groupComposite; + } + + @Override + protected void init(final boolean isReadOnly) { + if (isNewRecord()) { + ResourceDatasource resourceDatasource = new ResourceDatasource(); + Criteria criteria = new Criteria(ResourceDatasource.FILTER_GROUP_ID, + String.valueOf(this.groupComposite.getResourceGroup().getId())); + resourceDatasource.fetchData(criteria, new DSCallback() { + public void execute(DSResponse response, Object rawData, DSRequest request) { + if (response.getStatus() != DSResponse.STATUS_SUCCESS) { + throw new RuntimeException("Failed to load group member Resources."); + } + Record[] data = response.getData(); + memberResourceRecords = new ListGridRecord[data.length]; + for (int i = 0, dataLength = data.length; i < dataLength; i++) { + Record record = data[i]; + ListGridRecord listGridRecord = (ListGridRecord) record; + memberResourceRecords[i] = listGridRecord; + } + GroupOperationScheduleDetailsView.super.init(isReadOnly); + } + }); + } }
+ @Override + protected LocatableVLayout buildContentPane() { + LocatableVLayout contentPane = super.buildContentPane(); + + HTMLFlow hr = new HTMLFlow("<p/><hr/><p/>"); + contentPane.addMember(hr); + + DynamicForm executionModeForm = new DynamicForm(); + executionModeForm.setColWidths("250", "*"); + + RadioGroupItem executionModeItem = new RadioGroupItem("executionMode", "Member Resource Execution Order"); + LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(2); + valueMap.put("parallel", "Execute in parallel"); + valueMap.put("sequential", "Execute in the order specified below"); + executionModeItem.setValueMap(valueMap); + executionModeItem.setDefaultValue("parallel"); + + final CheckboxItem haltOnFailureItem = new CheckboxItem("haltOnFailure", "Halt on Failure?"); + haltOnFailureItem.setDefaultValue(false); + haltOnFailureItem.setVisible(false); + haltOnFailureItem.setLabelAsTitle(true); + + executionModeItem.addChangedHandler(new ChangedHandler() { + public void onChanged(ChangedEvent event) { + if (event.getValue().equals("parallel")) { + haltOnFailureItem.hide(); + } else { + haltOnFailureItem.show(); + } + } + }); + + executionModeForm.setFields(executionModeItem, haltOnFailureItem); + + contentPane.addMember(executionModeForm); + + ResourceCategory resourceCategory = this.groupComposite.getResourceGroup().getResourceType().getCategory(); + String memberIcon = ImageManager.getResourceIcon(resourceCategory); + ReorderableList memberExecutionOrderer = new ReorderableList(extendLocatorId("MemberExecutionOrderer"), + this.memberResourceRecords, "Member Resources", memberIcon); + contentPane.addMember(memberExecutionOrderer); + + return contentPane; + } }
commit 6cd53e7d6a9d96ea540a7061a653956c00b21f5e Author: Ian Springer ian.springer@redhat.com Date: Tue Jan 25 15:54:34 2011 -0500
fix bug where existing roles associated with a new role's subjects were removed from those subjects (https://bugzilla.redhat.com/show_bug.cgi?id=672684)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java index 93b1ca8..eba8968 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Set;
@@ -155,13 +156,22 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote {
// Now we must merge subjects and resource groups, since those fields in Role do not have persist cascade // enabled. + int[] subjectIds = new int[newRole.getSubjects().size()]; + int i = 0; for (Subject subject : newRole.getSubjects()) { - entityManager.merge(subject); + subjectIds[i++] = subject.getId(); } + addSubjectsToRole(whoami, newRole.getId(), subjectIds);
for (ResourceGroup resourceGroup : newRole.getResourceGroups()) { entityManager.merge(resourceGroup); } + int[] resourceGroupIds = new int[newRole.getResourceGroups().size()]; + i = 0; + for (ResourceGroup resourceGroup : newRole.getResourceGroups()) { + resourceGroupIds[i++] = resourceGroup.getId(); + } + addResourceGroupsToRole(whoami, newRole.getId(), resourceGroupIds);
return newRole; }