Skip to content

Commit

Permalink
more cleanup for multi-value container list panels.
Browse files Browse the repository at this point in the history
- new providers for assignments and shadows
- new details panel for assignments - containers on separated tabs
- default details panel is now "tabbed"

this should bring better UX for assignments and later for other containers which has rich data structure
  • Loading branch information
katkav committed Apr 19, 2021
1 parent ba2ad60 commit c7815a3
Show file tree
Hide file tree
Showing 32 changed files with 848 additions and 691 deletions.
Expand Up @@ -8,6 +8,8 @@

import java.util.*;

import com.evolveum.midpoint.model.common.util.DefaultColumnUtils;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
Expand Down Expand Up @@ -202,6 +204,15 @@ protected MultiFunctinalButtonDto load() {

}

@Override
protected List<IColumn<SelectableBean<O>, String>> createDefaultColumns() {
GuiObjectListViewType defaultView = DefaultColumnUtils.getDefaultView(getType());
if (defaultView == null) {
return null;
}
return getViewColumnsTransformed(defaultView.getColumn());
}

private DisplayType getNewObjectButtonStandardDisplayType() {
if (isCollectionViewPanelForCompiledView()) {

Expand Down
Expand Up @@ -91,11 +91,6 @@ protected List<ItemPath> getFixedSearchItems() {
return fixedSearchItems;
}

@Override
protected LoadableModel<Search<O>> getSearchModel() {
return super.getSearchModel();
}

protected final SelectableBeanObjectDataProvider<O> createSelectableBeanObjectDataProvider(SerializableSupplier<ObjectQuery> querySuplier,
SerializableFunction<SortParam<String>, List<ObjectOrdering>> orderingSuplier) {
List<O> preSelectedObjectList = getPreselectedObjectList();
Expand Down
@@ -0,0 +1,275 @@
/*
* Copyright (C) 2021 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/
package com.evolveum.midpoint.gui.impl.component;

import java.util.List;
import javax.xml.namespace.QName;

import org.apache.wicket.extensions.markup.html.tabs.ITab;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.gui.api.component.DisplayNamePanel;
import com.evolveum.midpoint.gui.api.component.tabs.PanelTab;
import com.evolveum.midpoint.gui.api.prism.wrapper.ItemWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerValueWrapper;
import com.evolveum.midpoint.gui.api.prism.wrapper.PrismContainerWrapper;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.gui.impl.prism.panel.SingleContainerPanel;
import com.evolveum.midpoint.gui.impl.prism.wrapper.ConstructionValueWrapper;
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil;
import com.evolveum.midpoint.web.component.assignment.ConstructionAssociationPanel;
import com.evolveum.midpoint.web.component.prism.ItemVisibility;
import com.evolveum.midpoint.web.model.PrismContainerWrapperModel;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

public class AssignmentsDetailsPanel extends MultivalueContainerDetailsPanel<AssignmentType> {

private static final Trace LOGGER = TraceManager.getTrace(AssignmentsDetailsPanel.class);
private boolean isEntitledAssignemnt;

public AssignmentsDetailsPanel(String id, IModel<PrismContainerValueWrapper<AssignmentType>> model, boolean isEntitledAssignment) {
super(id, model, !isEntitledAssignment);
this.isEntitledAssignemnt = isEntitledAssignment;
}

@NotNull
@Override
protected List<ITab> createTabs() {
List<ITab> tabs = super.createTabs();
if (isEntitledAssignemnt) {
tabs.add(getConstructionAssociationPanel());
return tabs;
}

AssignmentsUtil.AssignmentTypeType assignmentTypeType = AssignmentsUtil.getAssignmentType(getModelObject());
switch (assignmentTypeType) {
case CONSTRUCTION:
tabs.add(createConstructionTabs());
break;
case POLICY_RULE:
tabs.add(createTabs("AssignmentType.policyRule", AssignmentType.F_POLICY_RULE, PolicyRuleType.COMPLEX_TYPE));
break;
case FOCUS_MAPPING:
tabs.add(createTabs("AssignmentType.focusMappings", AssignmentType.F_FOCUS_MAPPINGS, MappingType.COMPLEX_TYPE));
break;
case PERSONA_CONSTRUCTION:
tabs.add(createTabs("AssignmentType.personaConstruction", AssignmentType.F_PERSONA_CONSTRUCTION, PersonaConstructionType.COMPLEX_TYPE));
break;
case ASSIGNMENT_RELATION:
tabs.add(createTabs("AssignmentType.assignmentRelation", AssignmentType.F_ASSIGNMENT_RELATION, AssignmentRelationType.COMPLEX_TYPE));
break;
}

tabs.add(createActivationTab());
tabs.add(createConditionTab());
return tabs;
}

private PanelTab getConstructionAssociationPanel() {
return new PanelTab(createStringResource("AssignmentPanel.inducedEntitlements")) {
@Override
public WebMarkupContainer createPanel(String panelId) {
IModel<PrismContainerWrapper<ConstructionType>> constructionModel = PrismContainerWrapperModel.fromContainerValueWrapper(getModel(), AssignmentType.F_CONSTRUCTION);
ConstructionAssociationPanel constructionDetailsPanel = new ConstructionAssociationPanel(panelId, constructionModel);
constructionDetailsPanel.setOutputMarkupId(true);
return constructionDetailsPanel;
}
};
}
@Override
protected ItemVisibility getBasicTabVisibity(ItemWrapper<?, ?> itemWrapper) {
return getContainerVisibility(itemWrapper);
}

@Override
protected boolean getBasicTabEditability(ItemWrapper<?, ?> itemWrapper) {
return getContainerReadability(itemWrapper);
}

@Override
protected DisplayNamePanel<AssignmentType> createDisplayNamePanel(String displayNamePanelId) {
IModel<AssignmentType> displayNameModel = getDisplayModel(getModelObject().getRealValue());
return new DisplayNamePanel<>(displayNamePanelId, displayNameModel) {

private static final long serialVersionUID = 1L;

@Override
protected QName getRelation() {
return getRelationForDisplayNamePanel(AssignmentsDetailsPanel.this.getModelObject());
}

@Override
protected IModel<String> getKindIntentLabelModel() {
return getKindIntentLabelModelForDisplayNamePanel(AssignmentsDetailsPanel.this.getModelObject());
}

};
}

@SuppressWarnings("unchecked")
private <C extends Containerable> IModel<C> getDisplayModel(AssignmentType assignment) {
return () -> {
if (assignment.getTargetRef() != null && assignment.getTargetRef().getOid() != null) {
Task task = getPageBase().createSimpleTask("Load target");
OperationResult result = task.getResult();
PrismObject<ObjectType> targetObject = WebModelServiceUtils.loadObject(assignment.getTargetRef(), getPageBase(), task, result);
return targetObject != null ? (C) targetObject.asObjectable() : null;
}
if (assignment.getConstruction() != null && assignment.getConstruction().getResourceRef() != null) {
if (assignment.getConstruction().getResourceRef().getOid() != null) {
Task task = getPageBase().createSimpleTask("Load resource");
OperationResult result = task.getResult();
PrismObject<?> object = WebModelServiceUtils.loadObject(assignment.getConstruction().getResourceRef(), getPageBase(), task, result);
if (object != null) {
return (C) object.asObjectable();
}
} else {
return (C) assignment.getConstruction();
}
} else if (assignment.getPersonaConstruction() != null) {
return (C) assignment.getPersonaConstruction();
} else if (assignment.getPolicyRule() != null) {
return (C) assignment.getPolicyRule();
}
return null;
};
}

private QName getRelationForDisplayNamePanel(PrismContainerValueWrapper<AssignmentType> modelObject) {
AssignmentType assignment = modelObject.getRealValue();
if (assignment.getTargetRef() != null) {
return assignment.getTargetRef().getRelation();
} else {
return null;
}
}

private IModel<String> getKindIntentLabelModelForDisplayNamePanel(PrismContainerValueWrapper<AssignmentType> modelObject) {
AssignmentType assignment = modelObject.getRealValue();
if (assignment.getConstruction() != null) {
PrismContainerValueWrapper<ConstructionType> constructionValue = null;
try {
PrismContainerWrapper<ConstructionType> construction = modelObject.findContainer(AssignmentType.F_CONSTRUCTION);
if (construction == null) {
return null;
}
constructionValue = construction.getValue();
} catch (SchemaException e) {
LOGGER.error("Unexpected problem during construction wrapper lookup, {}", e.getMessage(), e);
}
ShadowKindType kind;
String intent;
if (constructionValue instanceof ConstructionValueWrapper) {
kind = ((ConstructionValueWrapper) constructionValue).getKind();
intent = ((ConstructionValueWrapper) constructionValue).getIntent();
} else {
kind = assignment.getConstruction().getKind();
intent = assignment.getConstruction().getIntent();
}

return createStringResource("DisplayNamePanel.kindIntentLabel", kind, intent);
}
return Model.of();
}

protected boolean getContainerReadability(ItemWrapper<?, ?> wrapper) {
if (QNameUtil.match(ConstructionType.F_KIND, wrapper.getItemName())) {
return false;
}

return !QNameUtil.match(ConstructionType.F_INTENT, wrapper.getItemName());
}

private ItemVisibility getContainerVisibility(ItemWrapper<?, ?> wrapper) {
if (wrapper instanceof PrismContainerWrapper) {
return ItemVisibility.HIDDEN;
}
return ItemVisibility.AUTO;
}

private PanelTab createTabs(String titleKey, ItemPath path, QName type) {
return new PanelTab(createStringResource(titleKey)) {

@Override
public WebMarkupContainer createPanel(String panelId) {
return new SingleContainerPanel<>(panelId, PrismContainerWrapperModel.fromContainerValueWrapper(getModel(), path), type);
}
};

}
private PanelTab createConstructionTabs() {
return createTabs("AssignmentType.construction", AssignmentType.F_CONSTRUCTION, ConstructionType.COMPLEX_TYPE);
}

private PanelTab createActivationTab() {
return new PanelTab(createStringResource("AssignmentType.activation")) {
@Override
public WebMarkupContainer createPanel(String panelId) {
return new SingleContainerPanel<>(panelId,
PrismContainerWrapperModel.fromContainerValueWrapper(getModel(), AssignmentType.F_ACTIVATION), ActivationType.COMPLEX_TYPE) {

@Override
protected ItemVisibility getVisibility(ItemPath itemPath) {
if (ItemPath.create(AssignmentHolderType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_LOCKOUT_EXPIRATION_TIMESTAMP).equivalent(itemPath.namedSegmentsOnly())) {
return ItemVisibility.HIDDEN;
}

if (ItemPath.create(AssignmentHolderType.F_ASSIGNMENT, AssignmentType.F_ACTIVATION, ActivationType.F_LOCKOUT_STATUS).equivalent(itemPath.namedSegmentsOnly())) {
return ItemVisibility.HIDDEN;
}

if (ItemPath.create(AbstractRoleType.F_INDUCEMENT, AssignmentType.F_ACTIVATION, ActivationType.F_LOCKOUT_EXPIRATION_TIMESTAMP).equivalent(itemPath.namedSegmentsOnly())) {
return ItemVisibility.HIDDEN;
}

if (ItemPath.create(AbstractRoleType.F_INDUCEMENT, AssignmentType.F_ACTIVATION, ActivationType.F_LOCKOUT_STATUS).equivalent(itemPath.namedSegmentsOnly())) {
return ItemVisibility.HIDDEN;
}

return super.getVisibility(itemPath);
}
};
}
};
}

private PanelTab createConditionTab() {
return new PanelTab(createStringResource("AssignmentType.condition")) {

@Override
public WebMarkupContainer createPanel(String panelId) {
return new SingleContainerPanel<>(panelId, PrismContainerWrapperModel.fromContainerValueWrapper(getModel(), AssignmentType.F_CONDITION), MappingType.COMPLEX_TYPE) {

@Override
protected ItemVisibility getVisibility(ItemPath itemPath) {
ItemPath assignmentConditionExpressionPath = ItemPath.create(AssignmentHolderType.F_ASSIGNMENT, AssignmentType.F_CONDITION, MappingType.F_EXPRESSION);
ItemPath inducementConditionExpressionPath = ItemPath.create(AbstractRoleType.F_INDUCEMENT, AssignmentType.F_CONDITION, MappingType.F_EXPRESSION);
if (itemPath.namedSegmentsOnly().equivalent(assignmentConditionExpressionPath) || itemPath.namedSegmentsOnly().equivalent(inducementConditionExpressionPath)) {
return ItemVisibility.AUTO;
} else {
return ItemVisibility.HIDDEN;
}
}
};
}
};
}


}
Expand Up @@ -342,11 +342,6 @@ protected boolean isNewObjectButtonEnabled(){
return true;
}

protected boolean getNewObjectGenericButtonVisibility(){
return true;
}


protected DisplayType getNewObjectButtonDisplayType(){
return WebComponentUtil.createDisplayType(GuiStyleConstants.CLASS_ADD_NEW_OBJECT, "green", createStringResource("MainObjectListPanel.newObject").getString());
}
Expand Down Expand Up @@ -422,7 +417,7 @@ private void addingCheckAndIconColumnIfExists(List<IColumn<PO, String>> columns)
}
}

private List<IColumn<PO, String>> getViewColumnsTransformed(List<GuiObjectColumnType> customColumns){
protected List<IColumn<PO, String>> getViewColumnsTransformed(List<GuiObjectColumnType> customColumns){
List<IColumn<PO, String>> columns = new ArrayList<>();
if (customColumns == null || customColumns.isEmpty()) {
return columns;
Expand Down Expand Up @@ -696,11 +691,7 @@ private List<IColumn<PO, String>> initColumns() {

List<IColumn<PO, String>> others = createDefaultColumns();
if (others == null) {
GuiObjectListViewType defaultView = DefaultColumnUtils.getDefaultView(getType());
if (defaultView == null) {
return columns;
}
others = getViewColumnsTransformed(defaultView.getColumn());
return columns;
} else {
IColumn<PO, String> nameColumn = createNameColumn(null, null, null);
if (nameColumn != null) {
Expand All @@ -725,9 +716,7 @@ protected IColumn<PO, String> createNameColumn(IModel<String> displayModel, Stri
return null;
}

protected List<IColumn<PO, String>> createDefaultColumns() {
return null;
}
protected abstract List<IColumn<PO, String>> createDefaultColumns();

protected List<InlineMenuItem> createInlineMenu() {
return null;
Expand Down
Expand Up @@ -12,9 +12,8 @@
<wicket:child />
<div wicket:id="displayName"/>
<div class="top-level-prism-container">
<div wicket:id="basicPanel"> </div>
<div wicket:id="details" class="nav-tabs-custom"> </div>
</div>
<div wicket:id="specificContainersPanel" />
</div>
</wicket:panel>
</body>
Expand Down

0 comments on commit c7815a3

Please sign in to comment.