You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/02/05 17:01:06 UTC
[35/52] syncope git commit: [SYNCOPE-620] Console (JAR) in,
now time for console-reference
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Users.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Users.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Users.java
new file mode 100644
index 0000000..ed8419e
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/Users.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.AbstractSearchResultPanel;
+import org.apache.syncope.client.console.panels.AbstractSearchResultPanel.EventDataWrapper;
+import org.apache.syncope.client.console.panels.UserSearchPanel;
+import org.apache.syncope.client.console.panels.UserSearchResultPanel;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class Users extends BasePage {
+
+ private static final long serialVersionUID = 134681165644474568L;
+
+ private final static int EDIT_MODAL_WIN_HEIGHT = 550;
+
+ private final static int EDIT_MODAL_WIN_WIDTH = 800;
+
+ @SpringBean
+ private UserRestClient restClient;
+
+ public Users(final PageParameters parameters) {
+ super(parameters);
+
+ // Modal window for editing user attributes
+ final ModalWindow editModalWin = new ModalWindow("editModal");
+ editModalWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ editModalWin.setInitialHeight(EDIT_MODAL_WIN_HEIGHT);
+ editModalWin.setInitialWidth(EDIT_MODAL_WIN_WIDTH);
+ editModalWin.setCookieName("edit-modal");
+ add(editModalWin);
+
+ final AbstractSearchResultPanel searchResult =
+ new UserSearchResultPanel("searchResult", true, null, getPageReference(), restClient);
+ add(searchResult);
+
+ final AbstractSearchResultPanel listResult =
+ new UserSearchResultPanel("listResult", false, null, getPageReference(), restClient);
+ add(listResult);
+
+ // create new user
+ final AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) {
+
+ private static final long serialVersionUID = -7978723352517770644L;
+
+ @Override
+ protected void onClickInternal(final AjaxRequestTarget target) {
+ editModalWin.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690940L;
+
+ @Override
+ public Page createPage() {
+ return new EditUserModalPage(Users.this.getPageReference(), editModalWin, new UserTO());
+ }
+ });
+
+ editModalWin.show(target);
+ }
+ };
+ MetaDataRoleAuthorizationStrategy.authorize(
+ createLink, ENABLE, xmlRolesReader.getEntitlement("Users", "create"));
+ add(createLink);
+
+ setWindowClosedReloadCallback(editModalWin);
+
+ final Form searchForm = new Form("searchForm");
+ add(searchForm);
+
+ final UserSearchPanel searchPanel = new UserSearchPanel.Builder("searchPanel").build();
+ searchForm.add(searchPanel);
+
+ final ClearIndicatingAjaxButton searchButton =
+ new ClearIndicatingAjaxButton("search", new ResourceModel("search"), getPageReference()) {
+
+ private static final long serialVersionUID = -958724007591692537L;
+
+ @Override
+ protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+ final String fiql = searchPanel.buildFIQL();
+ LOG.debug("FIQL: " + fiql);
+
+ doSearch(target, fiql, searchResult);
+
+ Session.get().getFeedbackMessages().clear();
+ searchPanel.getSearchFeedback().refresh(target);
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+
+ searchPanel.getSearchFeedback().refresh(target);
+ }
+ };
+
+ searchForm.add(searchButton);
+ searchForm.setDefaultButton(searchButton);
+ }
+
+ private void doSearch(final AjaxRequestTarget target, final String fiql,
+ final AbstractSearchResultPanel resultsetPanel) {
+
+ if (fiql == null) {
+ error(getString(Constants.SEARCH_ERROR));
+ return;
+ }
+
+ resultsetPanel.search(fiql, target);
+ }
+
+ private void setWindowClosedReloadCallback(final ModalWindow window) {
+ window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+ private static final long serialVersionUID = 8804221891699487139L;
+
+ @Override
+ public void onClose(final AjaxRequestTarget target) {
+ final EventDataWrapper data = new EventDataWrapper();
+ data.setTarget(target);
+ data.setCreate(true);
+
+ send(getPage(), Broadcast.BREADTH, data);
+
+ if (isModalResult()) {
+ // reset modal result
+ setModalResult(false);
+ // set operation succeeded
+ getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+ // refresh feedback panel
+ feedbackPanel.refresh(target);
+ }
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ViewUserModalPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ViewUserModalPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ViewUserModalPage.java
new file mode 100644
index 0000000..d47e07f
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/ViewUserModalPage.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+
+public class ViewUserModalPage extends EditUserModalPage {
+
+ private static final long serialVersionUID = -8715255026876951611L;
+
+ public ViewUserModalPage(final PageReference callerPageRef, final ModalWindow window, final UserTO userTO) {
+ super(callerPageRef, window, userTO);
+ form.setEnabled(false);
+ form.get(CANCEL).setVisible(false);
+ }
+
+ @Override
+ protected AjaxButton getOnSubmit() {
+ AjaxButton submit = super.getOnSubmit();
+ submit.setVisible(false);
+ return submit;
+ }
+
+ @Override
+ protected void submitAction(final AjaxRequestTarget target, final Form form) {
+ // No submit allowed, read-only form
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/VirSchemaModalPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/VirSchemaModalPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/VirSchemaModalPage.java
new file mode 100644
index 0000000..daa65d6
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/VirSchemaModalPage.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+/**
+ * Modal window with Schema form.
+ */
+public class VirSchemaModalPage extends AbstractSchemaModalPage<VirSchemaTO> {
+
+ private static final long serialVersionUID = 5979623248182851337L;
+
+ public VirSchemaModalPage(final AttributableType kind) {
+ super(kind);
+ }
+
+ @Override
+ public void setSchemaModalPage(final PageReference pageRef, final ModalWindow window,
+ VirSchemaTO schema, final boolean createFlag) {
+
+ if (schema == null) {
+ schema = new VirSchemaTO();
+ }
+
+ final Form<VirSchemaTO> schemaForm = new Form<VirSchemaTO>(FORM);
+
+ schemaForm.setModel(new CompoundPropertyModel<VirSchemaTO>(schema));
+
+ final AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", getString("name"), new PropertyModel<String>(
+ schema, "name"));
+ name.addRequiredLabel();
+
+ name.setEnabled(createFlag);
+
+ final AjaxCheckBoxPanel readonly = new AjaxCheckBoxPanel("readonly", getString("readonly"),
+ new PropertyModel<Boolean>(schema, "readonly"));
+
+ final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(SUBMIT)) {
+
+ private static final long serialVersionUID = -958724007591692537L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+ VirSchemaTO schemaTO = (VirSchemaTO) form.getDefaultModelObject();
+ try {
+ if (createFlag) {
+ schemaRestClient.createVirSchema(kind, schemaTO);
+ } else {
+ schemaRestClient.updateVirSchema(kind, schemaTO);
+ }
+ if (pageRef.getPage() instanceof BasePage) {
+ ((BasePage) pageRef.getPage()).setModalResult(true);
+ }
+
+ window.close(target);
+ } catch (SyncopeClientException e) {
+ error(getString(Constants.ERROR) + ": " + e.getMessage());
+ feedbackPanel.refresh(target);
+ }
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+ feedbackPanel.refresh(target);
+ }
+ };
+
+ final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) {
+
+ private static final long serialVersionUID = -958724007591692537L;
+
+ @Override
+ protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+ window.close(target);
+ }
+ };
+
+ cancel.setDefaultFormProcessing(false);
+
+ String allowedRoles = createFlag
+ ? xmlRolesReader.getEntitlement("Schema", "create")
+ : xmlRolesReader.getEntitlement("Schema", "update");
+
+ MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, allowedRoles);
+
+ schemaForm.add(name);
+ schemaForm.add(readonly);
+
+ schemaForm.add(submit);
+ schemaForm.add(cancel);
+
+ add(schemaForm);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/WelcomePage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/WelcomePage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/WelcomePage.java
new file mode 100644
index 0000000..d9f884d
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/WelcomePage.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import org.apache.syncope.client.console.SyncopeApplication;
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.rest.UserSelfRestClient;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+/**
+ * Welcome page to display after successful login.
+ */
+public class WelcomePage extends WebPage {
+
+ private static final long serialVersionUID = 8851399358753120581L;
+
+ @SpringBean
+ private XMLRolesReader xmlRolesReader;
+
+ @SpringBean
+ private UserSelfRestClient userSelfRestClient;
+
+ public WelcomePage(final PageParameters parameters) {
+ super(parameters);
+ setupNavigationPanel();
+ setupEditProfileModal();
+ }
+
+ //To prevent warning: "leaking this in constructor java"
+ private void setupNavigationPanel() {
+ ((SyncopeApplication) getApplication()).setupNavigationPanel(this, xmlRolesReader, false);
+ }
+
+ private void setupEditProfileModal() {
+ ((SyncopeApplication) getApplication()).setupEditProfileModal(this, userSelfRestClient);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/XMLEditorPopupPage.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/XMLEditorPopupPage.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/XMLEditorPopupPage.java
new file mode 100644
index 0000000..b5a8d10
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/pages/XMLEditorPopupPage.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.pages;
+
+import java.io.IOException;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.WorkflowRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.wicket.util.io.IOUtils;
+
+public class XMLEditorPopupPage extends BasePopupPage {
+
+ private static final long serialVersionUID = 5816041644635271734L;
+
+ @SpringBean
+ private WorkflowRestClient wfRestClient;
+
+ public XMLEditorPopupPage() {
+ Form wfForm = new Form("workflowDefForm");
+
+ String definition;
+ try {
+ definition = IOUtils.toString(wfRestClient.getDefinition(MediaType.APPLICATION_XML_TYPE));
+ } catch (IOException e) {
+ LOG.error("Could not get workflow definition", e);
+ definition = StringUtils.EMPTY;
+ }
+ final TextArea<String> workflowDefArea = new TextArea<String>("workflowDefArea", new Model<String>(definition));
+ wfForm.add(workflowDefArea);
+
+ AjaxButton submit =
+ new ClearIndicatingAjaxButton(APPLY, new Model<String>(getString(SUBMIT)), getPageReference()) {
+
+ private static final long serialVersionUID = -958724007591692537L;
+
+ @Override
+ protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+ try {
+ wfRestClient.updateDefinition(
+ MediaType.APPLICATION_XML_TYPE, workflowDefArea.getModelObject());
+ info(getString(Constants.OPERATION_SUCCEEDED));
+ } catch (SyncopeClientException scee) {
+ error(getString(Constants.ERROR) + ": " + scee.getMessage());
+ }
+ feedbackPanel.refresh(target);
+ }
+
+ @Override
+ protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+ feedbackPanel.refresh(target);
+ }
+ };
+
+ final Button close = new Button("closePage", new Model<String>(getString(CANCEL)));
+
+ MetaDataRoleAuthorizationStrategy.authorize(
+ submit, ENABLE, xmlRolesReader.getEntitlement("Configuration", "workflowDefUpdate"));
+ wfForm.add(submit);
+ wfForm.add(close);
+ this.add(wfForm);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractProvisioningTasksPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractProvisioningTasksPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractProvisioningTasksPanel.java
new file mode 100644
index 0000000..e066aac
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractProvisioningTasksPanel.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.PushTaskModalPage;
+import org.apache.syncope.client.console.pages.SyncTaskModalPage;
+import org.apache.syncope.client.console.pages.Tasks;
+import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.request.http.WebResponse;
+
+public abstract class AbstractProvisioningTasksPanel<T extends AbstractProvisioningTaskTO> extends AbstractTasks {
+
+ private static final long serialVersionUID = -8674781241465369244L;
+
+ private final int paginatorRows;
+
+ protected WebMarkupContainer container;
+
+ protected ModalWindow window;
+
+ protected AjaxDataTablePanel<AbstractTaskTO, String> table;
+
+ private final Class<T> reference;
+
+ public AbstractProvisioningTasksPanel(final String id, final PageReference pageRef, final Class<T> reference) {
+ super(id, pageRef);
+
+ this.reference = reference;
+
+ container = new WebMarkupContainer("container");
+ container.setOutputMarkupId(true);
+ add(container);
+
+ window = new ModalWindow("taskWin");
+ window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ window.setInitialHeight(WIN_HEIGHT);
+ window.setInitialWidth(WIN_WIDTH);
+ window.setCookieName(VIEW_TASK_WIN_COOKIE_NAME);
+ add(window);
+
+ ((Tasks) pageRef.getPage()).setWindowClosedCallback(window, container);
+
+ paginatorRows = prefMan.getPaginatorRows(getWebRequest(), Constants.PREF_SYNC_TASKS_PAGINATOR_ROWS);
+ }
+
+ @Override
+ public void onEvent(final IEvent<?> event) {
+ if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
+ ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(container);
+ }
+ }
+
+ protected void initTasksTable() {
+
+ table = Tasks.updateTaskTable(
+ getColumns(),
+ new TasksProvider<T>(restClient, paginatorRows, getId(), this.reference),
+ container,
+ 0,
+ this.pageRef,
+ restClient);
+
+ Form paginatorForm = new Form("PaginatorForm");
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
+ prefMan.getPaginatorChoices());
+
+ rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ prefMan.set(getWebRequest(), (WebResponse) getResponse(), Constants.PREF_SYNC_TASKS_PAGINATOR_ROWS,
+ String.valueOf(paginatorRows));
+
+ table = Tasks.updateTaskTable(
+ getColumns(),
+ new TasksProvider<T>(restClient, paginatorRows, getId(), reference),
+ container,
+ table == null ? 0 : (int) table.getCurrentPage(),
+ pageRef,
+ restClient);
+
+ target.add(container);
+ }
+ });
+
+ paginatorForm.add(rowsChooser);
+ container.add(paginatorForm);
+
+ // create new task
+ AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", pageRef) {
+
+ private static final long serialVersionUID = -7978723352517770644L;
+
+ @Override
+ protected void onClickInternal(final AjaxRequestTarget target) {
+ window.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690940L;
+
+ @Override
+ public Page createPage() {
+ return reference.equals(SyncTaskTO.class)
+ ? new SyncTaskModalPage(window, new SyncTaskTO(), pageRef)
+ : new PushTaskModalPage(window, new PushTaskTO(), pageRef);
+ }
+ });
+
+ window.show(target);
+ }
+ };
+
+ MetaDataRoleAuthorizationStrategy.authorize(
+ createLink, RENDER, xmlRolesReader.getEntitlement(TASKS, "create"));
+
+ add(createLink);
+
+ }
+
+ protected abstract List<IColumn<AbstractTaskTO, String>> getColumns();
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchPanel.java
new file mode 100644
index 0000000..aa30fae
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchPanel.java
@@ -0,0 +1,401 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.cxf.jaxrs.ext.search.ConditionType;
+import org.apache.cxf.jaxrs.ext.search.SearchBean;
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.jaxrs.ext.search.client.CompleteCondition;
+import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
+import org.apache.syncope.client.console.rest.AuthRestClient;
+import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.rest.SchemaRestClient;
+import org.apache.syncope.common.lib.search.RoleFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.search.SearchableFields;
+import org.apache.syncope.common.lib.search.SpecialAttr;
+import org.apache.syncope.common.lib.search.SyncopeFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.search.SyncopeProperty;
+import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.wicket.feedback.FeedbackMessage;
+import org.apache.wicket.feedback.IFeedbackMessageFilter;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractSearchPanel extends Panel {
+
+ private static final long serialVersionUID = 5922413053568696414L;
+
+ /**
+ * Logger.
+ */
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractSearchPanel.class);
+
+ @SpringBean
+ protected SchemaRestClient schemaRestClient;
+
+ @SpringBean
+ protected ResourceRestClient resourceRestClient;
+
+ @SpringBean
+ protected AuthRestClient authRestClient;
+
+ protected IModel<List<String>> dnames;
+
+ protected IModel<List<String>> anames;
+
+ protected IModel<List<String>> resourceNames;
+
+ protected IModel<List<String>> entitlements;
+
+ protected IModel<List<SearchClause.Type>> types;
+
+ protected IModel<List<String>> roleNames;
+
+ protected NotificationPanel searchFeedback;
+
+ protected List<SearchClause> searchClauses;
+
+ protected WebMarkupContainer searchFormContainer;
+
+ protected AttributableType attributableType;
+
+ protected boolean required;
+
+ protected AbstractSearchPanel(final String id, final AttributableType attributableType) {
+ this(id, attributableType, null, true);
+ }
+
+ protected AbstractSearchPanel(final String id, final AttributableType attributableType,
+ final String fiql, final boolean required) {
+
+ super(id);
+ populate();
+
+ this.attributableType = attributableType;
+ this.required = required;
+
+ setOutputMarkupId(true);
+
+ searchFormContainer = new WebMarkupContainer("searchFormContainer");
+ searchFormContainer.setOutputMarkupId(true);
+
+ searchFeedback = new NotificationPanel("searchFeedback", "notificationpanel_top_right",
+ new IFeedbackMessageFilter() {
+
+ private static final long serialVersionUID = 6895024863321391672L;
+
+ @Override
+ public boolean accept(final FeedbackMessage message) {
+ boolean result;
+
+ // messages reported on the session have a null reporter
+ if (message.getReporter() == null) {
+ result = false;
+ } else {
+ // only accept messages coming from the children of the search form container
+ result = searchFormContainer.contains(message.getReporter(), true);
+ }
+
+ return result;
+ }
+ });
+ searchFeedback.setOutputMarkupId(true);
+ add(searchFeedback);
+
+ this.searchClauses = new ArrayList<SearchClause>();
+ this.searchClauses.add(new SearchClause());
+ if (StringUtils.isNotBlank(fiql)) {
+ try {
+ FiqlParser<SearchBean> fiqlParser = new FiqlParser<SearchBean>(
+ SearchBean.class, SyncopeFiqlSearchConditionBuilder.CONTEXTUAL_PROPERTIES);
+ List<SearchClause> parsed = getSearchClauses(fiqlParser.parse(fiql));
+
+ this.searchClauses.clear();
+ this.searchClauses.addAll(parsed);
+ } catch (Exception e) {
+ LOG.error("Unparseable FIQL expression '{}'", fiql, e);
+ }
+ }
+
+ searchFormContainer.add(new SearchView("searchView", searchClauses, searchFormContainer, required,
+ types, anames, dnames, roleNames, resourceNames, entitlements));
+ add(searchFormContainer);
+ }
+
+ protected void populate() {
+ dnames = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ return SearchableFields.get(attributableType == AttributableType.USER
+ ? SubjectType.USER : SubjectType.ROLE);
+ }
+ };
+
+ anames = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ return schemaRestClient.getSchemaNames(attributableType);
+ }
+ };
+
+ resourceNames = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ List<ResourceTO> resourceTOs = resourceRestClient.getAll();
+
+ List<String> result = new ArrayList<>(resourceTOs.size());
+
+ for (ResourceTO resource : resourceTOs) {
+ result.add(resource.getKey());
+ }
+
+ return result;
+ }
+ };
+
+ entitlements = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ List<String> result = authRestClient.getOwnedEntitlements();
+ Collections.sort(result);
+ return result;
+ }
+ };
+ }
+
+ public NotificationPanel getSearchFeedback() {
+ return searchFeedback;
+ }
+
+ private SearchClause getPrimitiveSearchClause(final SearchCondition<SearchBean> sc) {
+ SearchClause searchClause = new SearchClause();
+
+ String property = sc.getCondition().getKeySet().iterator().next();
+ searchClause.setProperty(property);
+ String value = sc.getCondition().get(property);
+ searchClause.setValue(value);
+
+ if (SpecialAttr.ROLES.toString().equals(property)) {
+ searchClause.setType(SearchClause.Type.MEMBERSHIP);
+ for (String label : roleNames.getObject()) {
+ if (value.equals(label.substring(0, label.indexOf(' ')))) {
+ searchClause.setProperty(label);
+ }
+ }
+ } else if (SpecialAttr.RESOURCES.toString().equals(property)) {
+ searchClause.setType(SearchClause.Type.RESOURCE);
+ } else if (SpecialAttr.ENTITLEMENTS.toString().equals(property)) {
+ searchClause.setType(SearchClause.Type.ENTITLEMENT);
+ } else {
+ searchClause.setType(SearchClause.Type.ATTRIBUTE);
+ }
+
+ switch (sc.getConditionType()) {
+ case EQUALS:
+ searchClause.setComparator(SpecialAttr.NULL.toString().equals(value)
+ ? SearchClause.Comparator.IS_NULL : SearchClause.Comparator.EQUALS);
+ break;
+
+ case NOT_EQUALS:
+ searchClause.setComparator(SpecialAttr.NULL.toString().equals(value)
+ ? SearchClause.Comparator.IS_NOT_NULL : SearchClause.Comparator.NOT_EQUALS);
+ break;
+
+ case GREATER_OR_EQUALS:
+ searchClause.setComparator(SearchClause.Comparator.GREATER_OR_EQUALS);
+ break;
+
+ case GREATER_THAN:
+ searchClause.setComparator(SearchClause.Comparator.GREATER_THAN);
+ break;
+
+ case LESS_OR_EQUALS:
+ searchClause.setComparator(SearchClause.Comparator.LESS_OR_EQUALS);
+ break;
+
+ case LESS_THAN:
+ searchClause.setComparator(SearchClause.Comparator.LESS_THAN);
+ break;
+
+ default:
+ break;
+ }
+
+ return searchClause;
+ }
+
+ private List<SearchClause> getCompoundSearchClause(final SearchCondition<SearchBean> sc) {
+ List<SearchClause> clauses = new ArrayList<SearchClause>();
+
+ for (SearchCondition<SearchBean> searchCondition : sc.getSearchConditions()) {
+ if (searchCondition.getStatement() == null) {
+ clauses.addAll(getCompoundSearchClause(searchCondition));
+ } else {
+ SearchClause clause = getPrimitiveSearchClause(searchCondition);
+ if (sc.getConditionType() == ConditionType.AND) {
+ clause.setOperator(SearchClause.Operator.AND);
+ }
+ if (sc.getConditionType() == ConditionType.OR) {
+ clause.setOperator(SearchClause.Operator.OR);
+ }
+ clauses.add(clause);
+ }
+ }
+
+ return clauses;
+ }
+
+ private List<SearchClause> getSearchClauses(final SearchCondition<SearchBean> sc) {
+ List<SearchClause> clauses = new ArrayList<SearchClause>();
+
+ if (sc.getStatement() == null) {
+ clauses.addAll(getCompoundSearchClause(sc));
+ } else {
+ clauses.add(getPrimitiveSearchClause(sc));
+ }
+
+ return clauses;
+ }
+
+ protected abstract SyncopeFiqlSearchConditionBuilder getSearchConditionBuilder();
+
+ public String buildFIQL() {
+ LOG.debug("Generating FIQL from List<SearchClause>: {}", searchClauses);
+
+ if (searchClauses.isEmpty() || searchClauses.get(0).getType() == null) {
+ return StringUtils.EMPTY;
+ }
+
+ SyncopeFiqlSearchConditionBuilder builder = getSearchConditionBuilder();
+
+ CompleteCondition prevCondition;
+ CompleteCondition condition = null;
+ for (int i = 0; i < searchClauses.size(); i++) {
+ prevCondition = condition;
+
+ switch (searchClauses.get(i).getType()) {
+ case ENTITLEMENT:
+ condition = searchClauses.get(i).getComparator() == SearchClause.Comparator.EQUALS
+ ? ((RoleFiqlSearchConditionBuilder) builder).
+ hasEntitlements(searchClauses.get(i).getProperty())
+ : ((RoleFiqlSearchConditionBuilder) builder).
+ hasNotEntitlements(searchClauses.get(i).getProperty());
+ break;
+
+ case MEMBERSHIP:
+ Long roleId = NumberUtils.toLong(searchClauses.get(i).getProperty().split(" ")[0]);
+ condition = searchClauses.get(i).getComparator() == SearchClause.Comparator.EQUALS
+ ? ((UserFiqlSearchConditionBuilder) builder).hasRoles(roleId)
+ : ((UserFiqlSearchConditionBuilder) builder).hasNotRoles(roleId);
+ break;
+
+ case RESOURCE:
+ condition = searchClauses.get(i).getComparator() == SearchClause.Comparator.EQUALS
+ ? builder.hasResources(searchClauses.get(i).getProperty())
+ : builder.hasNotResources(searchClauses.get(i).getProperty());
+ break;
+
+ case ATTRIBUTE:
+ SyncopeProperty property = builder.is(searchClauses.get(i).getProperty());
+ switch (searchClauses.get(i).getComparator()) {
+ case IS_NULL:
+ condition = builder.isNull(searchClauses.get(i).getProperty());
+ break;
+
+ case IS_NOT_NULL:
+ condition = builder.isNotNull(searchClauses.get(i).getProperty());
+ break;
+
+ case LESS_THAN:
+ condition = StringUtils.isNumeric(searchClauses.get(i).getProperty())
+ ? property.lessThan(NumberUtils.toDouble(searchClauses.get(i).getValue()))
+ : property.lexicalBefore(searchClauses.get(i).getValue());
+ break;
+
+ case LESS_OR_EQUALS:
+ condition = StringUtils.isNumeric(searchClauses.get(i).getProperty())
+ ? property.lessOrEqualTo(NumberUtils.toDouble(searchClauses.get(i).getValue()))
+ : property.lexicalNotAfter(searchClauses.get(i).getValue());
+ break;
+
+ case GREATER_THAN:
+ condition = StringUtils.isNumeric(searchClauses.get(i).getProperty())
+ ? property.greaterThan(NumberUtils.toDouble(searchClauses.get(i).getValue()))
+ : property.lexicalAfter(searchClauses.get(i).getValue());
+ break;
+
+ case GREATER_OR_EQUALS:
+ condition = StringUtils.isNumeric(searchClauses.get(i).getProperty())
+ ? property.greaterOrEqualTo(NumberUtils.toDouble(searchClauses.get(i).getValue()))
+ : property.lexicalNotBefore(searchClauses.get(i).getValue());
+ break;
+
+ case NOT_EQUALS:
+ condition = property.notEqualTo(searchClauses.get(i).getValue());
+ break;
+
+ case EQUALS:
+ default:
+ condition = property.equalTo(searchClauses.get(i).getValue());
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (i > 0) {
+ if (searchClauses.get(i).getOperator() == SearchClause.Operator.AND) {
+ condition = builder.and(prevCondition, condition);
+ }
+ if (searchClauses.get(i).getOperator() == SearchClause.Operator.OR) {
+ condition = builder.or(prevCondition, condition);
+ }
+ }
+ }
+
+ String fiql = condition == null ? StringUtils.EMPTY : condition.query();
+ LOG.debug("Generated FIQL: {}", fiql);
+ return fiql;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
new file mode 100644
index 0000000..386392c
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.client.console.commons.AttributableDataProvider;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.pages.AbstractBasePage;
+import org.apache.syncope.client.console.rest.AbstractSubjectRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.event.IEventSource;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractSearchResultPanel extends Panel implements IEventSource {
+
+ private static final long serialVersionUID = -9170191461250434024L;
+
+ /**
+ * Logger.
+ */
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractSearchResultPanel.class);
+
+ /**
+ * Edit modal window height.
+ */
+ private final static int EDIT_MODAL_WIN_HEIGHT = 550;
+
+ /**
+ * Edit modal window width.
+ */
+ private final static int EDIT_MODAL_WIN_WIDTH = 800;
+
+ /**
+ * Schemas to be shown modal window height.
+ */
+ private final static int DISPLAYATTRS_MODAL_WIN_HEIGHT = 550;
+
+ /**
+ * Schemas to be shown modal window width.
+ */
+ private final static int DISPLAYATTRS_MODAL_WIN_WIDTH = 550;
+
+ /**
+ * Schemas to be shown modal window height.
+ */
+ private final static int STATUS_MODAL_WIN_HEIGHT = 500;
+
+ /**
+ * Schemas to be shown modal window width.
+ */
+ private final static int STATUS_MODAL_WIN_WIDTH = 700;
+
+ /**
+ * Application preferences.
+ */
+ @SpringBean
+ protected PreferenceManager prefMan;
+
+ /**
+ * Role reader for authorizations management.
+ */
+ @SpringBean
+ protected XMLRolesReader xmlRolesReader;
+
+ protected final AbstractSubjectRestClient restClient;
+
+ /**
+ * Number of rows per page.
+ */
+ private final int rows;
+
+ /**
+ * Container used to refresh table.
+ */
+ protected final WebMarkupContainer container;
+
+ /**
+ * Feedback panel specified by the caller.
+ */
+ protected final NotificationPanel feedbackPanel;
+
+ /**
+ * Specify if results are about a filtered search or not. Using this attribute it is possible to use this panel to
+ * show results about user list and user search.
+ */
+ private final boolean filtered;
+
+ /**
+ * Filter used in case of filtered search.
+ */
+ private String fiql;
+
+ /**
+ * Result table.
+ */
+ private AjaxDataTablePanel<AbstractAttributableTO, String> resultTable;
+
+ /**
+ * Data provider used to search for users.
+ */
+ private AttributableDataProvider dataProvider;
+
+ /**
+ * Modal window to be used for user profile editing. Global visibility is required ...
+ */
+ protected final ModalWindow editmodal = new ModalWindow("editModal");
+
+ /**
+ * Modal window to be used for attributes choosing to display in tables.
+ */
+ protected final ModalWindow displaymodal = new ModalWindow("displayModal");
+
+ /**
+ * Modal window to be used for user status management.
+ */
+ protected final ModalWindow statusmodal = new ModalWindow("statusModal");
+
+ /**
+ * Owner page.
+ */
+ protected final AbstractBasePage page;
+
+ protected <T extends AbstractAttributableTO> AbstractSearchResultPanel(final String id, final boolean filtered,
+ final String fiql, final PageReference pageRef, final AbstractSubjectRestClient restClient) {
+
+ super(id);
+
+ setOutputMarkupId(true);
+
+ this.page = (AbstractBasePage) pageRef.getPage();
+
+ this.filtered = filtered;
+ this.fiql = fiql;
+ this.feedbackPanel = page.getFeedbackPanel();
+
+ this.restClient = restClient;
+
+ editmodal.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ editmodal.setInitialHeight(EDIT_MODAL_WIN_HEIGHT);
+ editmodal.setInitialWidth(EDIT_MODAL_WIN_WIDTH);
+ editmodal.setCookieName("edit-modal");
+ add(editmodal);
+
+ displaymodal.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ displaymodal.setInitialHeight(DISPLAYATTRS_MODAL_WIN_HEIGHT);
+ displaymodal.setInitialWidth(DISPLAYATTRS_MODAL_WIN_WIDTH);
+ displaymodal.setCookieName("display-modal");
+ add(displaymodal);
+
+ statusmodal.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ statusmodal.setInitialHeight(STATUS_MODAL_WIN_HEIGHT);
+ statusmodal.setInitialWidth(STATUS_MODAL_WIN_WIDTH);
+ statusmodal.setCookieName("status-modal");
+ add(statusmodal);
+
+ // Container for user search result
+ container = new WebMarkupContainer("container");
+ container.setOutputMarkupId(true);
+ add(container);
+
+ rows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_USERS_PAGINATOR_ROWS);
+ }
+
+ protected void initResultTable() {
+ // ---------------------------
+ // Result table initialization
+ // ---------------------------
+ updateResultTable(false);
+ // ---------------------------
+
+ // ---------------------------
+ // Rows-per-page selector
+ // ---------------------------
+ final Form paginatorForm = new Form("paginator");
+ container.add(paginatorForm);
+
+ final DropDownChoice<Integer> rowsChooser = new DropDownChoice<Integer>(
+ "rowsChooser", new PropertyModel<Integer>(this, "rows"), prefMan.getPaginatorChoices());
+
+ rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ prefMan.set(getRequest(), getResponse(), Constants.PREF_USERS_PAGINATOR_ROWS, String.valueOf(rows));
+
+ final EventDataWrapper data = new EventDataWrapper();
+ data.setTarget(target);
+ data.setRows(rows);
+
+ send(getParent(), Broadcast.BREADTH, data);
+ }
+ });
+ paginatorForm.add(rowsChooser);
+ // ---------------------------
+
+ setWindowClosedReloadCallback(statusmodal);
+ setWindowClosedReloadCallback(editmodal);
+ setWindowClosedReloadCallback(displaymodal);
+ }
+
+ public void search(final String fiql, final AjaxRequestTarget target) {
+ this.fiql = fiql;
+ dataProvider.setFIQL(fiql);
+ target.add(container);
+ }
+
+ private void updateResultTable(final boolean create) {
+ updateResultTable(create, rows);
+ }
+
+ private void updateResultTable(final boolean create, final int rows) {
+ dataProvider = new AttributableDataProvider(restClient, rows, filtered);
+ dataProvider.setFIQL(fiql);
+
+ final int currentPage = resultTable != null
+ ? (create
+ ? (int) resultTable.getPageCount() - 1
+ : (int) resultTable.getCurrentPage())
+ : 0;
+
+ resultTable = new AjaxDataTablePanel<AbstractAttributableTO, String>(
+ "resultTable",
+ getColumns(),
+ dataProvider,
+ rows,
+ getBulkActions(),
+ restClient,
+ "id",
+ getPageId(),
+ page.getPageReference());
+
+ resultTable.setCurrentPage(currentPage);
+
+ resultTable.setOutputMarkupId(true);
+
+ container.addOrReplace(resultTable);
+ }
+
+ protected abstract List<IColumn<AbstractAttributableTO, String>> getColumns();
+
+ @Override
+ public void onEvent(final IEvent<?> event) {
+ if (event.getPayload() instanceof EventDataWrapper) {
+ final EventDataWrapper data = (EventDataWrapper) event.getPayload();
+
+ if (data.getRows() < 1) {
+ updateResultTable(data.isCreate());
+ } else {
+ updateResultTable(data.isCreate(), data.getRows());
+ }
+
+ data.getTarget().add(container);
+ }
+ }
+
+ private void setWindowClosedReloadCallback(final ModalWindow window) {
+ window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+ private static final long serialVersionUID = 8804221891699487139L;
+
+ @Override
+ public void onClose(final AjaxRequestTarget target) {
+ final EventDataWrapper data = new EventDataWrapper();
+ data.setTarget(target);
+ data.setRows(rows);
+
+ send(getParent(), Broadcast.BREADTH, data);
+
+ if (page.isModalResult()) {
+ // reset modal result
+ page.setModalResult(false);
+ // set operation succeeded
+ getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+ // refresh feedback panel
+ feedbackPanel.refresh(target);
+ }
+ }
+ });
+ }
+
+ public static class EventDataWrapper {
+
+ private AjaxRequestTarget target;
+
+ private boolean create;
+
+ private int rows;
+
+ public AjaxRequestTarget getTarget() {
+ return target;
+ }
+
+ public void setTarget(final AjaxRequestTarget target) {
+ this.target = target;
+ }
+
+ public boolean isCreate() {
+ return create;
+ }
+
+ public void setCreate(boolean create) {
+ this.create = create;
+ }
+
+ public int getRows() {
+ return rows;
+ }
+
+ public void setRows(int rows) {
+ this.rows = rows;
+ }
+ }
+
+ protected abstract <T extends AbstractAttributableTO> Collection<ActionLink.ActionType> getBulkActions();
+
+ protected abstract String getPageId();
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java
new file mode 100644
index 0000000..381f878
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.rest.TaskRestClient;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public abstract class AbstractTasks extends Panel {
+
+ private static final long serialVersionUID = -1190836516156843561L;
+
+ protected static final String VIEW_TASK_WIN_COOKIE_NAME = "view-task-win";
+
+ protected static final int WIN_HEIGHT = 500;
+
+ protected static final int WIN_WIDTH = 700;
+
+ protected static final String TASKS = "Tasks";
+
+ protected PageReference pageRef;
+
+ @SpringBean
+ protected TaskRestClient restClient;
+
+ @SpringBean
+ protected PreferenceManager prefMan;
+
+ @SpringBean
+ protected XMLRolesReader xmlRolesReader;
+
+ public AbstractTasks(final String id, final PageReference pageRef) {
+ super(id);
+ this.pageRef = pageRef;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java
new file mode 100644
index 0000000..3bc7dd8
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeSession;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.Model;
+
+public class AccountInformationPanel extends AnnotatedBeanPanel {
+
+ private static final long serialVersionUID = 4228064224811390808L;
+
+ public <T extends AbstractAttributableTO> AccountInformationPanel(final String id, final UserTO userTO) {
+ super(id, userTO);
+
+ // ------------------------
+ // Change password date
+ // ------------------------
+ add(new Label("changePwdDate", new Model<String>(userTO.getChangePwdDate() == null
+ ? StringUtils.EMPTY
+ : SyncopeSession.get().getDateFormat().format(userTO.getChangePwdDate()))));
+ // ------------------------
+
+ // ------------------------
+ // Last login date
+ // ------------------------
+ add(new Label("lastLoginDate", new Model<String>(userTO.getLastLoginDate() == null
+ ? StringUtils.EMPTY
+ : SyncopeSession.get().getDateFormat().format(userTO.getLastLoginDate()))));
+ // ------------------------
+
+ // ------------------------
+ // Failed logins
+ // ------------------------
+ add(new Label("failedLogins", new Model<Integer>(userTO.getFailedLogins())));
+ // ------------------------
+
+ // ------------------------
+ // Token
+ // ------------------------
+ add(new Label("token", new Model<String>(userTO.getToken() == null
+ ? StringUtils.EMPTY
+ : userTO.getToken())));
+ // ------------------------
+
+ // ------------------------
+ // Token expire time
+ // ------------------------
+ add(new Label("tokenExpireTime", new Model<String>(userTO.getTokenExpireTime() == null
+ ? StringUtils.EMPTY
+ : SyncopeSession.get().getDateFormat().format(userTO.getTokenExpireTime()))));
+ // ------------------------
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
new file mode 100644
index 0000000..bfade98
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.client.console.commons.ActionTableCheckGroup;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+
+public class ActionDataTablePanel<T, S> extends DataTablePanel<T, S> {
+
+ private static final long serialVersionUID = -8826989026203543957L;
+
+ private static final String CANCEL = "cancel";
+
+ private final Form<T> bulkActionForm;
+
+ private final ActionLinksPanel actionPanel;
+
+ private final PageReference pageRef;
+
+ public ActionDataTablePanel(
+ final String id,
+ final List<IColumn<T, S>> columns,
+ final ISortableDataProvider<T, S> dataProvider,
+ final int rowsPerPage,
+ final PageReference pageRef) {
+
+ super(id);
+
+ this.pageRef = pageRef;
+
+ bulkActionForm = new Form<T>("groupForm");
+ add(bulkActionForm);
+
+ group = new ActionTableCheckGroup<T>("checkgroup", model) {
+
+ private static final long serialVersionUID = -8667764190925075389L;
+
+ @Override
+ public boolean isCheckable(final T element) {
+ return isElementEnabled(element);
+ }
+ };
+ group.add(new AjaxFormChoiceComponentUpdatingBehavior() {
+
+ private static final long serialVersionUID = -151291731388673682L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ // triggers AJAX form submit
+ }
+ });
+ bulkActionForm.add(group);
+
+ columns.add(0, new CheckGroupColumn<T, S>(group));
+ dataTable = new AjaxFallbackDefaultDataTable<T, S>("dataTable", columns, dataProvider, rowsPerPage);
+ group.add(dataTable);
+
+ final WebMarkupContainer actionPanelContainer = new WebMarkupContainer("actionPanelContainer");
+ bulkActionForm.add(actionPanelContainer);
+
+ actionPanel = new ActionLinksPanel("actions", new Model(), pageRef);
+ actionPanelContainer.add(actionPanel);
+
+ if (dataTable.getRowCount() == 0) {
+ actionPanelContainer.add(new AttributeModifier("style", "display: none"));
+ }
+
+ bulkActionForm.add(new ClearIndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL), pageRef) {
+
+ private static final long serialVersionUID = -2341391430136818025L;
+
+ @Override
+ protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+ // ignore
+ }
+ }.setVisible(false).setEnabled(false));
+ }
+
+ public void addAction(final ActionLink action, final ActionType type, final String pageId) {
+ actionPanel.add(action, type, pageId);
+ }
+
+ public void addAction(final ActionLink action, final ActionType type, final String pageId, final String actionId) {
+ actionPanel.add(action, type, pageId, actionId);
+ }
+
+ public void addAction(final ActionLink action, final ActionType type, final String pageId, final boolean enabled) {
+ actionPanel.add(action, type, pageId, enabled);
+ }
+
+ public void addCancelButton(final ModalWindow window) {
+
+ final AjaxButton cancel = new ClearIndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL), pageRef) {
+
+ private static final long serialVersionUID = -2341391430136818025L;
+
+ @Override
+ protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+ window.close(target);
+ }
+ }.feedbackPanelAutomaticReload(false);
+
+ cancel.setDefaultFormProcessing(false);
+ bulkActionForm.addOrReplace(cancel);
+ }
+
+ public Collection<T> getModelObject() {
+ return group.getModelObject();
+ }
+
+ public boolean isElementEnabled(final T element) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
new file mode 100644
index 0000000..563bd17
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.client.console.rest.BaseRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.panels.AbstractSearchResultPanel.EventDataWrapper;
+import org.apache.syncope.client.console.pages.AbstractBasePage;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.pages.BulkActionModalPage;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.markup.html.form.CheckGroup;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Fragment;
+
+public class AjaxDataTablePanel<T, S> extends DataTablePanel<T, S> {
+
+ private static final long serialVersionUID = -7264400471578272966L;
+
+ public AjaxDataTablePanel(
+ final String id,
+ final List<IColumn<T, S>> columns,
+ final ISortableDataProvider<T, S> dataProvider,
+ final int rowsPerPage,
+ final Collection<ActionLink.ActionType> actions,
+ final BaseRestClient bulkActionExecutor,
+ final String itemIdField,
+ final String pageId,
+ final PageReference pageRef) {
+
+ super(id);
+
+ final ModalWindow bulkModalWin = new ModalWindow("bulkModal");
+ bulkModalWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+ bulkModalWin.setInitialHeight(600);
+ bulkModalWin.setInitialWidth(900);
+ bulkModalWin.setCookieName("bulk-modal");
+ add(bulkModalWin);
+
+ bulkModalWin.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+ private static final long serialVersionUID = 8804221891699487149L;
+
+ @Override
+ public void onClose(final AjaxRequestTarget target) {
+ final EventDataWrapper data = new EventDataWrapper();
+ data.setTarget(target);
+ data.setRows(rowsPerPage);
+
+ send(pageRef.getPage(), Broadcast.BREADTH, data);
+
+ final AbstractBasePage page = (AbstractBasePage) pageRef.getPage();
+
+ if (page.isModalResult()) {
+ // reset modal result
+ page.setModalResult(false);
+ // set operation succeeded
+ getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+ // refresh feedback panel
+ target.add(page.getFeedbackPanel());
+ }
+ }
+ });
+
+ Fragment fragment = new Fragment("tablePanel", "bulkAvailable", this);
+ add(fragment);
+
+ Form<T> bulkActionForm = new Form<>("groupForm");
+ fragment.add(bulkActionForm);
+
+ group = new CheckGroup<>("checkgroup", model);
+ group.add(new AjaxFormChoiceComponentUpdatingBehavior() {
+
+ private static final long serialVersionUID = -151291731388673682L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ // triggers AJAX form submit
+ }
+ });
+ bulkActionForm.add(group);
+
+ columns.add(0, new CheckGroupColumn<T, S>(group));
+ dataTable = new AjaxFallbackDefaultDataTable<>("dataTable", columns, dataProvider, rowsPerPage);
+ group.add(dataTable);
+
+ fragment.add(new ClearIndicatingAjaxButton("bulkActionLink", bulkActionForm, pageRef) {
+
+ private static final long serialVersionUID = 382302811235019988L;
+
+ @Override
+ protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+ bulkModalWin.setPageCreator(new ModalWindow.PageCreator() {
+
+ private static final long serialVersionUID = -7834632442532690941L;
+
+ @Override
+ public Page createPage() {
+ return new BulkActionModalPage<>(
+ bulkModalWin,
+ group.getModelObject(),
+ columns,
+ actions,
+ bulkActionExecutor,
+ itemIdField,
+ pageId);
+ }
+ });
+
+ bulkModalWin.show(target);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java
new file mode 100644
index 0000000..714cb5f
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.panels;
+
+import org.apache.syncope.client.console.SyncopeSession;
+import org.apache.syncope.common.lib.to.AbstractAnnotatedBean;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+public class AnnotatedBeanPanel extends Panel {
+
+ private static final long serialVersionUID = 4228064224811390809L;
+
+ public <T extends AbstractAttributableTO> AnnotatedBeanPanel(
+ final String id, final AbstractAnnotatedBean sysInfoTO) {
+
+ super(id);
+
+ // ------------------------
+ // Creation date
+ // ------------------------
+ add(new Label("creationDate", new Model<String>(sysInfoTO.getCreationDate() != null
+ ? SyncopeSession.get().getDateFormat().format(sysInfoTO.getCreationDate()) : "")));
+ // ------------------------
+
+ // ------------------------
+ // Last change date
+ // ------------------------
+ add(new Label("lastChangeDate", new Model<String>(sysInfoTO.getLastChangeDate() != null
+ ? SyncopeSession.get().getDateFormat().format(sysInfoTO.getCreationDate()) : "")));
+ // ------------------------
+
+ // ------------------------
+ // Creator
+ // ------------------------
+ add(new Label("creator", new Model<String>(sysInfoTO.getCreator() != null
+ ? sysInfoTO.getCreator() : "")));
+ // ------------------------
+
+ // ------------------------
+ // Last modifier
+ // ------------------------
+ add(new Label("lastModifier", new Model<String>(sysInfoTO.getLastModifier() != null
+ ? sysInfoTO.getLastModifier() : "")));
+ // ------------------------
+
+ }
+}