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

io.imunity.upman.invitations.ProjectInvitationsView Maven / Gradle / Ivy

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

package io.imunity.upman.invitations;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.vaadin.data.Binder;
import com.vaadin.data.ValidationResult;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.shared.ui.datefield.DateTimeResolution;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.DateTimeField;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.VerticalLayout;

import io.imunity.upman.UpManNavigationInfoProviderBase;
import io.imunity.upman.UpManRootNavigationInfoProvider;
import io.imunity.upman.UpManUI;
import io.imunity.upman.common.UpManView;
import io.imunity.webelements.navigation.NavigationInfo;
import io.imunity.webelements.navigation.NavigationInfo.Type;
import pl.edu.icm.unity.MessageSource;
import pl.edu.icm.unity.engine.api.project.DelegatedGroup;
import pl.edu.icm.unity.engine.api.project.ProjectInvitation;
import pl.edu.icm.unity.engine.api.project.ProjectInvitationParam;
import pl.edu.icm.unity.engine.api.utils.PrototypeComponent;
import pl.edu.icm.unity.stdext.utils.EmailUtils;
import pl.edu.icm.unity.types.I18nString;
import pl.edu.icm.unity.types.basic.Group;
import pl.edu.icm.unity.types.basic.GroupDelegationConfiguration;
import pl.edu.icm.unity.webui.common.AbstractDialog;
import pl.edu.icm.unity.webui.common.Images;
import pl.edu.icm.unity.webui.common.NotificationPopup;
import pl.edu.icm.unity.webui.common.Styles;
import pl.edu.icm.unity.webui.common.groups.OptionalGroupsSelection;
import pl.edu.icm.unity.webui.exceptions.ControllerException;

/**
 * Invitations view
 * 
 * @author P.Piernik
 *
 */
@PrototypeComponent
public class ProjectInvitationsView extends CustomComponent implements UpManView {

	public static final String VIEW_NAME = "Invitations";

	private MessageSource msg;
	private ProjectInvitationsController controller;
	private DelegatedGroup project;
	private ProjectInvitationsComponent invitationsComponent;

	@Autowired
	public ProjectInvitationsView(MessageSource msg, ProjectInvitationsController controller) {
		this.msg = msg;
		this.controller = controller;
		setSizeFull();
	}

	@Override
	public void enter(ViewChangeEvent event) {
		try {
			project = UpManUI.getProjectGroup();
		} catch (ControllerException e) {
			NotificationPopup.showError(e);
			return;
		}
		VerticalLayout main = new VerticalLayout();
		main.setSizeFull();
		main.setMargin(false);
		setCompositionRoot(main);
		invitationsComponent = new ProjectInvitationsComponent(msg, controller, project.path);
		main.addComponent(invitationsComponent);
	}

	@Override
	public String getDisplayedName() {
		return msg.getMessage("UpManMenu.invitations");
	}

	@Override
	public String getViewName() {
		return VIEW_NAME;
	}

	@Override
	public com.vaadin.ui.Component getViewHeader() {
		HorizontalLayout header = new HorizontalLayout();
		header.setMargin(false);
		Label name = new Label(getDisplayedName());
		name.addStyleName(Styles.viewHeader.toString());
		Button addInvitationButton = new Button(msg.getMessage("Invitations.newInvite"),
				Images.add.getResource());
		addInvitationButton.addStyleName(Styles.buttonAction.toString());
		addInvitationButton.addClickListener(e -> {

			new NewInvitationDialog(msg, invitations -> {

				try {
					controller.addInvitations(invitations);
				} catch (ControllerException er) {
					NotificationPopup.showError(er);
				}
				invitationsComponent.reload();
			}).show();

		});

		try {
			Optional projectGroup = controller.getProjectGroups(project.path).stream()
					.filter(dg -> dg.path.equals(project.path)).findFirst();

			if (projectGroup.isPresent()) {
				GroupDelegationConfiguration config = projectGroup.get().delegationConfiguration;
				addInvitationButton.setVisible((config.registrationForm != null
						&& !config.registrationForm.isEmpty())
						|| (config.signupEnquiryForm != null
								&& !config.signupEnquiryForm.isEmpty()));

			}

		} catch (ControllerException er) {
			NotificationPopup.showError(er);
		}

		header.addComponents(name, addInvitationButton);
		header.setComponentAlignment(name, Alignment.MIDDLE_CENTER);
		header.setComponentAlignment(addInvitationButton, Alignment.MIDDLE_CENTER);
		return header;
	}

	@Component
	public class InvitationsNavigationInfoProvider extends UpManNavigationInfoProviderBase {
		@Autowired
		public InvitationsNavigationInfoProvider(MessageSource msg,
				ObjectFactory factory) {
			super(new NavigationInfo.NavigationInfoBuilder(VIEW_NAME, Type.View)
					.withParent(UpManRootNavigationInfoProvider.ID).withObjectFactory(factory)
					.withCaption(msg.getMessage("UpManMenu.invitations"))
					.withIcon(Images.envelope_open.getResource()).withPosition(2).build());

		}
	}

	private class NewInvitationDialog extends AbstractDialog {
		private Consumer> selectionConsumer;
		private TextArea email;
		private OptionalGroupsSelection groups;
		private DateTimeField lifeTime;
		private CheckBox allowModifyGroups;
		private Binder binder;

		public NewInvitationDialog(MessageSource msg,
				Consumer> selectionConsumer) {
			super(msg, msg.getMessage("NewInvitationDialog.caption"));
			this.selectionConsumer = selectionConsumer;
			setSizeEm(45, 28);
		}

		@Override
		protected Button createConfirmButton() {
			Button ok = super.createConfirmButton();
			ok.addStyleName(Styles.buttonAction.toString());
			return ok;
		}

		@Override
		protected FormLayout getContents() {
			email = new TextArea();
			email.setCaption(msg.getMessage("NewInvitationDialog.emails"));
			List allowedGroups = new ArrayList<>();
			try {
				allowedGroups.addAll(controller.getProjectGroups(project.path).stream()
						.filter(dg -> !dg.path.equals(project.path))
						.collect(Collectors.toList()));
			} catch (ControllerException e) {
				NotificationPopup.showError(e);
			}
			email.setWidth(20, Unit.EM);
			email.setHeight(6, Unit.EM);
			email.setDescription(msg.getMessage("NewInvitationDialog.emailsDesc"));
			email.setPlaceholder(msg.getMessage("NewInvitationDialog.emailsPrompt"));
			
			allowModifyGroups = new CheckBox(msg.getMessage("NewInvitationDialog.allowModifyGroups"));
			allowModifyGroups.setValue(false);
			allowModifyGroups.setEnabled(false);
			
			groups = new OptionalGroupsSelection(msg, true);
			groups.setCaption(msg.getMessage("NewInvitationDialog.groups"));
			groups.setItems(allowedGroups.stream().map(dg -> {
				Group g = new Group(dg.path);
				g.setDisplayedName(new I18nString(dg.displayedName));
				return g;
			}).collect(Collectors.toList()));
			groups.setDescription(msg.getMessage("NewInvitationDialog.groupsDesc"));

			groups.addValueChangeListener(e -> {
				if (e.getValue() == null || e.getValue().isEmpty())
				{
					allowModifyGroups.setEnabled(false);
					allowModifyGroups.setValue(false);
				} else
				{
					allowModifyGroups.setEnabled(true);

				}
			});
			
			lifeTime = new DateTimeField(msg.getMessage("NewInvitationDialog.invitationLivetime"));
			lifeTime.setResolution(DateTimeResolution.MINUTE);

			binder = new Binder<>(ProjectInvitationParams.class);
			binder.forField(email).asRequired(msg.getMessage("fieldRequired")).withValidator(v -> {
				for (String email : v.split("\n")) {
					if (EmailUtils.validate(email.trim()) != null)
						return false;
				}
				return true;
			}, msg.getMessage("NewInvitationDialog.incorrectEmail")).bind("contactAddress");
			binder.forField(lifeTime).asRequired(msg.getMessage("fieldRequired"))
					.withConverter(d -> d.atZone(ZoneId.systemDefault()).toInstant(),
							d -> LocalDateTime.ofInstant(d, ZoneId.systemDefault()))

					.withValidator((v, c) -> {
						return v.isAfter(Instant.now()) ? ValidationResult.ok()
								: ValidationResult.error(msg.getMessage(
										"NewInvitationDialog.invalidLifeTime"));
					}).bind("expiration");

			ProjectInvitationParams bean = new ProjectInvitationParams();
			bean.setExpiration(LocalDateTime.now(ZoneId.systemDefault())
					.plusDays(ProjectInvitation.DEFAULT_TTL_DAYS).atZone(ZoneId.systemDefault())
					.toInstant());
			binder.setBean(bean);

			FormLayout main = new FormLayout();
			main.setSpacing(true);
			main.setMargin(false);
			main.addComponents(email, groups, allowModifyGroups, lifeTime);
			main.setSizeFull();
			return main;
		}

		@Override
		protected void onConfirm() {
			if (!binder.validate().isOk())
				return;
			ProjectInvitationParams inv = binder.getBean();

			List params = new ArrayList<>();
			List selectedGroups = groups.getSelectedItems().stream().map(g -> g.toString())
					.collect(Collectors.toList());

			Stream.of(binder.getBean().getContactAddress().split("\n")).map(String::trim)
					.forEach(email -> params.add(new ProjectInvitationParam(project.path, email,
							selectedGroups, allowModifyGroups.getValue(), inv.getExpiration())));

			selectionConsumer.accept(params);
			close();
		}
	}

	// for binder only
	public static class ProjectInvitationParams {
		private String contactAddresses;
		private Instant expiration;

		public ProjectInvitationParams() {

		}

		public Instant getExpiration() {
			return expiration;
		}

		public void setExpiration(Instant expiration) {
			this.expiration = expiration;
		}

		public String getContactAddress() {
			return contactAddresses;
		}

		public void setContactAddress(String contactAddresses) {
			this.contactAddresses = contactAddresses;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy