http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java new file mode 100644 index 0000000..c47edcd --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Schema.java @@ -0,0 +1,467 @@ +/* + * 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.Field; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.PreferenceManager; +import org.apache.syncope.client.console.commons.SchemaModalPageFactory; +import org.apache.syncope.client.console.commons.SelectChoiceRenderer; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.panels.JQueryUITabbedPanel; +import org.apache.syncope.client.console.rest.SchemaRestClient; +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.ActionLink.ActionType; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel; +import org.apache.syncope.common.lib.to.AbstractSchemaTO; +import org.apache.syncope.common.lib.types.AttributableType; +import org.apache.syncope.common.lib.types.SchemaType; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.Page; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +import org.apache.wicket.ajax.markup.html.AjaxLink; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.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.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.PropertyColumn; +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider; +import org.apache.wicket.extensions.markup.html.tabs.AbstractTab; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +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.html.panel.Panel; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.util.ReflectionUtils; + +/** + * Schema WebPage. + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class Schema extends BasePage { + + private static final long serialVersionUID = 8091922398776299403L; + + private static final Map<SchemaType, List<String>> COL_NAMES = new HashMap<SchemaType, List<String>>() { + + private static final long serialVersionUID = 3109256773218160485L; + + { + put(SchemaType.PLAIN, Arrays.asList(new String[] { "key", "type", + "mandatoryCondition", "uniqueConstraint", "multivalue", "readonly" })); + put(SchemaType.DERIVED, Arrays.asList(new String[] { "key", "expression" })); + put(SchemaType.VIRTUAL, Arrays.asList(new String[] { "key", "readonly" })); + } + }; + + private static final Map<Map.Entry<AttributableType, SchemaType>, String> PAGINATOR_ROWS_KEYS = + new HashMap<Map.Entry<AttributableType, SchemaType>, String>() { + + private static final long serialVersionUID = 3109256773218160485L; + + { + put(new SimpleEntry<>(AttributableType.CONFIGURATION, SchemaType.PLAIN), + Constants.PREF_CONF_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.USER, SchemaType.PLAIN), + Constants.PREF_USER_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.USER, SchemaType.DERIVED), + Constants.PREF_USER_DER_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.USER, SchemaType.VIRTUAL), + Constants.PREF_USER_VIR_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.PLAIN), + Constants.PREF_MEMBERSHIP_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.DERIVED), + Constants.PREF_MEMBERSHIP_DER_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.MEMBERSHIP, SchemaType.VIRTUAL), + Constants.PREF_MEMBERSHIP_VIR_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.PLAIN), + Constants.PREF_ROLE_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.DERIVED), + Constants.PREF_ROLE_DER_SCHEMA_PAGINATOR_ROWS); + put(new SimpleEntry<>(AttributableType.ROLE, SchemaType.VIRTUAL), + Constants.PREF_ROLE_VIR_SCHEMA_PAGINATOR_ROWS); + } + }; + + private static final int WIN_WIDTH = 600; + + private static final int WIN_HEIGHT = 200; + + private static final int PLAIN_WIN_HEIGHT = 500; + + @SpringBean + private SchemaRestClient restClient; + + @SpringBean + private PreferenceManager prefMan; + + private final String allowedCreateRoles = xmlRolesReader.getEntitlement("Schema", "create"); + + private final String allowedReadRoles = xmlRolesReader.getEntitlement("Schema", "read"); + + private final String allowedDeleteRoles = xmlRolesReader.getEntitlement("Schema", "delete"); + + public Schema() { + super(); + + for (final AttributableType attrType : AttributableType.values()) { + final String attrTypeAsString = attrType.name().toLowerCase(); + + List<ITab> tabs = new ArrayList<>(); + + for (final SchemaType schemaType : SchemaType.values()) { + if (attrType != AttributableType.CONFIGURATION || schemaType == SchemaType.PLAIN) { + final String schemaTypeAsString = schemaType.name().toLowerCase(); + + tabs.add(new AbstractTab(new Model<>(getString(schemaTypeAsString))) { + + private static final long serialVersionUID = -5861786415855103549L; + + @Override + public WebMarkupContainer getPanel(final String panelId) { + return new SchemaTypePanel(panelId, attrType, schemaType); + } + }); + } + } + + add(new JQueryUITabbedPanel(attrTypeAsString + "Tabs", tabs)); + } + } + + private <T extends AbstractSchemaModalPage> List<IColumn> getColumns( + final WebMarkupContainer webContainer, final ModalWindow modalWindow, + final AttributableType attributableType, final SchemaType schemaType, + final Collection<String> fields) { + + List<IColumn> columns = new ArrayList<IColumn>(); + + for (final String field : fields) { + final Field clazzField = ReflectionUtils.findField(schemaType.getToClass(), field); + + if (clazzField != null) { + if (clazzField.getType().equals(Boolean.class) || clazzField.getType().equals(boolean.class)) { + columns.add(new AbstractColumn<AbstractSchemaTO, String>(new ResourceModel(field)) { + + private static final long serialVersionUID = 8263694778917279290L; + + @Override + public void populateItem(final Item<ICellPopulator<AbstractSchemaTO>> item, + final String componentId, final IModel<AbstractSchemaTO> model) { + + BeanWrapper bwi = new BeanWrapperImpl(model.getObject()); + Object obj = bwi.getPropertyValue(field); + + item.add(new Label(componentId, "")); + item.add(new AttributeModifier("class", new Model<String>(obj.toString()))); + } + + @Override + public String getCssClass() { + return "small_fixedsize"; + } + }); + } else { + IColumn column = new PropertyColumn(new ResourceModel(field), field, field) { + + private static final long serialVersionUID = 3282547854226892169L; + + @Override + public String getCssClass() { + String css = super.getCssClass(); + if ("key".equals(field)) { + css = StringUtils.isBlank(css) + ? "medium_fixedsize" + : css + " medium_fixedsize"; + } + return css; + } + }; + columns.add(column); + } + } + } + + columns.add(new AbstractColumn<AbstractSchemaTO, String>(new ResourceModel("actions", "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public String getCssClass() { + return "action"; + } + + @Override + public void populateItem(final Item<ICellPopulator<AbstractSchemaTO>> item, final String componentId, + final IModel<AbstractSchemaTO> model) { + + final AbstractSchemaTO schemaTO = model.getObject(); + + final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference()); + + panel.addWithRoles(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + modalWindow.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + AbstractSchemaModalPage page = SchemaModalPageFactory.getSchemaModalPage( + attributableType, schemaType); + + page.setSchemaModalPage(Schema.this.getPageReference(), modalWindow, schemaTO, false); + + return page; + } + }); + + modalWindow.show(target); + } + }, ActionType.EDIT, allowedReadRoles); + + panel.addWithRoles(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + + switch (schemaType) { + case DERIVED: + restClient.deleteDerSchema(attributableType, schemaTO.getKey()); + break; + + case VIRTUAL: + restClient.deleteVirSchema(attributableType, schemaTO.getKey()); + break; + + default: + restClient.deletePlainSchema(attributableType, schemaTO.getKey()); + break; + } + + info(getString(Constants.OPERATION_SUCCEEDED)); + feedbackPanel.refresh(target); + + target.add(webContainer); + } + }, ActionType.DELETE, allowedDeleteRoles); + + item.add(panel); + } + }); + + return columns; + } + + private Form<Void> getPaginatorForm(final WebMarkupContainer webContainer, + final AjaxFallbackDefaultDataTable dataTable, + final String formname, final SchemaTypePanel schemaTypePanel, final String rowsPerPagePrefName) { + + Form<Void> form = new Form<Void>(formname); + + final DropDownChoice<Integer> rowChooser = new DropDownChoice<Integer>("rowsChooser", + new PropertyModel<Integer>(schemaTypePanel, "pageRows"), prefMan.getPaginatorChoices(), + new SelectChoiceRenderer<Integer>()); + + rowChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + prefMan.set(getRequest(), getResponse(), rowsPerPagePrefName, rowChooser.getInput()); + dataTable.setItemsPerPage(rowChooser.getModelObject()); + + target.add(webContainer); + } + }); + + form.add(rowChooser); + + return form; + } + + private <T extends AbstractSchemaModalPage> AjaxLink<Void> getCreateSchemaLink(final ModalWindow modalWindow, + final AttributableType attrType, final SchemaType schemaType, final String winLinkName) { + + AjaxLink<Void> link = new ClearIndicatingAjaxLink<Void>(winLinkName, getPageReference()) { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + protected void onClickInternal(final AjaxRequestTarget target) { + modalWindow.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + T page = SchemaModalPageFactory.getSchemaModalPage(attrType, schemaType); + page.setSchemaModalPage(Schema.this.getPageReference(), modalWindow, null, true); + + return page; + } + }); + + modalWindow.show(target); + } + }; + + MetaDataRoleAuthorizationStrategy.authorize(link, ENABLE, allowedCreateRoles); + + return link; + + } + + private class SchemaProvider extends SortableDataProvider<AbstractSchemaTO, String> { + + private static final long serialVersionUID = -185944053385660794L; + + private final SortableDataProviderComparator<AbstractSchemaTO> comparator; + + private final AttributableType attrType; + + private final SchemaType schemaType; + + public SchemaProvider(final AttributableType attrType, final SchemaType schemaType) { + super(); + + this.attrType = attrType; + this.schemaType = schemaType; + + // Default sorting + setSort("key", SortOrder.ASCENDING); + + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator<AbstractSchemaTO> iterator(final long first, final long count) { + @SuppressWarnings("unchecked") + List<AbstractSchemaTO> list = + (List<AbstractSchemaTO>) restClient.getSchemas(this.attrType, this.schemaType); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return restClient.getSchemas(this.attrType, this.schemaType).size(); + } + + @Override + public IModel<AbstractSchemaTO> model(final AbstractSchemaTO object) { + return new CompoundPropertyModel<AbstractSchemaTO>(object); + } + } + + private class SchemaTypePanel extends Panel { + + private static final long serialVersionUID = 2854050613688773575L; + + private int pageRows; + + private final AttributableType attrType; + + private final SchemaType schemaType; + + public SchemaTypePanel(final String id, final AttributableType attrType, final SchemaType schemaType) { + super(id); + + this.attrType = attrType; + this.schemaType = schemaType; + + setup(); + } + + private void setup() { + ModalWindow editSchemaWin = new ModalWindow("editSchemaWin"); + editSchemaWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + editSchemaWin.setInitialWidth(WIN_WIDTH); + if (schemaType == SchemaType.PLAIN) { + editSchemaWin.setInitialHeight(PLAIN_WIN_HEIGHT); + } else { + editSchemaWin.setInitialHeight(WIN_HEIGHT); + } + editSchemaWin.setCookieName("editSchemaWin"); + editSchemaWin.setMarkupId("editSchemaWin"); + add(editSchemaWin); + + WebMarkupContainer schemaWrapContainer = new WebMarkupContainer("schemaWrapContainer"); + schemaWrapContainer.setOutputMarkupId(true); + if (schemaType != SchemaType.VIRTUAL) { + schemaWrapContainer.add(new AttributeModifier("style", "width:auto;")); + } + add(schemaWrapContainer); + + WebMarkupContainer schemaContainer = new WebMarkupContainer("schemaContainer"); + schemaContainer.setOutputMarkupId(true); + schemaWrapContainer.add(schemaContainer); + setWindowClosedCallback(editSchemaWin, schemaContainer); + + final String paginatorRowsKey = PAGINATOR_ROWS_KEYS.get( + new SimpleEntry<AttributableType, SchemaType>(attrType, schemaType)); + pageRows = prefMan.getPaginatorRows(getRequest(), paginatorRowsKey); + + List<IColumn> tableCols = getColumns(schemaContainer, editSchemaWin, attrType, + schemaType, COL_NAMES.get(schemaType)); + final AjaxFallbackDefaultDataTable table = new AjaxFallbackDefaultDataTable("datatable", tableCols, + new SchemaProvider(attrType, schemaType), pageRows); + table.setOutputMarkupId(true); + schemaContainer.add(table); + + schemaWrapContainer.add(getPaginatorForm(schemaContainer, table, "paginatorForm", this, paginatorRowsKey)); + + add(getCreateSchemaLink(editSchemaWin, attrType, schemaType, "createSchemaLink")); + } + } +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java new file mode 100644 index 0000000..12bfc2b --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/SecurityQuestionModalPage.java @@ -0,0 +1,111 @@ +/* + * 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.rest.SecurityQuestionRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.SecurityQuestionTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.markup.html.form.AjaxButton; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +class SecurityQuestionModalPage extends BaseModalPage { + + private static final long serialVersionUID = -6709838862698327502L; + + @SpringBean + private SecurityQuestionRestClient restClient; + + public SecurityQuestionModalPage(final PageReference pageRef, final ModalWindow window, + final SecurityQuestionTO securityQuestionTO, final boolean createFlag) { + + final Form<SecurityQuestionTO> form = + new Form<SecurityQuestionTO>(FORM, new CompoundPropertyModel<SecurityQuestionTO>(securityQuestionTO)); + + final AjaxTextFieldPanel contentFieldPanel = + new AjaxTextFieldPanel("content", "content", new PropertyModel<String>(securityQuestionTO, "content")); + contentFieldPanel.setRequired(true); + form.add(contentFieldPanel); + + AjaxButton submit = new IndicatingAjaxButton(APPLY, new Model<String>(getString(SUBMIT))) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + try { + if (createFlag) { + restClient.create(securityQuestionTO); + } else { + restClient.update(securityQuestionTO); + } + info(getString(Constants.OPERATION_SUCCEEDED)); + + Configuration callerPage = (Configuration) pageRef.getPage(); + callerPage.setModalResult(true); + + window.close(target); + } catch (SyncopeClientException scee) { + error(getString(Constants.ERROR) + ": " + scee.getMessage()); + feedbackPanel.refresh(target); + } + } + + @Override + protected void onError(final AjaxRequestTarget target, final Form<?> form) { + feedbackPanel.refresh(target); + } + }; + + final AjaxButton cancel = new IndicatingAjaxButton(CANCEL, new ResourceModel(CANCEL)) { + + private static final long serialVersionUID = -958724007591692537L; + + @Override + protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) { + window.close(target); + } + }; + + cancel.setDefaultFormProcessing(false); + + String allowedRoles = createFlag + ? xmlRolesReader.getEntitlement("SecurityQuestion", "create") + : xmlRolesReader.getEntitlement("SecurityQuestion", "update"); + MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE, allowedRoles); + + form.add(submit); + form.setDefaultButton(submit); + + form.add(cancel); + + add(form); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java new file mode 100644 index 0000000..9d0ede2 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/StatusModalPage.java @@ -0,0 +1,644 @@ +/* + * 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.Collection; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider; +import org.apache.syncope.client.console.commons.status.ConnObjectWrapper; +import org.apache.syncope.client.console.commons.status.Status; +import org.apache.syncope.client.console.commons.status.StatusBean; +import org.apache.syncope.client.console.commons.status.StatusUtils; +import org.apache.syncope.client.console.panels.ActionDataTablePanel; +import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; +import org.apache.syncope.common.lib.to.AbstractSubjectTO; +import org.apache.syncope.common.lib.to.BulkActionResult; +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.syncope.common.lib.types.ResourceAssociationActionType; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; +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.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.markup.ComponentTag; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.form.Form; +import org.apache.wicket.markup.html.form.PasswordTextField; +import org.apache.wicket.markup.html.panel.Fragment; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.StringResourceModel; + +public class StatusModalPage<T extends AbstractSubjectTO> extends AbstractStatusModalPage { + + private static final long serialVersionUID = -9148734710505211261L; + + private final AbstractSubjectTO subjectTO; + + private int rowsPerPage = 10; + + final StatusUtils statusUtils; + + final boolean statusOnly; + + // -------------------------------- + // password management fields .. + // -------------------------------- + final ClearIndicatingAjaxButton cancel; + + final WebMarkupContainer pwdMgt; + + final Form<?> pwdMgtForm; + + final AjaxCheckBoxPanel changepwd; + + final PasswordTextField password; + + final PasswordTextField confirm; + // -------------------------------- + + final PageReference pageRef; + + final ModalWindow window; + + final ActionDataTablePanel<StatusBean, String> table; + + final List<IColumn<StatusBean, String>> columns; + + public StatusModalPage( + final PageReference pageRef, + final ModalWindow window, + final AbstractSubjectTO attributableTO) { + + this(pageRef, window, attributableTO, false); + } + + public StatusModalPage( + final PageReference pageRef, + final ModalWindow window, + final AbstractSubjectTO subjectTO, + final boolean statusOnly) { + + super(); + + this.pageRef = pageRef; + this.window = window; + this.statusOnly = statusOnly; + this.subjectTO = subjectTO; + + statusUtils = new StatusUtils(subjectTO instanceof UserTO ? userRestClient : roleRestClient); + + add(new Label("displayName", subjectTO.getKey() + " " + + (subjectTO instanceof UserTO ? ((UserTO) subjectTO).getUsername() : ((RoleTO) subjectTO).getName()))); + + columns = new ArrayList<>(); + columns.add(new AbstractColumn<StatusBean, String>( + new StringResourceModel("resourceName", this, null, "Resource name"), "resourceName") { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public void populateItem( + final Item<ICellPopulator<StatusBean>> cellItem, + final String componentId, + final IModel<StatusBean> model) { + + cellItem.add(new Label(componentId, model.getObject().getResourceName()) { + + private static final long serialVersionUID = 8432079838783825801L; + + @Override + protected void onComponentTag(final ComponentTag tag) { + if (model.getObject().isLinked()) { + super.onComponentTag(tag); + } else { + tag.put("style", "color: #DDDDDD"); + } + } + }); + } + }); + + columns.add(new PropertyColumn<StatusBean, String>( + new StringResourceModel("accountLink", this, null, "Account link"), "accountLink", "accountLink")); + + columns.add(new AbstractColumn<StatusBean, String>( + new StringResourceModel("status", this, null, "")) { + + private static final long serialVersionUID = -3503023501954863131L; + + @Override + public String getCssClass() { + return "action"; + } + + @Override + public void populateItem( + final Item<ICellPopulator<StatusBean>> cellItem, + final String componentId, + final IModel<StatusBean> model) { + + if (model.getObject().isLinked()) { + cellItem.add(statusUtils.getStatusImagePanel(componentId, model.getObject(). + getStatus())); + } else { + cellItem.add(new Label(componentId, "")); + } + } + }); + + table = new ActionDataTablePanel<StatusBean, String>( + "resourceDatatable", + columns, + (ISortableDataProvider<StatusBean, String>) new AttributableStatusProvider(), + rowsPerPage, + pageRef) { + + private static final long serialVersionUID = 6510391461033818316L; + + @Override + public boolean isElementEnabled(final StatusBean element) { + return !statusOnly || element.getStatus() != Status.OBJECT_NOT_FOUND; + } + }; + table.setOutputMarkupId(true); + + final String pageId = subjectTO instanceof RoleTO ? "Roles" : "Users"; + + final Fragment pwdMgtFragment = new Fragment("pwdMgtFields", "pwdMgtFragment", this); + addOrReplace(pwdMgtFragment); + + pwdMgt = new WebMarkupContainer("pwdMgt"); + pwdMgtFragment.add(pwdMgt.setOutputMarkupId(true)); + + pwdMgtForm = new Form("pwdMgtForm"); + pwdMgtForm.setVisible(false).setEnabled(false); + pwdMgt.add(pwdMgtForm); + + password = new PasswordTextField("password", new Model<String>()); + pwdMgtForm.add(password.setRequired(false).setEnabled(false)); + + confirm = new PasswordTextField("confirm", new Model<String>()); + pwdMgtForm.add(confirm.setRequired(false).setEnabled(false)); + + changepwd = new AjaxCheckBoxPanel("changepwd", "changepwd", new Model<Boolean>(false)); + pwdMgtForm.add(changepwd.setModelObject(false)); + pwdMgtForm.add(new Label("changePwdLabel", new ResourceModel("changePwdLabel", "Password propagation"))); + + changepwd.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -1107858522700306810L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + password.setEnabled(changepwd.getModelObject()); + confirm.setEnabled(changepwd.getModelObject()); + target.add(pwdMgt); + } + }); + + cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) { + + private static final long serialVersionUID = -2341391430136818026L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + // ignore + window.close(target); + } + }.feedbackPanelAutomaticReload(false); + + pwdMgtForm.add(cancel); + + final ClearIndicatingAjaxButton goon = + new ClearIndicatingAjaxButton("continue", new ResourceModel("continue"), pageRef) { + + private static final long serialVersionUID = -2341391430136818027L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + // none + } + }; + + pwdMgtForm.add(goon); + + if (statusOnly) { + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + userRestClient.reactivate( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + + window.close(target); + } catch (Exception e) { + LOG.error("Error enabling resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.REACTIVATE, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + userRestClient.suspend( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + + if (pageRef.getPage() instanceof BasePage) { + ((BasePage) pageRef.getPage()).setModalResult(true); + } + + window.close(target); + } catch (Exception e) { + LOG.error("Error disabling resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.SUSPEND, pageId); + } else { + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + if (subjectTO instanceof UserTO) { + userRestClient.unlink( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + roleRestClient.unlink( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + window.close(target); + } catch (Exception e) { + LOG.error("Error unlinking resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.UNLINK, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + if (subjectTO instanceof UserTO) { + userRestClient.link( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + roleRestClient.link( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + window.close(target); + } catch (Exception e) { + LOG.error("Error linking resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.LINK, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + BulkActionResult bulkActionResult; + if (subjectTO instanceof UserTO) { + bulkActionResult = userRestClient.deprovision( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = roleRestClient.deprovision( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error de-provisioning user", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.DEPROVISION, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + + if (subjectTO instanceof UserTO) { + StatusModalPage.this.passwordManagement( + target, ResourceAssociationActionType.PROVISION, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = roleRestClient.provision( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error provisioning user", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + } + }.feedbackPanelAutomaticReload(!(subjectTO instanceof UserTO)), ActionLink.ActionType.PROVISION, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + final BulkActionResult bulkActionResult; + if (subjectTO instanceof UserTO) { + bulkActionResult = userRestClient.unassign( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } else { + bulkActionResult = roleRestClient.unassign( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error unassigning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }, ActionLink.ActionType.UNASSIGN, pageId); + + table.addAction(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (subjectTO instanceof UserTO) { + StatusModalPage.this.passwordManagement( + target, ResourceAssociationActionType.ASSIGN, table.getModelObject()); + } else { + try { + final BulkActionResult bulkActionResult = roleRestClient.assign( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(table.getModelObject())); + + ((BasePage) pageRef.getPage()).setModalResult(true); + loadBulkActionResultPage(table.getModelObject(), bulkActionResult); + } catch (Exception e) { + LOG.error("Error assigning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + } + }.feedbackPanelAutomaticReload(!(subjectTO instanceof UserTO)), ActionLink.ActionType.ASSIGN, pageId); + } + + table.addCancelButton(window); + add(table); + } + + private class AttributableStatusProvider extends AbstractStatusBeanProvider { + + private static final long serialVersionUID = 4586969457669796621L; + + public AttributableStatusProvider() { + super(statusOnly ? "resourceName" : "accountLink"); + } + + @SuppressWarnings("unchecked") + @Override + public List<StatusBean> getStatusBeans() { + final List<String> resources = new ArrayList<>(); + for (ResourceTO resourceTO : resourceRestClient.getAll()) { + resources.add(resourceTO.getKey()); + } + + final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(subjectTO); + + final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size() + 1); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean( + subjectTO, + entry.getResourceName(), + entry.getConnObjectTO(), + subjectTO instanceof RoleTO); + + statusBeans.add(statusBean); + resources.remove(entry.getResourceName()); + } + + if (statusOnly) { + final StatusBean syncope = new StatusBean(subjectTO, "Syncope"); + + syncope.setAccountLink(((UserTO) subjectTO).getUsername()); + + Status syncopeStatus = Status.UNDEFINED; + if (((UserTO) subjectTO).getStatus() != null) { + try { + syncopeStatus = Status.valueOf(((UserTO) subjectTO).getStatus().toUpperCase()); + } catch (IllegalArgumentException e) { + LOG.warn("Unexpected status found: {}", ((UserTO) subjectTO).getStatus(), e); + } + } + syncope.setStatus(syncopeStatus); + + statusBeans.add(syncope); + } else { + for (String resource : resources) { + final StatusBean statusBean = statusUtils.getStatusBean( + subjectTO, + resource, + null, + subjectTO instanceof RoleTO); + + statusBean.setLinked(false); + statusBeans.add(statusBean); + } + } + + return statusBeans; + } + } + + private void passwordManagement( + final AjaxRequestTarget target, + final ResourceAssociationActionType type, + final Collection<StatusBean> selection) { + + final ClearIndicatingAjaxButton goon = + new ClearIndicatingAjaxButton("continue", new ResourceModel("continue", "Continue"), pageRef) { + + private static final long serialVersionUID = -2341391430136818027L; + + @Override + protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) { + try { + if (StringUtils.isNotBlank(password.getModelObject()) + && !password.getModelObject().equals(confirm.getModelObject())) { + throw new Exception(getString("passwordMismatch")); + } + + final BulkActionResult bulkActionResult; + switch (type) { + case ASSIGN: + bulkActionResult = userRestClient.assign( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(selection), + changepwd.getModelObject(), + password.getModelObject()); + break; + case PROVISION: + bulkActionResult = userRestClient.provision( + subjectTO.getETagValue(), + subjectTO.getKey(), + new ArrayList<>(selection), + changepwd.getModelObject(), + password.getModelObject()); + break; + default: + bulkActionResult = null; + // ignore + } + + ((BasePage) pageRef.getPage()).setModalResult(true); + + if (bulkActionResult != null) { + loadBulkActionResultPage(selection, bulkActionResult); + } else { + + target.add(((BasePage) pageRef.getPage()).getFeedbackPanel()); + window.close(target); + } + } catch (Exception e) { + LOG.error("Error provisioning resources", e); + error(getString(Constants.ERROR) + ": " + e.getMessage()); + feedbackPanel.refresh(target); + } + } + }.feedbackPanelAutomaticReload(false); + + pwdMgtForm.addOrReplace(goon); + + table.setVisible(false); + pwdMgtForm.setVisible(true).setEnabled(true); + + target.add(table); + target.add(pwdMgt); + } + + private void loadBulkActionResultPage( + final Collection<StatusBean> selection, final BulkActionResult bulkActionResult) { + final List<String> resources = new ArrayList<String>(selection.size()); + for (StatusBean statusBean : selection) { + resources.add(statusBean.getResourceName()); + } + + final List<ConnObjectWrapper> connObjects = + statusUtils.getConnectorObjects(Collections.singletonList(subjectTO), resources); + + final List<StatusBean> statusBeans = new ArrayList<StatusBean>(connObjects.size()); + + for (ConnObjectWrapper entry : connObjects) { + final StatusBean statusBean = statusUtils.getStatusBean( + subjectTO, + entry.getResourceName(), + entry.getConnObjectTO(), + subjectTO instanceof RoleTO); + + statusBeans.add(statusBean); + } + + setResponsePage(new BulkActionResultModalPage<StatusBean, String>( + window, + statusBeans, + columns, + bulkActionResult, + "resourceName")); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.java new file mode 100644 index 0000000..544f670 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/SyncTaskModalPage.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.pages; + +import java.util.List; +import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel; +import org.apache.syncope.common.lib.to.SchedTaskTO; +import org.apache.syncope.common.lib.to.SyncTaskTO; +import org.apache.syncope.common.lib.types.MatchingRule; +import org.apache.syncope.common.lib.types.UnmatchingRule; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.markup.html.form.DropDownChoice; +import org.apache.wicket.model.PropertyModel; + +/** + * Modal window with Sync Task form. + */ +public class SyncTaskModalPage extends AbstractSyncTaskModalPage { + + private static final long serialVersionUID = 2148403203517274669L; + + public SyncTaskModalPage(final ModalWindow window, final SyncTaskTO taskTO, final PageReference pageRef) { + + super(window, taskTO, pageRef); + + // set default Matching rule + ((DropDownChoice) matchingRule.getField()).setDefaultModelObject(taskTO.getMatchingRule() == null + ? MatchingRule.UPDATE + : taskTO.getMatchingRule()); + profile.add(matchingRule); + + // set default Unmatching rule + ((DropDownChoice) unmatchingRule.getField()).setDefaultModelObject(taskTO.getUnmatchingRule() == null + ? UnmatchingRule.PROVISION + : taskTO.getUnmatchingRule()); + profile.add(unmatchingRule); + + final AjaxCheckBoxPanel fullReconciliation = new AjaxCheckBoxPanel("fullReconciliation", + getString("fullReconciliation"), new PropertyModel<Boolean>(taskTO, "fullReconciliation")); + profile.add(fullReconciliation); + } + + @Override + protected List<String> getSyncActions() { + return taskRestClient.getSyncActionsClasses(); + } + + @Override + public void submitAction(final SchedTaskTO taskTO) { + if (taskTO.getKey() > 0) { + taskRestClient.updateSyncTask((SyncTaskTO) taskTO); + } else { + taskRestClient.createSyncTask((SyncTaskTO) taskTO); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java new file mode 100644 index 0000000..c251d87 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/TaskModalPage.java @@ -0,0 +1,253 @@ +/* + * 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.Collections; +import java.util.Iterator; +import java.util.List; +import org.apache.syncope.client.console.commons.Constants; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn; +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.AjaxTextFieldPanel; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.AbstractTaskTO; +import org.apache.syncope.common.lib.to.NotificationTaskTO; +import org.apache.syncope.common.lib.to.PropagationTaskTO; +import org.apache.syncope.common.lib.to.SchedTaskTO; +import org.apache.syncope.common.lib.to.SyncTaskTO; +import org.apache.syncope.common.lib.to.TaskExecTO; +import org.apache.wicket.Component; +import org.apache.wicket.Page; +import org.apache.wicket.ajax.AjaxRequestTarget; +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.sort.SortOrder; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +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.Form; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.apache.wicket.model.ResourceModel; +import org.springframework.util.StringUtils; + +/** + * Modal window with Task form (to stop and start execution). + */ +public abstract class TaskModalPage extends BaseModalPage { + + private static final long serialVersionUID = -4110576026663173545L; + + protected WebMarkupContainer profile; + + protected WebMarkupContainer executions; + + protected Form<AbstractTaskTO> form; + + public TaskModalPage(final AbstractTaskTO taskTO) { + final ModalWindow taskExecMessageWin = new ModalWindow("taskExecMessageWin"); + taskExecMessageWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY); + taskExecMessageWin.setCookieName("task-exec-message-win-modal"); + add(taskExecMessageWin); + + form = new Form<>(FORM); + form.setModel(new CompoundPropertyModel<>(taskTO)); + add(form); + + profile = new WebMarkupContainer("profile"); + profile.setOutputMarkupId(true); + form.add(profile); + + executions = new WebMarkupContainer("executionContainer"); + executions.setOutputMarkupId(true); + form.add(executions); + + final Label idLabel = new Label("idLabel", new ResourceModel("key")); + profile.add(idLabel); + + final AjaxTextFieldPanel id = + new AjaxTextFieldPanel("key", getString("key"), new PropertyModel<String>(taskTO, "key")); + + id.setEnabled(false); + profile.add(id); + + final List<IColumn<TaskExecTO, String>> columns = new ArrayList<>(); + + final int paginatorRows = 10; + + columns.add(new PropertyColumn<TaskExecTO, String>(new ResourceModel("key"), "key", "key")); + columns.add(new DatePropertyColumn<TaskExecTO>(new ResourceModel("startDate"), "startDate", "startDate")); + columns.add(new DatePropertyColumn<TaskExecTO>(new ResourceModel("endDate"), "endDate", "endDate")); + columns.add(new PropertyColumn<TaskExecTO, String>(new ResourceModel("status"), "status", "status")); + columns.add(new ActionColumn<TaskExecTO, String>(new ResourceModel("actions", "")) { + + private static final long serialVersionUID = 2054811145491901166L; + + @Override + public ActionLinksPanel getActions(final String componentId, final IModel<TaskExecTO> model) { + + final TaskExecTO taskExecutionTO = 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) { + taskExecMessageWin.setPageCreator(new ModalWindow.PageCreator() { + + private static final long serialVersionUID = -7834632442532690940L; + + @Override + public Page createPage() { + return new ExecMessageModalPage(model.getObject().getMessage()); + } + }); + taskExecMessageWin.show(target); + } + }, ActionLink.ActionType.EDIT, TASKS, StringUtils.hasText(model.getObject().getMessage())); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target) { + try { + taskRestClient.deleteExecution(taskExecutionTO.getKey()); + + taskTO.getExecutions().remove(taskExecutionTO); + + info(getString(Constants.OPERATION_SUCCEEDED)); + } catch (SyncopeClientException scce) { + error(scce.getMessage()); + } + + feedbackPanel.refresh(target); + target.add(executions); + } + }, ActionLink.ActionType.DELETE, TASKS); + + return panel; + } + + @Override + public Component getHeader(final String componentId) { + final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), getPageReference()); + + panel.add(new ActionLink() { + + private static final long serialVersionUID = -7978723352517770644L; + + @Override + public void onClick(final AjaxRequestTarget target) { + if (target != null) { + final AjaxFallbackDefaultDataTable<TaskExecTO, String> currentTable = + new AjaxFallbackDefaultDataTable<TaskExecTO, String>("executionsTable", columns, + new TaskExecutionsProvider(getCurrentTaskExecution(taskTO)), paginatorRows); + currentTable.setOutputMarkupId(true); + target.add(currentTable); + executions.addOrReplace(currentTable); + } + } + }, ActionLink.ActionType.RELOAD, TASKS, "list"); + + return panel; + } + }); + + final AjaxFallbackDefaultDataTable<TaskExecTO, String> table = + new AjaxFallbackDefaultDataTable<TaskExecTO, String>("executionsTable", columns, + new TaskExecutionsProvider(getCurrentTaskExecution(taskTO)), paginatorRows); + + executions.add(table); + } + + protected static class TaskExecutionsProvider extends SortableDataProvider<TaskExecTO, String> { + + private static final long serialVersionUID = 8943636537120648961L; + + private SortableDataProviderComparator<TaskExecTO> comparator; + + private AbstractTaskTO taskTO; + + public TaskExecutionsProvider(final AbstractTaskTO taskTO) { + //Default sorting + this.taskTO = taskTO; + setSort("startDate", SortOrder.DESCENDING); + comparator = new SortableDataProviderComparator<TaskExecTO>(this); + } + + @Override + public Iterator<TaskExecTO> iterator(final long first, final long count) { + + List<TaskExecTO> list = taskTO.getExecutions(); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return taskTO.getExecutions().size(); + } + + @Override + public IModel<TaskExecTO> model(final TaskExecTO taskExecution) { + + return new AbstractReadOnlyModel<TaskExecTO>() { + + private static final long serialVersionUID = 7485475149862342421L; + + @Override + public TaskExecTO getObject() { + return taskExecution; + } + }; + } + } + + private AbstractTaskTO getCurrentTaskExecution(final AbstractTaskTO taskTO) { + final AbstractTaskTO currentTask = taskTO.getKey() == 0 + ? taskTO + : taskTO instanceof PropagationTaskTO + ? taskRestClient.readPropagationTask(taskTO.getKey()) + : taskTO instanceof NotificationTaskTO + ? taskRestClient.readNotificationTask(taskTO.getKey()) + : taskTO instanceof SyncTaskTO + ? taskRestClient.readSchedTask(SyncTaskTO.class, taskTO.getKey()) + : taskRestClient.readSchedTask(SchedTaskTO.class, taskTO.getKey()); + + taskTO.getExecutions().clear(); + taskTO.getExecutions().addAll(currentTask.getExecutions()); + return taskTO; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java b/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java new file mode 100644 index 0000000..296c365 --- /dev/null +++ b/client/console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java @@ -0,0 +1,230 @@ +/* + * 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.Comparator; +import java.util.Iterator; +import java.util.List; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.panels.AjaxDataTablePanel; +import org.apache.syncope.client.console.panels.NotificationTasks; +import org.apache.syncope.client.console.panels.PropagationTasks; +import org.apache.syncope.client.console.panels.PushTasksPanel; +import org.apache.syncope.client.console.panels.SchedTasks; +import org.apache.syncope.client.console.panels.SyncTasksPanel; +import org.apache.syncope.client.console.rest.BaseRestClient; +import org.apache.syncope.client.console.rest.TaskRestClient; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.common.lib.to.AbstractTaskTO; +import org.apache.syncope.common.lib.to.SchedTaskTO; +import org.apache.syncope.common.lib.to.TaskExecTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder; +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.util.SortableDataProvider; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.model.AbstractReadOnlyModel; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; + +public class Tasks extends BasePage { + + private static final long serialVersionUID = 5289215853622289061L; + + public Tasks() { + super(); + + add(new PropagationTasks("propagation", getPageReference())); + add(new NotificationTasks("notification", getPageReference())); + add(new SchedTasks("sched", getPageReference())); + add(new SyncTasksPanel("sync", getPageReference())); + add(new PushTasksPanel("push", getPageReference())); + + getPageReference(); + } + + @Override + public void setWindowClosedCallback(final ModalWindow window, final WebMarkupContainer container) { + + super.setWindowClosedCallback(window, container); + } + + public static class TaskExecutionsProvider extends SortableDataProvider<TaskExecTO, String> { + + private static final long serialVersionUID = -5401263348984206145L; + + private SortableDataProviderComparator<TaskExecTO> comparator; + + private AbstractTaskTO taskTO; + + public TaskExecutionsProvider(final AbstractTaskTO taskTO) { + super(); + + //Default sorting + this.taskTO = taskTO; + setSort("startDate", SortOrder.DESCENDING); + comparator = new SortableDataProviderComparator<TaskExecTO>(this); + } + + @Override + public Iterator<TaskExecTO> iterator(final long first, final long count) { + + List<TaskExecTO> list = getTaskDB(); + + Collections.sort(list, comparator); + + return list.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return getTaskDB().size(); + } + + @Override + public IModel<TaskExecTO> model(final TaskExecTO taskExecution) { + + return new AbstractReadOnlyModel<TaskExecTO>() { + + private static final long serialVersionUID = 7485475149862342421L; + + @Override + public TaskExecTO getObject() { + return taskExecution; + } + }; + } + + public List<TaskExecTO> getTaskDB() { + return taskTO.getExecutions(); + } + } + + public static class TasksProvider<T extends AbstractTaskTO> extends SortableDataProvider<T, String> { + + private static final long serialVersionUID = -20112718133295756L; + + private SortableDataProviderComparator<T> comparator; + + private TaskRestClient restClient; + + private int paginatorRows; + + private String id; + + private Class<T> reference; + + public TasksProvider( + final TaskRestClient restClient, final int paginatorRows, final String id, final Class<T> reference) { + + super(); + + //Default sorting + setSort("key", SortOrder.DESCENDING); + comparator = new SortableDataProviderComparator<>(this); + this.paginatorRows = paginatorRows; + this.restClient = restClient; + this.id = id; + this.reference = reference; + } + + @Override + public Iterator<T> iterator(final long first, final long count) { + final List<T> tasks = new ArrayList<>(); + + final int page = ((int) first / paginatorRows); + + for (T task : restClient.list(reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort())) { + if (task instanceof SchedTaskTO && ((SchedTaskTO) task).getLastExec() == null + && task.getExecutions() != null && !task.getExecutions().isEmpty()) { + + Collections.sort(task.getExecutions(), new Comparator<TaskExecTO>() { + + @Override + public int compare(final TaskExecTO left, final TaskExecTO right) { + return left.getStartDate().compareTo(right.getStartDate()); + } + }); + + ((SchedTaskTO) task).setLastExec(task.getExecutions().get(task.getExecutions().size() - 1). + getStartDate()); + } + tasks.add(task); + } + + Collections.sort(tasks, comparator); + return tasks.iterator(); + } + + @Override + public long size() { + return restClient.count(id); + } + + @Override + public IModel<T> model(final T object) { + return new CompoundPropertyModel<>(object); + } + } + + /** + * Update task table. + * + * @param columns columns. + * @param dataProvider data provider. + * @param container container. + * @param currentPage current page index. + * @param pageRef page reference + * @param restClient syncope base rest client + * @return data table. + */ + public static AjaxDataTablePanel<AbstractTaskTO, String> updateTaskTable( + final List<IColumn<AbstractTaskTO, String>> columns, + final TasksProvider<? extends AbstractTaskTO> dataProvider, + final WebMarkupContainer container, + final int currentPage, + final PageReference pageRef, + final BaseRestClient restClient) { + + @SuppressWarnings("unchecked") + final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<>( + "datatable", + columns, + (ISortableDataProvider<AbstractTaskTO, String>) dataProvider, + dataProvider.paginatorRows, + Arrays.asList(new ActionLink.ActionType[] { + ActionLink.ActionType.DELETE, ActionLink.ActionType.DRYRUN, ActionLink.ActionType.EXECUTE }), + restClient, + "key", + TASKS, + pageRef); + + table.setCurrentPage(currentPage); + table.setOutputMarkupId(true); + + container.addOrReplace(table); + + return table; + } +}
