http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java new file mode 100644 index 0000000..0fabe59 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Resources.java @@ -0,0 +1,723 @@ +/* + * 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.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.PreferenceManager; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.panels.AbstractSearchResultPanel; +import org.apache.syncope.client.console.panels.AjaxDataTablePanel; +import org.apache.syncope.client.console.rest.ConnectorRestClient; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel; +import org.apache.syncope.client.console.wicket.markup.html.form.LinkPanel; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.ConnInstanceTO; +import org.apache.syncope.common.lib.to.ResourceTO; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Component; +import org.apache.wicket.Page; +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.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.grid.ICellPopulator; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn; +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.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.StringResourceModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.spring.injection.annot.SpringBean; + +/** + * Resources WebPage. + */ +public class Resources extends BasePage { + + private static final long serialVersionUID = -3789252860990261728L; + + private static final int WIN_HEIGHT = 600; + + private static final int WIN_WIDTH = 1100; + + @SpringBean + private ConnectorRestClient connectorRestClient; + + @SpringBean + private PreferenceManager prefMan; + + private final ModalWindow createResourceWin; + + private final ModalWindow editResourceWin; + + private final ModalWindow createConnectorWin; + + private final ModalWindow editConnectorWin; + + private final int resourcePaginatorRows; + + private final int connectorPaginatorRows; + + private WebMarkupContainer resourceContainer; + + private WebMarkupContainer connectorContainer; + + /** + * Modal window to be used for user status management. + */ + protected final ModalWindow statusmodal = new ModalWindow("statusModal"); + + /** + * 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; + + public Resources(final PageParameters parameters) { + super(parameters); + + add(createResourceWin = new ModalWindow("createResourceWin")); + add(editResourceWin = new ModalWindow("editResourceWin")); + add(createConnectorWin = new ModalWindow("createConnectorWin")); + add(editConnectorWin = new ModalWindow("editConnectorWin")); + + statusmodal.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + statusmodal.setInitialHeight(STATUS_MODAL_WIN_HEIGHT); + statusmodal.setInitialWidth(STATUS_MODAL_WIN_WIDTH); + statusmodal.setCookieName("status-modal"); + add(statusmodal); + + AjaxLink<Void> reloadLink = new ClearIndicatingAjaxLink<Void>("reloadLink", getPageReference()) { + + private static final long serialVersionUID = 3109256773218160485L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + try { + connectorRestClient.reload(); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (Exception e) { + error(getString(Constants.ERROR) + ": " + e.getMessage()); + } + feedbackPanel.refresh(target); + target.add(connectorContainer); + } + + @Override + protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) { + super.updateAjaxAttributes(attributes); + + final AjaxCallListener ajaxCallListener = new AjaxCallListener() { + + private static final long serialVersionUID = 7160235486520935153L; + + @Override + public CharSequence getPrecondition(final Component component) { + return "if (!confirm('" + getString("confirmReloadConnectors") + "')) " + + "{return false;} else {return true;}"; + } + }; + attributes.getAjaxCallListeners().add(ajaxCallListener); + } + }; + MetaDataRoleAuthorizationStrategy.authorize(reloadLink, ENABLE, xmlRolesReader.getEntitlement( + "Connectors", "reload")); + add(reloadLink); + + resourcePaginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_RESOURCES_PAGINATOR_ROWS); + connectorPaginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_CONNECTORS_PAGINATOR_ROWS); + + setupResources(); + setupConnectors(); + } + + private void setupResources() { + List<IColumn<ResourceTO, String>> columns = new ArrayList<>(); + + columns.add(new PropertyColumn<ResourceTO, String>(new StringResourceModel("key", this, null), "key", "key")); + + columns.add(new AbstractColumn<ResourceTO, String>( + new StringResourceModel("connector", this, null, "connector")) { + + private static final long serialVersionUID = 8263694778917279290L; + + @Override + public void populateItem(final Item<ICellPopulator<ResourceTO>> cellItem, final String componentId, + final IModel<ResourceTO> rowModel) { + + final AjaxLink<String> editLink = + new ClearIndicatingAjaxLink<String>("link", getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + + editConnectorWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ConnectorModalPage(Resources.this.getPageReference(), + editConnectorWin, + connectorRestClient.read(rowModel.getObject().getConnectorId())); + } + }); + + editConnectorWin.show(target); + } + }; + editLink.add(new Label("linkTitle", rowModel.getObject().getConnectorDisplayName())); + + LinkPanel editConnPanel = new LinkPanel(componentId); + editConnPanel.add(editLink); + + cellItem.add(editConnPanel); + + MetaDataRoleAuthorizationStrategy.authorize(editConnPanel, ENABLE, xmlRolesReader. + getEntitlement( + "Connectors", "read")); + } + }); + + columns.add(new AbstractColumn<ResourceTO, String>( + new StringResourceModel("propagationPrimary", this, null)) { + + private static final long serialVersionUID = -3503023501954863131L; + + @Override + public void populateItem(final Item<ICellPopulator<ResourceTO>> item, + final String componentId, final IModel<ResourceTO> model) { + + item.add(new Label(componentId, "")); + item.add(new AttributeModifier("class", new Model<>( + Boolean.toString(model.getObject().isPropagationPrimary())))); + } + + @Override + public String getCssClass() { + return "narrowcolumn"; + } + }); + + columns.add(new PropertyColumn<ResourceTO, String>(new StringResourceModel( + "propagationPriority", this, null), "propagationPriority", "propagationPriority") { + + @Override + public String getCssClass() { + return "narrowcolumn"; + } + }); + + columns.add(new AbstractColumn<ResourceTO, String>(new StringResourceModel("actions", this, null, "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public String getCssClass() { + return "action"; + } + + @Override + public void populateItem(final Item<ICellPopulator<ResourceTO>> cellItem, final String componentId, + final IModel<ResourceTO> model) { + + final ResourceTO resourceTO = model.getObject(); + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference()); + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + statusmodal.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ProvisioningModalPage<>( + getPageReference(), statusmodal, model.getObject(), UserTO.class); + } + }); + + statusmodal.show(target); + } + }, ActionLink.ActionType.MANAGE_USERS, "Resources"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + + statusmodal.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ProvisioningModalPage<>( + getPageReference(), statusmodal, model.getObject(), RoleTO.class); + } + }); + + statusmodal.show(target); + } + }, ActionLink.ActionType.MANAGE_ROLES, "Resources"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + resourceTO.setUsyncToken(null); + resourceTO.setRsyncToken(null); + try { + resourceRestClient.update(resourceTO); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException e) { + error(getString(Constants.ERROR) + ":" + e.getMessage()); + + LOG.error("While resetting sync token from " + resourceTO.getKey(), e); + } + + feedbackPanel.refresh(target); + target.add(resourceContainer); + } + }, ActionLink.ActionType.RESET, "Resources"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + editResourceWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ResourceModalPage(Resources.this.getPageReference(), + editResourceWin, resourceTO, false); + } + }); + + editResourceWin.show(target); + } + }, ActionLink.ActionType.EDIT, "Resources"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + resourceRestClient.delete(resourceTO.getKey()); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException e) { + error(getString(Constants.ERROR) + ": " + e.getMessage()); + + LOG.error("While deleting resource " + resourceTO.getKey(), e); + } + + feedbackPanel.refresh(target); + target.add(resourceContainer); + } + }, ActionLink.ActionType.DELETE, "Resources"); + + cellItem.add(panel); + } + }); + + final AjaxDataTablePanel<ResourceTO, String> table = new AjaxDataTablePanel<>( + "resourceDatatable", + columns, + (ISortableDataProvider<ResourceTO, String>) new ResourcesProvider(), + resourcePaginatorRows, + Arrays.asList(new ActionLink.ActionType[] { ActionLink.ActionType.DELETE }), + resourceRestClient, + "key", + "Resources", + getPageReference()); + + resourceContainer = new WebMarkupContainer("resourceContainer"); + resourceContainer.add(table); + resourceContainer.setOutputMarkupId(true); + + add(resourceContainer); + + setWindowClosedCallback(createResourceWin, resourceContainer); + setWindowClosedCallback(editResourceWin, resourceContainer); + + createResourceWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + createResourceWin.setInitialHeight(WIN_HEIGHT); + createResourceWin.setInitialWidth(WIN_WIDTH); + createResourceWin.setCookieName("create-res-modal"); + + editResourceWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + editResourceWin.setInitialHeight(WIN_HEIGHT); + editResourceWin.setInitialWidth(WIN_WIDTH); + editResourceWin.setCookieName("edit-res-modal"); + + AjaxLink<Void> createResourceLink = + new ClearIndicatingAjaxLink<Void>("createResourceLink", getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + createResourceWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + final ResourceModalPage windows = new ResourceModalPage(Resources.this. + getPageReference(), + editResourceWin, new ResourceTO(), true); + return windows; + } + }); + + createResourceWin.show(target); + } + }; + + MetaDataRoleAuthorizationStrategy.authorize(createResourceLink, ENABLE, xmlRolesReader.getEntitlement( + "Resources", "create")); + + add(createResourceLink); + + @SuppressWarnings("rawtypes") + final Form paginatorForm = new Form("resourcePaginatorForm"); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, + "resourcePaginatorRows"), 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_RESOURCES_PAGINATOR_ROWS, + String.valueOf(resourcePaginatorRows)); + + table.setItemsPerPage(resourcePaginatorRows); + target.add(resourceContainer); + } + }); + + paginatorForm.add(rowsChooser); + add(paginatorForm); + } + + private void setupConnectors() { + List<IColumn<ConnInstanceTO, String>> columns = new ArrayList<>(); + + columns.add(new PropertyColumn<ConnInstanceTO, String>( + new StringResourceModel("key", this, null), "key", "key")); + columns.add(new PropertyColumn<ConnInstanceTO, String>( + new StringResourceModel("name", this, null), "connectorName", "connectorName")); + columns.add(new PropertyColumn<ConnInstanceTO, String>( + new StringResourceModel("displayName", this, null), "displayName", "displayName")); + columns.add(new PropertyColumn<ConnInstanceTO, String>( + new StringResourceModel("bundleName", this, null), "bundleName", "bundleName")); + columns.add(new PropertyColumn<ConnInstanceTO, String>( + new StringResourceModel("version", this, null), "version", "version")); + columns.add(new AbstractColumn<ConnInstanceTO, String>(new StringResourceModel("actions", this, null, "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public String getCssClass() { + return "action"; + } + + @Override + public void populateItem(final Item<ICellPopulator<ConnInstanceTO>> cellItem, final String componentId, + final IModel<ConnInstanceTO> model) { + + final ConnInstanceTO connectorTO = model.getObject(); + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + editConnectorWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ConnectorModalPage(Resources.this.getPageReference(), editConnectorWin, + connectorTO); + } + }); + + editConnectorWin.show(target); + } + }, ActionLink.ActionType.EDIT, "Connectors"); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + connectorRestClient.delete(connectorTO.getKey()); + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException e) { + error(getString(Constants.ERROR) + ": " + e.getMessage()); + + LOG.error("While deleting connector " + connectorTO.getKey(), e); + } + + target.add(connectorContainer); + feedbackPanel.refresh(target); + } + }, ActionLink.ActionType.DELETE, "Connectors"); + + cellItem.add(panel); + } + }); + + final AjaxDataTablePanel<ConnInstanceTO, String> table = new AjaxDataTablePanel<ConnInstanceTO, String>( + "connectorDatatable", + columns, + (ISortableDataProvider<ConnInstanceTO, String>) new ConnectorsProvider(), + connectorPaginatorRows, + Arrays.asList(new ActionLink.ActionType[] { ActionLink.ActionType.DELETE }), + connectorRestClient, + "key", + "Connectors", + getPageReference()); + + connectorContainer = new WebMarkupContainer("connectorContainer"); + connectorContainer.add(table); + connectorContainer.setOutputMarkupId(true); + + MetaDataRoleAuthorizationStrategy.authorize(connectorContainer, RENDER, xmlRolesReader.getEntitlement( + "Connectors", "list")); + + add(connectorContainer); + + setWindowClosedCallback(createConnectorWin, connectorContainer); + setWindowClosedCallback(editConnectorWin, connectorContainer); + + createConnectorWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + createConnectorWin.setInitialHeight(WIN_HEIGHT); + createConnectorWin.setInitialWidth(WIN_WIDTH); + createConnectorWin.setCookieName("create-conn-modal"); + + editConnectorWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + editConnectorWin.setInitialHeight(WIN_HEIGHT); + editConnectorWin.setInitialWidth(WIN_WIDTH); + editConnectorWin.setCookieName("edit-conn-modal"); + + AjaxLink<Void> createConnectorLink = + new ClearIndicatingAjaxLink<Void>("createConnectorLink", getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + createConnectorWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + ConnectorModalPage form = new ConnectorModalPage(Resources.this.getPageReference(), + editConnectorWin, new ConnInstanceTO()); + return form; + } + }); + + createConnectorWin.show(target); + } + }; + + MetaDataRoleAuthorizationStrategy.authorize(createConnectorLink, ENABLE, xmlRolesReader.getEntitlement( + "Connectors", "create")); + + add(createConnectorLink); + + @SuppressWarnings("rawtypes") + Form paginatorForm = new Form("connectorPaginatorForm"); + + MetaDataRoleAuthorizationStrategy.authorize(paginatorForm, RENDER, xmlRolesReader.getEntitlement( + "Connectors", "list")); + + final DropDownChoice<Integer> rowsChooser = new DropDownChoice<Integer>( + "rowsChooser", + new PropertyModel<Integer>(this, + "connectorPaginatorRows"), + prefMan.getPaginatorChoices()); + + rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(AjaxRequestTarget target) { + prefMan.set(getRequest(), getResponse(), Constants.PREF_CONNECTORS_PAGINATOR_ROWS, + String.valueOf(connectorPaginatorRows)); + table.setItemsPerPage(connectorPaginatorRows); + + target.add(connectorContainer); + } + }); + + paginatorForm.add(rowsChooser); + add(paginatorForm); + } + + class ResourcesProvider extends SortableDataProvider<ResourceTO, String> { + + private static final long serialVersionUID = -9055916672926643975L; + + private final SortableDataProviderComparator<ResourceTO> comparator; + + public ResourcesProvider() { + super(); + //Default sorting + setSort("key", SortOrder.ASCENDING); + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator<ResourceTO> iterator(final long first, final long count) { + List<ResourceTO> list = resourceRestClient.getAll(); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return resourceRestClient.getAll().size(); + } + + @Override + public IModel<ResourceTO> model(final ResourceTO resource) { + return new AbstractReadOnlyModel<ResourceTO>() { + + private static final long serialVersionUID = 8952474152465381634L; + + @Override + public ResourceTO getObject() { + return resource; + } + }; + } + } + + private class ConnectorsProvider extends SortableDataProvider<ConnInstanceTO, String> { + + private static final long serialVersionUID = 4445909568349448518L; + + private final SortableDataProviderComparator<ConnInstanceTO> comparator; + + public ConnectorsProvider() { + super(); + //Default sorting + setSort("key", SortOrder.ASCENDING); + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator<ConnInstanceTO> iterator(long first, long count) { + List<ConnInstanceTO> list = connectorRestClient.getAllConnectors(); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return connectorRestClient.getAllConnectors().size(); + } + + @Override + public IModel<ConnInstanceTO> model(final ConnInstanceTO connector) { + + return new AbstractReadOnlyModel<ConnInstanceTO>() { + + private static final long serialVersionUID = -6033068018293569398L; + + @Override + public ConnInstanceTO getObject() { + return connector; + } + }; + } + } + + @Override + public void onEvent(final IEvent<?> event) { + if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) { + ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(resourceContainer); + ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(connectorContainer); + } + } +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/ResultStatusModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/ResultStatusModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/ResultStatusModalPage.java new file mode 100644 index 0000000..b6ecb9e --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/ResultStatusModalPage.java @@ -0,0 +1,425 @@ +/* + * 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.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.Mode; +import org.apache.syncope.client.console.commons.status.Status; +import org.apache.syncope.client.console.commons.status.StatusUtils; +import org.apache.syncope.common.lib.to.AbstractSubjectTO; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.syncope.common.lib.to.ConnObjectTO; +import org.apache.syncope.common.lib.to.PropagationStatus; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.common.lib.types.PropagationTaskExecStatus; +import org.apache.wicket.Component; +import org.apache.wicket.Page; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.ComponentTag; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.image.Image; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.markup.html.list.ListView; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.request.resource.ContextRelativeResource; + +/** + * Show user or role status after performing a successful operation. + */ +public class ResultStatusModalPage extends BaseModalPage { + + private static final long serialVersionUID = 2646115294319713723L; + + private static final String IMG_PREFIX = "/img/statuses/"; + + private final AbstractSubjectTO subject; + + private final Mode mode; + + /** + * Status management utilities. + */ + private final StatusUtils statusUtils; + + public static class Builder implements Serializable { + + private static final long serialVersionUID = 220361441802274899L; + + private ModalWindow window; + + private Mode mode; + + private AbstractSubjectTO subject; + + public Builder(final ModalWindow window, final AbstractSubjectTO attributable) { + this.window = window; + this.subject = attributable; + } + + public ResultStatusModalPage.Builder mode(final Mode mode) { + this.mode = mode; + return this; + } + + public ResultStatusModalPage build() { + return new ResultStatusModalPage(this); + } + } + + private ResultStatusModalPage(final Builder builder) { + super(); + this.subject = builder.subject; + statusUtils = new StatusUtils(this.userRestClient); + if (builder.mode == null) { + this.mode = Mode.ADMIN; + } else { + this.mode = builder.mode; + } + + final BaseModalPage page = this; + + final WebMarkupContainer container = new WebMarkupContainer("container"); + container.setOutputMarkupId(true); + add(container); + + final Fragment fragment = new Fragment("resultFrag", mode == Mode.SELF + ? "userSelfResultFrag" + : "propagationResultFrag", this); + fragment.setOutputMarkupId(true); + container.add(fragment); + + if (mode == Mode.ADMIN) { + // add Syncope propagation status + PropagationStatus syncope = new PropagationStatus(); + syncope.setResource("Syncope"); + syncope.setStatus(PropagationTaskExecStatus.SUCCESS); + + List<PropagationStatus> propagations = new ArrayList<PropagationStatus>(); + propagations.add(syncope); + propagations.addAll(subject.getPropagationStatusTOs()); + + fragment.add(new Label("info", + ((subject instanceof UserTO) && ((UserTO) subject).getUsername() != null) + ? ((UserTO) subject).getUsername() + : ((subject instanceof RoleTO) && ((RoleTO) subject).getName() != null) + ? ((RoleTO) subject).getName() + : String.valueOf(subject.getKey()))); + + final ListView<PropagationStatus> propRes = new ListView<PropagationStatus>("resources", + propagations) { + + private static final long serialVersionUID = -1020475259727720708L; + + @Override + protected void populateItem(final ListItem<PropagationStatus> item) { + final PropagationStatus propTO = (PropagationStatus) item.getDefaultModelObject(); + + final ListView attributes = getConnObjectView(propTO); + + final Fragment attrhead; + if (attributes.getModelObject() == null || attributes.getModelObject().isEmpty()) { + attrhead = new Fragment("attrhead", "emptyAttrHeadFrag", page); + } else { + attrhead = new Fragment("attrhead", "attrHeadFrag", page); + } + + item.add(attrhead); + item.add(attributes); + + attrhead.add(new Label("resource", propTO.getResource())); + + attrhead.add(new Label("propagation", propTO.getStatus() == null + ? "UNDEFINED" : propTO.getStatus().toString())); + + final Image image; + final String alt, title; + final ModalWindow failureWindow = new ModalWindow("failureWindow"); + final AjaxLink<?> failureWindowLink = new AjaxLink<Void>("showFailureWindow") { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(AjaxRequestTarget target) { + failureWindow.show(target); + } + }; + + switch (propTO.getStatus()) { + + case SUCCESS: + case SUBMITTED: + case CREATED: + image = new Image("icon", + new ContextRelativeResource(IMG_PREFIX + Status.ACTIVE.toString() + + Constants.PNG_EXT)); + alt = "success icon"; + title = "success"; + failureWindow.setVisible(false); + failureWindowLink.setEnabled(false); + break; + + default: + image = new Image("icon", + new ContextRelativeResource(IMG_PREFIX + Status.SUSPENDED.toString() + + Constants.PNG_EXT)); + alt = "failure icon"; + title = "failure"; + } + + image.add(new Behavior() { + + private static final long serialVersionUID = 1469628524240283489L; + + @Override + public void onComponentTag(final Component component, final ComponentTag tag) { + tag.put("alt", alt); + tag.put("title", title); + } + }); + final FailureMessageModalPage executionFailureMessagePage; + if (propTO.getFailureReason() == null) { + executionFailureMessagePage = + new FailureMessageModalPage(failureWindow.getContentId(), StringUtils.EMPTY); + } else { + executionFailureMessagePage = + new FailureMessageModalPage(failureWindow.getContentId(), propTO.getFailureReason()); + } + + failureWindow.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return executionFailureMessagePage; + } + }); + failureWindow.setCookieName("failureWindow"); + failureWindow.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + failureWindowLink.add(image); + attrhead.add(failureWindowLink); + attrhead.add(failureWindow); + } + }; + fragment.add(propRes); + } + + final AjaxLink<Void> close = new IndicatingAjaxLink<Void>("close") { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + builder.window.close(target); + } + }; + container.add(close); + + setOutputMarkupId(true); + } + + /** + * Get remote attributes list view. + * + * @param propTO propagation TO. + * @return list view. + */ + private ListView<String> getConnObjectView(final PropagationStatus propTO) { + final ConnObjectTO before = propTO.getBeforeObj(); + final ConnObjectTO after = propTO.getAfterObj(); + + // sorted in reversed presentation order + final List<String> head = new ArrayList<String>(); + if (subject instanceof UserTO) { + head.add(ConnIdSpecialAttributeName.PASSWORD); + head.add(ConnIdSpecialAttributeName.ENABLE); + } + head.add(ConnIdSpecialAttributeName.UID); + head.add(ConnIdSpecialAttributeName.NAME); + + final Map<String, AttrTO> beforeAttrMap = before == null + ? Collections.<String, AttrTO>emptyMap() + : before.getPlainAttrMap(); + + final Map<String, AttrTO> afterAttrMap = after == null + ? Collections.<String, AttrTO>emptyMap() + : after.getPlainAttrMap(); + + final Set<String> attributes = new HashSet<String>(); + attributes.addAll(beforeAttrMap.keySet()); + attributes.addAll(afterAttrMap.keySet()); + + if (!(subject instanceof UserTO)) { + attributes.remove(ConnIdSpecialAttributeName.PASSWORD); + attributes.remove(ConnIdSpecialAttributeName.ENABLE); + } + + final List<String> profile = new ArrayList<String>(); + profile.addAll(attributes); + profile.removeAll(head); + Collections.sort(profile); + + for (String attr : head) { + if (attributes.contains(attr)) { + profile.add(0, attr); + } + } + + return new ListView<String>("attrs", profile) { + + private static final long serialVersionUID = 4949588177564901031L; + + @Override + protected void populateItem(final ListItem<String> item) { + String name = item.getModelObject(); + + final Fragment beforeValue; + final Fragment afterValue; + if (ConnIdSpecialAttributeName.ENABLE.equals(name)) { + beforeValue = getStatusIcon("beforeValue", propTO.getResource(), before); + afterValue = getStatusIcon("afterValue", propTO.getResource(), after); + } else { + beforeValue = getLabelValue("beforeValue", name, beforeAttrMap); + afterValue = getLabelValue("afterValue", name, afterAttrMap); + } + + item.add(new Label("attrName", new ResourceModel(name, name))); + + item.add(beforeValue); + item.add(afterValue); + } + }; + } + + /** + * Get fragment for attribute value (not remote status). + * + * @param id component id to be replaced with the fragment content. + * @param attrName remote attribute name + * @param attrMap remote attributes map. + * @return fragment. + */ + private Fragment getLabelValue(final String id, final String attrName, final Map<String, AttrTO> attrMap) { + final String value; + + final AttrTO attr = attrMap.get(attrName); + + if (attr == null || attr.getValues() == null || attr.getValues().isEmpty()) { + value = ""; + } else { + if (ConnIdSpecialAttributeName.PASSWORD.equals(attrName)) { + value = "********"; + } else { + value = attr.getValues().size() > 1 + ? attr.getValues().toString() + : attr.getValues().get(0); + } + } + + Component label = new Label("value", value.length() > 50 ? value.substring(0, 50) + "..." : value). + add(new Behavior() { + + private static final long serialVersionUID = 1469628524240283489L; + + @Override + public void onComponentTag(final Component component, final ComponentTag tag) { + tag.put("title", value); + } + }); + + final Fragment frag = new Fragment(id, "attrValueFrag", this); + frag.add(label); + + return frag; + } + + /** + * Get fragment for user status icon. + * + * @param id component id to be replaced with the fragment content + * @param resourceName resource name + * @param objectTO connector object TO + * @return fragment. + */ + private Fragment getStatusIcon(final String id, final String resourceName, final ConnObjectTO objectTO) { + final Image image; + final String alt, title; + switch (statusUtils.getStatusBean( + subject, resourceName, objectTO, this.subject instanceof RoleTO).getStatus()) { + + case ACTIVE: + image = new Image("status", + new ContextRelativeResource(IMG_PREFIX + Status.ACTIVE.toString() + Constants.PNG_EXT)); + alt = "active icon"; + title = "Enabled"; + break; + + case SUSPENDED: + image = new Image("status", + new ContextRelativeResource(IMG_PREFIX + Status.SUSPENDED.toString() + Constants.PNG_EXT)); + alt = "inactive icon"; + title = "Disabled"; + break; + + default: + image = null; + alt = null; + title = null; + } + + final Fragment frag; + if (image == null) { + frag = new Fragment(id, "emptyFrag", this); + } else { + image.add(new Behavior() { + + private static final long serialVersionUID = 1469628524240283489L; + + @Override + public void onComponentTag(final Component component, final ComponentTag tag) { + tag.put("alt", alt); + tag.put("title", title); + tag.put("width", "12px"); + tag.put("height", "12px"); + } + }); + + frag = new Fragment(id, "remoteStatusFrag", this); + frag.add(image); + } + + return frag; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleModalPage.java new file mode 100644 index 0000000..3cb9148 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleModalPage.java @@ -0,0 +1,162 @@ +/* + * 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.util.ArrayList; +import java.util.List; +import org.apache.commons.lang3.SerializationUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.Mode; +import org.apache.syncope.client.console.panels.RolePanel; +import org.apache.syncope.common.lib.AttributableOperations; +import org.apache.syncope.common.lib.mod.RoleMod; +import org.apache.syncope.common.lib.to.RoleTO; +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.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.ResourceModel; + +/** + * Modal window with Role form. + */ +public class RoleModalPage extends BaseModalPage { + + private static final long serialVersionUID = -1732493223434085205L; + + protected final PageReference pageRef; + + protected final ModalWindow window; + + protected final Mode mode; + + protected final boolean createFlag; + + protected final RolePanel rolePanel; + + protected RoleTO originalRoleTO; + + public RoleModalPage(final PageReference pageRef, final ModalWindow window, final RoleTO roleTO) { + this(pageRef, window, roleTO, Mode.ADMIN); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public RoleModalPage(final PageReference pageRef, final ModalWindow window, final RoleTO roleTO, final Mode mode) { + super(); + + this.pageRef = pageRef; + this.window = window; + this.mode = mode; + + this.createFlag = roleTO.getKey() == 0; + if (!createFlag) { + originalRoleTO = SerializationUtils.clone(roleTO); + } + + final Form<RoleTO> form = new Form<RoleTO>("roleForm"); + form.setMultiPart(true); + + add(new Label("displayName", roleTO.getKey() == 0 ? "" : roleTO.getDisplayName())); + + form.setModel(new CompoundPropertyModel<RoleTO>(roleTO)); + + this.rolePanel = new RolePanel.Builder("rolePanel").form(form).roleTO(roleTO). + roleModalPageMode(mode).pageRef(getPageReference()).build(); + form.add(rolePanel); + + final AjaxButton submit = new IndicatingAjaxButton(SUBMIT, new ResourceModel(SUBMIT)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + submitAction(target, form); + + if (pageRef.getPage() instanceof BasePage) { + ((BasePage) pageRef.getPage()).setModalResult(true); + } + + closeAction(target, form); + } catch (Exception e) { + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + form.add(submit); + form.setDefaultButton(submit); + + 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) { + closeAction(target, form); + } + }; + cancel.setDefaultFormProcessing(false); + form.add(cancel); + + MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, xmlRolesReader.getEntitlement("Roles", + createFlag + ? "create" + : "update")); + + add(form); + } + + protected void submitAction(final AjaxRequestTarget target, final Form<?> form) { + final RoleTO roleTO = (RoleTO) form.getDefaultModelObject(); + final List<String> entitlementList = new ArrayList<String>(rolePanel.getSelectedEntitlements()); + roleTO.getEntitlements().clear(); + roleTO.getEntitlements().addAll(entitlementList); + + RoleTO result; + if (createFlag) { + result = roleRestClient.create(roleTO); + } else { + RoleMod roleMod = AttributableOperations.diff(roleTO, originalRoleTO); + + // update role just if it is changed + if (roleMod.isEmpty()) { + result = roleTO; + } else { + result = roleRestClient.update(originalRoleTO.getETagValue(), roleMod); + } + } + + setResponsePage(new ResultStatusModalPage.Builder(window, result).build()); + } + + protected void closeAction(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleSelectModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleSelectModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleSelectModalPage.java new file mode 100644 index 0000000..26b1aea --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleSelectModalPage.java @@ -0,0 +1,105 @@ +/* + * 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.lang.reflect.Constructor; +import javax.swing.tree.DefaultMutableTreeNode; +import org.apache.syncope.client.console.commons.RoleTreeBuilder; +import org.apache.syncope.client.console.wicket.markup.html.tree.DefaultMutableTreeNodeExpansion; +import org.apache.syncope.client.console.wicket.markup.html.tree.DefaultMutableTreeNodeExpansionModel; +import org.apache.syncope.client.console.wicket.markup.html.tree.TreeRoleProvider; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.wicket.Component; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.markup.html.repeater.tree.DefaultNestedTree; +import org.apache.wicket.extensions.markup.html.repeater.tree.ITreeProvider; +import org.apache.wicket.extensions.markup.html.repeater.tree.NestedTree; +import org.apache.wicket.extensions.markup.html.repeater.tree.content.Folder; +import org.apache.wicket.extensions.markup.html.repeater.tree.theme.WindowsTheme; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class RoleSelectModalPage extends BaseModalPage { + + private static final long serialVersionUID = 2106489458494696439L; + + @SpringBean + private RoleTreeBuilder roleTreeBuilder; + + private final NestedTree<DefaultMutableTreeNode> tree; + + public RoleSelectModalPage(final PageReference pageRef, final ModalWindow window, final Class<?> payloadClass) { + super(); + + final ITreeProvider<DefaultMutableTreeNode> treeProvider = new TreeRoleProvider(roleTreeBuilder, true); + final DefaultMutableTreeNodeExpansionModel treeModel = new DefaultMutableTreeNodeExpansionModel(); + + tree = new DefaultNestedTree<DefaultMutableTreeNode>("treeTable", treeProvider, treeModel) { + + private static final long serialVersionUID = 7137658050662575546L; + + @Override + protected Component newContentComponent(final String id, final IModel<DefaultMutableTreeNode> node) { + final DefaultMutableTreeNode treeNode = node.getObject(); + final RoleTO roleTO = (RoleTO) treeNode.getUserObject(); + + return new Folder<DefaultMutableTreeNode>(id, RoleSelectModalPage.this.tree, node) { + + private static final long serialVersionUID = 9046323319920426493L; + + @Override + protected boolean isClickable() { + return true; + } + + @Override + protected IModel<?> newLabelModel(final IModel<DefaultMutableTreeNode> model) { + return new Model<>(roleTO.getDisplayName()); + } + + @Override + protected void onClick(final AjaxRequestTarget target) { + super.onClick(target); + + try { + Constructor<?> constructor = payloadClass.getConstructor(Long.class); + Object payload = constructor.newInstance(roleTO.getKey()); + + send(pageRef.getPage(), Broadcast.BREADTH, payload); + } catch (Exception e) { + LOG.error("Could not send role select event", e); + } + + window.close(target); + } + }; + } + }; + tree.add(new WindowsTheme()); + tree.setOutputMarkupId(true); + + DefaultMutableTreeNodeExpansion.get().expandAll(); + + this.add(tree); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleTemplateModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleTemplateModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleTemplateModalPage.java new file mode 100644 index 0000000..6639517 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/RoleTemplateModalPage.java @@ -0,0 +1,50 @@ +/* + * 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.Mode; +import org.apache.syncope.common.lib.to.RoleTO; +import org.apache.syncope.common.lib.to.SyncTaskTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.form.Form; + +public class RoleTemplateModalPage extends RoleModalPage { + + private static final long serialVersionUID = -3849135555203409845L; + + private final SyncTaskTO syncTaskTO; + + public RoleTemplateModalPage(final PageReference callerPageRef, final ModalWindow window, + final SyncTaskTO syncTaskTO) { + + super(callerPageRef, window, syncTaskTO.getRoleTemplate() == null + ? new RoleTO() + : syncTaskTO.getRoleTemplate(), Mode.TEMPLATE); + + this.syncTaskTO = syncTaskTO; + } + + @Override + protected void submitAction(final AjaxRequestTarget target, final Form form) { + syncTaskTO.setRoleTemplate((RoleTO) form.getModelObject()); + taskRestClient.updateSyncTask(syncTaskTO); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Roles.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Roles.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Roles.java new file mode 100644 index 0000000..8310792 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Roles.java @@ -0,0 +1,186 @@ +/* + * 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.RoleSearchPanel; +import org.apache.syncope.client.console.panels.RoleSearchResultPanel; +import org.apache.syncope.client.console.panels.RoleSummaryPanel; +import org.apache.syncope.client.console.rest.RoleRestClient; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; +import org.apache.syncope.client.console.wicket.markup.html.tree.TreeRolePanel; +import org.apache.wicket.Session; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.event.IEvent; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.WebMarkupContainer; +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; + +/** + * Roles WebPage. + */ +public class Roles extends BasePage { + + private static final long serialVersionUID = -2147758241610831969L; + + private static final int WIN_HEIGHT = 500; + + private static final int WIN_WIDTH = 800; + + @SpringBean + private RoleRestClient restClient; + + private final ModalWindow editRoleWin; + + private final WebMarkupContainer roleTabsContainer; + + public Roles(final PageParameters parameters) { + super(parameters); + + roleTabsContainer = new WebMarkupContainer("roleTabsContainer"); + roleTabsContainer.setOutputMarkupId(true); + add(roleTabsContainer); + + editRoleWin = new ModalWindow("editRoleWin"); + editRoleWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + editRoleWin.setInitialHeight(WIN_HEIGHT); + editRoleWin.setInitialWidth(WIN_WIDTH); + editRoleWin.setCookieName("edit-role-modal"); + add(editRoleWin); + + final TreeRolePanel treePanel = new TreeRolePanel("treePanel"); + treePanel.setOutputMarkupId(true); + roleTabsContainer.add(treePanel); + + final RoleSummaryPanel summaryPanel = new RoleSummaryPanel.Builder("summaryPanel") + .window(editRoleWin).callerPageRef(Roles.this.getPageReference()).build(); + roleTabsContainer.add(summaryPanel); + + editRoleWin.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() { + + private static final long serialVersionUID = 8804221891699487139L; + + @Override + public void onClose(final AjaxRequestTarget target) { + final RoleSummaryPanel summaryPanel = (RoleSummaryPanel) roleTabsContainer.get("summaryPanel"); + + final TreeNodeClickUpdate data = new TreeNodeClickUpdate(target, + summaryPanel == null || summaryPanel.getSelectedNode() == null + ? 0 + : summaryPanel.getSelectedNode().getKey()); + + send(getPage(), Broadcast.BREADTH, data); + + if (modalResult) { + getSession().info(getString(Constants.OPERATION_SUCCEEDED)); + feedbackPanel.refresh(target); + modalResult = false; + } + + } + }); + + final AbstractSearchResultPanel searchResult = + new RoleSearchResultPanel("searchResult", true, null, getPageReference(), restClient); + add(searchResult); + + final Form searchForm = new Form("searchForm"); + add(searchForm); + + final RoleSearchPanel searchPanel = new RoleSearchPanel.Builder("searchPanel").build(); + searchForm.add(searchPanel); + + searchForm.add(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("Node condition {}", 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); + } + }); + } + + 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); + } + + @Override + public void onEvent(final IEvent<?> event) { + super.onEvent(event); + + if (event.getPayload() instanceof TreeNodeClickUpdate) { + final TreeNodeClickUpdate update = (TreeNodeClickUpdate) event.getPayload(); + + final RoleSummaryPanel summaryPanel = new RoleSummaryPanel.Builder("summaryPanel") + .window(editRoleWin).callerPageRef(Roles.this.getPageReference()) + .selectedNodeId(update.getSelectedNodeId()).build(); + + roleTabsContainer.addOrReplace(summaryPanel); + update.getTarget().add(roleTabsContainer); + } + } + + public static class TreeNodeClickUpdate { + + private final AjaxRequestTarget target; + + private Long selectedNodeId; + + public TreeNodeClickUpdate(final AjaxRequestTarget target, final Long selectedNodeId) { + this.target = target; + this.selectedNodeId = selectedNodeId; + } + + public AjaxRequestTarget getTarget() { + return target; + } + + public Long getSelectedNodeId() { + return selectedNodeId; + } + + public void setSelectedNodeId(final Long selectedNodeId) { + this.selectedNodeId = selectedNodeId; + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/SchedTaskModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/SchedTaskModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/SchedTaskModalPage.java new file mode 100644 index 0000000..6222717 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/SchedTaskModalPage.java @@ -0,0 +1,68 @@ +/* + * 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.util.List; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel; +import org.apache.syncope.common.lib.to.SchedTaskTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.model.PropertyModel; + +/** + * Modal window with Task form (to stop and start execution). + */ +public class SchedTaskModalPage extends AbstractSchedTaskModalPage { + + private static final long serialVersionUID = -2501860242590060867L; + + public SchedTaskModalPage(final ModalWindow window, final SchedTaskTO taskTO, final PageReference callerPageRef) { + + super(window, taskTO, callerPageRef); + + final IModel<List<String>> classNames = new LoadableDetachableModel<List<String>>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List<String> load() { + return taskRestClient.getJobClasses(); + } + }; + + final AjaxDropDownChoicePanel<String> className = new AjaxDropDownChoicePanel<String>("jobClassName", + getString("class"), new PropertyModel<String>(taskTO, "jobClassName")); + className.setChoices(classNames.getObject()); + className.addRequiredLabel(); + className.setEnabled(taskTO.getKey() == 0); + className.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize"); + profile.add(className); + } + + @Override + public void submitAction(final SchedTaskTO taskTO) { + if (taskTO.getKey() > 0) { + taskRestClient.updateSchedTask(taskTO); + } else { + taskRestClient.createSchedTask(taskTO); + } + } +}
