package org.orienteer.core.widget; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.wicket.Component; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method; import org.apache.wicket.ajax.json.JSONArray; import org.apache.wicket.ajax.json.JSONException; import org.apache.wicket.ajax.json.JSONObject; import org.apache.wicket.behavior.AbstractAjaxBehavior; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.head.CssHeaderItem; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; import org.apache.wicket.markup.head.OnDomReadyHeaderItem; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.panel.GenericPanel; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.resource.CssResourceReference; import org.apache.wicket.request.resource.PackageResourceReference; import org.apache.wicket.util.template.PackageTextTemplate; import org.apache.wicket.util.template.TextTemplate; import org.apache.wicket.util.visit.IVisit; import org.apache.wicket.util.visit.IVisitor; import org.orienteer.core.OrienteerWebSession; import org.orienteer.core.component.meta.IDisplayModeAware; import org.orienteer.core.component.property.DisplayMode; import org.orienteer.core.module.OWidgetsModule; import org.orienteer.core.widget.command.AddWidgetCommand; import org.orienteer.core.widget.command.KeepUnsavedDashboardCommand; import org.orienteer.core.widget.command.ConfigureDashboardCommand; import org.orienteer.core.widget.command.SilentSaveDashboardCommand; import org.orienteer.core.widget.command.UnhideWidgetCommand; import org.orienteer.core.widget.support.IDashboardSupport; import ru.ydn.wicket.wicketorientdb.model.ODocumentModel; import ru.ydn.wicket.wicketorientdb.security.OSecurityHelper; import ru.ydn.wicket.wicketorientdb.security.OrientPermission; import static org.orienteer.core.module.OWidgetsModule.*; import com.google.common.base.Predicate; import com.google.common.reflect.TypeToken; import com.google.inject.Inject; import com.orientechnologies.orient.core.db.document.ODatabaseDocument; import com.orientechnologies.orient.core.metadata.schema.OClass; import com.orientechnologies.orient.core.record.impl.ODocument; import de.agilecoders.wicket.webjars.request.resource.WebjarsCssResourceReference; import de.agilecoders.wicket.webjars.request.resource.WebjarsJavaScriptResourceReference; /** * Dashboard is {@link Panel} to allow manipulation with a set of {@link AbstractWidget}s * * @param <T> the type of main data object */ public class DashboardPanel<T> extends GenericPanel<T> implements IDisplayModeAware { @Inject protected IDashboardManager dashboardManager; @Inject protected IWidgetTypesRegistry widgetTypesRegistry; @Inject private IDashboardSupport dashboardSupport; private String domain; private String tab; private ConfigureDashboardCommand configureCommand; private RepeatingView commands; private RepeatingView widgets; private AbstractDefaultAjaxBehavior ajaxBehavior; private IModel<DisplayMode> dashboardModeModel = DisplayMode.VIEW.asModel(); private IModel<ODocument> dashboardDocumentModel = new ODocumentModel(); private IWidgetFilter<T> widgetsFilter; public DashboardPanel(String id, String domain, String tab, IModel<T> model, IWidgetFilter<T> widgetsFilter) { super(id, model); this.domain = domain; this.tab = tab; this.widgetsFilter = widgetsFilter; WebMarkupContainer commandsContainer = new WebMarkupContainer("commandsContainer"); OSecurityHelper.secureComponent(commandsContainer, OSecurityHelper.requireOClass(OWidgetsModule.OCLASS_DASHBOARD, OrientPermission.UPDATE)); commandsContainer.add(configureCommand = new ConfigureDashboardCommand("configure", dashboardDocumentModel)); commands = new RepeatingView("commands"); commands.add(new AddWidgetCommand<T>(commands.newChildId(), dashboardDocumentModel)); commands.add(new UnhideWidgetCommand<T>(commands.newChildId(), dashboardDocumentModel)); commands.add(new SilentSaveDashboardCommand(commands.newChildId(), dashboardDocumentModel)); commands.add(new KeepUnsavedDashboardCommand(commands.newChildId(), dashboardDocumentModel)); commandsContainer.add(commands); add(commandsContainer); widgets = new RepeatingView("widgets"); add(widgets); setOutputMarkupId(true); loadDashboard(); dashboardSupport.initDashboardPanel(this); } public ODocument loadDashboard() { return loadDashboard(lookupDashboardDocument(domain, tab, getModel())); } /** * Load this dashboard from specified dashboard document. If document is null: default dashboard will be built * @param doc dashboard document * @return document from which this document was built */ public ODocument loadDashboard(ODocument doc) { if(doc!=null) { dashboardDocumentModel.setObject(doc); List<ODocument> widgets = doc.field(OPROPERTY_WIDGETS); for (ODocument widgetDoc : widgets) { addWidget(createWidgetFromDocument(widgetDoc)); } } else { buildDashboard(); } return doc; } protected ODocument lookupDashboardDocument(String domain, String tab, IModel<T> model) { return dashboardManager.getExistingDashboard(domain, tab, getModel()); } protected void buildDashboard() { List<IWidgetType<T>> widgets = widgetTypesRegistry.lookupByDomainAndTab(domain, tab, getWidgetsFilter()); for(int i=0;i<widgets.size();i++) { IWidgetType<T> type = widgets.get(i); if(type.isAutoEnable()) { AbstractWidget<T> widget = type.instanciate(newWidgetId(), getModel(), dashboardManager.createWidgetDocument(type)); addWidget(widget); } } } public IWidgetFilter<T> getWidgetsFilter() { return widgetsFilter; } public DashboardPanel<T> setWidgetsFilter(IWidgetFilter<T> widgetsFilter) { this.widgetsFilter = widgetsFilter; return this; } @SuppressWarnings("unchecked") private AbstractWidget<T> createWidgetFromDocument(ODocument widgetDoc) { IWidgetType<T> type = null; if(widgetDoc!=null) type = (IWidgetType<T>)widgetTypesRegistry.lookupByTypeId((String)widgetDoc.field(OPROPERTY_TYPE_ID)); return type!=null ? type.instanciate(newWidgetId(), getModel(), widgetDoc) : new NotFoundWidget<T>(newWidgetId(), getModel(), new ODocumentModel(widgetDoc)); } /** * Store dashboard configuration in a document * @return document - can't be null */ public ODocument storeDashboard() { ODocument doc = dashboardDocumentModel.getObject(); if(doc==null) { doc = new ODocument(OCLASS_DASHBOARD); doc.field(OPROPERTY_DOMAIN, domain); doc.field(OPROPERTY_TAB, tab); doc.save(); dashboardDocumentModel.setObject(doc); } List<AbstractWidget<T>> components = getWidgets(); List<ODocument> widgets = new ArrayList<ODocument>(); for (AbstractWidget<T> widget : components) { widget.saveSettings(); ODocument widgetDoc = widget.getWidgetDocument(); widgetDoc.save(); widgets.add(widgetDoc); } doc.field(OPROPERTY_WIDGETS, widgets); doc.save(); return doc; } public String newWidgetId() { return widgets.newChildId(); } public List<AbstractWidget<T>> getWidgets() { final List<AbstractWidget<T>> ret = new ArrayList<AbstractWidget<T>>(); visitChildren(AbstractWidget.class, new IVisitor<AbstractWidget<T>, Void>() { @Override public void component(AbstractWidget<T> object, IVisit<Void> visit) { ret.add(object); visit.dontGoDeeper(); } }); return ret; } public AbstractWidget<T> addWidget(AbstractWidget<T> widget) { widgets.add(widget); return widget; } public AbstractWidget<T> addWidget(IWidgetType<T> description) { return addWidget(description, dashboardManager.createWidgetDocument(description)); } public AbstractWidget<T> addWidget(IWidgetType<T> description, ODocument widgetDoc) { return addWidget(description.instanciate(newWidgetId(), getModel(), widgetDoc)); } public AbstractWidget<T> addWidget(String widgetId) { return addWidget((IWidgetType<T>)widgetTypesRegistry.lookupByTypeId(widgetId)); } public AbstractWidget<T> addWidget(String widgetId, ODocument widgetDoc) { return addWidget((IWidgetType<T>)widgetTypesRegistry.lookupByTypeId(widgetId), widgetDoc); } public DashboardPanel<T> deleteWidget(AbstractWidget<T> widget) { widgets.remove(widget); return this; } @Override protected void onComponentTag(ComponentTag tag) { super.onComponentTag(tag); tag.append("class", "dashboard", " "); } @Override protected void onConfigure() { super.onConfigure(); if(DisplayMode.EDIT.equals(dashboardModeModel.getObject())) { commands.setVisibilityAllowed(true); configureCommand.setVisibilityAllowed(false); } else { commands.setVisibilityAllowed(false); configureCommand.setVisibilityAllowed(true); } } public String getDomain() { return domain; } public String getTab() { return tab; } public RepeatingView getWidgetsContainer() { return widgets; } public IDashboardSupport getDashboardSupport() { return dashboardSupport; } @Override protected void detachModel() { super.detachModel(); dashboardDocumentModel.detach(); dashboardModeModel.detach(); } @Override public IModel<DisplayMode> getModeModel() { return dashboardModeModel; } @Override public DisplayMode getModeObject() { return dashboardModeModel.getObject(); } public IModel<ODocument> getDashboardDocumentModel() { return dashboardDocumentModel; } public ODocument getDashboardDocument() { return dashboardDocumentModel.getObject(); } }