HomePresenter.java
/*
** Module : HomePresenter.java
** Abstract : HomePresenter is a main presenter.
**
** Copyright (c) 2017, Golden Code Development Corporation.
**
** -#- -I- --Date-- ----------------Description----------------------
** 001 HC 20170228 Created initial version.
** 002 EVL 20170926 Javadoc fixes.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.admin.client.application.home;
import java.util.*;
import java.util.function.Consumer;
import java.util.logging.Level;
import com.goldencode.p2j.admin.*;
import com.goldencode.p2j.admin.client.*;
import com.goldencode.p2j.admin.client.application.*;
import com.goldencode.p2j.admin.client.application.PrintingContext.PreviewDialogParameters;
import com.goldencode.p2j.admin.client.application.PrintingContext.Range;
import com.goldencode.p2j.admin.client.application.home.accounts.AccountType;
import com.goldencode.p2j.admin.client.widget.dialog.*;
import com.goldencode.p2j.admin.shared.*;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.*;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import com.google.inject.*;
import com.google.web.bindery.event.shared.*;
import com.gwtplatform.mvp.client.*;
import com.gwtplatform.mvp.client.annotations.*;
import com.gwtplatform.mvp.client.presenter.slots.*;
import com.gwtplatform.mvp.client.proxy.*;
import com.gwtplatform.mvp.shared.proxy.*;
/**
* Home presenter.
*/
public class HomePresenter
extends BasePresenter<HomePresenter.MyView, HomePresenter.MyProxy>
implements MenuService
{
/**
* Presenter's view.
*/
interface MyView
extends View
{
/**
* Returns the modal widget parent.
*
* @return See above.
*/
HasWidgets getModalParent();
}
/**
* The presenter's proxy.
*/
@ProxyStandard
@NameToken(NameTokens.HOME)
interface MyProxy
extends ProxyPlace<HomePresenter>
{
}
/** Menu slot */
public static final PermanentSlot<MenuPresenter> SLOT_MENU = new PermanentSlot<>();
/** Content slot */
public static final NestedSlot SLOT_CONTENT = new NestedSlot();
/** Callback called at the time the menu needs to be initialized */
private static MenuSetupCallback menuSetupCallback;
/** Flag that is set to true when the menu is built */
private static boolean menuBuilt = false;
/** Menu presenter */
private MenuPresenter menu;
/** Input dialog provider */
private Provider<InputDialog> inputDialog;
/** Admin service reference */
private AdminServiceAsync adm;
/** Alarm service reference */
private Alarm alarm;
/** Modal dialogs */
private ModalDialogs modalDialogs;
/** Place token formatter reference */
private TokenFormatter tokenFormatter;
/**
* Ctor.
*
* @param eventBus
* Event bus reference.
* @param view
* Presenter's view.
* @param proxy
* Presenter's proxy.
* @param menu
* Menu presenter.
* @param inputDialog
* Input dialog presenter.
* @param adm
* Admin service reference.
* @param alarm
* Alarm service reference.
* @param modalDialogs
* Modal dialogs.
* @param placeManager
* Place manager reference.
* @param tokenFormatter
* Token formatter reference.
*/
@Inject
HomePresenter(EventBus eventBus,
MyView view,
MyProxy proxy,
MenuPresenter menu,
Provider<InputDialog> inputDialog,
AdminServiceAsync adm,
Alarm alarm,
ModalDialogs modalDialogs,
PlaceManager placeManager,
TokenFormatter tokenFormatter)
{
super(eventBus, view, proxy, ApplicationPresenter.SLOT_MAIN, placeManager);
this.menu = menu;
this.inputDialog = inputDialog;
this.adm = adm;
this.alarm = alarm;
this.modalDialogs = modalDialogs;
this.tokenFormatter = tokenFormatter;
}
/**
* Sets the menu setup callback.
*
* @param callback
* An instance of {@link MenuSetupCallback}.
*/
public static void registerMenuSetupCallback(MenuSetupCallback callback)
{
menuSetupCallback = callback;
}
/**
* Adds menu entry into the main menu at the specified position.
*
* @param position
* The position where the new menu entry will be added.
* @param menuDef
* The new menu entry.
*/
@Override
public void addMenu(StandardMenu position, MenuDef menuDef)
{
Document doc = Document.get();
Element menu = doc.getElementById(position.getId()).getParentElement();
Element menuParent = menu.getParentElement();
LIElement newMenu = doc.createLIElement();
StringBuilder sb = new StringBuilder();
sb.append("<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">");
sb.append(menuDef.label);
sb.append("<b class=\"caret\"></b></a>");
sb.append("<ul class=\"dropdown-menu multi-level\">");
if (menuDef.subMenus != null)
{
for (MenuDef subMenu : menuDef.subMenus)
{
// <li><a href="#{nameTokens.getSessions}">Sessions</a></li>
sb.append("<li><a href=");
if (subMenu.placeToken != null)
{
sb.append("\"#" + subMenu.placeToken + "\"");
}
else
{
sb.append("\"javascript:void(0)\"");
sb.append(" id=\"ext-menu_" + subMenu.hashCode() +"\"");
}
sb.append("\">");
sb.append(subMenu.label);
sb.append("</a></li>");
}
}
sb.append("</ul>");
newMenu.setInnerHTML(sb.toString());
menuParent.insertAfter(newMenu, menu);
// bind handlers
if (menuDef.subMenus != null)
{
for (MenuDef subMenu : menuDef.subMenus)
{
String id = "" + subMenu.hashCode();
Element el = doc.getElementById("ext-menu_" + id);
if (el == null)
{
continue;
}
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
if (menuDef.handler != null)
{
menuDef.handler.run();
}
});
}
}
}
/**
* Appends menu entry under the given standard menu at the specified position that defines
* the target site within the given standard menu. If the specified position is out of the
* existing range or a negative value, then the menu entry is appended at the end of the menu
* item list of the given standard menu.
*
* @param position
* Defines the standard menu to which the new menu entry will be added as a sub menu.
* @param subMenuPosition
* Defines the menu items site where the new menu entry will be added.
* @param menuDef
* The new menu entry.
*/
@Override
public void appendNewItemTo(StandardMenu position, int subMenuPosition, MenuDef menuDef)
{
Document doc = Document.get();
Element menu = doc.getElementById(position.getId()).getParentElement();
Element[] subMenuArray = findDescendants(menu, "li.dropdown-submenu");
boolean outOfRange = (subMenuArray.length <= subMenuPosition) || (subMenuPosition < 0);
Element site;
if (outOfRange)
{
Element[] holder = findDescendants(menu, "ul.dropdown-menu");
site = holder[0];
}
else
{
site = subMenuArray[subMenuPosition];
Element[] holder = findDescendants(site, "ul.dropdown-menu");
site = holder[0];
}
LIElement newMenu = doc.createLIElement();
StringBuilder sb = new StringBuilder();
sb.append("<a href=");
if (menuDef.placeToken != null)
{
sb.append("\"#" + menuDef.placeToken + "\"");
}
else
{
sb.append("\"javascript:void(0)\"");
sb.append(" id=\"ext-menu_" + menuDef.hashCode() +"\"");
}
sb.append("\">");
sb.append(menuDef.label);
sb.append("</a>");
newMenu.setInnerHTML(sb.toString());
site.insertAfter(newMenu, null);
// bind handler
String id = "" + menuDef.hashCode();
Element el = doc.getElementById("ext-menu_" + id);
if (el != null)
{
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
if (menuDef.handler != null)
{
menuDef.handler.run();
}
});
}
}
/**
* Lifecycle method called when binding the object.
* <p>
* <b>Important :</b> Make sure you call your parent class {@link #onBind()}. Also, do
* not call directly, call {@link #bind()} instead.
* <p>
* Any event handler should be
* initialised here rather than in the constructor. Also, it is good practice to
* perform any costly initialisation here.
*/
@Override
protected void onBind()
{
super.onBind();
setInSlot(SLOT_MENU, menu);
// do this very early in home presenter to check valid authenticated session. if the
// session is not authenticated server will return 401 and AdminCallback will redirect
// to login
adm.getServerName(new AdminCallback<String>()
{
@Override
public void onDone(String result)
{
// no-op
}
});
}
/**
* Lifecycle method called whenever this presenter is about to be
* revealed.
*/
@Override
protected void onReveal()
{
super.onReveal();
if (menuBuilt)
{
return;
}
setupLogOffHandler();
setupBackupDirectoryHandler();
setupReloadDirectoryHandler();
setupShutdownHandler();
setupShowACLByAccountHandler();
setupBulkAuthModeUpdateHandler();
setupClearMessagesHandler();
setupAboutAdminClientHandler();
setupPrintHandler();
setupTargetRefreshHandler();
setupTargetLiveHandler();
buildMenu();
if (menuSetupCallback != null)
{
menuSetupCallback.onMenuInitialized(this);
}
menuBuilt = true;
}
/**
* Initilized the logoff link handler.
*/
private void setupLogOffHandler()
{
Element el = Document.get().getElementById("menu-logoff");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
modalDialogs.showYesNo("Logoff Confirmation",
"You are about to be logged off. Continue?",
MessageType.QUESTION,
res ->
{
if (res != 0)
{
return;
}
adm.isRefreshPending(new AdminCallback<Boolean>()
{
@Override
public void onDone(Boolean result)
{
if (result != null && result)
{
modalDialogs.showYesNo("Refresh Confirmation",
"Warning: there are changes to the " +
"directory which have not yet been re-read into " +
"the security cache. Refresh cache now?",
MessageType.QUESTION,
button ->
{
if (button == 0)
{
logoff();
}
});
}
else
{
logoff();
}
}
});
});
});
}
/**
* Initializes the backup directory menu item click handler.
*/
private void setupBackupDirectoryHandler()
{
Element el = Document.get().getElementById("menu-backup-directory");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
InputDialog.Field fInput;
InputDialog dlg = inputDialog.get();
dlg.build("Backing up Directory",
"Enter the backup file name and press the Backup button",
new InputDialog.Field[]
{
fInput = new InputDialog.Field(null, String.class)
});
dlg.setSaveButtonText("Backup");
dlg.show(getView().getModalParent(), vals ->
{
if (vals != null)
{
String path = (String) vals.get(fInput);
adm.backupDirectory(path, new AdminCallback<Boolean>(adm, alarm)
{
@Override
public void onDone(Boolean result)
{
// no-op
}
});
}
});
});
}
/**
* Initializes the reload directory menu item click handler.
*/
private void setupReloadDirectoryHandler()
{
Element el = Document.get().getElementById("menu-reload-directory");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
InputDialog.Field fInput;
InputDialog dlg = inputDialog.get();
dlg.build("Reloading Directory",
"Enter the backup file name and press the Reload button",
new InputDialog.Field[]
{
fInput = new InputDialog.Field(null, String.class)
});
dlg.setSaveButtonText("Reload");
dlg.show(getView().getModalParent(), vals ->
{
if (vals != null)
{
String path = (String) vals.get(fInput);
adm.backupDirectory(path, new AdminCallback<Boolean>(adm, alarm)
{
@Override
public void onDone(Boolean result)
{
// no-op
}
});
}
});
});
}
/**
* Initializes the server shutdown menu item click handler.
*/
private void setupShutdownHandler()
{
Element el = Document.get().getElementById("menu-shutdown");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
modalDialogs.showYesNo("Server Shutdown Confirmation",
"You are about to shut the server down. Continue?",
MessageType.QUESTION,
res ->
{
if (res != 0)
{
return;
}
adm.shutdown(new AdminCallback<Boolean>(adm, alarm)
{
@Override
public void onDone(Boolean result)
{
if (result != null && result)
{
PlaceRequest req = new PlaceRequest.Builder()
.nameToken("").build();
getPlaceManager().revealPlace(req);
}
}
});
});
});
}
/**
* Initializes the bulk auth mode menu item click handler.
*/
private void setupBulkAuthModeUpdateHandler()
{
Element el = Document.get().getElementById("mitem-bulk-auth-mode-update");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event -> {
modalDialogs.showYesNo(
"Confirm Bulk Update",
"WARNING, authentication mode will be updated for ALL "
+ "accounts of the specified type.\nDo you want to continue?",
MessageType.QUESTION,
res -> {
if (res != 0)
{
return;
}
BulkAuthModeUpdateView.Binder binder = GWT
.create(BulkAuthModeUpdateView.Binder.class);
BulkAuthModeUpdateView bulkAuthModeUpdateView = new BulkAuthModeUpdateView(
binder);
getView().getModalParent().add(bulkAuthModeUpdateView.getModal());
AsyncAction<Boolean, TaggedName[]> action1
= new AsyncAction<Boolean, TaggedName[]>()
{
@Override
public void accept(Boolean v)
{
adm.listAuthPlugins(delegate);
}
@Override
public void onFailure(Throwable caught)
{
logger.log(Level.SEVERE, "Failed to call listAuthPlugins", caught);
}
};
action1.then(new Consumer<TaggedName[]>(){
@Override
public void accept(TaggedName[] result)
{
bulkAuthModeUpdateView.setCustomAuthPlugins(result);
bulkAuthModeUpdateView.getModal().show();
bulkAuthModeUpdateView.addHideHandler(() -> {
getView().getModalParent().remove(bulkAuthModeUpdateView.getModal());
});
bulkAuthModeUpdateView.getUpdateAction().addClickHandler(new ClickHandler()
{
@Override
public void onClick(ClickEvent event)
{
int targetAccounts = AccountType.valueOf(
bulkAuthModeUpdateView.getAccountsType()
.getSelectedValue()).getType();
ClientContext ctxt = ClientContext.instance();
String identity = ctxt.getIdentity();
String[] excludedAccounts = new String[] {identity};
int authMode = bulkAuthModeUpdateView.getModes().getSelectedIndex();
String authPlugin;
if (bulkAuthModeUpdateView.getPlugins().isEnabled())
{
authPlugin = bulkAuthModeUpdateView.getPlugins().getSelectedValue();
}
else
{
authPlugin = "";
}
adm.bulkAuthModeUpdate(
targetAccounts,
excludedAccounts,
authMode,
authPlugin,
new AdminCallback<Integer>(adm, alarm)
{
@Override
public void onDone(Integer result)
{
logger.info("updated #accounts: " + result);
if (result != null && result >= 0)
{
bulkAuthModeUpdateView.getModal().hide();
}
}
});
}
});
}
});
action1.accept(true);
});
});
}
/**
* Initializes the clear server messages menu item click handler.
*/
private void setupClearMessagesHandler()
{
Element el = Document.get().getElementById("menu-clear-messages");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
PlaceRequest req = new PlaceRequest.Builder().nameToken(NameTokens.SERVER_MESSAGES).with("action", "clear").build();
getPlaceManager().revealPlace(req);
});
}
/**
* Initializes the about menu item click handler.
*/
private void setupAboutAdminClientHandler()
{
Element el = Document.get().getElementById("menu-about");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
adm.getVersionInfo(new AsyncCallback<String>()
{
@Override
public void onSuccess(String result)
{
AboutDialogView view = new AboutDialogView(GWT.create(
AboutDialogView.Binder.class));
view.setLogo("fwd.png");
view.setTitle("About Administration Console");
StringBuilder about = new StringBuilder();
about.append("GWT Administration client to manage<br/> the FWD server.<br/>");
about.append("The current version: ").append(result);
view.setAboutHtml(about.toString());
getView().getModalParent().add(view.getModal());
view.addHideHandler(() -> {getView().getModalParent().remove(view.getModal());});
view.getModal().show();
}
@Override
public void onFailure(Throwable caught)
{
logger.log(Level.SEVERE, "Failed to call getVersionInfo", caught);
}
});
});
}
/**
* Initializes the preview selection dialog menu item click handler.
*
* @param pctx
* The printing context
* @param done
* The consumer of this action
*/
private void displayPreviewSelectionDialog(PrintingContext pctx, Consumer<Range> done)
{
int selectedRecordsNumber = pctx.getDataSize(Range.SELECTION);
int allRecordsNumber = pctx.getDataSize(Range.ALL);
final InputDialog.Field fRange;
InputDialog inputDialog = this.inputDialog.get();
Map<String, String> translationMap = new HashMap<String, String>();
String allRangeLabel = pctx.getPreviewDialogParameter(PreviewDialogParameters.RANGE_ALL_LABEL);
translationMap.put(PrintingContext.Range.ALL.name(), allRangeLabel);
String selRangeLabel = pctx.getPreviewDialogParameter(PreviewDialogParameters.RANGE_SELECTION_LABEL);
translationMap.put(PrintingContext.Range.SELECTION.name(), selRangeLabel);
inputDialog.setTranslationMap(translationMap);
InputDialog.Field[] fields;
String hlpText = pctx.getPreviewDialogParameter(PreviewDialogParameters.HELP_TEXT);
if (selectedRecordsNumber > 0 && allRecordsNumber > 1)
{
PrintingContext.Range currentValue = PrintingContext.Range.SELECTION;
fields = new InputDialog.Field[]
{
fRange = new InputDialog.Field("Range", currentValue)
};
}
else
{
fRange = null;
fields = new InputDialog.Field[]
{
//empty fields
};
}
String title = pctx.getPreviewDialogParameter(PreviewDialogParameters.TITLE);
inputDialog.setSaveButtonText("OK");
inputDialog.setLabelSize(1);
inputDialog.build(title, hlpText, fields);
inputDialog.show(getView().getModalParent(), true, values ->
{
if (values != null)
{
PrintingContext.Range selectedRange;
if (fRange != null)
{
selectedRange = (PrintingContext.Range) values.get(fRange);
}
else
{
selectedRange = PrintingContext.Range.ALL;
}
done.accept(selectedRange);
}
});
}
/**
* Used by {@link #setupPrintHandler()} to build print query parameters from the print context.
*
* @param printingContext
* Print context.
*
* @return Print query parameters.
*/
private Map<String, String> buildSelectionURLParameters(PrintingContext printingContext)
{
HashMap<String, String> parameters = new HashMap<String, String>();
Object selection = printingContext.getReportParameters().get(
com.goldencode.p2j.admin.shared.ReportParameters.SELECTION);
if (selection instanceof TaggedName[])
{
TaggedName[] selectedRows = (TaggedName[]) selection;
for(int i = 0; i < selectedRows.length; i++)
{
parameters.put(
com.goldencode.p2j.admin.shared.ReportParameters.SELECTION.getParameter() + String.valueOf(i),
selectedRows[i].getName());
}
}
return parameters;
}
/**
* Initializes the print menu item click handler.
*/
private void setupPrintHandler()
{
Element el = Document.get().getElementById("menu-print");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
Presenter p = HomePresenter.this.getChild(HomePresenter.SLOT_CONTENT);
if (p != null && p.getView() instanceof PrintingContext)
{
PrintingContext printingContext = (PrintingContext) p.getView();
displayPreviewSelectionDialog(printingContext, (range)-> {
PlaceRequest.Builder builder = new PlaceRequest.Builder().nameToken(NameTokens.PRINT_PREVIEW)
.with(com.goldencode.p2j.admin.shared.ReportParameters.TITLE.getParameter(),
printingContext.getReportParameters().get(
com.goldencode.p2j.admin.shared.ReportParameters.TITLE).toString())
.with(com.goldencode.p2j.admin.shared.ReportParameters.REPORT_ID.getParameter(),
printingContext.getReportParameters().get(
com.goldencode.p2j.admin.shared.ReportParameters.REPORT_ID)
.toString())
.with(com.goldencode.p2j.admin.shared.ReportParameters.PAPER_FORMAT.getParameter(),
printingContext.getReportParameters().get(
com.goldencode.p2j.admin.shared.ReportParameters.PAPER_FORMAT).toString())
.with(com.goldencode.p2j.admin.shared.ReportParameters.PAPER_ORIENT.getParameter(),
printingContext.getReportParameters().get(
com.goldencode.p2j.admin.shared.ReportParameters.PAPER_ORIENT).toString())
.with(NameTokens.getTokenParameter(), printingContext.getPathToPrintPreviewOwner());
if (range == Range.SELECTION)
{
builder.with(buildSelectionURLParameters(printingContext));
}
PlaceRequest req = builder.build();
getPlaceManager().revealPlace(req);
});
}
else
{
modalDialogs.showInfo("Printing", "No print service found.", () -> {
});
}
});
}
/**
* Logs off currently logged in user.
*/
private void logoff()
{
ClientContext.instance().reset("", "");
Cookies.removeCookie("JSESSIONID");
PlaceRequest req = new PlaceRequest.Builder().nameToken(NameTokens.LOGIN).build();
getView().setInSlot(SLOT_CONTENT, null);
getPlaceManager().revealPlace(req);
}
/**
* Initializes the show ACL by account menu item click handler.
*/
private void setupShowACLByAccountHandler()
{
Element el = Document.get().getElementById("menu-acl-showbyacc");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
InputDialog.Field fInput;
InputDialog dlg = inputDialog.get();
dlg.build("Account Name", new InputDialog.Field[]
{
fInput = new InputDialog.Field(null, String.class)
});
dlg.setSaveButtonText("OK");
dlg.show(getView().getModalParent(), vals ->
{
if (vals == null)
{
return;
}
String acctName = (String) vals.get(fInput);
PlaceRequest req = NameTokens.buildACLPlaceRequest(acctName);
getPlaceManager().revealPlace(req);
});
});
}
/**
* Initializes the show ACL by resource name menu item click handler.
*
* @param adminDef
* The administrator plugins definitions
*/
private void buildShowACLByResourceMenu(AdminDef adminDef)
{
Element el = Document.get().getElementById("menu-acl-showbyresource");
StringBuilder sb = new StringBuilder();
TreeSet<String> resTypes = new TreeSet<>();
resTypes.addAll(adminDef.customAclEditors);
// make sure system, admin, net, directory appear at the top in this order
String[] predefined = new String[] {"system", "admin", "net", "directory"};
List<String> customOrder = new ArrayList<>(resTypes.size());
for (String resType : predefined)
{
if (resTypes.contains(resType))
{
customOrder.add(resType);
resTypes.remove(resType);
}
}
customOrder.addAll(resTypes);
for (String key : customOrder)
{
PlaceRequest req = NameTokens.buildACLResourcePlaceRequest(key);
sb.append("<li><a href=\"#");
sb.append(tokenFormatter.toPlaceToken(req));
sb.append("\">");
sb.append(key);
sb.append("</a></li>");
}
el.setInnerHTML(sb.toString());
}
/**
* Enables or disables individual menu items according to the permissions of the logged in
* user.
*
* @param adminDef
* The administrator plugins definitions
*/
private void updateMenuAuthorization(AdminDef adminDef)
{
AdminProfile[] profile = adminDef.profile;
// process profile and enable/disable the menu items
if (profile != null)
{
Document doc = Document.get();
Element cns = doc.getElementById("menu-console");
Element acc = doc.getElementById("menu-accounts");
Element acl = doc.getElementById("menu-acl");
Element rts = doc.getElementById("menu-runset");
Element gen = doc.getElementById("menu-config");
Element tgt = doc.getElementById("menu-target");
for (int i = 0; i < profile.length; i++)
{
setEnabled(cns, profile, "/console");
setEnabled(acc, profile, "/accounts");
setEnabled(acl, profile, "/access_control");
setEnabled(rts, profile, "/runtime");
setEnabled(gen, profile, "/configuration");
setEnabled(tgt, profile, "/target");
}
}
}
/**
* Enables a menu item.
*
* @param el
* A DOM element representing the menu item to enable.
* @param profiles
* Admin profile.
* @param name
* Admin profile name.
*/
private void setEnabled(Element el, AdminProfile[] profiles, String name)
{
boolean found = false;
for (AdminProfile profile : profiles)
{
if (profile.name.equals(name))
{
found = true;
}
}
if (found)
{
el.removeClassName("disabled");
}
else
{
el.addClassName("disabled");
}
}
/**
* Fetches admin definition data from the server and builds the main menu from this data.
*/
private void buildMenu()
{
adm.getAdminDef(new AdminCallback<AdminDef>()
{
@Override
public void onDone(AdminDef result)
{
if (result == null)
{
return;
}
buildShowACLByResourceMenu(result);
updateMenuAuthorization(result);
}
});
}
/**
* Initializes the live menu item click handler.
*/
private void setupTargetLiveHandler()
{
Element el = Document.get().getElementById("menu-target-live");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
modalDialogs.showYesNo("Confirmation",
"Sets the live server's directory as the target. Continue?",
MessageType.QUESTION,
res ->
{
if (res != 0)
{
return;
}
adm.setTargetLive(true, new AdminCallback<Integer>(adm, alarm)
{
@Override
public void onDone(Integer result)
{
ClientContext context = ClientContext.instance();
if (result == -1)
{
alarm.ring();
}
else
{
context.setSecurityCacheSerialNumber(result);
logger.log(Level.INFO, "live[" + result + "]");
}
}
});
});
});
}
/**
* Initializes the refresh menu item click handler.
*/
private void setupTargetRefreshHandler()
{
adm.canRefresh(new AdminCallback<Boolean>(adm, alarm)
{
@Override
public void onDone(Boolean result)
{
Element el = Document.get().getElementById("menu-target-refresh");
if (result != null && result)
{
el.removeClassName("disabled");
attachRefreshHandler();
}
else
{
el.addClassName("disabled");
}
}
});
}
/**
* Attach click handler to the refresh menu item.
*/
private void attachRefreshHandler()
{
Element el = Document.get().getElementById("menu-target-refresh");
Event.sinkEvents(el, Event.ONCLICK | Event.ONTOUCHSTART);
Event.setEventListener(el, event ->
{
modalDialogs.showYesNo("Confirmation",
"You are about to refresh the security cache. Continue?",
MessageType.QUESTION,
res ->
{
if (res != 0)
{
return;
}
adm.targetRefresh(new AdminCallback<Integer>(adm, alarm)
{
@Override
public void onDone(Integer result)
{
ClientContext context = ClientContext.instance();
int serialNumber;
try
{
serialNumber = context.getSecurityCacheSerialNumber();
}
catch(NumberFormatException ex)
{
logger.log(Level.SEVERE,
"Corrupted 'securityCacheSerialNumber' cookie", ex);
serialNumber = -1;
}
if (result >= serialNumber)
{
context.setSecurityCacheSerialNumber(result);
logger.log(Level.INFO, "live[" + result + "]");
}
else
{
alarm.ring();
}
}
});
});
});
}
/**
* Finds the descendants of the given element filtered by the given selector. Uses the jQuery
* find function.
*
* @param e
* The given ancestor html element
* @param selector
* The given selector
*
* @return The descendants of the given element filtered by the given selector
*/
private native Element[] findDescendants(final Element e, final String selector) /*-{
var jqResult = $wnd.jQuery(e).find(selector);
var result = [];
for(var i = 0; i < jqResult.length; i++)
{
result.push(jqResult[i]);
}
return result;
}-*/;
}