All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.imunity.console.views.directory_browser.attributes.AttributesGrid Maven / Gradle / Ivy

There is a newer version: 4.0.3
Show newest version
/*
 * Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
 * See LICENCE.txt file for licensing information.
 */

package io.imunity.console.views.directory_browser.attributes;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Hr;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.function.SerializablePredicate;
import io.imunity.console.attribute.AttributeEditDialog;
import io.imunity.console.attribute.AttributeEditor;
import io.imunity.console.views.directory_browser.EntityWithLabel;
import io.imunity.vaadin.elements.ColumnToggleMenu;
import io.imunity.vaadin.elements.NotificationPresenter;
import io.imunity.vaadin.elements.grid.ActionMenuWithHandlerSupport;
import io.imunity.vaadin.elements.grid.GridWithActionColumn;
import io.imunity.vaadin.elements.grid.SingleActionHandler;
import io.imunity.vaadin.endpoint.common.ComponentWithToolbar;
import io.imunity.vaadin.endpoint.common.Toolbar;
import io.imunity.vaadin.endpoint.common.WebSession;
import io.imunity.vaadin.endpoint.common.bus.EventsBus;
import io.imunity.vaadin.endpoint.common.plugins.attributes.AttributeHandlerRegistry;
import pl.edu.icm.unity.base.attribute.Attribute;
import pl.edu.icm.unity.base.attribute.AttributeExt;
import pl.edu.icm.unity.base.attribute.AttributeType;
import pl.edu.icm.unity.base.entity.EntityParam;
import pl.edu.icm.unity.base.message.MessageSource;
import pl.edu.icm.unity.engine.api.attributes.AttributeClassHelper;
import pl.edu.icm.unity.engine.api.utils.MessageUtils;
import pl.edu.icm.unity.engine.api.utils.PrototypeComponent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static io.imunity.console.tprofile.Constants.FORM_PROFILE;
import static io.imunity.vaadin.elements.CSSVars.SMALL_MARGIN;
import static io.imunity.vaadin.elements.CssClassNames.*;
import static pl.edu.icm.unity.engine.api.utils.TimeUtil.formatStandardInstant;


@PrototypeComponent
public class AttributesGrid extends VerticalLayout
{
	private final MessageSource msg;
	private final AttributesController controller;
	private final AttributeHandlerRegistry registry;
	private final NotificationPresenter notificationPresenter;
	private final GridWithActionColumn attributesGrid;
	private final SerializablePredicate internalAttrsFilter;
	private final SerializablePredicate effectiveAttrsFilter;
	private final EventsBus bus;

	private AttributeClassHelper acHelper;
	private Map attributeTypes;
	private EntityWithLabel owner;
	private String groupPath;

	AttributesGrid(MessageSource msg, AttributesController controller, AttributeHandlerRegistry registry,
			NotificationPresenter notificationPresenter)
	{
		this.msg = msg;
		this.controller = controller;
		this.registry = registry;
		this.notificationPresenter = notificationPresenter;
		this.bus = WebSession.getCurrent().getEventBus();

		attributesGrid = new GridWithActionColumn<>(msg::getMessage, Collections.emptyList());

		attributesGrid.addShowDetailsColumn(new ComponentRenderer<>(controller::getDetailsComponent));

		Grid.Column nameColumn = attributesGrid.addColumn(Attribute::getName)
				.setHeader(msg.getMessage("AttributesGrid.nameCaption"))
				.setSortable(true)
				.setAutoWidth(true)
				.setResizable(true);

		attributesGrid.addComponentColumn(controller::getShortAttrValuesRepresentation)
				.setHeader(msg.getMessage("AttributesGrid.valueCaption"))
				.setSortable(true)
				.setAutoWidth(true)
				.setResizable(true);

		ColumnToggleMenu columnToggleMenu = new ColumnToggleMenu();

		Grid.Column createdOnColumn = attributesGrid.addColumn(a -> a.getCreationTs() != null ?
						formatStandardInstant(a.getCreationTs().toInstant()) : "")
				.setHeader(msg.getMessage("AttributesGrid.createCaption"))
				.setResizable(true)
				.setSortable(true)
				.setAutoWidth(true);
		createdOnColumn.setVisible(false);
		columnToggleMenu.addColumn(msg.getMessage("AttributesGrid.createCaption"), createdOnColumn);

		Grid.Column updatedOnColumn = attributesGrid.addColumn(a -> a.getUpdateTs() != null ?
						formatStandardInstant(a.getUpdateTs().toInstant()) : "")
				.setHeader(msg.getMessage("AttributesGrid.updateCaption"))
				.setResizable(true)
				.setSortable(true)
				.setAutoWidth(true);
		updatedOnColumn.setVisible(false);
		columnToggleMenu.addColumn(msg.getMessage("AttributesGrid.updateCaption"), updatedOnColumn);

		Grid.Column sourceColumn = attributesGrid.addColumn(a -> getSourceName(msg, a))
				.setHeader(msg.getMessage("AttributesGrid.sourceCaption"))
				.setResizable(true)
				.setSortable(true)
				.setAutoWidth(true);
		sourceColumn.setVisible(false);
		columnToggleMenu.addColumn(msg.getMessage("AttributesGrid.sourceCaption"), sourceColumn);

		attributesGrid.setClassNameGenerator(a ->
		{
			StringBuilder style = new StringBuilder();
			if (checkAttributeImmutable(a) || !a.isDirect())
				style.append(" ").append(IMMUTABLE_ATTRIBUTE.getName());
			if (acHelper.isMandatory(a.getName()))
				style.append(" ").append(BOLD.getName());
			return style.toString().trim();
		});
		attributesGrid.sort(GridSortOrder.asc(nameColumn).build());

		attributesGrid.addHamburgerActions(getRowActionsHandlers());
		attributesGrid.addThemeVariants(GridVariant.LUMO_COMPACT);
		attributesGrid.setActionColumnHeader(getActions(columnToggleMenu));

		attributesGrid.setMultiSelect(true);
		attributesGrid.setSizeFull();

		ActionMenuWithHandlerSupport hamburgerMenu = new ActionMenuWithHandlerSupport<>();
		hamburgerMenu.addActionHandlers(getGlobalHamburgerHandlers());

		attributesGrid.addSelectionListener(hamburgerMenu.getSelectionListener());

		Toolbar toolbar = new Toolbar<>();
		toolbar.setWidthFull();
		toolbar.addCompactHamburger(hamburgerMenu, Alignment.END);
		Button button = new Button(msg.getMessage("add"), VaadinIcon.PLUS_CIRCLE_O.create());
		button.addClickListener(e -> showAddDialog());
		button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		toolbar.add(button);
		ComponentWithToolbar componentWithToolbar = new ComponentWithToolbar(attributesGrid, toolbar);
		componentWithToolbar.setSizeFull();
		componentWithToolbar.setClassName(SMALL_GAP.getName());
		add(componentWithToolbar);
		setSizeFull();
		setPadding(false);

		effectiveAttrsFilter = AttributeExt::isDirect;
		internalAttrsFilter = a -> !checkAttributeImmutable(a);

		hamburgerMenu.add(new Hr());

		MenuItem showEffective = hamburgerMenu.addItem(msg.getMessage("Attribute.showEffective"),
				c -> updateAttributesFilter(!c.getSource().isChecked(), effectiveAttrsFilter));
		showEffective.setCheckable(true);
		showEffective.setChecked(true);

		MenuItem showInternal = hamburgerMenu.addItem(msg.getMessage("Attribute.showInternal"),
				c -> updateAttributesFilter(!c.getSource().isChecked(), internalAttrsFilter));
		showInternal.setCheckable(true);
		showInternal.setChecked(false);

		updateAttributesFilter(false, effectiveAttrsFilter);
		updateAttributesFilter(true, internalAttrsFilter);
	}

	private String getSourceName(MessageSource msg, AttributeExt a)
	{
		if (a.getTranslationProfile() != null)
		{
			if(a.getTranslationProfile().equals(FORM_PROFILE))
				return msg.getMessage("Attribute.formAutomation");
			return a.getTranslationProfile() + (a.getRemoteIdp() != null ? " " + a.getRemoteIdp() : "");
		}
		else if (a.isDirect())
			return msg.getMessage("Attribute.direct");
		 else
			return msg.getMessage("Attribute.fromStatement");
	}

	private HorizontalLayout getActions(ColumnToggleMenu columnToggleMenu)
	{
		Span actions = new Span(msg.getMessage("actions"));
		HorizontalLayout horizontalLayout = new HorizontalLayout(actions, columnToggleMenu.getTarget());
		horizontalLayout.setSpacing(false);
		horizontalLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
		actions.getStyle().set("margin-right", SMALL_MARGIN.value());
		return horizontalLayout;
	}

	private void updateAttributesFilter(boolean add, SerializablePredicate filter)
	{
		if (add)
			attributesGrid.addFilter(filter);
		else
			attributesGrid.removeFilter(filter);
	}

	private boolean checkAttributeImmutable(AttributeExt attribute)
	{
		AttributeType attributeType = attributeTypes.get(attribute.getName());
		if (attributeType == null)
			return false;
		return attributeType.isInstanceImmutable();
	}

	private List> getRowActionsHandlers()
	{
		SingleActionHandler edit = SingleActionHandler.builder4Edit(msg::getMessage, AttributeExt.class)
				.withDisabledPredicate(this::isAttributeEditable).withHandler(this::showEditDialog)
				.build();
		return Arrays.asList(edit, getDeleteAction());
	}

	private void showEditDialog(Collection target)
	{
		Attribute attribute = target.iterator().next();
		AttributeType attributeType = attributeTypes.get(attribute.getName());
		AttributeEditor attributeEditor = new AttributeEditor(msg, attributeType, attribute, getEntityParam(),
				registry);
		AttributeEditDialog dialog = new AttributeEditDialog(msg, msg.getMessage("Attribute.editAttribute"),
				this::updateAttribute, attributeEditor);
		dialog.addActionButtonListener(this::refresh);
		dialog.open();
	}

	private List> getGlobalHamburgerHandlers()
	{
		return Collections.singletonList(getDeleteAction());
	}

	private void showAddDialog()
	{
		List allowed = new ArrayList<>(attributeTypes.size());
		for (AttributeType at : attributeTypes.values())
		{
			if (at.isInstanceImmutable())
				continue;
			if (acHelper.isAllowed(at.getName()))
			{
				boolean used = false;
				for (AttributeExt a : attributesGrid.getElements())
					if (a.isDirect() && a.getName().equals(at.getName()))
					{
						used = true;
						break;
					}
				if (!used)
					allowed.add(at);
			}
		}

		if (allowed.isEmpty())
		{
			notificationPresenter.showNotice(msg.getMessage("notice"),
					msg.getMessage("Attribute.noAvailableAttributes"));
			return;
		}

		AttributeEditor attributeEditor = new AttributeEditor(msg, allowed, getEntityParam(), groupPath,
				registry, true);
		AttributeEditDialog dialog = new AttributeEditDialog(msg, msg.getMessage("Attribute.addAttribute"),
				this::addAttribute, attributeEditor);
		dialog.open();
	}

	private boolean updateAttribute(Attribute attribute)
	{
		controller.updateAttribute(getEntityParam(), attribute, bus);

		attributesGrid.getElements().stream()
				.filter(a -> a.getName().equals(attribute.getName())).findFirst().ifPresent(
						toReplace -> attributesGrid.replaceElement(toReplace, new AttributeExt(attribute, true)));

		return true;
	}

	private boolean addAttribute(Attribute attribute)
	{
		controller.addAttribute(getEntityParam(), attribute, bus);

		refresh();
		return true;
	}

	private SingleActionHandler getDeleteAction()
	{
		return SingleActionHandler.builder4Delete(msg::getMessage, AttributeExt.class)
				.withDisabledPredicate(a -> isAttributeEditable(a) || checkAttributeMandatory(a))
				.withHandler(this::deleteHandler).build();
	}

	private void deleteHandler(Collection items)
	{
		String confirmText = MessageUtils.createConfirmFromNames(msg, items);

		new ConfirmDialog(
				msg.getMessage("ConfirmDialog.confirm"),
				msg.getMessage("Attribute.removeConfirm", confirmText),
				msg.getMessage("ok"),
				e -> removeAttributes(items),
				msg.getMessage("cancel"),
				e ->
				{
				}
		).open();
	}

	private void removeAttributes(Collection items)
	{
		controller.removeAttribute(getEntityParam(), items, bus);
		items.forEach(attributesGrid::removeElement);

		refresh();
	}

	private void refresh()
	{
		Collection attributesCol = controller.getAttributes(owner, groupPath);
		acHelper = controller.getAttributeClassHelper(getEntityParam(), groupPath);
		attributeTypes = controller.getAttributeTypes();
		attributesGrid.setItems(attributesCol);
	}

	EntityParam getEntityParam()
	{
		return new EntityParam(owner.getEntity().getId());
	}

	private boolean isAttributeEditable(AttributeExt item)
	{
		return checkAttributeImmutable(item) || !item.isDirect();
	}

	private boolean checkAttributeMandatory(AttributeExt item)
	{
		return acHelper.isMandatory(item.getName());

	}

	public void setInput(EntityWithLabel owner, String groupPath)
	{
		this.owner = owner;
		this.groupPath = groupPath;
		refresh();
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy