package org.brixcms.plugin.jpa.web.admin; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.event.Broadcast; import org.apache.wicket.event.IEvent; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.brixcms.auth.Action.Context; import org.brixcms.plugin.jpa.JpaPluginLocator; import org.brixcms.plugin.jpa.Persistable; import org.brixcms.plugin.jpa.web.admin.filter.FilterPanel.FilterChanged; import org.brixcms.web.generic.BrixGenericPanel; import com.inmethod.grid.IGridColumn; import com.inmethod.grid.SizeUnit; import com.inmethod.grid.column.AbstractColumn; import com.inmethod.grid.column.CheckBoxColumn; import com.inmethod.grid.datagrid.DataGrid; import com.inmethod.grid.datagrid.DefaultDataGrid; /** * @author dan.simko@gmail.com */ @SuppressWarnings("serial") public class GridPanel<T extends Persistable<ID>, ID extends Serializable, F extends Serializable> extends Panel { private JpaPluginLocator<T, ID, F> pluginLocator; private DataGrid<GridDataSource<T, ID, F>, T, Object> grid; private Label selectionLabel; private GridDataSource<T, ID, F> dataSource; public GridPanel(String id, JpaPluginLocator<T, ID, F> locator) { super(id); setOutputMarkupId(true); this.pluginLocator = locator; List<IGridColumn<GridDataSource<T, ID, F>, T, Object>> columns = new ArrayList<IGridColumn<GridDataSource<T, ID, F>, T, Object>>(); columns.add(new IdColumn()); pluginLocator.getPlugin().addGridColumns(columns); columns.add(0, new CheckBoxColumn<GridDataSource<T, ID, F>, T, Object>("checkbox")); dataSource = new GridDataSource<T, ID, F>(pluginLocator); grid = new DefaultDataGrid<GridDataSource<T, ID, F>, T, Object>("grid", dataSource, columns) { @Override public void onItemSelectionChanged(IModel<T> item, boolean newValue) { super.onItemSelectionChanged(item, newValue); getRequestCycle().find(AjaxRequestTarget.class).ifPresent(t -> { t.add(selectionLabel); Collection<IModel<T>> selected = getSelectedItems(); if (selected.isEmpty()) { send(getPage(), Broadcast.BREADTH, new SelectionChangedEvent<T>(new EntityModel<>(null))); } else { send(getPage(), Broadcast.BREADTH, new SelectionChangedEvent<T>(selected.iterator().next())); } }); } @Override protected void onRowClicked(AjaxRequestTarget target, IModel<T> model) { super.onRowClicked(target, model); selectItem(model, true); } }; grid.setRowsPerPage(10); grid.setContentHeight(15, SizeUnit.EM); grid.setAllowSelectMultiple(false); grid.setCleanSelectionOnPageChange(false); add(grid); add(new CheckBox("allowSelectMultiple", new Model<Boolean>() { @Override public Boolean getObject() { return grid.isAllowSelectMultiple(); } @Override public void setObject(Boolean bool) { grid.setAllowSelectMultiple(bool); } }).add(new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { target.add(GridPanel.this); } })); add(selectionLabel = new Label("currentSelection", new Model<Integer>() { @Override public Integer getObject() { return grid.getSelectedItems().size(); } })); selectionLabel.setOutputMarkupId(true); add(new Link<Void>("clone") { @Override public void onClick() { pluginLocator.getPlugin().clone(getSelectedItems()); } @Override public boolean isVisible() { if (grid.getSelectedItems().isEmpty()) { return false; } for (T entity : getSelectedItems()) { if (!pluginLocator.getPlugin().canCloneEntity(entity, Context.ADMINISTRATION)) { return false; } } return true; } }); add(new Link<Void>("delete") { @Override public void onClick() { pluginLocator.getPlugin().delete(getSelectedItems()); grid.resetSelectedItems(); send(getPage(), Broadcast.BREADTH, new SelectionChangedEvent<T>(new EntityModel<>(null))); } @Override public boolean isVisible() { if (grid.getSelectedItems().isEmpty()) { return false; } for (T entity : getSelectedItems()) { if (!pluginLocator.getPlugin().canDeleteEntity(entity, Context.ADMINISTRATION)) { return false; } } return true; } }); } private List<T> getSelectedItems() { List<T> list = new ArrayList<T>(); Collection<IModel<T>> selected = grid.getSelectedItems(); for (IModel<T> model : selected) { model.detach(); list.add(model.getObject()); } return list; } private class IdColumn extends AbstractColumn<GridDataSource<T, ID, F>, T, Object> { public IdColumn() { super("id", new ResourceModel("jpa-plugin.id"), "id"); setInitialSize(50); } @Override public Component newCell(WebMarkupContainer parent, String componentId, IModel<T> rowModel) { return new IdPanel(componentId, rowModel); } }; @Override public void onEvent(IEvent<?> event) { super.onEvent(event); Object payload = event.getPayload(); if (payload instanceof FilterChanged) { @SuppressWarnings("unchecked") FilterChanged<T, ID, F> e = (FilterChanged<T, ID, F>) payload; dataSource.getFilters().clear(); dataSource.getFilters().addAll(e.getEntries()); } } private class IdPanel extends BrixGenericPanel<T> { public IdPanel(String id, final IModel<T> model) { super(id, model); Link<?> link; add(link = new Link<Void>("select") { @Override public void onClick() { grid.selectItem(model, true); send(getPage(), Broadcast.BREADTH, new SelectionChangedEvent<T>(model)); } }); link.add(new Label("label", new PropertyModel<String>(model, "id"))); } } public static class SelectionChangedEvent<T> implements Serializable { private final IModel<T> selected; public SelectionChangedEvent(IModel<T> selected) { this.selected = selected; } public IModel<T> getSelected() { return selected; } } }