http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractSearchResultPanel.java new file mode 100644 index 0000000..6139ee4 --- /dev/null +++ b/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<>( + "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<>( + "resultTable", + getColumns(), + dataProvider, + rows, + getBulkActions(), + restClient, + "key", + 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/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AbstractTasks.java new file mode 100644 index 0000000..381f878 --- /dev/null +++ b/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/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AccountInformationPanel.java new file mode 100644 index 0000000..3bc7dd8 --- /dev/null +++ b/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/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ActionDataTablePanel.java new file mode 100644 index 0000000..bfade98 --- /dev/null +++ b/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/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AjaxDataTablePanel.java new file mode 100644 index 0000000..563bd17 --- /dev/null +++ b/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/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnnotatedBeanPanel.java new file mode 100644 index 0000000..714cb5f --- /dev/null +++ b/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() : ""))); + // ------------------------ + + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/AttrTemplatesPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AttrTemplatesPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AttrTemplatesPanel.java new file mode 100644 index 0000000..1601ca7 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AttrTemplatesPanel.java @@ -0,0 +1,167 @@ +/* + * 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.Collections; +import java.util.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.SelectChoiceRenderer; +import org.apache.syncope.client.console.rest.SchemaRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.NonI18nPalette; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.syncope.common.lib.types.SchemaType; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.extensions.markup.html.form.palette.component.Recorder; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.util.ListModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class AttrTemplatesPanel extends Panel { + + public enum Type { + + rPlainAttrTemplates, + rDerAttrTemplates, + rVirAttrTemplates, + mPlainAttrTemplates, + mDerAttrTemplates, + mVirAttrTemplates; + + } + + private static final long serialVersionUID = 1016028222120619000L; + + @SpringBean + private SchemaRestClient schemaRestClient; + + private final RoleTO roleTO; + + private final NonI18nPalette<String> rPlainAttrTemplates; + + private final NonI18nPalette<String> rDerAttrTemplates; + + private final NonI18nPalette<String> rVirAttrTemplates; + + public AttrTemplatesPanel(final String id, final RoleTO roleTO) { + super(id); + this.roleTO = roleTO; + + rPlainAttrTemplates = buildPalette(Type.rPlainAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.ROLE, SchemaType.PLAIN)); + this.add(rPlainAttrTemplates); + rDerAttrTemplates = buildPalette(Type.rDerAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.ROLE, SchemaType.DERIVED)); + this.add(rDerAttrTemplates); + rVirAttrTemplates = buildPalette(Type.rVirAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.ROLE, SchemaType.VIRTUAL)); + this.add(rVirAttrTemplates); + + this.add(buildPalette(Type.mPlainAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.MEMBERSHIP, SchemaType.PLAIN))); + this.add(buildPalette(Type.mDerAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.MEMBERSHIP, SchemaType.DERIVED))); + this.add(buildPalette(Type.mVirAttrTemplates, + schemaRestClient.getSchemaNames(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL))); + } + + private NonI18nPalette<String> buildPalette(final Type type, final List<String> allSchemas) { + if (allSchemas != null && !allSchemas.isEmpty()) { + Collections.sort(allSchemas); + } + ListModel<String> availableSchemas = new ListModel<>(allSchemas); + + return new NonI18nPalette<String>(type.name(), new PropertyModel<List<String>>(roleTO, type.name()), + availableSchemas, new SelectChoiceRenderer<String>(), 8, false, true) { + + private static final long serialVersionUID = 2295567122085510330L; + + @Override + protected Recorder<String> newRecorderComponent() { + final Recorder<String> recorder = super.newRecorderComponent(); + + switch (type) { + case rPlainAttrTemplates: + case rDerAttrTemplates: + case rVirAttrTemplates: + recorder.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + send(getPage(), Broadcast.BREADTH, new RoleAttrTemplatesChange(type, target)); + } + }); + break; + + default: + } + + return recorder; + } + }; + } + + public Collection<String> getSelected(final Type type) { + Collection<String> selected; + switch (type) { + case rPlainAttrTemplates: + selected = this.rPlainAttrTemplates.getModelCollection(); + break; + + case rDerAttrTemplates: + selected = this.rDerAttrTemplates.getModelCollection(); + break; + + case rVirAttrTemplates: + selected = this.rVirAttrTemplates.getModelCollection(); + break; + + default: + selected = Collections.emptyList(); + } + + return selected; + } + + public static class RoleAttrTemplatesChange { + + private final Type type; + + private final AjaxRequestTarget target; + + public RoleAttrTemplatesChange(final Type type, final AjaxRequestTarget target) { + this.type = type; + this.target = target; + } + + public Type getType() { + return type; + } + + public AjaxRequestTarget getTarget() { + return target; + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/DataTablePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/DataTablePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/DataTablePanel.java new file mode 100644 index 0000000..a5f6588 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/DataTablePanel.java @@ -0,0 +1,113 @@ +/* + * 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.HashSet; +import java.util.Iterator; +import java.util.Set; +import org.apache.wicket.Component; +import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable; +import org.apache.wicket.extensions.markup.html.repeater.data.grid.DataGridView; +import org.apache.wicket.markup.html.form.CheckGroup; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.IModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class DataTablePanel<T, S> extends Panel { + + private static final long serialVersionUID = -7264400471578272966L; + + /** + * Logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(DataTablePanel.class); + + protected CheckGroup<T> group; + + protected AjaxFallbackDefaultDataTable<T, S> dataTable; + + protected IModel<Collection<T>> model; + + public DataTablePanel(final String id) { + super(id); + + model = new IModel<Collection<T>>() { + + private static final long serialVersionUID = 4886729136344643465L; + + private Collection<T> values = new HashSet<T>(); + + @Override + public Collection<T> getObject() { + // Someone or something call this method to change the model: this is not the right behavior. + // Return a copy of the model object in order to avoid SYNCOPE-465 + return new HashSet<T>(values); + } + + @Override + public void setObject(final Collection<T> selected) { + final Collection<T> all = getGroupModelObjects(); + values.removeAll(all); + values.addAll(selected); + } + + @Override + public void detach() { + } + }; + } + + public final void setCurrentPage(final long page) { + dataTable.setCurrentPage(page); + } + + public final long getRowCount() { + return dataTable.getRowCount(); + } + + public final long getCurrentPage() { + return dataTable.getCurrentPage(); + } + + public final long getPageCount() { + return dataTable.getPageCount(); + } + + public void setItemsPerPage(final int resourcePaginatorRows) { + dataTable.setItemsPerPage(resourcePaginatorRows); + } + + protected Collection<T> getGroupModelObjects() { + final Set<T> res = new HashSet<T>(); + + final Component rows = group.get("dataTable:body:rows"); + if (rows instanceof DataGridView) { + @SuppressWarnings("unchecked") + final Iterator<Item<T>> iter = ((DataGridView<T>) rows).getItems(); + + while (iter.hasNext()) { + res.add(iter.next().getModelObject()); + } + } + return res; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/DerAttrsPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/DerAttrsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/DerAttrsPanel.java new file mode 100644 index 0000000..d68038f --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/DerAttrsPanel.java @@ -0,0 +1,206 @@ +/* + * 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.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.panels.AttrTemplatesPanel.RoleAttrTemplatesChange; +import org.apache.syncope.client.console.rest.RoleRestClient; +import org.apache.syncope.client.console.rest.SchemaRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDecoratedCheckbox; +import org.apache.syncope.common.lib.to.AbstractAttributableTO; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.syncope.common.lib.to.MembershipTO; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.attributes.AjaxCallListener; +import org.apache.wicket.ajax.attributes.AjaxRequestAttributes; +import org.apache.wicket.ajax.attributes.IAjaxCallListener; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.event.IEvent; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; +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.form.TextField; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class DerAttrsPanel extends Panel { + + private static final long serialVersionUID = -5387344116983102292L; + + @SpringBean + private SchemaRestClient schemaRestClient; + + @SpringBean + private RoleRestClient roleRestClient; + + private final AttrTemplatesPanel attrTemplates; + + public <T extends AbstractAttributableTO> DerAttrsPanel(final String id, final T entityTO) { + this(id, entityTO, null); + } + + public <T extends AbstractAttributableTO> DerAttrsPanel(final String id, final T entityTO, + final AttrTemplatesPanel attrTemplates) { + + super(id); + this.attrTemplates = attrTemplates; + setOutputMarkupId(true); + + final IModel<List<String>> derSchemas = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + List<String> derSchemaNames; + + if (entityTO instanceof RoleTO) { + final RoleTO roleTO = (RoleTO) entityTO; + + if (attrTemplates == null) { + derSchemaNames = roleTO.getRDerAttrTemplates(); + } else { + derSchemaNames = new ArrayList<>( + attrTemplates.getSelected(AttrTemplatesPanel.Type.rDerAttrTemplates)); + if (roleTO.isInheritTemplates() && roleTO.getParent() != 0) { + derSchemaNames.addAll(roleRestClient.read(roleTO.getParent()).getRDerAttrTemplates()); + } + } + } else if (entityTO instanceof UserTO) { + derSchemaNames = schemaRestClient.getDerSchemaNames(AttributableType.USER); + } else { + derSchemaNames = roleRestClient.read(((MembershipTO) entityTO).getRoleId()).getMDerAttrTemplates(); + } + + return derSchemaNames; + } + }; + + final WebMarkupContainer attributesContainer = new WebMarkupContainer("derAttrContainer"); + + attributesContainer.setOutputMarkupId(true); + add(attributesContainer); + + AjaxButton addAttributeBtn = new IndicatingAjaxButton("addAttributeBtn", new ResourceModel("addAttributeBtn")) { + + private static final long serialVersionUID = -4804368561204623354L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + entityTO.getDerAttrs().add(new AttrTO()); + target.add(attributesContainer); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + target.add(attributesContainer); + } + }; + add(addAttributeBtn.setDefaultFormProcessing(false)); + + ListView<AttrTO> attributes = new ListView<AttrTO>("attrs", + new PropertyModel<List<? extends AttrTO>>(entityTO, "derAttrs")) { + + private static final long serialVersionUID = 9101744072914090143L; + + @Override + protected void populateItem(final ListItem<AttrTO> item) { + final AttrTO attributeTO = item.getModelObject(); + + item.add(new AjaxDecoratedCheckbox("toRemove", new Model<>(Boolean.FALSE)) { + + private static final long serialVersionUID = 7170946748485726506L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + entityTO.getDerAttrs().remove(attributeTO); + target.add(attributesContainer); + } + + @Override + protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) { + super.updateAjaxAttributes(attributes); + + IAjaxCallListener ajaxCallListener = new AjaxCallListener() { + + private static final long serialVersionUID = 7160235486520935153L; + + @Override + public CharSequence getPrecondition(final Component component) { + return "if (!confirm('" + getString("confirmDelete") + "')) return false;"; + } + }; + attributes.getAjaxCallListeners().add(ajaxCallListener); + } + }); + + final DropDownChoice<String> schemaChoice = new DropDownChoice<String>("schema", + new PropertyModel<String>(attributeTO, "schema"), derSchemas); + schemaChoice.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + attributeTO.setSchema(schemaChoice.getModelObject()); + } + }); + schemaChoice.setRequired(true); + schemaChoice.setOutputMarkupId(true); + schemaChoice.setRequired(true); + item.add(schemaChoice); + + final List<String> values = attributeTO.getValues(); + if (values == null || values.isEmpty()) { + item.add(new TextField<String>("value", + new Model<String>(null)).setVisible(false)); + } else { + item.add(new TextField<String>("value", + new Model<String>(values.get(0))).setEnabled(false)); + } + } + }; + attributesContainer.add(attributes); + } + + @Override + public void onEvent(final IEvent<?> event) { + if ((event.getPayload() instanceof RoleAttrTemplatesChange)) { + final RoleAttrTemplatesChange update = (RoleAttrTemplatesChange) event.getPayload(); + if (attrTemplates != null && update.getType() == AttrTemplatesPanel.Type.rDerAttrTemplates) { + update.getTarget().add(this); + } + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/EventSelectionPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/EventSelectionPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/EventSelectionPanel.java new file mode 100644 index 0000000..5332cb5 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/EventSelectionPanel.java @@ -0,0 +1,243 @@ +/* + * 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.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.wicket.markup.html.list.AltListView; +import org.apache.syncope.common.lib.to.EventCategoryTO; +import org.apache.syncope.common.lib.types.AuditElements; +import org.apache.syncope.common.lib.types.AuditLoggerName; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.event.IEvent; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Check; +import org.apache.wicket.markup.html.form.CheckGroup; +import org.apache.wicket.markup.html.form.CheckGroupSelector; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +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.ResourceModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class EventSelectionPanel extends Panel { + + /** + * Logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(EventSelectionPanel.class); + + private static final long serialVersionUID = 752233163798301002L; + + private final Set<String> selected = new HashSet<String>(); + + public EventSelectionPanel( + final String id, final EventCategoryTO eventCategoryTO, final IModel<List<String>> model) { + super(id); + setOutputMarkupId(true); + + final List<String> events = getEvents(eventCategoryTO); + + // needed to avoid model reset: model have to be managed into SelectedEventsPanel + selected.addAll(model.getObject()); + + final CheckGroup<String> successGroup = new CheckGroup<String>( + "successGroup", + selected); + + successGroup.add(new AjaxFormChoiceComponentUpdatingBehavior() { + + private static final long serialVersionUID = -151291731388673682L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + + final Set<String> toBeRemoved = new HashSet<>(); + final Set<String> toBeAdded = new HashSet<>(); + + for (String event : getEvents(eventCategoryTO)) { + final String eventString = AuditLoggerName.buildEvent( + eventCategoryTO.getType(), + eventCategoryTO.getCategory(), + eventCategoryTO.getSubcategory(), + event, + AuditElements.Result.SUCCESS); + + if (successGroup.getModelObject().contains(eventString)) { + toBeAdded.add(eventString); + } else { + toBeRemoved.add(eventString); + } + } + + send(EventSelectionPanel.this.getPage(), Broadcast.BREADTH, + new SelectedEventsPanel.EventSelectionChanged(target, toBeAdded, toBeRemoved)); + } + }); + + successGroup.setVisible(!events.isEmpty()); + add(successGroup); + + add(new Label("successLabel", new ResourceModel("Success", "Success"))).setVisible(!events.isEmpty()); + + final CheckGroupSelector successSelector = new CheckGroupSelector("successSelector", successGroup); + successSelector.setVisible(!events.isEmpty()); + add(successSelector); + + final ListView<String> categoryView = new AltListView<String>("categoryView", events) { + + private static final long serialVersionUID = 4949588177564901031L; + + @Override + protected void populateItem(final ListItem<String> item) { + final String subcategory = item.getModelObject(); + + item.add(new Label("subcategory", new ResourceModel(subcategory, subcategory))); + } + }; + add(categoryView); + + final ListView<String> successView = new AltListView<String>("successView", events) { + + private static final long serialVersionUID = 4949588177564901031L; + + @Override + protected void populateItem(final ListItem<String> item) { + final String event = item.getModelObject(); + + final Check<String> successCheck = new Check<>("successCheck", + new Model<String>(AuditLoggerName.buildEvent( + eventCategoryTO.getType(), + eventCategoryTO.getCategory(), + eventCategoryTO.getSubcategory(), + event, + AuditElements.Result.SUCCESS)), + successGroup); + item.add(successCheck); + } + }; + successGroup.add(successView); + + final CheckGroup<String> failureGroup = new CheckGroup<String>( + "failureGroup", + selected); + + failureGroup.add(new AjaxFormChoiceComponentUpdatingBehavior() { + + private static final long serialVersionUID = -151291731388673682L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + + final Set<String> toBeRemoved = new HashSet<>(); + final Set<String> toBeAdded = new HashSet<>(); + + for (String event : getEvents(eventCategoryTO)) { + final String eventString = AuditLoggerName.buildEvent( + eventCategoryTO.getType(), + eventCategoryTO.getCategory(), + eventCategoryTO.getSubcategory(), + event, + AuditElements.Result.FAILURE); + + if (failureGroup.getModelObject().contains(eventString)) { + toBeAdded.add(eventString); + } else { + toBeRemoved.add(eventString); + } + } + + send(EventSelectionPanel.this.getPage(), Broadcast.BREADTH, + new SelectedEventsPanel.EventSelectionChanged(target, toBeAdded, toBeRemoved)); + } + }); + + failureGroup.setVisible(!events.isEmpty()); + add(failureGroup); + + add(new Label("failureLabel", new ResourceModel("Failure", "Failure"))).setVisible(!events.isEmpty()); + + final CheckGroupSelector failureSelector = new CheckGroupSelector("failureSelector", failureGroup); + failureSelector.setVisible(!events.isEmpty()); + add(failureSelector); + + final ListView<String> failureView = new AltListView<String>("failureView", events) { + + private static final long serialVersionUID = 4949588177564901031L; + + @Override + protected void populateItem(final ListItem<String> item) { + final String event = item.getModelObject(); + + final Check<String> failureCheck = new Check<>("failureCheck", + new Model<String>(AuditLoggerName.buildEvent( + eventCategoryTO.getType(), + eventCategoryTO.getCategory(), + eventCategoryTO.getSubcategory(), + event, + AuditElements.Result.FAILURE)), + failureGroup); + item.add(failureCheck); + } + }; + failureGroup.add(failureView); + } + + private List<String> getEvents(final EventCategoryTO eventCategoryTO) { + final List<String> res; + + res = eventCategoryTO.getEvents(); + + if (res.isEmpty()) { + if ((AuditElements.EventCategoryType.PROPAGATION == eventCategoryTO.getType() + || AuditElements.EventCategoryType.SYNCHRONIZATION == eventCategoryTO.getType() + || AuditElements.EventCategoryType.PUSH == eventCategoryTO.getType()) + && StringUtils.isEmpty(eventCategoryTO.getCategory())) { + res.add(eventCategoryTO.getType().toString()); + } else if (AuditElements.EventCategoryType.TASK == eventCategoryTO.getType() + && StringUtils.isNotEmpty(eventCategoryTO.getCategory())) { + res.add(eventCategoryTO.getCategory()); + } + } else { + Collections.sort(res); + } + + return res; + } + + /** + * To be extended in order to add actions on events. + * + * @param event event. + */ + protected abstract void onEventAction(final IEvent<?> event); + + @Override + public void onEvent(final IEvent<?> event) { + onEventAction(event); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/ImagePanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ImagePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImagePanel.java new file mode 100644 index 0000000..7969c63 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ImagePanel.java @@ -0,0 +1,44 @@ +/* + * 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.wicket.Component; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.markup.html.image.Image; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.request.resource.ContextRelativeResource; + +public class ImagePanel extends Panel { + + private static final long serialVersionUID = 5564818820574092960L; + + final Image img; + + public ImagePanel(final String id, final ContextRelativeResource img) { + super(id); + this.img = new Image("img", img); + add(this.img); + } + + @Override + public Component add(final Behavior... behaviors) { + this.img.add(behaviors); + return this; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/JQueryUITabbedPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/JQueryUITabbedPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/JQueryUITabbedPanel.java new file mode 100644 index 0000000..d898ba6 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/JQueryUITabbedPanel.java @@ -0,0 +1,45 @@ +/* + * 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.wicket.extensions.ajax.markup.html.tabs.AjaxTabbedPanel; +import org.apache.wicket.extensions.markup.html.tabs.ITab; + +/** + * AjaxTabbedPanel with JQueryUI styling. + */ +public class JQueryUITabbedPanel<T extends ITab> extends AjaxTabbedPanel<T> { + + private static final long serialVersionUID = -5059184710433341333L; + + public JQueryUITabbedPanel(final String id, final List<T> tabs) { + super(id, tabs); + } + + @Override + protected String getTabContainerCssClass() { + return ""; + } + + @Override + protected String getSelectedTabCssClass() { + return "ui-state-active selected"; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/panels/LayoutsPanel.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/LayoutsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/LayoutsPanel.java new file mode 100644 index 0000000..26f1894 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/LayoutsPanel.java @@ -0,0 +1,130 @@ +/* + * 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.AttrLayoutType; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.SelectChoiceRenderer; +import org.apache.syncope.client.console.commons.XMLRolesReader; +import org.apache.syncope.client.console.rest.ConfigurationRestClient; +import org.apache.syncope.client.console.rest.SchemaRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.util.ListModel; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LayoutsPanel extends Panel { + + /** + * Logger. + */ + private static final Logger LOG = LoggerFactory.getLogger(LayoutsPanel.class); + + private static final long serialVersionUID = -6804066913177804275L; + + private static final String CANCEL = "cancel"; + + private static final String APPLY = "apply"; + + @SpringBean + protected XMLRolesReader xmlRolesReader; + + @SpringBean + private SchemaRestClient schemaRestClient; + + @SpringBean + private ConfigurationRestClient confRestClient; + + @SuppressWarnings("unchecked") + public LayoutsPanel(final String id, final AttrLayoutType attrLayoutType, final NotificationPanel feedbackPanel) { + super(id); + + final WebMarkupContainer container = new WebMarkupContainer("container"); + container.setOutputMarkupId(true); + + final Form<String> form = new Form<String>("form"); + form.setOutputMarkupId(true); + + final AttrTO attrLayout = confRestClient.readAttrLayout(attrLayoutType); + form.setModel(new CompoundPropertyModel(attrLayout.getValues())); + + final List<String> fields = schemaRestClient.getPlainSchemaNames(attrLayoutType.getAttrType()); + final ListModel<String> selectedFields = + new ListModel<String>(attrLayout.getValues().isEmpty() ? fields : attrLayout.getValues()); + final ListModel<String> availableFields = new ListModel<String>(fields); + + form.add(new AjaxPalettePanel<String>("fields", selectedFields, availableFields, + new SelectChoiceRenderer<String>(), true, true)); + + final AjaxButton submit = new IndicatingAjaxButton(APPLY, new ResourceModel(APPLY)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + confRestClient.set(attrLayout); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (Exception e) { + LOG.error("While saving layout configuration", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + } + feedbackPanel.refresh(target); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + error(getString(Constants.ERROR) + ": While saving layout configuration"); + feedbackPanel.refresh(target); + } + }; + + form.add(submit); + + final IndicatingAjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + target.add(container); + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + } + }; + + cancel.setDefaultFormProcessing(false); + form.add(cancel); + container.add(form); + add(container); + } +}
