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

io.imunity.furms.ui.views.user_settings.projects.ProjectView Maven / Gradle / Ivy

There is a newer version: 4.3.1
Show newest version
/*
 * Copyright (c) 2020 Bixbit s.c. All rights reserved.
 * See LICENSE file for licensing information.
 */

package io.imunity.furms.ui.views.user_settings.projects;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.OptionalParameter;
import com.vaadin.flow.router.Route;
import io.imunity.furms.api.alarms.AlarmService;
import io.imunity.furms.api.project_allocation.ProjectAllocationService;
import io.imunity.furms.api.projects.ProjectService;
import io.imunity.furms.api.resource_access.ResourceAccessService;
import io.imunity.furms.api.validation.exceptions.UserWithoutFenixIdValidationError;
import io.imunity.furms.domain.project_allocation.ProjectAllocationId;
import io.imunity.furms.domain.project_allocation.ProjectAllocationResolved;
import io.imunity.furms.domain.project_allocation_installation.ProjectAllocationInstallation;
import io.imunity.furms.domain.project_allocation_installation.ProjectDeallocation;
import io.imunity.furms.domain.projects.Project;
import io.imunity.furms.domain.projects.ProjectId;
import io.imunity.furms.domain.resource_access.UserGrant;
import io.imunity.furms.ui.components.DenseGrid;
import io.imunity.furms.ui.components.FurmsViewComponent;
import io.imunity.furms.ui.components.GridActionMenu;
import io.imunity.furms.ui.components.GridActionsButtonLayout;
import io.imunity.furms.ui.components.MenuButton;
import io.imunity.furms.ui.components.PageTitle;
import io.imunity.furms.ui.components.AllocationDetailsComponentFactory;
import io.imunity.furms.ui.components.ResourceProgressBar;
import io.imunity.furms.ui.components.RouterGridLink;
import io.imunity.furms.ui.components.StatusLayout;
import io.imunity.furms.ui.components.ViewHeaderLayout;
import io.imunity.furms.ui.components.layout.BreadCrumbParameter;
import io.imunity.furms.ui.project_allocation.ProjectAllocationDataSnapshot;
import io.imunity.furms.ui.views.user_settings.UserSettingsMenu;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.vaadin.flow.component.icon.VaadinIcon.ANGLE_DOWN;
import static com.vaadin.flow.component.icon.VaadinIcon.ANGLE_RIGHT;
import static com.vaadin.flow.component.icon.VaadinIcon.REFRESH;
import static com.vaadin.flow.component.icon.VaadinIcon.SPLINE_CHART;
import static io.imunity.furms.domain.resource_access.AccessStatus.GRANTED_STATUES;
import static io.imunity.furms.ui.utils.NotificationUtils.showErrorNotification;
import static io.imunity.furms.ui.utils.VaadinExceptionHandler.handleExceptions;
import static java.util.Comparator.comparing;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@Route(value = "users/settings/project", layout = UserSettingsMenu.class)
@PageTitle(key = "view.user-settings.projects.page.title")
public class ProjectView extends FurmsViewComponent {
	private final ProjectService projectService;
	private final ProjectAllocationService service;
	private final ResourceAccessService resourceAccessService;
	private final AlarmService alarmService;

	private final Grid grid;
	private ProjectId projectId;
	private UsersProjectAllocationDataSnapshot projectDataSnapshot;
	private BreadCrumbParameter breadCrumbParameter;

	public ProjectView(ProjectService projectService, ProjectAllocationService projectAllocationService, ResourceAccessService resourceAccessService, AlarmService alarmService) {
		this.projectService = projectService;
		this.service = projectAllocationService;
		this.alarmService = alarmService;
		this.resourceAccessService = resourceAccessService;
		this.grid = createCommunityGrid();

		ViewHeaderLayout headerLayout = new ViewHeaderLayout(
			getTranslation("view.project-admin.resource-allocations.page.header")
		);

		getContent().add(headerLayout, grid);
	}

	private Grid createCommunityGrid() {
		Grid grid = new DenseGrid<>(ProjectAllocationGridModel.class);

		grid.addComponentColumn(allocation -> {
			Icon icon = grid.isDetailsVisible(allocation) ? ANGLE_DOWN.create() : ANGLE_RIGHT.create();
			return new Div(icon, new Label(allocation.siteName));
		})
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.1"))
			.setSortable(true);
		grid.addColumn(model -> model.name)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.2"))
			.setSortable(true)
			.setComparator(model -> model.name.toLowerCase());
		grid.addColumn(model -> model.resourceTypeName)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.3"))
			.setSortable(true);
		grid.addColumn(model -> model.amountWithUnit)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.4"))
			.setSortable(true)
			.setComparator(comparing(model -> model.amountWithUnit.amount));
		grid.addColumn(model -> model.consumedWithUnit)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.5"))
			.setSortable(true)
			.setComparator(comparing(model -> model.consumedWithUnit.amount));
		grid.addColumn(model -> model.remainingWithUnit)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.6"))
			.setSortable(true)
			.setComparator(comparing(model -> model.remainingWithUnit.amount));
		grid.addComponentColumn(c -> {
			Optional projectAllocationInstallations = projectDataSnapshot.getParent().getAllocation(c.id);
			Optional deallocation = projectDataSnapshot.getParent().getDeallocationStatus(c.id);
			if(deallocation.isPresent()) {
				int statusId = deallocation.get().status.getPersistentId();
				return new StatusLayout(
					getTranslation("view.community-admin.project-allocation.deallocation-status." + statusId),
					deallocation.flatMap(x -> x.errorMessage).map(x -> x.message).orElse(null),
					getContent()
				);
			}
			return projectAllocationInstallations.map(installation -> {
					final int statusId = installation.status.getPersistentId();
					return new StatusLayout(getTranslation("view.community-admin.project-allocation.status." + statusId),
						installation.errorMessage.map(x -> x.message).orElse(null),
						getContent());
				}).orElseGet(StatusLayout::new);
		})
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.7"))
			.setSortable(true);
		grid.addColumn(x -> getEnabledValue(x.id, x.accessibleForAllProjectMembers))
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.8"))
			.setSortable(true);
		grid.addComponentColumn(model ->
			new ResourceProgressBar(
				model.amountWithUnit.amount,
				model.consumedWithUnit.amount,
				projectDataSnapshot.projectAllocationDataSnapshot.getAlarmThreshold(model.id)
			)
		)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.9"))
			.setTextAlign(ColumnTextAlign.CENTER);
		grid.addComponentColumn(this::createLastColumnContent)
			.setHeader(getTranslation("view.user-settings.project-allocation.grid.column.10"))
			.setTextAlign(ColumnTextAlign.END);


		grid.setItemDetailsRenderer(new ComponentRenderer<>(c -> AllocationDetailsComponentFactory
			.create(projectDataSnapshot.getParent().getChunks(c.id), c.amountWithUnit.unit)));
		grid.setSelectionMode(Grid.SelectionMode.NONE);

		return grid;
	}

	private String getEnabledValue(ProjectAllocationId allocationId, boolean accessibleForAllProjectMembers) {
		if(accessibleForAllProjectMembers)
			return getTranslation("view.project-admin.resource-access.grid.access.enabled");
		UserGrant userGrant =  projectDataSnapshot.getUserGrant(allocationId);
		if(userGrant != null && GRANTED_STATUES.contains(userGrant.status))
			return getTranslation("view.project-admin.resource-access.grid.access.enabled");
		return getTranslation("view.project-admin.resource-access.grid.access.disabled");
	}

	private HorizontalLayout createLastColumnContent(ProjectAllocationGridModel projectAllocationGridModel) {
		return new GridActionsButtonLayout(
			new RouterGridLink(SPLINE_CHART, projectAllocationGridModel.id.id.toString(),
				ProjectResourceAllocationsDetailsView.class, "projectId", projectAllocationGridModel.projectId.id.toString()),
			createContextMenu()
		);
	}

	private Component createContextMenu() {
		GridActionMenu contextMenu = new GridActionMenu();

		contextMenu.addItem(new MenuButton(getTranslation("view.user-settings.ssh-keys.grid.menu.refresh"),
			REFRESH), e -> loadGridContent());

		getContent().add(contextMenu);
		return contextMenu.getTarget();
	}

	private void loadGridContent() {
		try {
			projectDataSnapshot = new UsersProjectAllocationDataSnapshot(
				new ProjectAllocationDataSnapshot(
					service.findAllInstallations(projectId),
					service.findAllUninstallations(projectId),
					service.findAllChunks(projectId),
					alarmService.findAll(projectId)
			),
				resourceAccessService.findCurrentUserGrants(projectId).stream()
					.collect(toMap(grant -> grant.projectAllocationId, identity())));
			grid.setItems(loadServicesViewsModels());
		} catch (UserWithoutFenixIdValidationError e){
			showErrorNotification(getTranslation("user.without.fenixid.error.message"));
		}
		catch (Exception e){
			showErrorNotification(getTranslation("base.error.message"));
		}
	}

	private List loadServicesViewsModels() {
		return handleExceptions(() -> service.findAllWithRelatedObjects(projectId))
			.orElseGet(Collections::emptySet)
			.stream()
			.map(this::gridMap)
			.sorted(comparing(resourceTypeViewModel -> resourceTypeViewModel.name.toLowerCase()))
			.collect(toList());
	}

	private ProjectAllocationGridModel gridMap(ProjectAllocationResolved projectAllocation) {
		return ProjectAllocationGridModel.builder()
			.id(projectAllocation.id)
			.projectId(projectAllocation.projectId)
			.siteName(projectAllocation.site.getName())
			.resourceTypeName(projectAllocation.resourceType.name)
			.resourceTypeUnit(projectAllocation.resourceType.unit)
			.name(projectAllocation.name)
			.amount(projectAllocation.amount)
			.consumed(projectAllocation.consumed)
			.accessibleForAllProjectMembers(projectAllocation.resourceType.accessibleForAllProjectMembers)
			.build();
	}

	public static class UsersProjectAllocationDataSnapshot {
		private final ProjectAllocationDataSnapshot projectAllocationDataSnapshot;
		private final Map allocationIdToGrants;

		UsersProjectAllocationDataSnapshot(ProjectAllocationDataSnapshot projectAllocationDataSnapshot, Map allocationIdToGrants) {
			this.projectAllocationDataSnapshot = projectAllocationDataSnapshot;
			this.allocationIdToGrants = allocationIdToGrants;
		}

		ProjectAllocationDataSnapshot getParent() {
			return projectAllocationDataSnapshot;
		}

		UserGrant getUserGrant(ProjectAllocationId allocationId) {
			return allocationIdToGrants.get(allocationId);
		}
	}

	@Override
	public void setParameter(BeforeEvent event, @OptionalParameter String projectId) {
		ProjectId pId = new ProjectId(projectId);
		Project project = handleExceptions(() -> projectService.findById(pId))
			.flatMap(identity())
			.orElseThrow(IllegalStateException::new);
		this.projectId = pId;
		breadCrumbParameter = new BreadCrumbParameter(
			project.getId().id.toString(), project.getName(), getTranslation("view.user-settings.projects.bread-crumb")
		);
		loadGridContent();
	}

	@Override
	public Optional getParameter() {
		return Optional.ofNullable(breadCrumbParameter);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy