mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-25 06:58:39 +00:00
normalized line endings
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sse.gwt.adminconsole</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sse.gwt.adminconsole</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
|
||||
+458
-458
@@ -1,458 +1,458 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.logical.shared.SelectionEvent;
|
||||
import com.google.gwt.event.logical.shared.SelectionHandler;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.DockPanel;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||
import com.google.gwt.user.client.ui.TabLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.gwt.client.AbstractEntryPoint;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.ServerInfoRetriever;
|
||||
import com.sap.sse.gwt.client.panels.AbstractTabLayoutPanel;
|
||||
import com.sap.sse.gwt.client.panels.HorizontalTabLayoutPanel;
|
||||
import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel;
|
||||
import com.sap.sse.security.shared.Permission;
|
||||
import com.sap.sse.security.shared.PermissionsForRoleProvider;
|
||||
import com.sap.sse.security.shared.WildcardPermission;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.UserStatusEventHandler;
|
||||
import com.sap.sse.security.ui.loginpanel.LoginPanelCss;
|
||||
import com.sap.sse.security.ui.shared.UserDTO;
|
||||
|
||||
/**
|
||||
* A panel that can be used to implement an administration console. Widgets can be arranged in vertical and horizontal
|
||||
* tabs ("L-shape"). The top-level element is the vertical tab panel. Widgets may either be added directly as the
|
||||
* content of one vertical tab, or a horizontal tab panel can be added as the content widget of a vertical tab, in turn
|
||||
* holding widgets in horizontal tabs.
|
||||
* <p>
|
||||
*
|
||||
* After constructing an instance of this class, there are three ways for adding widgets:
|
||||
* <ul>
|
||||
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, Permission)} adds a widget as a content
|
||||
* element of a vertical tab</li>
|
||||
* <li>{@link #addVerticalTab(String, String, Permission)} creates a horizontal tab panel and adds it as a content
|
||||
* element of a vertical tab</li>
|
||||
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, Permission)} adds a widget as a
|
||||
* content element of a horizontal tab</li>
|
||||
* </ul>
|
||||
*
|
||||
* Widgets to be added need to be wrapped as {@link RefreshableAdminConsolePanel} holding the widget and receiving the
|
||||
* refresh call when the widget is shown because the user has selected the tab. If the component doesn't require any
|
||||
* refresh logic, an instance of {@link DefaultRefreshableAdminConsolePanel} can be used to wrap the widget.
|
||||
* <p>
|
||||
*
|
||||
* After the widgets have been added, {@link #initUI()} must be called to assemble all tabs for the current user's
|
||||
* roles. The {@link #initUI()} method must be called each time more widgets have been added dynamically.
|
||||
* <p>
|
||||
*
|
||||
* For each widget added, a {@link Permission set of permissions} needs to be specified, any of which is sufficient to
|
||||
* get to see the widget. When the user changes or has his/her permissions updated the set of tabs visible will be
|
||||
* adjusted according to the new roles available for the logged-in user.
|
||||
* <p>
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class AdminConsolePanel extends DockLayoutPanel implements HandleTabSelectable{
|
||||
private final UserService userService;
|
||||
|
||||
/**
|
||||
* The administration console's UI depends on the user's roles. When the roles change then so shall the display of
|
||||
* tabs. Required {@link Permission}s tell when they are to be made available based on the user's actual
|
||||
* permissions. This map keeps track of the dependencies and allows the UI to adjust to role changes.<p>
|
||||
*
|
||||
* The values are the permissions, at least one of which is required from the user to be able to see the widget.
|
||||
*/
|
||||
private final LinkedHashSet<Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>> roleSpecificTabs;
|
||||
|
||||
private final Map<Widget, Set<Permission>> permissionsAnyOfWhichIsRequiredToSeeWidget;
|
||||
|
||||
private final SelectionHandler<Integer> tabSelectionHandler;
|
||||
|
||||
/**
|
||||
* The top-level vertical tab panel
|
||||
*/
|
||||
private final VerticalTabLayoutPanel topLevelTabPanel;
|
||||
|
||||
private final VerticalOrHorizontalTabLayoutPanel topLevelTabPanelWrapper;
|
||||
|
||||
/**
|
||||
* Keys are the results of calling {@link RefreshableAdminConsolePanel#getWidget()} on their associated values. This
|
||||
* allows the panel to find the refresh target when a widget has been selected in a tab panel.
|
||||
*/
|
||||
private final Map<Widget, RefreshableAdminConsolePanel> panelsByWidget;
|
||||
|
||||
private final PermissionsForRoleProvider permissionsForRoleProvider;
|
||||
|
||||
/**
|
||||
* Generic selection handler that forwards selected tabs to a refresher that ensures that data gets reloaded. If
|
||||
* you add a new tab then make sure to have a look at #refreshDataFor(Widget widget) to ensure that upon
|
||||
* selection your tab gets the data refreshed.
|
||||
*/
|
||||
private class TabSelectionHandler implements SelectionHandler<Integer> {
|
||||
@Override
|
||||
public void onSelection(SelectionEvent<Integer> event) {
|
||||
Object source = event.getSource();
|
||||
if (source != null) {
|
||||
if (source instanceof HorizontalTabLayoutPanel) {
|
||||
final HorizontalTabLayoutPanel tabPanel = ((HorizontalTabLayoutPanel) source);
|
||||
final Widget selectedPanel = tabPanel.getWidget(event.getSelectedItem());
|
||||
refreshDataFor(selectedPanel);
|
||||
} else if (source instanceof VerticalTabLayoutPanel) {
|
||||
final VerticalTabLayoutPanel verticalTabLayoutPanel = (VerticalTabLayoutPanel) source;
|
||||
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel.getSelectedIndex());
|
||||
if (widgetAssociatedToVerticalTab instanceof HorizontalTabLayoutPanel) {
|
||||
HorizontalTabLayoutPanel selectedTabLayoutPanel = (HorizontalTabLayoutPanel) widgetAssociatedToVerticalTab;
|
||||
final int selectedIndex = selectedTabLayoutPanel.getSelectedIndex();
|
||||
if (selectedIndex >= 0) {
|
||||
widgetAssociatedToVerticalTab = selectedTabLayoutPanel.getWidget(selectedIndex);
|
||||
}
|
||||
}
|
||||
refreshDataFor(widgetAssociatedToVerticalTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshDataFor(Widget target) {
|
||||
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(unwrapScrollPanel(target));
|
||||
if (refreshTarget != null) {
|
||||
refreshTarget.refreshAfterBecomingVisible();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If the <code>widgetMaybeWrappedByScrollPanel</code> is a scroll panel, returns the content widget,
|
||||
* otherwise <code>widgetMaybeWrappedByScrollPanel</code> is returned.
|
||||
*/
|
||||
private static Widget unwrapScrollPanel(Widget widgetMaybeWrappedByScrollPanel) {
|
||||
final Widget target;
|
||||
if (widgetMaybeWrappedByScrollPanel instanceof ScrollPanel) {
|
||||
target = ((ScrollPanel) widgetMaybeWrappedByScrollPanel).getWidget();
|
||||
} else {
|
||||
target = widgetMaybeWrappedByScrollPanel;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public AdminConsolePanel(UserService userService, PermissionsForRoleProvider permissionsForRoleProvider,
|
||||
ServerInfoRetriever buildVersionRetriever, String releaseNotesAnchorLabel,
|
||||
String releaseNotesURL, ErrorReporter errorReporter, LoginPanelCss loginPanelCss, StringMessages stringMessages) {
|
||||
super(Unit.EM);
|
||||
this.permissionsForRoleProvider = permissionsForRoleProvider;
|
||||
this.permissionsAnyOfWhichIsRequiredToSeeWidget = new HashMap<>();
|
||||
this.userService = userService;
|
||||
roleSpecificTabs = new LinkedHashSet<>();
|
||||
this.panelsByWidget = new HashMap<>();
|
||||
getUserService().addUserStatusEventHandler(new UserStatusEventHandler() {
|
||||
@Override
|
||||
public void onUserStatusChange(UserDTO user) {
|
||||
updateTabDisplayForCurrentUser(user);
|
||||
}
|
||||
});
|
||||
tabSelectionHandler = new TabSelectionHandler();
|
||||
topLevelTabPanel = new VerticalTabLayoutPanel(2.5, Unit.EM);
|
||||
topLevelTabPanel.addSelectionHandler(tabSelectionHandler);
|
||||
topLevelTabPanel.ensureDebugId("AdministrationTabs");
|
||||
topLevelTabPanelWrapper = new VerticalOrHorizontalTabLayoutPanel() {
|
||||
@Override
|
||||
public void add(Widget child, String text, boolean asHtml) {
|
||||
topLevelTabPanel.add(child, text, asHtml);
|
||||
topLevelTabPanel.forceLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child) {
|
||||
return topLevelTabPanel.remove(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child, boolean fireEvents) {
|
||||
return topLevelTabPanel.remove(topLevelTabPanel.getWidgetIndex(child), fireEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getPanel() {
|
||||
return topLevelTabPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTab(int index) {
|
||||
topLevelTabPanel.selectTab(index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidgetIndex(Widget child) {
|
||||
return topLevelTabPanel.getWidgetIndex(child);
|
||||
}
|
||||
};
|
||||
final DockPanel informationPanel = new DockPanel();
|
||||
informationPanel.setSize("100%", "95%");
|
||||
informationPanel.setSpacing(10);
|
||||
informationPanel.add(errorReporter.getPersistentInformationWidget(), DockPanel.CENTER);
|
||||
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(buildVersionRetriever, errorReporter, stringMessages);
|
||||
sysinfoPanel.ensureDebugId("SystemInformation");
|
||||
final Anchor releaseNotesLink = new Anchor(new SafeHtmlBuilder().appendEscaped(releaseNotesAnchorLabel).toSafeHtml(), releaseNotesURL);
|
||||
sysinfoPanel.add(releaseNotesLink);
|
||||
informationPanel.add(sysinfoPanel, DockPanel.EAST);
|
||||
informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
this.addSouth(informationPanel, 2.5);
|
||||
this.add(topLevelTabPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke this method after having added all panels using
|
||||
* {@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
|
||||
* {@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
|
||||
* {@link #addVerticalTab(String, String, AdminConsoleFeatures)}. Tabs can also dynamically be added after calling
|
||||
* this method, but then this method needs to be invoked again to ensure that all all tabs are properly displayed
|
||||
* for the current panel's state.
|
||||
*/
|
||||
public void initUI() {
|
||||
updateTabDisplayForCurrentUser(getUserService().getCurrentUser());
|
||||
if (topLevelTabPanel.getWidgetCount() > 0) {
|
||||
topLevelTabPanel.selectTab(0);
|
||||
}
|
||||
}
|
||||
|
||||
private UserService getUserService() {
|
||||
return userService;
|
||||
}
|
||||
|
||||
private static interface VerticalOrHorizontalTabLayoutPanel {
|
||||
void add(Widget child, String text, boolean asHtml);
|
||||
|
||||
boolean remove(Widget child);
|
||||
|
||||
boolean remove(Widget child, boolean fireEvents);
|
||||
|
||||
Widget getPanel();
|
||||
|
||||
void selectTab(int index);
|
||||
|
||||
int getWidgetIndex(Widget child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new horizontal tab panel to the top-level vertical tab panel.
|
||||
*
|
||||
* @return the horizontal tab panel that was created and added to the top-level vertical tab panel; the panel returned can be specified
|
||||
* as argument to {@link #addToTabPanel(TabLayoutPanel, Widget, String, AdminConsoleFeatures)}.
|
||||
*/
|
||||
public HorizontalTabLayoutPanel addVerticalTab(String tabTitle, String tabDebugId, Permission... requiresAnyOfThesePermissions) {
|
||||
final HorizontalTabLayoutPanel newTabPanel = new HorizontalTabLayoutPanel(2.5, Unit.EM);
|
||||
AbstractEntryPoint.setTabPanelSize(newTabPanel, "100%", "100%");
|
||||
newTabPanel.addSelectionHandler(tabSelectionHandler);
|
||||
newTabPanel.ensureDebugId(tabDebugId);
|
||||
remeberWidgetLocationAndPermissions(topLevelTabPanelWrapper, newTabPanel, tabTitle, requiresAnyOfThesePermissions);
|
||||
return newTabPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an administration panel as an entry to the top-level vertical panel, without an intermediary horizontal tab panel.
|
||||
* This is useful for panels that form a top-level category of its own but don't require multiple panels to represent this
|
||||
* top-level category.
|
||||
*/
|
||||
public void addToVerticalTabPanel(final RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
addToTabPanel(topLevelTabPanelWrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
|
||||
}
|
||||
|
||||
private ScrollPanel wrapInScrollPanel(Widget panelToAdd) {
|
||||
ScrollPanel scrollPanel = new ScrollPanel();
|
||||
scrollPanel.add(panelToAdd);
|
||||
panelToAdd.setSize("100%", "100%");
|
||||
return scrollPanel;
|
||||
}
|
||||
|
||||
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
VerticalOrHorizontalTabLayoutPanel wrapper = new VerticalOrHorizontalTabLayoutPanel() {
|
||||
@Override
|
||||
public void add(Widget child, String text, boolean asHtml) {
|
||||
tabPanel.add(child, text, asHtml);
|
||||
tabPanel.forceLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child) {
|
||||
return tabPanel.remove(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child, boolean fireEvents) {
|
||||
return tabPanel.remove(tabPanel.getWidgetIndex(child), fireEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getPanel() {
|
||||
return tabPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTab(int index) {
|
||||
tabPanel.selectTab(index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidgetIndex(Widget child) {
|
||||
return tabPanel.getWidgetIndex(child);
|
||||
}
|
||||
};
|
||||
addToTabPanel(wrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers in which tab panel the <code>panelToAdd</code> is to be displayed and for which feature; additionally, remembers adds
|
||||
* a hook so that when the <code>panelToAdd</code>'s widget is selected then the {@link RefreshableAdminConsolePanel#refreshAfterBecomingVisible()}
|
||||
* method can be called.
|
||||
*/
|
||||
private void addToTabPanel(VerticalOrHorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
remeberWidgetLocationAndPermissions(tabPanel, wrapInScrollPanel(panelToAdd.getWidget()), tabTitle, requiresAnyOfThesePermissions);
|
||||
panelsByWidget.put(panelToAdd.getWidget(), panelToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the tab panel in which the <code>widgetToAdd</code> is to be displayed and which permissions are
|
||||
* sufficient to see the widget. For the <code>tabPanel</code>, all permissions provided here are added to the tab
|
||||
* panel's permissions so that the user will see the tab panel as soon as the user may see any of the widgets inside
|
||||
* that panel
|
||||
*
|
||||
* @param requiresAnyOfThesePermissions
|
||||
* zero or more permissions; if no permissions are provided, the user will never be able to see the
|
||||
* widget. Otherwise, if any of these permissions implies any of the permissions the user has, the user
|
||||
* will be shown the widget. In particular, a "*" wildcard permission will show the widget to all users,
|
||||
* regardless their actual permissions.
|
||||
*/
|
||||
private void remeberWidgetLocationAndPermissions(VerticalOrHorizontalTabLayoutPanel tabPanel, Widget widgetToAdd,
|
||||
String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
roleSpecificTabs.add(new Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>(tabPanel, widgetToAdd, tabTitle));
|
||||
final HashSet<Permission> permissionsAsSet = new HashSet<>(Arrays.asList(requiresAnyOfThesePermissions));
|
||||
permissionsAnyOfWhichIsRequiredToSeeWidget.put(widgetToAdd, permissionsAsSet);
|
||||
Set<Permission> permissionsForTabPanel = permissionsAnyOfWhichIsRequiredToSeeWidget.get(tabPanel.getPanel());
|
||||
if (permissionsForTabPanel == null) {
|
||||
permissionsForTabPanel = new HashSet<>();
|
||||
permissionsAnyOfWhichIsRequiredToSeeWidget.put(tabPanel.getPanel(), permissionsForTabPanel);
|
||||
}
|
||||
permissionsForTabPanel.addAll(permissionsAsSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* After initialization or whenever the user changes, the tab display is adjusted based on which roles are required
|
||||
* to see which tabs. See {@link #roleSpecificTabs}. A selection event is fired when the tab currently selected
|
||||
* was removed and another tab was therefore selected.
|
||||
*/
|
||||
private void updateTabDisplayForCurrentUser(UserDTO user) {
|
||||
final Widget selectedPanel = getSelectedTab(null);
|
||||
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
|
||||
final Widget widgetToAddOrRemove = e.getB();
|
||||
if (user != null && userHasPermissionsToSeeWidget(user, e.getB())) {
|
||||
if (e.getA().getWidgetIndex(widgetToAddOrRemove) == -1) {
|
||||
e.getA().add(widgetToAddOrRemove, e.getC(), /* asHtml */false);
|
||||
}
|
||||
} else {
|
||||
e.getA().remove(widgetToAddOrRemove, /* fireEvents */ false);
|
||||
}
|
||||
}
|
||||
getSelectedTab(selectedPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the top-level selected tab is a horizontal tab panel, its selected panel is returned; otherwise, the selected
|
||||
* top-level panel is returned. If no top-level panel exists or is selected, {@code null} is returned.
|
||||
*
|
||||
* @param reselectCurrentSelectionIfNotSameAsThis
|
||||
* if not {@code null}, the selected panel is {@link AbstractTabLayoutPanel#selectTab(Widget) selected}
|
||||
* again in case it isn't the same as {@code reselectCurrentSelectionIfNotSameAsThis}, firing a selection
|
||||
* event
|
||||
*/
|
||||
private Widget getSelectedTab(Widget reselectCurrentSelectionIfNotSameAsThis) {
|
||||
final Widget topLevelSelectedTab;
|
||||
Widget selectedTabInHorizontalTabPanel = null;
|
||||
if (topLevelTabPanel.getSelectedIndex() != -1) {
|
||||
topLevelSelectedTab = unwrapScrollPanel(topLevelTabPanel.getWidget(topLevelTabPanel.getSelectedIndex()));
|
||||
if (topLevelSelectedTab instanceof AbstractTabLayoutPanel) {
|
||||
AbstractTabLayoutPanel p = (AbstractTabLayoutPanel) topLevelSelectedTab;
|
||||
if (p.getSelectedIndex() != -1) {
|
||||
selectedTabInHorizontalTabPanel = unwrapScrollPanel(p.getWidget(p.getSelectedIndex()));
|
||||
if (reselectCurrentSelectionIfNotSameAsThis != null && selectedTabInHorizontalTabPanel != reselectCurrentSelectionIfNotSameAsThis) {
|
||||
SelectionEvent.fire(p, p.getSelectedIndex());
|
||||
}
|
||||
} else {
|
||||
selectedTabInHorizontalTabPanel = null;
|
||||
}
|
||||
} else {
|
||||
if (reselectCurrentSelectionIfNotSameAsThis != null && topLevelSelectedTab != reselectCurrentSelectionIfNotSameAsThis) {
|
||||
SelectionEvent.fire(topLevelTabPanel, topLevelTabPanel.getSelectedIndex());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
topLevelSelectedTab = null;
|
||||
}
|
||||
return selectedTabInHorizontalTabPanel != null ? selectedTabInHorizontalTabPanel : topLevelSelectedTab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTabByNames(String verticalTabName, String horizontalTabName, Map<String, String> params) {
|
||||
if (verticalTabName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Widget widgetForSetup = null; //Remember widget for set up
|
||||
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
|
||||
VerticalOrHorizontalTabLayoutPanel panel = e.getA();
|
||||
Widget currentWidget = e.getB();
|
||||
if (panel == topLevelTabPanelWrapper && verticalTabName.equals(e.getC())) { // for vertical panel
|
||||
int index = panel.getWidgetIndex(currentWidget);
|
||||
panel.selectTab(index);
|
||||
if (horizontalTabName == null) {//If we don't have horizontal tab will setup vertical tab.
|
||||
widgetForSetup = currentWidget;
|
||||
}
|
||||
} else if (horizontalTabName != null && horizontalTabName.equals(e.getC())) { // for horizontal panel
|
||||
int index = panel.getWidgetIndex(currentWidget);
|
||||
panel.selectTab(index);
|
||||
widgetForSetup = currentWidget;
|
||||
}
|
||||
}
|
||||
panelsByWidget.get(unwrapScrollPanel(widgetForSetup)).setupWidgetByParams(params);;
|
||||
}
|
||||
|
||||
/**
|
||||
* A user is defined to have permission to see a widget if the widget's required permissions imply any of the permissions the
|
||||
* user has. This may at first seem the wrong way around. However, the problem is that a widget cannot express a general permission
|
||||
* that is implied by any detailed permissions. Wildcard permissions don't work this way. Instead, a wildcard permission implies
|
||||
* detailed permissions. This way, if the widget requires, say, "event:*:*" (or "event" for short), this permission implies
|
||||
* all more detailed event permissions such as "event:write:9456192873". Therefore, the permissions provided for widgets
|
||||
* must imply a permission the user has in order for the user to see the tab. More detailed permissions checks can then be
|
||||
* applied at a more detailed level of the UI and, of course, in the back end. Additionally, if any of the user's permissions
|
||||
* implies the required permission (e.g., the user having "*" as the administrator's permission), permission to see the widget
|
||||
* is also implied.
|
||||
*/
|
||||
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
|
||||
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
|
||||
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
|
||||
for (String userStringPermission : user.getAllPermissions(permissionsForRoleProvider)) {
|
||||
WildcardPermission userPermission = new WildcardPermission(userStringPermission);
|
||||
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.logical.shared.SelectionEvent;
|
||||
import com.google.gwt.event.logical.shared.SelectionHandler;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.DockPanel;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||
import com.google.gwt.user.client.ui.TabLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.gwt.client.AbstractEntryPoint;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.ServerInfoRetriever;
|
||||
import com.sap.sse.gwt.client.panels.AbstractTabLayoutPanel;
|
||||
import com.sap.sse.gwt.client.panels.HorizontalTabLayoutPanel;
|
||||
import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel;
|
||||
import com.sap.sse.security.shared.Permission;
|
||||
import com.sap.sse.security.shared.PermissionsForRoleProvider;
|
||||
import com.sap.sse.security.shared.WildcardPermission;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
import com.sap.sse.security.ui.client.UserStatusEventHandler;
|
||||
import com.sap.sse.security.ui.loginpanel.LoginPanelCss;
|
||||
import com.sap.sse.security.ui.shared.UserDTO;
|
||||
|
||||
/**
|
||||
* A panel that can be used to implement an administration console. Widgets can be arranged in vertical and horizontal
|
||||
* tabs ("L-shape"). The top-level element is the vertical tab panel. Widgets may either be added directly as the
|
||||
* content of one vertical tab, or a horizontal tab panel can be added as the content widget of a vertical tab, in turn
|
||||
* holding widgets in horizontal tabs.
|
||||
* <p>
|
||||
*
|
||||
* After constructing an instance of this class, there are three ways for adding widgets:
|
||||
* <ul>
|
||||
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, Permission)} adds a widget as a content
|
||||
* element of a vertical tab</li>
|
||||
* <li>{@link #addVerticalTab(String, String, Permission)} creates a horizontal tab panel and adds it as a content
|
||||
* element of a vertical tab</li>
|
||||
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, Permission)} adds a widget as a
|
||||
* content element of a horizontal tab</li>
|
||||
* </ul>
|
||||
*
|
||||
* Widgets to be added need to be wrapped as {@link RefreshableAdminConsolePanel} holding the widget and receiving the
|
||||
* refresh call when the widget is shown because the user has selected the tab. If the component doesn't require any
|
||||
* refresh logic, an instance of {@link DefaultRefreshableAdminConsolePanel} can be used to wrap the widget.
|
||||
* <p>
|
||||
*
|
||||
* After the widgets have been added, {@link #initUI()} must be called to assemble all tabs for the current user's
|
||||
* roles. The {@link #initUI()} method must be called each time more widgets have been added dynamically.
|
||||
* <p>
|
||||
*
|
||||
* For each widget added, a {@link Permission set of permissions} needs to be specified, any of which is sufficient to
|
||||
* get to see the widget. When the user changes or has his/her permissions updated the set of tabs visible will be
|
||||
* adjusted according to the new roles available for the logged-in user.
|
||||
* <p>
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class AdminConsolePanel extends DockLayoutPanel implements HandleTabSelectable{
|
||||
private final UserService userService;
|
||||
|
||||
/**
|
||||
* The administration console's UI depends on the user's roles. When the roles change then so shall the display of
|
||||
* tabs. Required {@link Permission}s tell when they are to be made available based on the user's actual
|
||||
* permissions. This map keeps track of the dependencies and allows the UI to adjust to role changes.<p>
|
||||
*
|
||||
* The values are the permissions, at least one of which is required from the user to be able to see the widget.
|
||||
*/
|
||||
private final LinkedHashSet<Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>> roleSpecificTabs;
|
||||
|
||||
private final Map<Widget, Set<Permission>> permissionsAnyOfWhichIsRequiredToSeeWidget;
|
||||
|
||||
private final SelectionHandler<Integer> tabSelectionHandler;
|
||||
|
||||
/**
|
||||
* The top-level vertical tab panel
|
||||
*/
|
||||
private final VerticalTabLayoutPanel topLevelTabPanel;
|
||||
|
||||
private final VerticalOrHorizontalTabLayoutPanel topLevelTabPanelWrapper;
|
||||
|
||||
/**
|
||||
* Keys are the results of calling {@link RefreshableAdminConsolePanel#getWidget()} on their associated values. This
|
||||
* allows the panel to find the refresh target when a widget has been selected in a tab panel.
|
||||
*/
|
||||
private final Map<Widget, RefreshableAdminConsolePanel> panelsByWidget;
|
||||
|
||||
private final PermissionsForRoleProvider permissionsForRoleProvider;
|
||||
|
||||
/**
|
||||
* Generic selection handler that forwards selected tabs to a refresher that ensures that data gets reloaded. If
|
||||
* you add a new tab then make sure to have a look at #refreshDataFor(Widget widget) to ensure that upon
|
||||
* selection your tab gets the data refreshed.
|
||||
*/
|
||||
private class TabSelectionHandler implements SelectionHandler<Integer> {
|
||||
@Override
|
||||
public void onSelection(SelectionEvent<Integer> event) {
|
||||
Object source = event.getSource();
|
||||
if (source != null) {
|
||||
if (source instanceof HorizontalTabLayoutPanel) {
|
||||
final HorizontalTabLayoutPanel tabPanel = ((HorizontalTabLayoutPanel) source);
|
||||
final Widget selectedPanel = tabPanel.getWidget(event.getSelectedItem());
|
||||
refreshDataFor(selectedPanel);
|
||||
} else if (source instanceof VerticalTabLayoutPanel) {
|
||||
final VerticalTabLayoutPanel verticalTabLayoutPanel = (VerticalTabLayoutPanel) source;
|
||||
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel.getSelectedIndex());
|
||||
if (widgetAssociatedToVerticalTab instanceof HorizontalTabLayoutPanel) {
|
||||
HorizontalTabLayoutPanel selectedTabLayoutPanel = (HorizontalTabLayoutPanel) widgetAssociatedToVerticalTab;
|
||||
final int selectedIndex = selectedTabLayoutPanel.getSelectedIndex();
|
||||
if (selectedIndex >= 0) {
|
||||
widgetAssociatedToVerticalTab = selectedTabLayoutPanel.getWidget(selectedIndex);
|
||||
}
|
||||
}
|
||||
refreshDataFor(widgetAssociatedToVerticalTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshDataFor(Widget target) {
|
||||
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(unwrapScrollPanel(target));
|
||||
if (refreshTarget != null) {
|
||||
refreshTarget.refreshAfterBecomingVisible();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* If the <code>widgetMaybeWrappedByScrollPanel</code> is a scroll panel, returns the content widget,
|
||||
* otherwise <code>widgetMaybeWrappedByScrollPanel</code> is returned.
|
||||
*/
|
||||
private static Widget unwrapScrollPanel(Widget widgetMaybeWrappedByScrollPanel) {
|
||||
final Widget target;
|
||||
if (widgetMaybeWrappedByScrollPanel instanceof ScrollPanel) {
|
||||
target = ((ScrollPanel) widgetMaybeWrappedByScrollPanel).getWidget();
|
||||
} else {
|
||||
target = widgetMaybeWrappedByScrollPanel;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public AdminConsolePanel(UserService userService, PermissionsForRoleProvider permissionsForRoleProvider,
|
||||
ServerInfoRetriever buildVersionRetriever, String releaseNotesAnchorLabel,
|
||||
String releaseNotesURL, ErrorReporter errorReporter, LoginPanelCss loginPanelCss, StringMessages stringMessages) {
|
||||
super(Unit.EM);
|
||||
this.permissionsForRoleProvider = permissionsForRoleProvider;
|
||||
this.permissionsAnyOfWhichIsRequiredToSeeWidget = new HashMap<>();
|
||||
this.userService = userService;
|
||||
roleSpecificTabs = new LinkedHashSet<>();
|
||||
this.panelsByWidget = new HashMap<>();
|
||||
getUserService().addUserStatusEventHandler(new UserStatusEventHandler() {
|
||||
@Override
|
||||
public void onUserStatusChange(UserDTO user) {
|
||||
updateTabDisplayForCurrentUser(user);
|
||||
}
|
||||
});
|
||||
tabSelectionHandler = new TabSelectionHandler();
|
||||
topLevelTabPanel = new VerticalTabLayoutPanel(2.5, Unit.EM);
|
||||
topLevelTabPanel.addSelectionHandler(tabSelectionHandler);
|
||||
topLevelTabPanel.ensureDebugId("AdministrationTabs");
|
||||
topLevelTabPanelWrapper = new VerticalOrHorizontalTabLayoutPanel() {
|
||||
@Override
|
||||
public void add(Widget child, String text, boolean asHtml) {
|
||||
topLevelTabPanel.add(child, text, asHtml);
|
||||
topLevelTabPanel.forceLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child) {
|
||||
return topLevelTabPanel.remove(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child, boolean fireEvents) {
|
||||
return topLevelTabPanel.remove(topLevelTabPanel.getWidgetIndex(child), fireEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getPanel() {
|
||||
return topLevelTabPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTab(int index) {
|
||||
topLevelTabPanel.selectTab(index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidgetIndex(Widget child) {
|
||||
return topLevelTabPanel.getWidgetIndex(child);
|
||||
}
|
||||
};
|
||||
final DockPanel informationPanel = new DockPanel();
|
||||
informationPanel.setSize("100%", "95%");
|
||||
informationPanel.setSpacing(10);
|
||||
informationPanel.add(errorReporter.getPersistentInformationWidget(), DockPanel.CENTER);
|
||||
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(buildVersionRetriever, errorReporter, stringMessages);
|
||||
sysinfoPanel.ensureDebugId("SystemInformation");
|
||||
final Anchor releaseNotesLink = new Anchor(new SafeHtmlBuilder().appendEscaped(releaseNotesAnchorLabel).toSafeHtml(), releaseNotesURL);
|
||||
sysinfoPanel.add(releaseNotesLink);
|
||||
informationPanel.add(sysinfoPanel, DockPanel.EAST);
|
||||
informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
this.addSouth(informationPanel, 2.5);
|
||||
this.add(topLevelTabPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke this method after having added all panels using
|
||||
* {@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
|
||||
* {@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} or
|
||||
* {@link #addVerticalTab(String, String, AdminConsoleFeatures)}. Tabs can also dynamically be added after calling
|
||||
* this method, but then this method needs to be invoked again to ensure that all all tabs are properly displayed
|
||||
* for the current panel's state.
|
||||
*/
|
||||
public void initUI() {
|
||||
updateTabDisplayForCurrentUser(getUserService().getCurrentUser());
|
||||
if (topLevelTabPanel.getWidgetCount() > 0) {
|
||||
topLevelTabPanel.selectTab(0);
|
||||
}
|
||||
}
|
||||
|
||||
private UserService getUserService() {
|
||||
return userService;
|
||||
}
|
||||
|
||||
private static interface VerticalOrHorizontalTabLayoutPanel {
|
||||
void add(Widget child, String text, boolean asHtml);
|
||||
|
||||
boolean remove(Widget child);
|
||||
|
||||
boolean remove(Widget child, boolean fireEvents);
|
||||
|
||||
Widget getPanel();
|
||||
|
||||
void selectTab(int index);
|
||||
|
||||
int getWidgetIndex(Widget child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new horizontal tab panel to the top-level vertical tab panel.
|
||||
*
|
||||
* @return the horizontal tab panel that was created and added to the top-level vertical tab panel; the panel returned can be specified
|
||||
* as argument to {@link #addToTabPanel(TabLayoutPanel, Widget, String, AdminConsoleFeatures)}.
|
||||
*/
|
||||
public HorizontalTabLayoutPanel addVerticalTab(String tabTitle, String tabDebugId, Permission... requiresAnyOfThesePermissions) {
|
||||
final HorizontalTabLayoutPanel newTabPanel = new HorizontalTabLayoutPanel(2.5, Unit.EM);
|
||||
AbstractEntryPoint.setTabPanelSize(newTabPanel, "100%", "100%");
|
||||
newTabPanel.addSelectionHandler(tabSelectionHandler);
|
||||
newTabPanel.ensureDebugId(tabDebugId);
|
||||
remeberWidgetLocationAndPermissions(topLevelTabPanelWrapper, newTabPanel, tabTitle, requiresAnyOfThesePermissions);
|
||||
return newTabPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an administration panel as an entry to the top-level vertical panel, without an intermediary horizontal tab panel.
|
||||
* This is useful for panels that form a top-level category of its own but don't require multiple panels to represent this
|
||||
* top-level category.
|
||||
*/
|
||||
public void addToVerticalTabPanel(final RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
addToTabPanel(topLevelTabPanelWrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
|
||||
}
|
||||
|
||||
private ScrollPanel wrapInScrollPanel(Widget panelToAdd) {
|
||||
ScrollPanel scrollPanel = new ScrollPanel();
|
||||
scrollPanel.add(panelToAdd);
|
||||
panelToAdd.setSize("100%", "100%");
|
||||
return scrollPanel;
|
||||
}
|
||||
|
||||
public void addToTabPanel(final HorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
VerticalOrHorizontalTabLayoutPanel wrapper = new VerticalOrHorizontalTabLayoutPanel() {
|
||||
@Override
|
||||
public void add(Widget child, String text, boolean asHtml) {
|
||||
tabPanel.add(child, text, asHtml);
|
||||
tabPanel.forceLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child) {
|
||||
return tabPanel.remove(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Widget child, boolean fireEvents) {
|
||||
return tabPanel.remove(tabPanel.getWidgetIndex(child), fireEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget getPanel() {
|
||||
return tabPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTab(int index) {
|
||||
tabPanel.selectTab(index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidgetIndex(Widget child) {
|
||||
return tabPanel.getWidgetIndex(child);
|
||||
}
|
||||
};
|
||||
addToTabPanel(wrapper, panelToAdd, tabTitle, requiresAnyOfThesePermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers in which tab panel the <code>panelToAdd</code> is to be displayed and for which feature; additionally, remembers adds
|
||||
* a hook so that when the <code>panelToAdd</code>'s widget is selected then the {@link RefreshableAdminConsolePanel#refreshAfterBecomingVisible()}
|
||||
* method can be called.
|
||||
*/
|
||||
private void addToTabPanel(VerticalOrHorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
remeberWidgetLocationAndPermissions(tabPanel, wrapInScrollPanel(panelToAdd.getWidget()), tabTitle, requiresAnyOfThesePermissions);
|
||||
panelsByWidget.put(panelToAdd.getWidget(), panelToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remembers the tab panel in which the <code>widgetToAdd</code> is to be displayed and which permissions are
|
||||
* sufficient to see the widget. For the <code>tabPanel</code>, all permissions provided here are added to the tab
|
||||
* panel's permissions so that the user will see the tab panel as soon as the user may see any of the widgets inside
|
||||
* that panel
|
||||
*
|
||||
* @param requiresAnyOfThesePermissions
|
||||
* zero or more permissions; if no permissions are provided, the user will never be able to see the
|
||||
* widget. Otherwise, if any of these permissions implies any of the permissions the user has, the user
|
||||
* will be shown the widget. In particular, a "*" wildcard permission will show the widget to all users,
|
||||
* regardless their actual permissions.
|
||||
*/
|
||||
private void remeberWidgetLocationAndPermissions(VerticalOrHorizontalTabLayoutPanel tabPanel, Widget widgetToAdd,
|
||||
String tabTitle, Permission... requiresAnyOfThesePermissions) {
|
||||
roleSpecificTabs.add(new Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>(tabPanel, widgetToAdd, tabTitle));
|
||||
final HashSet<Permission> permissionsAsSet = new HashSet<>(Arrays.asList(requiresAnyOfThesePermissions));
|
||||
permissionsAnyOfWhichIsRequiredToSeeWidget.put(widgetToAdd, permissionsAsSet);
|
||||
Set<Permission> permissionsForTabPanel = permissionsAnyOfWhichIsRequiredToSeeWidget.get(tabPanel.getPanel());
|
||||
if (permissionsForTabPanel == null) {
|
||||
permissionsForTabPanel = new HashSet<>();
|
||||
permissionsAnyOfWhichIsRequiredToSeeWidget.put(tabPanel.getPanel(), permissionsForTabPanel);
|
||||
}
|
||||
permissionsForTabPanel.addAll(permissionsAsSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* After initialization or whenever the user changes, the tab display is adjusted based on which roles are required
|
||||
* to see which tabs. See {@link #roleSpecificTabs}. A selection event is fired when the tab currently selected
|
||||
* was removed and another tab was therefore selected.
|
||||
*/
|
||||
private void updateTabDisplayForCurrentUser(UserDTO user) {
|
||||
final Widget selectedPanel = getSelectedTab(null);
|
||||
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
|
||||
final Widget widgetToAddOrRemove = e.getB();
|
||||
if (user != null && userHasPermissionsToSeeWidget(user, e.getB())) {
|
||||
if (e.getA().getWidgetIndex(widgetToAddOrRemove) == -1) {
|
||||
e.getA().add(widgetToAddOrRemove, e.getC(), /* asHtml */false);
|
||||
}
|
||||
} else {
|
||||
e.getA().remove(widgetToAddOrRemove, /* fireEvents */ false);
|
||||
}
|
||||
}
|
||||
getSelectedTab(selectedPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the top-level selected tab is a horizontal tab panel, its selected panel is returned; otherwise, the selected
|
||||
* top-level panel is returned. If no top-level panel exists or is selected, {@code null} is returned.
|
||||
*
|
||||
* @param reselectCurrentSelectionIfNotSameAsThis
|
||||
* if not {@code null}, the selected panel is {@link AbstractTabLayoutPanel#selectTab(Widget) selected}
|
||||
* again in case it isn't the same as {@code reselectCurrentSelectionIfNotSameAsThis}, firing a selection
|
||||
* event
|
||||
*/
|
||||
private Widget getSelectedTab(Widget reselectCurrentSelectionIfNotSameAsThis) {
|
||||
final Widget topLevelSelectedTab;
|
||||
Widget selectedTabInHorizontalTabPanel = null;
|
||||
if (topLevelTabPanel.getSelectedIndex() != -1) {
|
||||
topLevelSelectedTab = unwrapScrollPanel(topLevelTabPanel.getWidget(topLevelTabPanel.getSelectedIndex()));
|
||||
if (topLevelSelectedTab instanceof AbstractTabLayoutPanel) {
|
||||
AbstractTabLayoutPanel p = (AbstractTabLayoutPanel) topLevelSelectedTab;
|
||||
if (p.getSelectedIndex() != -1) {
|
||||
selectedTabInHorizontalTabPanel = unwrapScrollPanel(p.getWidget(p.getSelectedIndex()));
|
||||
if (reselectCurrentSelectionIfNotSameAsThis != null && selectedTabInHorizontalTabPanel != reselectCurrentSelectionIfNotSameAsThis) {
|
||||
SelectionEvent.fire(p, p.getSelectedIndex());
|
||||
}
|
||||
} else {
|
||||
selectedTabInHorizontalTabPanel = null;
|
||||
}
|
||||
} else {
|
||||
if (reselectCurrentSelectionIfNotSameAsThis != null && topLevelSelectedTab != reselectCurrentSelectionIfNotSameAsThis) {
|
||||
SelectionEvent.fire(topLevelTabPanel, topLevelTabPanel.getSelectedIndex());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
topLevelSelectedTab = null;
|
||||
}
|
||||
return selectedTabInHorizontalTabPanel != null ? selectedTabInHorizontalTabPanel : topLevelSelectedTab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectTabByNames(String verticalTabName, String horizontalTabName, Map<String, String> params) {
|
||||
if (verticalTabName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Widget widgetForSetup = null; //Remember widget for set up
|
||||
for (Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String> e : roleSpecificTabs) {
|
||||
VerticalOrHorizontalTabLayoutPanel panel = e.getA();
|
||||
Widget currentWidget = e.getB();
|
||||
if (panel == topLevelTabPanelWrapper && verticalTabName.equals(e.getC())) { // for vertical panel
|
||||
int index = panel.getWidgetIndex(currentWidget);
|
||||
panel.selectTab(index);
|
||||
if (horizontalTabName == null) {//If we don't have horizontal tab will setup vertical tab.
|
||||
widgetForSetup = currentWidget;
|
||||
}
|
||||
} else if (horizontalTabName != null && horizontalTabName.equals(e.getC())) { // for horizontal panel
|
||||
int index = panel.getWidgetIndex(currentWidget);
|
||||
panel.selectTab(index);
|
||||
widgetForSetup = currentWidget;
|
||||
}
|
||||
}
|
||||
panelsByWidget.get(unwrapScrollPanel(widgetForSetup)).setupWidgetByParams(params);;
|
||||
}
|
||||
|
||||
/**
|
||||
* A user is defined to have permission to see a widget if the widget's required permissions imply any of the permissions the
|
||||
* user has. This may at first seem the wrong way around. However, the problem is that a widget cannot express a general permission
|
||||
* that is implied by any detailed permissions. Wildcard permissions don't work this way. Instead, a wildcard permission implies
|
||||
* detailed permissions. This way, if the widget requires, say, "event:*:*" (or "event" for short), this permission implies
|
||||
* all more detailed event permissions such as "event:write:9456192873". Therefore, the permissions provided for widgets
|
||||
* must imply a permission the user has in order for the user to see the tab. More detailed permissions checks can then be
|
||||
* applied at a more detailed level of the UI and, of course, in the back end. Additionally, if any of the user's permissions
|
||||
* implies the required permission (e.g., the user having "*" as the administrator's permission), permission to see the widget
|
||||
* is also implied.
|
||||
*/
|
||||
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
|
||||
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
|
||||
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
|
||||
for (String userStringPermission : user.getAllPermissions(permissionsForRoleProvider)) {
|
||||
WildcardPermission userPermission = new WildcardPermission(userStringPermission);
|
||||
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-26
@@ -1,26 +1,26 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public class DefaultRefreshableAdminConsolePanel<W extends Widget> implements RefreshableAdminConsolePanel {
|
||||
@Override
|
||||
public void refreshAfterBecomingVisible() {
|
||||
}
|
||||
|
||||
private final W widget;
|
||||
|
||||
public DefaultRefreshableAdminConsolePanel(W widget) {
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupWidgetByParams(Map<String, String> params){
|
||||
}
|
||||
|
||||
@Override
|
||||
public W getWidget() {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public class DefaultRefreshableAdminConsolePanel<W extends Widget> implements RefreshableAdminConsolePanel {
|
||||
@Override
|
||||
public void refreshAfterBecomingVisible() {
|
||||
}
|
||||
|
||||
private final W widget;
|
||||
|
||||
public DefaultRefreshableAdminConsolePanel(W widget) {
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupWidgetByParams(Map<String, String> params){
|
||||
}
|
||||
|
||||
@Override
|
||||
public W getWidget() {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
|
||||
+23
-23
@@ -1,23 +1,23 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public interface RefreshableAdminConsolePanel {
|
||||
/**
|
||||
* Invoked when the {@link #getWidget widget} has become visible, e.g., by the user
|
||||
* selecting the tab holding the panel.
|
||||
*/
|
||||
void refreshAfterBecomingVisible();
|
||||
|
||||
/**
|
||||
* The widget representing the panel to place in the administration console
|
||||
*/
|
||||
Widget getWidget();
|
||||
|
||||
/**
|
||||
* Invoked when the we handle selected tab by name {@link HandleTabSelectable} to set up a tab with parameters.
|
||||
*/
|
||||
void setupWidgetByParams(Map<String, String> params);
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
public interface RefreshableAdminConsolePanel {
|
||||
/**
|
||||
* Invoked when the {@link #getWidget widget} has become visible, e.g., by the user
|
||||
* selecting the tab holding the panel.
|
||||
*/
|
||||
void refreshAfterBecomingVisible();
|
||||
|
||||
/**
|
||||
* The widget representing the panel to place in the administration console
|
||||
*/
|
||||
Widget getWidget();
|
||||
|
||||
/**
|
||||
* Invoked when the we handle selected tab by name {@link HandleTabSelectable} to set up a tab with parameters.
|
||||
*/
|
||||
void setupWidgetByParams(Map<String, String> params);
|
||||
}
|
||||
|
||||
+96
-96
@@ -1,96 +1,96 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
public interface StringMessages extends Messages {
|
||||
String upload();
|
||||
|
||||
String remove();
|
||||
|
||||
String removeResult(String status, String message);
|
||||
|
||||
String uploadSuccessful();
|
||||
|
||||
String fileUploadResult(String status, String message);
|
||||
|
||||
String removeUploadedFile();
|
||||
|
||||
String pleaseOnlyUploadContentYouHaveAllUsageRightsFor();
|
||||
|
||||
String send();
|
||||
|
||||
String version(String buildVersion);
|
||||
|
||||
String unknown();
|
||||
|
||||
String refresh();
|
||||
|
||||
String explainReplicasRegistered();
|
||||
|
||||
String explainConnectionsToMaster();
|
||||
|
||||
String stopAllReplicas();
|
||||
|
||||
String connectToMaster();
|
||||
|
||||
String stopConnectionToMaster();
|
||||
|
||||
String errorStartingReplication(String b, String c, String message);
|
||||
|
||||
String loading();
|
||||
|
||||
String registeredAt(String string);
|
||||
|
||||
String dropReplicaConnection();
|
||||
|
||||
String replicables();
|
||||
|
||||
String averageNumberOfOperationsPerMessage();
|
||||
|
||||
String numberOfQueueMessagesSent();
|
||||
|
||||
String averageMessageSize();
|
||||
|
||||
String totalSize();
|
||||
|
||||
String totalNumberOfOperations();
|
||||
|
||||
String explainNoConnectionsFromReplicas();
|
||||
|
||||
String warningServerIsReplica();
|
||||
|
||||
String replicatingFromMaster(String hostname, int messagingPort, int servletPort, String messagingHostname,
|
||||
String exchangeName, String string);
|
||||
|
||||
String explainNoConnectionsToMaster();
|
||||
|
||||
String errorFetchingReplicaData(String message);
|
||||
|
||||
String connect();
|
||||
|
||||
String enterMaster();
|
||||
|
||||
String cancel();
|
||||
|
||||
String hostname();
|
||||
|
||||
String explainReplicationHostname();
|
||||
|
||||
String exchangeHost();
|
||||
|
||||
String explainExchangeHostName();
|
||||
|
||||
String exchangeName();
|
||||
|
||||
String explainReplicationExchangeName();
|
||||
|
||||
String messagingPortNumber();
|
||||
|
||||
String explainReplicationExchangePort();
|
||||
|
||||
String servletPortNumber();
|
||||
|
||||
String explainReplicationServletPort();
|
||||
|
||||
String ok();
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
public interface StringMessages extends Messages {
|
||||
String upload();
|
||||
|
||||
String remove();
|
||||
|
||||
String removeResult(String status, String message);
|
||||
|
||||
String uploadSuccessful();
|
||||
|
||||
String fileUploadResult(String status, String message);
|
||||
|
||||
String removeUploadedFile();
|
||||
|
||||
String pleaseOnlyUploadContentYouHaveAllUsageRightsFor();
|
||||
|
||||
String send();
|
||||
|
||||
String version(String buildVersion);
|
||||
|
||||
String unknown();
|
||||
|
||||
String refresh();
|
||||
|
||||
String explainReplicasRegistered();
|
||||
|
||||
String explainConnectionsToMaster();
|
||||
|
||||
String stopAllReplicas();
|
||||
|
||||
String connectToMaster();
|
||||
|
||||
String stopConnectionToMaster();
|
||||
|
||||
String errorStartingReplication(String b, String c, String message);
|
||||
|
||||
String loading();
|
||||
|
||||
String registeredAt(String string);
|
||||
|
||||
String dropReplicaConnection();
|
||||
|
||||
String replicables();
|
||||
|
||||
String averageNumberOfOperationsPerMessage();
|
||||
|
||||
String numberOfQueueMessagesSent();
|
||||
|
||||
String averageMessageSize();
|
||||
|
||||
String totalSize();
|
||||
|
||||
String totalNumberOfOperations();
|
||||
|
||||
String explainNoConnectionsFromReplicas();
|
||||
|
||||
String warningServerIsReplica();
|
||||
|
||||
String replicatingFromMaster(String hostname, int messagingPort, int servletPort, String messagingHostname,
|
||||
String exchangeName, String string);
|
||||
|
||||
String explainNoConnectionsToMaster();
|
||||
|
||||
String errorFetchingReplicaData(String message);
|
||||
|
||||
String connect();
|
||||
|
||||
String enterMaster();
|
||||
|
||||
String cancel();
|
||||
|
||||
String hostname();
|
||||
|
||||
String explainReplicationHostname();
|
||||
|
||||
String exchangeHost();
|
||||
|
||||
String explainExchangeHostName();
|
||||
|
||||
String exchangeName();
|
||||
|
||||
String explainReplicationExchangeName();
|
||||
|
||||
String messagingPortNumber();
|
||||
|
||||
String explainReplicationExchangePort();
|
||||
|
||||
String servletPortNumber();
|
||||
|
||||
String explainReplicationServletPort();
|
||||
|
||||
String ok();
|
||||
}
|
||||
|
||||
+37
-37
@@ -1,37 +1,37 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.dom.client.Style;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.ServerInfoDTO;
|
||||
import com.sap.sse.gwt.client.ServerInfoRetriever;
|
||||
|
||||
public class SystemInformationPanel extends FlowPanel {
|
||||
|
||||
private final Label buildVersionText;
|
||||
|
||||
public SystemInformationPanel(final ServerInfoRetriever buildVersionRetriever, final ErrorReporter errorReporter, final StringMessages stringMessages) {
|
||||
super();
|
||||
buildVersionText = new Label("");
|
||||
addFloatingWidget(buildVersionText);
|
||||
buildVersionRetriever.getServerInfo(new AsyncCallback<ServerInfoDTO>() {
|
||||
@Override
|
||||
public void onSuccess(ServerInfoDTO result) {
|
||||
buildVersionText.setText(stringMessages.version(result.getBuildVersion()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
buildVersionText.setText(stringMessages.version(stringMessages.unknown()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addFloatingWidget(Widget w) {
|
||||
w.getElement().getStyle().setFloat(Style.Float.LEFT);
|
||||
add(w);
|
||||
}
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.dom.client.Style;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.ServerInfoDTO;
|
||||
import com.sap.sse.gwt.client.ServerInfoRetriever;
|
||||
|
||||
public class SystemInformationPanel extends FlowPanel {
|
||||
|
||||
private final Label buildVersionText;
|
||||
|
||||
public SystemInformationPanel(final ServerInfoRetriever buildVersionRetriever, final ErrorReporter errorReporter, final StringMessages stringMessages) {
|
||||
super();
|
||||
buildVersionText = new Label("");
|
||||
addFloatingWidget(buildVersionText);
|
||||
buildVersionRetriever.getServerInfo(new AsyncCallback<ServerInfoDTO>() {
|
||||
@Override
|
||||
public void onSuccess(ServerInfoDTO result) {
|
||||
buildVersionText.setText(stringMessages.version(result.getBuildVersion()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
buildVersionText.setText(stringMessages.version(stringMessages.unknown()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addFloatingWidget(Widget w) {
|
||||
w.getElement().getStyle().setFloat(Style.Float.LEFT);
|
||||
add(w);
|
||||
}
|
||||
}
|
||||
|
||||
+200
-200
@@ -1,200 +1,200 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.dom.client.InputElement;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.google.gwt.json.client.JSONParser;
|
||||
import com.google.gwt.json.client.JSONValue;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FileUpload;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
|
||||
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
|
||||
import com.google.gwt.user.client.ui.HasValue;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SubmitButton;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
|
||||
/**
|
||||
* A {@link TextBox} together with an upload button that can use the file storage service to
|
||||
* save the file and produce a URL for it which is then taken over into the text field.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class URLFieldWithFileUpload extends Composite implements HasValue<String> {
|
||||
private final TextBox urlTextBox;
|
||||
|
||||
private final FileUpload fileUploadField;
|
||||
|
||||
private String uri;
|
||||
|
||||
private final Button removeButton;
|
||||
|
||||
private boolean valueChangeHandlerInitialized = false;
|
||||
|
||||
public URLFieldWithFileUpload(final StringMessages stringMessages) {
|
||||
final VerticalPanel mainPanel = new VerticalPanel();
|
||||
final HorizontalPanel imageUrlPanel = new HorizontalPanel();
|
||||
mainPanel.add(new Label(stringMessages.pleaseOnlyUploadContentYouHaveAllUsageRightsFor()));
|
||||
mainPanel.add(imageUrlPanel);
|
||||
|
||||
final FormPanel removePanel = new FormPanel();
|
||||
removePanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
|
||||
@Override
|
||||
public void onSubmitComplete(SubmitCompleteEvent event) {
|
||||
final JSONObject resultJson = parseAfterReplacingSurroundingPreElement(event.getResults()).isObject();
|
||||
Window.alert(stringMessages.removeResult(resultJson.get("status").isString().stringValue(),
|
||||
resultJson.get("message") == null ? "" : resultJson.get("message").isString().stringValue()));
|
||||
setURL("");
|
||||
}
|
||||
});
|
||||
removePanel.setMethod(FormPanel.METHOD_POST);
|
||||
removeButton = new Button(stringMessages.removeUploadedFile());
|
||||
removeButton.setEnabled(false); // the button shall only be enabled as long as we know the URI for removal
|
||||
removeButton.ensureDebugId("RemoveButton");
|
||||
removeButton.setTitle(stringMessages.remove());
|
||||
removeButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
removePanel.setAction("/sailingserver/api/v1/file?uri="+uri);
|
||||
removePanel.submit();
|
||||
uri = null;
|
||||
}
|
||||
});
|
||||
removePanel.add(removeButton);
|
||||
urlTextBox = new TextBox();
|
||||
urlTextBox.setWidth("400px");
|
||||
imageUrlPanel.add(urlTextBox);
|
||||
imageUrlPanel.add(removePanel);
|
||||
|
||||
// the upload panel
|
||||
FormPanel uploadFormPanel = new FormPanel();
|
||||
mainPanel.add(uploadFormPanel);
|
||||
HorizontalPanel uploadPanel = new HorizontalPanel();
|
||||
uploadPanel.setSpacing(3);
|
||||
uploadFormPanel.add(uploadPanel);
|
||||
uploadFormPanel.setAction("/sailingserver/fileupload");
|
||||
uploadFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
|
||||
uploadFormPanel.setMethod(FormPanel.METHOD_POST);
|
||||
fileUploadField = new FileUpload();
|
||||
final Label uploadLabel = new Label(stringMessages.upload()+ ":");
|
||||
uploadPanel.add(uploadLabel);
|
||||
uploadPanel.setCellVerticalAlignment(uploadLabel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
uploadPanel.add(fileUploadField);
|
||||
final InputElement inputElement = fileUploadField.getElement().cast();
|
||||
inputElement.setName("file");
|
||||
final SubmitButton submitButton = new SubmitButton(stringMessages.send());
|
||||
submitButton.setEnabled(false);
|
||||
fileUploadField.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
if(fileUploadField.getFilename() != null && !fileUploadField.getFilename().isEmpty()) {
|
||||
submitButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
uploadPanel.add(submitButton);
|
||||
uploadFormPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
|
||||
@Override
|
||||
public void onSubmitComplete(SubmitCompleteEvent event) {
|
||||
String result = event.getResults();
|
||||
JSONArray resultJson = parseAfterReplacingSurroundingPreElement(result).isArray();
|
||||
if (resultJson != null) {
|
||||
if (resultJson.get(0).isObject().get("file_uri") != null) {
|
||||
uri = resultJson.get(0).isObject().get("file_uri").isString().stringValue();
|
||||
setValue(uri, true);
|
||||
removeButton.setEnabled(true);
|
||||
Window.alert(stringMessages.uploadSuccessful());
|
||||
} else {
|
||||
Window.alert(stringMessages.fileUploadResult(resultJson.get(0).isObject().get("status").isString().stringValue(),
|
||||
resultJson.get(0).isObject().get("message").isString().stringValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
initWidget(mainPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if the trimmed URL field contents are empty
|
||||
*/
|
||||
public String getURL() {
|
||||
final String trimmedUrl = urlTextBox.getValue().trim();
|
||||
return trimmedUrl.isEmpty() ? null : trimmedUrl;
|
||||
}
|
||||
|
||||
public void setURL(String imageURL) {
|
||||
if (imageURL == null) {
|
||||
urlTextBox.setValue("");
|
||||
uri = null;
|
||||
removeButton.setEnabled(false);
|
||||
} else {
|
||||
urlTextBox.setValue(imageURL);
|
||||
uri = imageURL;
|
||||
removeButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public FocusWidget getInitialFocusWidget() {
|
||||
return urlTextBox;
|
||||
}
|
||||
|
||||
private HandlerRegistration addChangeHandler(ChangeHandler handler) {
|
||||
return addDomHandler(handler, ChangeEvent.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
|
||||
if (!valueChangeHandlerInitialized) {
|
||||
valueChangeHandlerInitialized = true;
|
||||
addChangeHandler(new ChangeHandler() {
|
||||
public void onChange(ChangeEvent event) {
|
||||
ValueChangeEvent.fire(URLFieldWithFileUpload.this, getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
return addHandler(handler, ValueChangeEvent.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return getURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
setURL(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value, boolean fireEvents) {
|
||||
setValue(value);
|
||||
if (fireEvents) {
|
||||
ValueChangeEvent.fire(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://github.com/twilson63/ngUpload/issues/43 and
|
||||
* https://www.sencha.com/forum/showthread.php?132949-Fileupload-Invalid-JSON-string. The JSON response of the file
|
||||
* upload is wrapped by a <pre> element which needs to be stripped off if present to allow the JSON parser to
|
||||
* succeed.
|
||||
*/
|
||||
private JSONValue parseAfterReplacingSurroundingPreElement(String jsonString) {
|
||||
return JSONParser.parseStrict(jsonString.replaceFirst("<pre[^>]*>(.*)</pre>", "$1"));
|
||||
}
|
||||
}
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
|
||||
import com.google.gwt.dom.client.InputElement;
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.json.client.JSONArray;
|
||||
import com.google.gwt.json.client.JSONObject;
|
||||
import com.google.gwt.json.client.JSONParser;
|
||||
import com.google.gwt.json.client.JSONValue;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FileUpload;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.FormPanel;
|
||||
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
|
||||
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
|
||||
import com.google.gwt.user.client.ui.HasValue;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SubmitButton;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
|
||||
/**
|
||||
* A {@link TextBox} together with an upload button that can use the file storage service to
|
||||
* save the file and produce a URL for it which is then taken over into the text field.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class URLFieldWithFileUpload extends Composite implements HasValue<String> {
|
||||
private final TextBox urlTextBox;
|
||||
|
||||
private final FileUpload fileUploadField;
|
||||
|
||||
private String uri;
|
||||
|
||||
private final Button removeButton;
|
||||
|
||||
private boolean valueChangeHandlerInitialized = false;
|
||||
|
||||
public URLFieldWithFileUpload(final StringMessages stringMessages) {
|
||||
final VerticalPanel mainPanel = new VerticalPanel();
|
||||
final HorizontalPanel imageUrlPanel = new HorizontalPanel();
|
||||
mainPanel.add(new Label(stringMessages.pleaseOnlyUploadContentYouHaveAllUsageRightsFor()));
|
||||
mainPanel.add(imageUrlPanel);
|
||||
|
||||
final FormPanel removePanel = new FormPanel();
|
||||
removePanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
|
||||
@Override
|
||||
public void onSubmitComplete(SubmitCompleteEvent event) {
|
||||
final JSONObject resultJson = parseAfterReplacingSurroundingPreElement(event.getResults()).isObject();
|
||||
Window.alert(stringMessages.removeResult(resultJson.get("status").isString().stringValue(),
|
||||
resultJson.get("message") == null ? "" : resultJson.get("message").isString().stringValue()));
|
||||
setURL("");
|
||||
}
|
||||
});
|
||||
removePanel.setMethod(FormPanel.METHOD_POST);
|
||||
removeButton = new Button(stringMessages.removeUploadedFile());
|
||||
removeButton.setEnabled(false); // the button shall only be enabled as long as we know the URI for removal
|
||||
removeButton.ensureDebugId("RemoveButton");
|
||||
removeButton.setTitle(stringMessages.remove());
|
||||
removeButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
removePanel.setAction("/sailingserver/api/v1/file?uri="+uri);
|
||||
removePanel.submit();
|
||||
uri = null;
|
||||
}
|
||||
});
|
||||
removePanel.add(removeButton);
|
||||
urlTextBox = new TextBox();
|
||||
urlTextBox.setWidth("400px");
|
||||
imageUrlPanel.add(urlTextBox);
|
||||
imageUrlPanel.add(removePanel);
|
||||
|
||||
// the upload panel
|
||||
FormPanel uploadFormPanel = new FormPanel();
|
||||
mainPanel.add(uploadFormPanel);
|
||||
HorizontalPanel uploadPanel = new HorizontalPanel();
|
||||
uploadPanel.setSpacing(3);
|
||||
uploadFormPanel.add(uploadPanel);
|
||||
uploadFormPanel.setAction("/sailingserver/fileupload");
|
||||
uploadFormPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
|
||||
uploadFormPanel.setMethod(FormPanel.METHOD_POST);
|
||||
fileUploadField = new FileUpload();
|
||||
final Label uploadLabel = new Label(stringMessages.upload()+ ":");
|
||||
uploadPanel.add(uploadLabel);
|
||||
uploadPanel.setCellVerticalAlignment(uploadLabel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
uploadPanel.add(fileUploadField);
|
||||
final InputElement inputElement = fileUploadField.getElement().cast();
|
||||
inputElement.setName("file");
|
||||
final SubmitButton submitButton = new SubmitButton(stringMessages.send());
|
||||
submitButton.setEnabled(false);
|
||||
fileUploadField.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
if(fileUploadField.getFilename() != null && !fileUploadField.getFilename().isEmpty()) {
|
||||
submitButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
uploadPanel.add(submitButton);
|
||||
uploadFormPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
|
||||
@Override
|
||||
public void onSubmitComplete(SubmitCompleteEvent event) {
|
||||
String result = event.getResults();
|
||||
JSONArray resultJson = parseAfterReplacingSurroundingPreElement(result).isArray();
|
||||
if (resultJson != null) {
|
||||
if (resultJson.get(0).isObject().get("file_uri") != null) {
|
||||
uri = resultJson.get(0).isObject().get("file_uri").isString().stringValue();
|
||||
setValue(uri, true);
|
||||
removeButton.setEnabled(true);
|
||||
Window.alert(stringMessages.uploadSuccessful());
|
||||
} else {
|
||||
Window.alert(stringMessages.fileUploadResult(resultJson.get(0).isObject().get("status").isString().stringValue(),
|
||||
resultJson.get(0).isObject().get("message").isString().stringValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
initWidget(mainPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if the trimmed URL field contents are empty
|
||||
*/
|
||||
public String getURL() {
|
||||
final String trimmedUrl = urlTextBox.getValue().trim();
|
||||
return trimmedUrl.isEmpty() ? null : trimmedUrl;
|
||||
}
|
||||
|
||||
public void setURL(String imageURL) {
|
||||
if (imageURL == null) {
|
||||
urlTextBox.setValue("");
|
||||
uri = null;
|
||||
removeButton.setEnabled(false);
|
||||
} else {
|
||||
urlTextBox.setValue(imageURL);
|
||||
uri = imageURL;
|
||||
removeButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public FocusWidget getInitialFocusWidget() {
|
||||
return urlTextBox;
|
||||
}
|
||||
|
||||
private HandlerRegistration addChangeHandler(ChangeHandler handler) {
|
||||
return addDomHandler(handler, ChangeEvent.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
|
||||
if (!valueChangeHandlerInitialized) {
|
||||
valueChangeHandlerInitialized = true;
|
||||
addChangeHandler(new ChangeHandler() {
|
||||
public void onChange(ChangeEvent event) {
|
||||
ValueChangeEvent.fire(URLFieldWithFileUpload.this, getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
return addHandler(handler, ValueChangeEvent.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return getURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
setURL(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value, boolean fireEvents) {
|
||||
setValue(value);
|
||||
if (fireEvents) {
|
||||
ValueChangeEvent.fire(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://github.com/twilson63/ngUpload/issues/43 and
|
||||
* https://www.sencha.com/forum/showthread.php?132949-Fileupload-Invalid-JSON-string. The JSON response of the file
|
||||
* upload is wrapped by a <pre> element which needs to be stripped off if present to allow the JSON parser to
|
||||
* succeed.
|
||||
*/
|
||||
private JSONValue parseAfterReplacingSurroundingPreElement(String jsonString) {
|
||||
return JSONParser.parseStrict(jsonString.replaceFirst("<pre[^>]*>(.*)</pre>", "$1"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user