modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java | 11 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertHistoryView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TableSection.java | 26 ++++-- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/view/AbstractSectionedLeftNavigationView.java | 42 +++++++--- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java | 5 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java | 37 ++++++-- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletWindow.java | 8 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/recent/alerts/RecentAlertsPortlet.java | 33 +++++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/ReportTopView.java | 9 +- 9 files changed, 140 insertions(+), 35 deletions(-)
New commits: commit edcb7e6230d6bd47593d2e6183e27c9afb30f2db Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Jan 11 16:27:10 2011 -0500
[BZ 662068 all actions/buttons for recent alerts portlet always disabled. Unable to Ack alerts] In short this is due to the fact that the recent alerts portlet is like the recent alerts report, they are both "subsystem" views. As such the single alert listing can include alerts for which the user may or may not have alert (write) perms. Both the portlet and the report view simply disallowed the buttons to be safe. There are only really three alternatives, disallow all buttons, allow the buttons only for inv managers, or code up granular button enablement that involves perm checking on the resources backing each alert.
I took option 2 which at least allows inv managers the ability to process the alerts en masse from the portlet or the report. Other users will need to navigate to the alert or resource from the links provided, and process alerts from there.
This change makes available the user's global perms to any portlet, and also any AbstractSectionedLeftNavigationView (the latter for the reports view).
Also, fixed the alert links in the portlet. This required a slight enhancement to TableSection, the ability to override the automatic html link wrapping of "name" fields.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java index e819c36..3976caa 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java @@ -131,8 +131,15 @@ public class LinkManager { return link; }
- public static String getSubsystemAlertHistoryLink() { - return "/rhq/subsystem/alertHistory.xhtml"; + public static String getSubsystemAlertHistoryLink(int resourceId, int alertHistoryId) { + String link; + if (GWT) { + link = "#Resource/" + resourceId + "/Alerts/History/" + alertHistoryId; + } else { + link = "/rhq/subsystem/alertHistory.xhtml"; + } + + return link; }
public static String getSubsystemAlertDefsLink() { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertHistoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertHistoryView.java index bf936be..4d3c2bc 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertHistoryView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertHistoryView.java @@ -108,10 +108,10 @@ public class AlertHistoryView extends TableSection<AlertDataSource> { protected void configureTable() { ArrayList<ListGridField> dataSourceFields = getDataSource().getListGridFields(); getListGrid().setFields(dataSourceFields.toArray(new ListGridField[dataSourceFields.size()])); - setupTableInteractions(); + setupTableInteractions(this.hasWriteAccess); }
- private void setupTableInteractions() { + protected void setupTableInteractions(final boolean hasWriteAccess) { TableActionEnablement singleTargetEnablement = hasWriteAccess ? TableActionEnablement.ANY : TableActionEnablement.NEVER;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TableSection.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TableSection.java index 0b2d1e6..cd25235 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TableSection.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/TableSection.java @@ -115,13 +115,7 @@ public abstract class TableSection<DS extends RPCDataSource> extends Table<DS> i ListGrid grid = getListGrid(); ListGridField field = (grid != null) ? grid.getField(getDetailsLinkColumnName()) : null; if (field != null) { - field.setCellFormatter(new CellFormatter() { - public String format(Object value, ListGridRecord record, int i, int i1) { - Integer recordId = getId(record); - String detailsUrl = "#" + getBasePath() + "/" + recordId; - return SeleniumUtility.getLocatableHref(detailsUrl, value.toString(), null); - } - }); + field.setCellFormatter(getDetailsLinkColumnCellFormatter()); }
// Make double-clicking the row an alternate means to go to the details view. @@ -133,6 +127,24 @@ public abstract class TableSection<DS extends RPCDataSource> extends Table<DS> i }); }
+ /** + * Override if you don't want the detailsLinkColumn to have the default link wrapper. + * @return the desired CellFormatter. + */ + protected CellFormatter getDetailsLinkColumnCellFormatter() { + return new CellFormatter() { + public String format(Object value, ListGridRecord record, int i, int i1) { + Integer recordId = getId(record); + String detailsUrl = "#" + getBasePath() + "/" + recordId; + return SeleniumUtility.getLocatableHref(detailsUrl, value.toString(), null); + } + }; + } + + /** + * Override if you don't want FIELD_NAME to be wrapped ina link. + * @return the name of the field to be wrapped, or null if no field should be wrapped. + */ protected String getDetailsLinkColumnName() { return FIELD_NAME; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/view/AbstractSectionedLeftNavigationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/view/AbstractSectionedLeftNavigationView.java index 0951e8d..3cfe369 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/view/AbstractSectionedLeftNavigationView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/view/AbstractSectionedLeftNavigationView.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set;
import com.allen_sauer.gwt.log.client.Log; import com.smartgwt.client.types.VisibilityMode; @@ -34,9 +35,12 @@ import com.smartgwt.client.widgets.tree.Tree; import com.smartgwt.client.widgets.tree.TreeGrid; import com.smartgwt.client.widgets.tree.TreeNode;
+import org.rhq.core.domain.authz.Permission; import org.rhq.enterprise.gui.coregui.client.BookmarkableView; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.InitializableView; +import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener; +import org.rhq.enterprise.gui.coregui.client.PermissionsLoader; import org.rhq.enterprise.gui.coregui.client.RefreshableView; import org.rhq.enterprise.gui.coregui.client.ViewId; import org.rhq.enterprise.gui.coregui.client.ViewPath; @@ -55,7 +59,7 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableTreeGrid; */ public abstract class AbstractSectionedLeftNavigationView extends LocatableHLayout implements BookmarkableView, InitializableView { - + private String viewId; private boolean initialized; private ViewId currentSectionViewId; @@ -68,6 +72,9 @@ public abstract class AbstractSectionedLeftNavigationView extends LocatableHLayo private Map<String, TreeGrid> treeGrids = new LinkedHashMap<String, TreeGrid>(); private Map<String, NavigationSection> sectionsByName;
+ // Capture the user's global permissions for use by any dashboard or portlet that may need it for rendering. + private Set<Permission> globalPermissions; + public AbstractSectionedLeftNavigationView(String viewId) { super(viewId); this.viewId = viewId; @@ -90,19 +97,26 @@ public abstract class AbstractSectionedLeftNavigationView extends LocatableHLayo sectionStack.setWidth(250); sectionStack.setHeight100();
- List<NavigationSection> sections = getNavigationSections(); - this.sectionsByName = new HashMap<String, NavigationSection>(sections.size()); - for (NavigationSection section : sections) { - TreeGrid treeGrid = buildTreeGridForSection(section); - addSection(treeGrid); - treeGrid.getTree().openAll(); - this.sectionsByName.put(section.getName(), section); - } + new PermissionsLoader().loadExplicitGlobalPermissions(new PermissionsLoadedListener() { + + public void onPermissionsLoaded(Set<Permission> permissions) { + globalPermissions = permissions; + + List<NavigationSection> sections = getNavigationSections(); + sectionsByName = new HashMap<String, NavigationSection>(sections.size()); + for (NavigationSection section : sections) { + TreeGrid treeGrid = buildTreeGridForSection(section); + addSection(treeGrid); + treeGrid.getTree().openAll(); + sectionsByName.put(section.getName(), section); + }
- addMember(sectionStack); - addMember(contentCanvas); + addMember(sectionStack); + addMember(contentCanvas);
- this.initialized = true; + initialized = true; + } + }); }
@Override @@ -249,4 +263,8 @@ public abstract class AbstractSectionedLeftNavigationView extends LocatableHLayo } }
+ public Set<Permission> getGlobalPermissions() { + return globalPermissions; + } + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java index 3460e3e..ea18f1a 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java @@ -47,6 +47,7 @@ import com.smartgwt.client.widgets.menu.events.ItemClickHandler; import com.smartgwt.client.widgets.menu.events.MenuItemClickEvent;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.dashboard.Dashboard; import org.rhq.core.domain.dashboard.DashboardPortlet; @@ -523,6 +524,10 @@ public class DashboardView extends LocatableVLayout { return storedDashboard; }
+ public Set<Permission> getGlobalPermissions() { + return dashboardsView.getGlobalPermissions(); + } + public void setEditMode(boolean editMode) { this.editMode = editMode; if (editMode) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java index 4e9d197..d5fe712 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardsView.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set;
import com.google.gwt.user.client.History; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -42,12 +43,15 @@ import com.smartgwt.client.widgets.tab.events.TabCloseClickEvent; import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.dashboard.Dashboard; import org.rhq.core.domain.dashboard.DashboardPortlet; import org.rhq.enterprise.gui.coregui.client.BookmarkableView; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.InitializableView; +import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener; +import org.rhq.enterprise.gui.coregui.client.PermissionsLoader; import org.rhq.enterprise.gui.coregui.client.ViewPath; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTab; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTabSet; @@ -94,6 +98,9 @@ public class DashboardsView extends LocatableVLayout implements BookmarkableView
private DashboardGWTServiceAsync dashboardService = GWTServiceLookup.getDashboardService();
+ // Capture the user's global permissions for use by any dashboard or portlet that may need it for rendering. + private Set<Permission> globalPermissions; + private boolean initialized = false;
public DashboardsView(String locatorId) { @@ -114,16 +121,25 @@ public class DashboardsView extends LocatableVLayout implements BookmarkableView }
public void onSuccess(final List<Dashboard> result) { - initialized = true; + // now, a second async call to load global perms + new PermissionsLoader().loadExplicitGlobalPermissions(new PermissionsLoadedListener() {
- if (result.isEmpty()) { - // if the user has no dashboards persist a default dashboard for him to work with. In - // this way we're always working with a persisted dashboard and real entities. - addDefaultDashboard(); + public void onPermissionsLoaded(Set<Permission> permissions) { + globalPermissions = permissions;
- } else { - updateDashboards(result); - } + if (result.isEmpty()) { + // if the user has no dashboards persist a default dashboard for him to work with. In + // this way we're always working with a persisted dashboard and real entities. + addDefaultDashboard(); + + } else { + updateDashboards(result); + + } + + initialized = true; + } + }); } }); } @@ -402,4 +418,9 @@ public class DashboardsView extends LocatableVLayout implements BookmarkableView public boolean isInitialized() { return initialized; } + + public Set<Permission> getGlobalPermissions() { + return globalPermissions; + } + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletWindow.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletWindow.java index d8c083d..664b234 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletWindow.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletWindow.java @@ -22,6 +22,8 @@ */ package org.rhq.enterprise.gui.coregui.client.dashboard;
+import java.util.Set; + import com.smartgwt.client.types.DragAppearance; import com.smartgwt.client.types.HeaderControls; import com.smartgwt.client.types.Overflow; @@ -35,6 +37,7 @@ import com.smartgwt.client.widgets.events.CloseClientEvent; import com.smartgwt.client.widgets.events.DragResizeStopEvent; import com.smartgwt.client.widgets.events.DragResizeStopHandler;
+import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.dashboard.DashboardPortlet; import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHeaderControl; @@ -210,4 +213,9 @@ public class PortletWindow extends LocatableWindow { public void save() { this.dashboardView.save(); } + + public Set<Permission> getGlobalPermissions() { + return dashboardView.getGlobalPermissions(); + } + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/recent/alerts/RecentAlertsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/recent/alerts/RecentAlertsPortlet.java index b32390f..8edef2d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/recent/alerts/RecentAlertsPortlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/recent/alerts/RecentAlertsPortlet.java @@ -18,6 +18,8 @@ */ package org.rhq.enterprise.gui.coregui.client.dashboard.portlets.recent.alerts;
+import java.util.Set; + import com.google.gwt.user.client.Timer; import com.smartgwt.client.types.Overflow; import com.smartgwt.client.widgets.Canvas; @@ -29,14 +31,18 @@ import com.smartgwt.client.widgets.form.fields.SelectItem; import com.smartgwt.client.widgets.form.fields.SpacerItem; import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.layout.VLayout;
import org.rhq.core.domain.alert.AlertPriority; +import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.dashboard.DashboardPortlet; import org.rhq.core.domain.resource.ResourceType; import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.Messages; import org.rhq.enterprise.gui.coregui.client.UserSessionManager; import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; @@ -51,6 +57,7 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHLayout; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableLabel; import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout; +import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/** * @author Simeon Pinder @@ -580,6 +587,32 @@ public class RecentAlertsPortlet extends AlertHistoryView implements CustomSetti defaultReloader.schedule(retrievedRefreshInterval); } } + + @Override + protected void setupTableInteractions(boolean hasWriteAccess) { + // The portlet is a "subsystem" view. Meaning the alerts displayed can be from any accessible group for + // the user. This means the user can have varying permissions on the underlying groups and/or resources, + // which makes button enablement tricky. So, for the portlet don't even show the buttons unless the user + // is inventory manager. Other users will just have to navigate to the alert in question in order to + // manipulate it. + + //determine if the user is inventory manager and if so render the buttons + Set<Permission> permissions = this.portletWindow.getGlobalPermissions(); + if ((null != permissions) && permissions.contains(Permission.MANAGE_INVENTORY)) { + super.setupTableInteractions(true); + } + } + + protected CellFormatter getDetailsLinkColumnCellFormatter() { + return new CellFormatter() { + public String format(Object value, ListGridRecord record, int i, int i1) { + Integer recordId = getId(record); + Integer resourceId = record.getAttributeAsInt("resourceId"); + String detailsUrl = LinkManager.getSubsystemAlertHistoryLink(resourceId, recordId); + return SeleniumUtility.getLocatableHref(detailsUrl, value.toString(), null); + } + }; + } }
/** Bundles a ResourceSelector instance with labelling in Canvas for display. diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/ReportTopView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/ReportTopView.java index cc57951..5b0cd5c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/ReportTopView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/ReportTopView.java @@ -29,6 +29,7 @@ import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Label; import com.smartgwt.client.widgets.layout.VLayout;
+import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.enterprise.gui.coregui.client.ImageManager; import org.rhq.enterprise.gui.coregui.client.admin.AdministrationView; @@ -43,7 +44,6 @@ import org.rhq.enterprise.gui.coregui.client.components.view.NavigationSection; import org.rhq.enterprise.gui.coregui.client.components.view.ViewFactory; import org.rhq.enterprise.gui.coregui.client.components.view.ViewName; import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.platform.PlatformSummaryPortlet; -import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.operation.history.AbstractOperationHistoryListView; import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configuration.ConfigurationHistoryView; import org.rhq.enterprise.gui.coregui.client.report.measurement.MeasurementOOBView; import org.rhq.enterprise.gui.coregui.client.report.operation.SubsystemOperationHistoryListView; @@ -120,16 +120,17 @@ public class ReportTopView extends AbstractSectionedLeftNavigationView { NavigationItem recentOperationsItem = new NavigationItem(SubsystemOperationHistoryListView.VIEW_ID, "subsystems/control/Operation_16.png", new ViewFactory() { public Canvas createView() { - return new SubsystemOperationHistoryListView(extendLocatorId(SubsystemOperationHistoryListView.VIEW_ID.getName())); + return new SubsystemOperationHistoryListView( + extendLocatorId(SubsystemOperationHistoryListView.VIEW_ID.getName())); } });
NavigationItem recentAlertsItem = new NavigationItem(AlertHistoryView.SUBSYSTEM_VIEW_ID, "subsystems/alert/Alert_LOW_16.png", new ViewFactory() { public Canvas createView() { - // TODO: how do we know if the user is able to ack the alerts? right now, I hardcode false to not allow it return new SubsystemResourceAlertView( - extendLocatorId(AlertHistoryView.SUBSYSTEM_VIEW_ID.getName()), false); + extendLocatorId(AlertHistoryView.SUBSYSTEM_VIEW_ID.getName()), getGlobalPermissions().contains( + Permission.MANAGE_INVENTORY)); } });
rhq-commits@lists.fedorahosted.org