Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/pepper-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@
<dependency>
<groupId>pepper-mm</groupId>
<artifactId>pepper-mm</artifactId>
<version>2026.3.0</version>
<version>2026.4.0</version>
</dependency>
<dependency>
<groupId>pepper-mm</groupId>
<artifactId>pepper-edit</artifactId>
<version>2026.3.0</version>
<version>2026.4.0</version>
</dependency>

<!-- Sirius Components -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,20 @@ public final class MessageConstants {

public static final String PAGE_RISKS_TITLE = "PAGE_RISKS_TITLE";

public static final String RESOURCE_FORM_TITLE = "RESOURCE_FORM_TITLE";

public static final String PAGE_RESOURCE_AVAILABILITY = "PAGE_RESOURCE_AVAILABILITY";

public static final String PAGE_RESOURCE_AVAILABILITY_TITLE = "PAGE_RESOURCE_AVAILABILITY_TITLE";

public static final String UNAVAILABILITY_PERIOD_FORM_TITLE = "UNAVAILABILITY_PERIOD_FORM_TITLE";

public static final String CREATE_NEW_UNAVAILABILITY_PERIOD = "CREATE_NEW_UNAVAILABILITY_PERIOD";

public static final String CREATE_NEW_UNAVAILABILITY_PERIOD_HELP = "CREATE_NEW_UNAVAILABILITY_PERIOD_HELP";

public static final String DELETE_UNAVAILABILITY_PERIOD = "DELETE_UNAVAILABILITY_PERIOD";

public static final String INVALID_INPUT = "INVALID_INPUT";

public static final String CREATE_NEW_WORKPACKAGE = "CREATE_NEW_WORKPACKAGE";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import pepper.starter.messages.IPepperMMMessageService;
import pepper.starter.messages.MessageConstants;
import pepper.peppermm.Project;
import pepper.peppermm.Resource;
import pepper.peppermm.UnavailabilityPeriod;

import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -45,6 +47,10 @@ public class PepperMMEditingContextDescriptionProvider implements IEditingContex

public static final String PROJECT_FORM_ID = "projectFormDescription";

public static final String RESOURCE_FORM_ID = "resourceFormDescription";

public static final String UNAVAILABILITY_PERIOD_FORM_ID = "unavailabilityPeriodFormDescription";

private final ComposedAdapterFactory composedAdapterFactory;

private final ILabelService labelService;
Expand Down Expand Up @@ -84,6 +90,10 @@ public List<IRepresentationDescription> getRepresentationDescriptions(IEditingCo
PageDescription workpackagesPageDescription = new WorkpackagesPageDescription(this.labelService, this.identityService, this.objectSearchService, this.cursorBasedNavigationServices, this.composedAdapterFactory, this.pepperMMMessageService, this.feedbackMessageService).getWorkpackagesPageDescription();
PageDescription workpackageArtefactPageDescription = new WorkpackageArtefactPageDescription(this.labelService, this.identityService, this.objectSearchService, this.cursorBasedNavigationServices, this.composedAdapterFactory, this.pepperMMMessageService, this.feedbackMessageService).getWorkpackageArtefactsPageDescription();
PageDescription risksPageDescription = new RisksPageDescription(this.labelService, this.identityService, this.objectSearchService, this.cursorBasedNavigationServices, this.composedAdapterFactory, this.pepperMMMessageService, this.feedbackMessageService).getRisksPageDescription();
PageDescription resourceAvailabilityPageDescription = new ResourceAvailabilityPageDescription(this.labelService, this.identityService, this.objectSearchService, this.cursorBasedNavigationServices, this.composedAdapterFactory,
this.pepperMMMessageService, this.feedbackMessageService).getPageDescription();
PageDescription unavailabilityPeriodPageDescription = new UnavailabilityPeriodPageDescription(this.labelService, this.identityService, this.objectSearchService, this.composedAdapterFactory, this.pepperMMMessageService,
this.feedbackMessageService).getPageDescription();


FormDescription projectFormDescription = FormDescription.newFormDescription(PROJECT_FORM_ID)
Expand All @@ -96,7 +106,25 @@ public List<IRepresentationDescription> getRepresentationDescriptions(IEditingCo
.pageDescriptions(List.of(projectPageDescription, customerPageDescription, planningAndCostingPageDescription, workpackagesPageDescription, workpackageArtefactPageDescription, risksPageDescription))
.iconURLsProvider(vm -> List.of())
.build();
return List.of(projectFormDescription);
FormDescription resourceFormDescription = FormDescription.newFormDescription(RESOURCE_FORM_ID)
.label(this.pepperMMMessageService.getMessage(MessageConstants.RESOURCE_FORM_TITLE))
.idProvider(new GetOrCreateRandomIdProvider())
.labelProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.RESOURCE_FORM_TITLE))
.targetObjectIdProvider(this::getTargetObjectId)
.canCreatePredicate(this::canCreateResourceForm)
.pageDescriptions(List.of(resourceAvailabilityPageDescription))
.iconURLsProvider(vm -> List.of())
.build();
FormDescription unavailabilityPeriodFormDescription = FormDescription.newFormDescription(UNAVAILABILITY_PERIOD_FORM_ID)
.label(this.pepperMMMessageService.getMessage(MessageConstants.UNAVAILABILITY_PERIOD_FORM_TITLE))
.idProvider(new GetOrCreateRandomIdProvider())
.labelProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.UNAVAILABILITY_PERIOD_FORM_TITLE))
.targetObjectIdProvider(this::getTargetObjectId)
.canCreatePredicate(this::canCreateUnavailabilityPeriodForm)
.pageDescriptions(List.of(unavailabilityPeriodPageDescription))
.iconURLsProvider(vm -> List.of())
.build();
return List.of(projectFormDescription, resourceFormDescription, unavailabilityPeriodFormDescription);
}

private String getTargetObjectId(VariableManager variableManager) {
Expand All @@ -110,4 +138,16 @@ private boolean canCreate(VariableManager variableManager) {
.filter(Project.class::isInstance)
.isPresent();
}

private boolean canCreateResourceForm(VariableManager variableManager) {
return variableManager.get(VariableManager.SELF, EObject.class)
.filter(Resource.class::isInstance)
.isPresent();
}

private boolean canCreateUnavailabilityPeriodForm(VariableManager variableManager) {
return variableManager.get(VariableManager.SELF, EObject.class)
.filter(UnavailabilityPeriod.class::isInstance)
.isPresent();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*******************************************************************************
* Copyright (c) 2024, 2026 CEA LIST.

@ncouvert ncouvert Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright (c) 2026 Obeo.

intead of Copyright (c) 2024, 2026 CEA LIST. for new files

* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
******************************************************************************/
package pepper.starter.services.descriptions;

import pepper.peppermm.PepperFactory;
import pepper.peppermm.Resource;
import pepper.starter.messages.IPepperMMMessageService;
import pepper.starter.messages.MessageConstants;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.sirius.components.core.api.IFeedbackMessageService;
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.ILabelService;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.core.api.labels.StyledString;
import org.eclipse.sirius.components.emf.tables.CursorBasedNavigationServices;
import org.eclipse.sirius.components.forms.ButtonStyle;
import org.eclipse.sirius.components.forms.WidgetIdProvider;
import org.eclipse.sirius.components.forms.description.AbstractControlDescription;
import org.eclipse.sirius.components.forms.description.ButtonDescription;
import org.eclipse.sirius.components.forms.description.GroupDescription;
import org.eclipse.sirius.components.forms.description.PageDescription;
import org.eclipse.sirius.components.representations.Success;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.tables.descriptions.LineDescription;
import org.eclipse.sirius.components.tables.descriptions.PaginatedData;
import org.eclipse.sirius.components.tables.descriptions.TableDescription;
import org.eclipse.sirius.components.widget.table.TableWidgetDescription;

/**
* This class is used to provide the resource availability page description.
*
* @author Obeo
*/
public class ResourceAvailabilityPageDescription {

public static final String UNAVAILABILITY_PERIODS_TABLE_ID = "unavailabilityPeriodsTableId";

private final ILabelService labelService;

private final IIdentityService identityService;

private final IObjectSearchService objectSearchService;

private final CursorBasedNavigationServices cursorBasedNavigationServices;

private final ComposedAdapterFactory composedAdapterFactory;

private final IPepperMMMessageService pepperMMMessageService;

private final IFeedbackMessageService feedbackMessageService;

public ResourceAvailabilityPageDescription(ILabelService labelService, IIdentityService identityService, IObjectSearchService objectSearchService, CursorBasedNavigationServices cursorBasedNavigationServices,
ComposedAdapterFactory composedAdapterFactory, IPepperMMMessageService pepperMMMessageService, IFeedbackMessageService feedbackMessageService) {
this.labelService = labelService;
this.identityService = identityService;
this.objectSearchService = objectSearchService;
this.cursorBasedNavigationServices = cursorBasedNavigationServices;
this.composedAdapterFactory = composedAdapterFactory;
this.pepperMMMessageService = pepperMMMessageService;
this.feedbackMessageService = feedbackMessageService;
}

PageDescription getPageDescription() {
List<AbstractControlDescription> controlDescriptions = new ArrayList<>();

Function<VariableManager, String> labelProvider = variableManager -> variableManager.get(VariableManager.SELF, Object.class)
.map(this.labelService::getStyledLabel)
.map(StyledString::toString)
.orElse(null);

LineDescription lineDescription = LineDescription.newLineDescription("Unavailability Periods - Line")
.targetObjectIdProvider(this::getTargetObjectId)
.targetObjectKindProvider(this::getTargetObjectKind)
.semanticElementsProvider(this.getSemanticElementsProvider())
.headerLabelProvider(labelProvider)
.headerIconURLsProvider(vm -> List.of())
.headerIndexLabelProvider(vm -> "")
.initialHeightProvider(vm -> 60)
.isResizablePredicate(vm -> true)
.depthLevelProvider(vm -> 0)
.hasChildrenProvider(vm -> false)
.build();

WidgetDescriptionBuilderHelper widgetDescriptionBuilderHelper = new WidgetDescriptionBuilderHelper(this::getTargetObjectId, this.labelService, this.identityService, this.objectSearchService, this.composedAdapterFactory,
this.pepperMMMessageService, this.feedbackMessageService);
TableDescription tableDescription = TableDescription.newTableDescription(UNAVAILABILITY_PERIODS_TABLE_ID)
.label("")
.targetObjectIdProvider(this::getTargetObjectId)
.targetObjectKindProvider(this::getTargetObjectKind)
.labelProvider(labelProvider)
.isStripeRowPredicate(vm -> true)
.lineDescription(lineDescription)
.columnDescriptions(List.of(widgetDescriptionBuilderHelper.buildFeaturesColumnDescription(PepperFactory.eINSTANCE.createUnavailabilityPeriod())))
.cellDescriptions(widgetDescriptionBuilderHelper.buildCellDescription())
.iconURLsProvider(vm -> List.of())
.enableSubRows(false)
.pageSizeOptionsProvider(vm -> List.of(10, 20))
.defaultPageSizeIndexProvider(vm -> 1)
.build();

TableWidgetDescription tableWidgetDescription = TableWidgetDescription.newTableWidgetDescription("unavailabilityPeriodsTableWidgetId")
.idProvider(new WidgetIdProvider())
.labelProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.PAGE_RESOURCE_AVAILABILITY_TITLE))
.targetObjectIdProvider(this::getTargetObjectId)
.diagnosticsProvider(variableManager -> List.of())
.kindProvider(object -> "")
.messageProvider(object -> "")
.tableDescription(tableDescription)
.build();

controlDescriptions.add(tableWidgetDescription);

GroupDescription group = GroupDescription.newGroupDescription("resourceAvailabilityGroupId")
.idProvider(variableManager -> "resourceAvailabilityGroupId")
.labelProvider(variableManager -> "")
.semanticElementsProvider(variableManager -> Collections.singletonList(variableManager.getVariables().get(VariableManager.SELF)))
.controlDescriptions(controlDescriptions)
.toolbarActionDescriptions(List.of(this.getCreateUnavailabilityPeriodButtonDescription()))
.build();

return PageDescription.newPageDescription("resourceAvailabilityPageId")
.idProvider(variableManager -> "resourceAvailabilityPageId")
.labelProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.PAGE_RESOURCE_AVAILABILITY))
.semanticElementsProvider(variableManager -> Collections.singletonList(variableManager.getVariables().get(VariableManager.SELF)))
.groupDescriptions(List.of(group))
.canCreatePredicate(variableManager -> true)
.build();
}

private Function<VariableManager, PaginatedData> getSemanticElementsProvider() {
return variableManager -> variableManager.get(VariableManager.SELF, Resource.class)
.map(Resource::getUnavailabilityPeriods)
.map(periods -> this.cursorBasedNavigationServices.toPaginatedData(periods.stream().map(Object.class::cast).toList(),
variableManager.get("cursor", Object.class).orElse(null),
variableManager.get("direction", String.class).orElse(null),
variableManager.get("size", Integer.class).orElse(10)))
.orElseGet(() -> new PaginatedData(List.of(), false, false, 0));
}

private ButtonDescription getCreateUnavailabilityPeriodButtonDescription() {
return ButtonDescription.newButtonDescription("createUnavailabilityPeriod")
.idProvider(new WidgetIdProvider())
.targetObjectIdProvider(this::getTargetObjectId)
.labelProvider(variableManager -> "")
.iconURLProvider(variableManager -> List.of())
.isReadOnlyProvider(variableManager -> false)
.buttonLabelProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.CREATE_NEW_UNAVAILABILITY_PERIOD))
.imageURLProvider(variableManager -> "icons/full/obj16/UnavailabilityPeriod.svg")
.pushButtonHandler(variableManager -> {
variableManager.get(VariableManager.SELF, Resource.class)
.ifPresent(resource -> resource.getUnavailabilityPeriods().add(PepperFactory.eINSTANCE.createUnavailabilityPeriod()));
return new Success();
})
.diagnosticsProvider(variableManager -> List.of())
.kindProvider(variableManager -> "")
.messageProvider(variableManager -> "")
.styleProvider(variableManager -> ButtonStyle.newButtonStyle()
.backgroundColor("#ffffff")
.foregroundColor("#261E58")
.build())
.helpTextProvider(variableManager -> this.pepperMMMessageService.getMessage(MessageConstants.CREATE_NEW_UNAVAILABILITY_PERIOD_HELP))
.build();
}

private String getTargetObjectId(VariableManager variableManager) {
return variableManager.get(VariableManager.SELF, Object.class)
.map(this.identityService::getId)
.orElse(null);
}

private String getTargetObjectKind(VariableManager variableManager) {
return variableManager.get(VariableManager.SELF, Object.class)
.map(this.identityService::getId)
.orElse(null);
}
}
Loading
Loading